Skip to content

Commit f70ea01

Browse files
tomratbertdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent db316d5 commit f70ea01

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed

include/linux/skbuff.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <net/flow_dissector.h>
3838
#include <linux/splice.h>
3939
#include <linux/in6.h>
40+
#include <net/flow.h>
4041

4142
/* A. Checksumming of received packets by device.
4243
*
@@ -945,6 +946,26 @@ static inline __u32 skb_get_hash(struct sk_buff *skb)
945946
return skb->hash;
946947
}
947948

949+
__u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6);
950+
951+
static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6)
952+
{
953+
if (!skb->l4_hash && !skb->sw_hash)
954+
__skb_get_hash_flowi6(skb, fl6);
955+
956+
return skb->hash;
957+
}
958+
959+
__u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl);
960+
961+
static inline __u32 skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4)
962+
{
963+
if (!skb->l4_hash && !skb->sw_hash)
964+
__skb_get_hash_flowi4(skb, fl4);
965+
966+
return skb->hash;
967+
}
968+
948969
__u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb);
949970

950971
static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)

net/core/flow_dissector.c

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,15 @@ void make_flow_keys_digest(struct flow_keys_digest *digest,
590590
}
591591
EXPORT_SYMBOL(make_flow_keys_digest);
592592

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+
593602
/**
594603
* __skb_get_hash: calculate a flow hash
595604
* @skb: sk_buff to calculate flow hash from
@@ -609,10 +618,8 @@ void __skb_get_hash(struct sk_buff *skb)
609618
hash = ___skb_get_hash(skb, &keys, hashrnd);
610619
if (!hash)
611620
return;
612-
if (keys.ports.ports)
613-
skb->l4_hash = 1;
614-
skb->sw_hash = 1;
615-
skb->hash = hash;
621+
622+
__skb_set_sw_hash(skb, hash, &keys);
616623
}
617624
EXPORT_SYMBOL(__skb_get_hash);
618625

@@ -624,6 +631,49 @@ __u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb)
624631
}
625632
EXPORT_SYMBOL(skb_get_hash_perturb);
626633

634+
__u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6)
635+
{
636+
struct flow_keys keys;
637+
638+
memset(&keys, 0, sizeof(keys));
639+
640+
memcpy(&keys.addrs.v6addrs.src, &fl6->saddr,
641+
sizeof(keys.addrs.v6addrs.src));
642+
memcpy(&keys.addrs.v6addrs.dst, &fl6->daddr,
643+
sizeof(keys.addrs.v6addrs.dst));
644+
keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
645+
keys.ports.src = fl6->fl6_sport;
646+
keys.ports.dst = fl6->fl6_dport;
647+
keys.keyid.keyid = fl6->fl6_gre_key;
648+
keys.tags.flow_label = (__force u32)fl6->flowlabel;
649+
keys.basic.ip_proto = fl6->flowi6_proto;
650+
651+
__skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys);
652+
653+
return skb->hash;
654+
}
655+
EXPORT_SYMBOL(__skb_get_hash_flowi6);
656+
657+
__u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4)
658+
{
659+
struct flow_keys keys;
660+
661+
memset(&keys, 0, sizeof(keys));
662+
663+
keys.addrs.v4addrs.src = fl4->saddr;
664+
keys.addrs.v4addrs.dst = fl4->daddr;
665+
keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
666+
keys.ports.src = fl4->fl4_sport;
667+
keys.ports.dst = fl4->fl4_dport;
668+
keys.keyid.keyid = fl4->fl4_gre_key;
669+
keys.basic.ip_proto = fl4->flowi4_proto;
670+
671+
__skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys);
672+
673+
return skb->hash;
674+
}
675+
EXPORT_SYMBOL(__skb_get_hash_flowi4);
676+
627677
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
628678
const struct flow_keys *keys, int hlen)
629679
{

0 commit comments

Comments
 (0)