Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: Add functions to get skb->hash based on flow structures

Add skb_get_hash_flowi6 and skb_get_hash_flowi4 which derive an sk_buff
hash from flowi6 and flowi4 structures respectively. These functions
can be called when creating a packet in the output path where the new
sk_buff does not yet contain a fully formed packet that is parsable by
flow dissector.

Signed-off-by: Tom Herbert <tom@herbertland.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tom Herbert and committed by
David S. Miller
f70ea018 db316d57

+75 -4
+21
include/linux/skbuff.h
··· 37 37 #include <net/flow_dissector.h> 38 38 #include <linux/splice.h> 39 39 #include <linux/in6.h> 40 + #include <net/flow.h> 40 41 41 42 /* A. Checksumming of received packets by device. 42 43 * ··· 942 941 { 943 942 if (!skb->l4_hash && !skb->sw_hash) 944 943 __skb_get_hash(skb); 944 + 945 + return skb->hash; 946 + } 947 + 948 + __u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6); 949 + 950 + static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6) 951 + { 952 + if (!skb->l4_hash && !skb->sw_hash) 953 + __skb_get_hash_flowi6(skb, fl6); 954 + 955 + return skb->hash; 956 + } 957 + 958 + __u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl); 959 + 960 + static inline __u32 skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4) 961 + { 962 + if (!skb->l4_hash && !skb->sw_hash) 963 + __skb_get_hash_flowi4(skb, fl4); 945 964 946 965 return skb->hash; 947 966 }
+54 -4
net/core/flow_dissector.c
··· 590 590 } 591 591 EXPORT_SYMBOL(make_flow_keys_digest); 592 592 593 + static inline void __skb_set_sw_hash(struct sk_buff *skb, u32 hash, 594 + struct flow_keys *keys) 595 + { 596 + if (keys->ports.ports) 597 + skb->l4_hash = 1; 598 + skb->sw_hash = 1; 599 + skb->hash = hash; 600 + } 601 + 593 602 /** 594 603 * __skb_get_hash: calculate a flow hash 595 604 * @skb: sk_buff to calculate flow hash from ··· 618 609 hash = ___skb_get_hash(skb, &keys, hashrnd); 619 610 if (!hash) 620 611 return; 621 - if (keys.ports.ports) 622 - skb->l4_hash = 1; 623 - skb->sw_hash = 1; 624 - skb->hash = hash; 612 + 613 + __skb_set_sw_hash(skb, hash, &keys); 625 614 } 626 615 EXPORT_SYMBOL(__skb_get_hash); 627 616 ··· 630 623 return ___skb_get_hash(skb, &keys, perturb); 631 624 } 632 625 EXPORT_SYMBOL(skb_get_hash_perturb); 626 + 627 + __u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6) 628 + { 629 + struct flow_keys keys; 630 + 631 + memset(&keys, 0, sizeof(keys)); 632 + 633 + memcpy(&keys.addrs.v6addrs.src, &fl6->saddr, 634 + sizeof(keys.addrs.v6addrs.src)); 635 + memcpy(&keys.addrs.v6addrs.dst, &fl6->daddr, 636 + sizeof(keys.addrs.v6addrs.dst)); 637 + keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; 638 + keys.ports.src = fl6->fl6_sport; 639 + keys.ports.dst = fl6->fl6_dport; 640 + keys.keyid.keyid = fl6->fl6_gre_key; 641 + keys.tags.flow_label = (__force u32)fl6->flowlabel; 642 + keys.basic.ip_proto = fl6->flowi6_proto; 643 + 644 + __skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys); 645 + 646 + return skb->hash; 647 + } 648 + EXPORT_SYMBOL(__skb_get_hash_flowi6); 649 + 650 + __u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4) 651 + { 652 + struct flow_keys keys; 653 + 654 + memset(&keys, 0, sizeof(keys)); 655 + 656 + keys.addrs.v4addrs.src = fl4->saddr; 657 + keys.addrs.v4addrs.dst = fl4->daddr; 658 + keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; 659 + keys.ports.src = fl4->fl4_sport; 660 + keys.ports.dst = fl4->fl4_dport; 661 + keys.keyid.keyid = fl4->fl4_gre_key; 662 + keys.basic.ip_proto = fl4->flowi4_proto; 663 + 664 + __skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys); 665 + 666 + return skb->hash; 667 + } 668 + EXPORT_SYMBOL(__skb_get_hash_flowi4); 633 669 634 670 u32 __skb_get_poff(const struct sk_buff *skb, void *data, 635 671 const struct flow_keys *keys, int hlen)