aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJarno Rajahalme <jarno@ovn.org>2017-02-09 14:22:01 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-09 22:59:34 -0500
commit316d4d78cf9b6795b83f97c45368748741df418c (patch)
treee1a5001b3df43bc608a143fc16c6a7f2ff039807 /net/openvswitch
parentdd41d33f0b033885211a5d6f3ee19e73238aa9ee (diff)
openvswitch: Pack struct sw_flow_key.
struct sw_flow_key has two 16-bit holes. Move the most matched conntrack match fields there. In some typical cases this reduces the size of the key that needs to be hashed into half and into one cache line. Signed-off-by: Jarno Rajahalme <jarno@ovn.org> Acked-by: Joe Stringer <joe@ovn.org> Acked-by: Pravin B Shelar <pshelar@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/conntrack.c40
-rw-r--r--net/openvswitch/conntrack.h8
-rw-r--r--net/openvswitch/flow.h14
-rw-r--r--net/openvswitch/flow_netlink.c11
4 files changed, 39 insertions, 34 deletions
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 8b15bab70583..c2d452eab0c5 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -152,7 +152,7 @@ static void __ovs_ct_update_key_orig_tp(struct sw_flow_key *key,
152 const struct nf_conntrack_tuple *orig, 152 const struct nf_conntrack_tuple *orig,
153 u8 icmp_proto) 153 u8 icmp_proto)
154{ 154{
155 key->ct.orig_proto = orig->dst.protonum; 155 key->ct_orig_proto = orig->dst.protonum;
156 if (orig->dst.protonum == icmp_proto) { 156 if (orig->dst.protonum == icmp_proto) {
157 key->ct.orig_tp.src = htons(orig->dst.u.icmp.type); 157 key->ct.orig_tp.src = htons(orig->dst.u.icmp.type);
158 key->ct.orig_tp.dst = htons(orig->dst.u.icmp.code); 158 key->ct.orig_tp.dst = htons(orig->dst.u.icmp.code);
@@ -166,8 +166,8 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
166 const struct nf_conntrack_zone *zone, 166 const struct nf_conntrack_zone *zone,
167 const struct nf_conn *ct) 167 const struct nf_conn *ct)
168{ 168{
169 key->ct.state = state; 169 key->ct_state = state;
170 key->ct.zone = zone->id; 170 key->ct_zone = zone->id;
171 key->ct.mark = ovs_ct_get_mark(ct); 171 key->ct.mark = ovs_ct_get_mark(ct);
172 ovs_ct_get_labels(ct, &key->ct.labels); 172 ovs_ct_get_labels(ct, &key->ct.labels);
173 173
@@ -195,10 +195,10 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
195 return; 195 return;
196 } 196 }
197 } 197 }
198 /* Clear 'ct.orig_proto' to mark the non-existence of conntrack 198 /* Clear 'ct_orig_proto' to mark the non-existence of conntrack
199 * original direction key fields. 199 * original direction key fields.
200 */ 200 */
201 key->ct.orig_proto = 0; 201 key->ct_orig_proto = 0;
202} 202}
203 203
204/* Update 'key' based on skb->_nfct. If 'post_ct' is true, then OVS has 204/* Update 'key' based on skb->_nfct. If 'post_ct' is true, then OVS has
@@ -228,7 +228,7 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
228 if (ct->master) 228 if (ct->master)
229 state |= OVS_CS_F_RELATED; 229 state |= OVS_CS_F_RELATED;
230 if (keep_nat_flags) { 230 if (keep_nat_flags) {
231 state |= key->ct.state & OVS_CS_F_NAT_MASK; 231 state |= key->ct_state & OVS_CS_F_NAT_MASK;
232 } else { 232 } else {
233 if (ct->status & IPS_SRC_NAT) 233 if (ct->status & IPS_SRC_NAT)
234 state |= OVS_CS_F_SRC_NAT; 234 state |= OVS_CS_F_SRC_NAT;
@@ -259,11 +259,11 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
259int ovs_ct_put_key(const struct sw_flow_key *swkey, 259int ovs_ct_put_key(const struct sw_flow_key *swkey,
260 const struct sw_flow_key *output, struct sk_buff *skb) 260 const struct sw_flow_key *output, struct sk_buff *skb)
261{ 261{
262 if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, output->ct.state)) 262 if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, output->ct_state))
263 return -EMSGSIZE; 263 return -EMSGSIZE;
264 264
265 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && 265 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
266 nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, output->ct.zone)) 266 nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, output->ct_zone))
267 return -EMSGSIZE; 267 return -EMSGSIZE;
268 268
269 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && 269 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
@@ -275,14 +275,14 @@ int ovs_ct_put_key(const struct sw_flow_key *swkey,
275 &output->ct.labels)) 275 &output->ct.labels))
276 return -EMSGSIZE; 276 return -EMSGSIZE;
277 277
278 if (swkey->ct.orig_proto) { 278 if (swkey->ct_orig_proto) {
279 if (swkey->eth.type == htons(ETH_P_IP)) { 279 if (swkey->eth.type == htons(ETH_P_IP)) {
280 struct ovs_key_ct_tuple_ipv4 orig = { 280 struct ovs_key_ct_tuple_ipv4 orig = {
281 output->ipv4.ct_orig.src, 281 output->ipv4.ct_orig.src,
282 output->ipv4.ct_orig.dst, 282 output->ipv4.ct_orig.dst,
283 output->ct.orig_tp.src, 283 output->ct.orig_tp.src,
284 output->ct.orig_tp.dst, 284 output->ct.orig_tp.dst,
285 output->ct.orig_proto, 285 output->ct_orig_proto,
286 }; 286 };
287 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4, 287 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
288 sizeof(orig), &orig)) 288 sizeof(orig), &orig))
@@ -293,7 +293,7 @@ int ovs_ct_put_key(const struct sw_flow_key *swkey,
293 IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.dst), 293 IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.dst),
294 output->ct.orig_tp.src, 294 output->ct.orig_tp.src,
295 output->ct.orig_tp.dst, 295 output->ct.orig_tp.dst,
296 output->ct.orig_proto, 296 output->ct_orig_proto,
297 }; 297 };
298 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6, 298 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
299 sizeof(orig), &orig)) 299 sizeof(orig), &orig))
@@ -612,11 +612,11 @@ static bool skb_nfct_cached(struct net *net,
612 * due to an upcall. If the connection was not confirmed, it is not 612 * due to an upcall. If the connection was not confirmed, it is not
613 * cached and needs to be run through conntrack again. 613 * cached and needs to be run through conntrack again.
614 */ 614 */
615 if (!ct && key->ct.state & OVS_CS_F_TRACKED && 615 if (!ct && key->ct_state & OVS_CS_F_TRACKED &&
616 !(key->ct.state & OVS_CS_F_INVALID) && 616 !(key->ct_state & OVS_CS_F_INVALID) &&
617 key->ct.zone == info->zone.id) { 617 key->ct_zone == info->zone.id) {
618 ct = ovs_ct_find_existing(net, &info->zone, info->family, skb, 618 ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
619 !!(key->ct.state 619 !!(key->ct_state
620 & OVS_CS_F_NAT_MASK)); 620 & OVS_CS_F_NAT_MASK));
621 if (ct) 621 if (ct)
622 nf_ct_get(skb, &ctinfo); 622 nf_ct_get(skb, &ctinfo);
@@ -740,7 +740,7 @@ static void ovs_nat_update_key(struct sw_flow_key *key,
740 if (maniptype == NF_NAT_MANIP_SRC) { 740 if (maniptype == NF_NAT_MANIP_SRC) {
741 __be16 src; 741 __be16 src;
742 742
743 key->ct.state |= OVS_CS_F_SRC_NAT; 743 key->ct_state |= OVS_CS_F_SRC_NAT;
744 if (key->eth.type == htons(ETH_P_IP)) 744 if (key->eth.type == htons(ETH_P_IP))
745 key->ipv4.addr.src = ip_hdr(skb)->saddr; 745 key->ipv4.addr.src = ip_hdr(skb)->saddr;
746 else if (key->eth.type == htons(ETH_P_IPV6)) 746 else if (key->eth.type == htons(ETH_P_IPV6))
@@ -762,7 +762,7 @@ static void ovs_nat_update_key(struct sw_flow_key *key,
762 } else { 762 } else {
763 __be16 dst; 763 __be16 dst;
764 764
765 key->ct.state |= OVS_CS_F_DST_NAT; 765 key->ct_state |= OVS_CS_F_DST_NAT;
766 if (key->eth.type == htons(ETH_P_IP)) 766 if (key->eth.type == htons(ETH_P_IP))
767 key->ipv4.addr.dst = ip_hdr(skb)->daddr; 767 key->ipv4.addr.dst = ip_hdr(skb)->daddr;
768 else if (key->eth.type == htons(ETH_P_IPV6)) 768 else if (key->eth.type == htons(ETH_P_IPV6))
@@ -886,7 +886,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
886 * NAT after the nf_conntrack_in() call. We can actually clear 886 * NAT after the nf_conntrack_in() call. We can actually clear
887 * the whole state, as it will be re-initialized below. 887 * the whole state, as it will be re-initialized below.
888 */ 888 */
889 key->ct.state = 0; 889 key->ct_state = 0;
890 890
891 /* Update the key, but keep the NAT flags. */ 891 /* Update the key, but keep the NAT flags. */
892 ovs_ct_update_key(skb, info, key, true, true); 892 ovs_ct_update_key(skb, info, key, true, true);
@@ -902,9 +902,9 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
902 * 902 *
903 * NAT will be done only if the CT action has NAT, and only 903 * NAT will be done only if the CT action has NAT, and only
904 * once per packet (per zone), as guarded by the NAT bits in 904 * once per packet (per zone), as guarded by the NAT bits in
905 * the key->ct.state. 905 * the key->ct_state.
906 */ 906 */
907 if (info->nat && !(key->ct.state & OVS_CS_F_NAT_MASK) && 907 if (info->nat && !(key->ct_state & OVS_CS_F_NAT_MASK) &&
908 (nf_ct_is_confirmed(ct) || info->commit) && 908 (nf_ct_is_confirmed(ct) || info->commit) &&
909 ovs_ct_nat(net, key, info, skb, ct, ctinfo) != NF_ACCEPT) { 909 ovs_ct_nat(net, key, info, skb, ct, ctinfo) != NF_ACCEPT) {
910 return -EINVAL; 910 return -EINVAL;
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h
index 9e92445dc092..bc7efd1867ab 100644
--- a/net/openvswitch/conntrack.h
+++ b/net/openvswitch/conntrack.h
@@ -76,14 +76,14 @@ static inline int ovs_ct_execute(struct net *net, struct sk_buff *skb,
76static inline void ovs_ct_fill_key(const struct sk_buff *skb, 76static inline void ovs_ct_fill_key(const struct sk_buff *skb,
77 struct sw_flow_key *key) 77 struct sw_flow_key *key)
78{ 78{
79 key->ct.state = 0; 79 key->ct_state = 0;
80 key->ct.zone = 0; 80 key->ct_zone = 0;
81 key->ct.mark = 0; 81 key->ct.mark = 0;
82 memset(&key->ct.labels, 0, sizeof(key->ct.labels)); 82 memset(&key->ct.labels, 0, sizeof(key->ct.labels));
83 /* Clear 'ct.orig_proto' to mark the non-existence of original 83 /* Clear 'ct_orig_proto' to mark the non-existence of original
84 * direction key fields. 84 * direction key fields.
85 */ 85 */
86 key->ct.orig_proto = 0; 86 key->ct_orig_proto = 0;
87} 87}
88 88
89static inline int ovs_ct_put_key(const struct sw_flow_key *swkey, 89static inline int ovs_ct_put_key(const struct sw_flow_key *swkey,
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 76e05b25f030..a9bc1c875965 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -85,6 +85,11 @@ struct sw_flow_key {
85 struct vlan_head cvlan; 85 struct vlan_head cvlan;
86 __be16 type; /* Ethernet frame type. */ 86 __be16 type; /* Ethernet frame type. */
87 } eth; 87 } eth;
88 /* Filling a hole of two bytes. */
89 u8 ct_state;
90 u8 ct_orig_proto; /* CT original direction tuple IP
91 * protocol.
92 */
88 union { 93 union {
89 struct { 94 struct {
90 __be32 top_lse; /* top label stack entry */ 95 __be32 top_lse; /* top label stack entry */
@@ -96,6 +101,7 @@ struct sw_flow_key {
96 u8 frag; /* One of OVS_FRAG_TYPE_*. */ 101 u8 frag; /* One of OVS_FRAG_TYPE_*. */
97 } ip; 102 } ip;
98 }; 103 };
104 u16 ct_zone; /* Conntrack zone. */
99 struct { 105 struct {
100 __be16 src; /* TCP/UDP/SCTP source port. */ 106 __be16 src; /* TCP/UDP/SCTP source port. */
101 __be16 dst; /* TCP/UDP/SCTP destination port. */ 107 __be16 dst; /* TCP/UDP/SCTP destination port. */
@@ -138,16 +144,12 @@ struct sw_flow_key {
138 } ipv6; 144 } ipv6;
139 }; 145 };
140 struct { 146 struct {
141 /* Connection tracking fields. */ 147 /* Connection tracking fields not packed above. */
142 u8 state;
143 u8 orig_proto; /* CT orig tuple IP protocol. */
144 u16 zone;
145 u32 mark;
146 struct { 148 struct {
147 __be16 src; /* CT orig tuple tp src port. */ 149 __be16 src; /* CT orig tuple tp src port. */
148 __be16 dst; /* CT orig tuple tp dst port. */ 150 __be16 dst; /* CT orig tuple tp dst port. */
149 } orig_tp; 151 } orig_tp;
150 152 u32 mark;
151 struct ovs_key_ct_labels labels; 153 struct ovs_key_ct_labels labels;
152 } ct; 154 } ct;
153 155
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 989f38f120bb..6f5fa50f716d 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1072,14 +1072,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1072 return -EINVAL; 1072 return -EINVAL;
1073 } 1073 }
1074 1074
1075 SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask); 1075 SW_FLOW_KEY_PUT(match, ct_state, ct_state, is_mask);
1076 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE); 1076 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
1077 } 1077 }
1078 if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) && 1078 if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
1079 ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) { 1079 ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) {
1080 u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]); 1080 u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
1081 1081
1082 SW_FLOW_KEY_PUT(match, ct.zone, ct_zone, is_mask); 1082 SW_FLOW_KEY_PUT(match, ct_zone, ct_zone, is_mask);
1083 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE); 1083 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
1084 } 1084 }
1085 if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) && 1085 if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) &&
@@ -1107,7 +1107,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1107 SW_FLOW_KEY_PUT(match, ipv4.ct_orig.dst, ct->ipv4_dst, is_mask); 1107 SW_FLOW_KEY_PUT(match, ipv4.ct_orig.dst, ct->ipv4_dst, is_mask);
1108 SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask); 1108 SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
1109 SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask); 1109 SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1110 SW_FLOW_KEY_PUT(match, ct.orig_proto, ct->ipv4_proto, is_mask); 1110 SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv4_proto, is_mask);
1111 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4); 1111 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4);
1112 } 1112 }
1113 if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)) { 1113 if (*attrs & (1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6)) {
@@ -1123,7 +1123,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
1123 is_mask); 1123 is_mask);
1124 SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask); 1124 SW_FLOW_KEY_PUT(match, ct.orig_tp.src, ct->src_port, is_mask);
1125 SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask); 1125 SW_FLOW_KEY_PUT(match, ct.orig_tp.dst, ct->dst_port, is_mask);
1126 SW_FLOW_KEY_PUT(match, ct.orig_proto, ct->ipv6_proto, is_mask); 1126 SW_FLOW_KEY_PUT(match, ct_orig_proto, ct->ipv6_proto, is_mask);
1127 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6); 1127 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6);
1128 } 1128 }
1129 1129
@@ -1564,6 +1564,9 @@ int ovs_nla_get_flow_metadata(struct net *net,
1564 memset(&match, 0, sizeof(match)); 1564 memset(&match, 0, sizeof(match));
1565 match.key = key; 1565 match.key = key;
1566 1566
1567 key->ct_state = 0;
1568 key->ct_zone = 0;
1569 key->ct_orig_proto = 0;
1567 memset(&key->ct, 0, sizeof(key->ct)); 1570 memset(&key->ct, 0, sizeof(key->ct));
1568 memset(&key->ipv4.ct_orig, 0, sizeof(key->ipv4.ct_orig)); 1571 memset(&key->ipv4.ct_orig, 0, sizeof(key->ipv4.ct_orig));
1569 memset(&key->ipv6.ct_orig, 0, sizeof(key->ipv6.ct_orig)); 1572 memset(&key->ipv6.ct_orig, 0, sizeof(key->ipv6.ct_orig));