diff options
author | Tom Herbert <therbert@google.com> | 2014-07-02 00:33:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:14:21 -0400 |
commit | a3b18ddb9cc1056eea24e3edc1828cfb3fd0726f (patch) | |
tree | 5100dd399922df55b29a1acf2b5a4dcc332c10b4 | |
parent | cb1ce2ef387b01686469487edd45994872d52d73 (diff) |
net: Only do flow_dissector hash computation once per packet
Add sw_hash flag to skbuff to indicate that skb->hash was computed
from flow_dissector. This flag is checked in skb_get_hash to avoid
repeatedly trying to compute the hash (ie. in the case that no L4 hash
can be computed).
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/skbuff.h | 9 | ||||
-rw-r--r-- | net/core/flow_dissector.c | 2 |
2 files changed, 9 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b297af70ac30..890fb3307dd6 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -455,6 +455,7 @@ static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1, | |||
455 | * @ooo_okay: allow the mapping of a socket to a queue to be changed | 455 | * @ooo_okay: allow the mapping of a socket to a queue to be changed |
456 | * @l4_hash: indicate hash is a canonical 4-tuple hash over transport | 456 | * @l4_hash: indicate hash is a canonical 4-tuple hash over transport |
457 | * ports. | 457 | * ports. |
458 | * @sw_hash: indicates hash was computed in software stack | ||
458 | * @wifi_acked_valid: wifi_acked was set | 459 | * @wifi_acked_valid: wifi_acked was set |
459 | * @wifi_acked: whether frame was acked on wifi or not | 460 | * @wifi_acked: whether frame was acked on wifi or not |
460 | * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS | 461 | * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS |
@@ -562,6 +563,7 @@ struct sk_buff { | |||
562 | __u8 pfmemalloc:1; | 563 | __u8 pfmemalloc:1; |
563 | __u8 ooo_okay:1; | 564 | __u8 ooo_okay:1; |
564 | __u8 l4_hash:1; | 565 | __u8 l4_hash:1; |
566 | __u8 sw_hash:1; | ||
565 | __u8 wifi_acked_valid:1; | 567 | __u8 wifi_acked_valid:1; |
566 | __u8 wifi_acked:1; | 568 | __u8 wifi_acked:1; |
567 | __u8 no_fcs:1; | 569 | __u8 no_fcs:1; |
@@ -575,7 +577,7 @@ struct sk_buff { | |||
575 | __u8 encap_hdr_csum:1; | 577 | __u8 encap_hdr_csum:1; |
576 | __u8 csum_valid:1; | 578 | __u8 csum_valid:1; |
577 | __u8 csum_complete_sw:1; | 579 | __u8 csum_complete_sw:1; |
578 | /* 3/5 bit hole (depending on ndisc_nodetype presence) */ | 580 | /* 2/4 bit hole (depending on ndisc_nodetype presence) */ |
579 | kmemcheck_bitfield_end(flags2); | 581 | kmemcheck_bitfield_end(flags2); |
580 | 582 | ||
581 | #if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL | 583 | #if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL |
@@ -830,13 +832,14 @@ static inline void | |||
830 | skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type) | 832 | skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type) |
831 | { | 833 | { |
832 | skb->l4_hash = (type == PKT_HASH_TYPE_L4); | 834 | skb->l4_hash = (type == PKT_HASH_TYPE_L4); |
835 | skb->sw_hash = 0; | ||
833 | skb->hash = hash; | 836 | skb->hash = hash; |
834 | } | 837 | } |
835 | 838 | ||
836 | void __skb_get_hash(struct sk_buff *skb); | 839 | void __skb_get_hash(struct sk_buff *skb); |
837 | static inline __u32 skb_get_hash(struct sk_buff *skb) | 840 | static inline __u32 skb_get_hash(struct sk_buff *skb) |
838 | { | 841 | { |
839 | if (!skb->l4_hash) | 842 | if (!skb->l4_hash && !skb->sw_hash) |
840 | __skb_get_hash(skb); | 843 | __skb_get_hash(skb); |
841 | 844 | ||
842 | return skb->hash; | 845 | return skb->hash; |
@@ -850,6 +853,7 @@ static inline __u32 skb_get_hash_raw(const struct sk_buff *skb) | |||
850 | static inline void skb_clear_hash(struct sk_buff *skb) | 853 | static inline void skb_clear_hash(struct sk_buff *skb) |
851 | { | 854 | { |
852 | skb->hash = 0; | 855 | skb->hash = 0; |
856 | skb->sw_hash = 0; | ||
853 | skb->l4_hash = 0; | 857 | skb->l4_hash = 0; |
854 | } | 858 | } |
855 | 859 | ||
@@ -862,6 +866,7 @@ static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb) | |||
862 | static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) | 866 | static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) |
863 | { | 867 | { |
864 | to->hash = from->hash; | 868 | to->hash = from->hash; |
869 | to->sw_hash = from->sw_hash; | ||
865 | to->l4_hash = from->l4_hash; | 870 | to->l4_hash = from->l4_hash; |
866 | }; | 871 | }; |
867 | 872 | ||
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index c5f3912dad4c..5f362c1d0332 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -256,6 +256,8 @@ void __skb_get_hash(struct sk_buff *skb) | |||
256 | if (keys.ports) | 256 | if (keys.ports) |
257 | skb->l4_hash = 1; | 257 | skb->l4_hash = 1; |
258 | 258 | ||
259 | skb->sw_hash = 1; | ||
260 | |||
259 | skb->hash = __flow_hash_from_keys(&keys); | 261 | skb->hash = __flow_hash_from_keys(&keys); |
260 | } | 262 | } |
261 | EXPORT_SYMBOL(__skb_get_hash); | 263 | EXPORT_SYMBOL(__skb_get_hash); |