aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/Kconfig3
-rw-r--r--net/openvswitch/actions.c32
-rw-r--r--net/openvswitch/conntrack.c145
-rw-r--r--net/openvswitch/conntrack.h9
-rw-r--r--net/openvswitch/datapath.c9
-rw-r--r--net/openvswitch/datapath.h1
-rw-r--r--net/openvswitch/flow.h2
-rw-r--r--net/openvswitch/flow_netlink.c133
-rw-r--r--net/openvswitch/flow_netlink.h6
-rw-r--r--net/openvswitch/flow_table.c26
-rw-r--r--net/openvswitch/flow_table.h2
-rw-r--r--net/openvswitch/vport-geneve.c13
-rw-r--r--net/openvswitch/vport-gre.c8
-rw-r--r--net/openvswitch/vport-internal_dev.c46
-rw-r--r--net/openvswitch/vport-vxlan.c19
-rw-r--r--net/openvswitch/vport.c109
-rw-r--r--net/openvswitch/vport.h35
17 files changed, 288 insertions, 310 deletions
diff --git a/net/openvswitch/Kconfig b/net/openvswitch/Kconfig
index 2a071f470d57..d143aa9f6654 100644
--- a/net/openvswitch/Kconfig
+++ b/net/openvswitch/Kconfig
@@ -5,7 +5,8 @@
5config OPENVSWITCH 5config OPENVSWITCH
6 tristate "Open vSwitch" 6 tristate "Open vSwitch"
7 depends on INET 7 depends on INET
8 depends on (!NF_CONNTRACK || NF_CONNTRACK) 8 depends on !NF_CONNTRACK || \
9 (NF_CONNTRACK && (!NF_DEFRAG_IPV6 || NF_DEFRAG_IPV6))
9 select LIBCRC32C 10 select LIBCRC32C
10 select MPLS 11 select MPLS
11 select NET_MPLS_GSO 12 select NET_MPLS_GSO
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 315f5330b6e5..dba635d086b2 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -684,7 +684,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
684{ 684{
685 if (skb_network_offset(skb) > MAX_L2_LEN) { 685 if (skb_network_offset(skb) > MAX_L2_LEN) {
686 OVS_NLERR(1, "L2 header too long to fragment"); 686 OVS_NLERR(1, "L2 header too long to fragment");
687 return; 687 goto err;
688 } 688 }
689 689
690 if (ethertype == htons(ETH_P_IP)) { 690 if (ethertype == htons(ETH_P_IP)) {
@@ -708,8 +708,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
708 struct rt6_info ovs_rt; 708 struct rt6_info ovs_rt;
709 709
710 if (!v6ops) { 710 if (!v6ops) {
711 kfree_skb(skb); 711 goto err;
712 return;
713 } 712 }
714 713
715 prepare_frag(vport, skb); 714 prepare_frag(vport, skb);
@@ -728,8 +727,12 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
728 WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.", 727 WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
729 ovs_vport_name(vport), ntohs(ethertype), mru, 728 ovs_vport_name(vport), ntohs(ethertype), mru,
730 vport->dev->mtu); 729 vport->dev->mtu);
731 kfree_skb(skb); 730 goto err;
732 } 731 }
732
733 return;
734err:
735 kfree_skb(skb);
733} 736}
734 737
735static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, 738static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -765,7 +768,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
765 struct sw_flow_key *key, const struct nlattr *attr, 768 struct sw_flow_key *key, const struct nlattr *attr,
766 const struct nlattr *actions, int actions_len) 769 const struct nlattr *actions, int actions_len)
767{ 770{
768 struct ip_tunnel_info info;
769 struct dp_upcall_info upcall; 771 struct dp_upcall_info upcall;
770 const struct nlattr *a; 772 const struct nlattr *a;
771 int rem; 773 int rem;
@@ -793,11 +795,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
793 if (vport) { 795 if (vport) {
794 int err; 796 int err;
795 797
796 upcall.egress_tun_info = &info; 798 err = dev_fill_metadata_dst(vport->dev, skb);
797 err = ovs_vport_get_egress_tun_info(vport, skb, 799 if (!err)
798 &upcall); 800 upcall.egress_tun_info = skb_tunnel_info(skb);
799 if (err)
800 upcall.egress_tun_info = NULL;
801 } 801 }
802 802
803 break; 803 break;
@@ -968,7 +968,7 @@ static int execute_masked_set_action(struct sk_buff *skb,
968 case OVS_KEY_ATTR_CT_STATE: 968 case OVS_KEY_ATTR_CT_STATE:
969 case OVS_KEY_ATTR_CT_ZONE: 969 case OVS_KEY_ATTR_CT_ZONE:
970 case OVS_KEY_ATTR_CT_MARK: 970 case OVS_KEY_ATTR_CT_MARK:
971 case OVS_KEY_ATTR_CT_LABEL: 971 case OVS_KEY_ATTR_CT_LABELS:
972 err = -EINVAL; 972 err = -EINVAL;
973 break; 973 break;
974 } 974 }
@@ -1099,12 +1099,18 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
1099 break; 1099 break;
1100 1100
1101 case OVS_ACTION_ATTR_CT: 1101 case OVS_ACTION_ATTR_CT:
1102 if (!is_flow_key_valid(key)) {
1103 err = ovs_flow_key_update(skb, key);
1104 if (err)
1105 return err;
1106 }
1107
1102 err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key, 1108 err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
1103 nla_data(a)); 1109 nla_data(a));
1104 1110
1105 /* Hide stolen IP fragments from user space. */ 1111 /* Hide stolen IP fragments from user space. */
1106 if (err == -EINPROGRESS) 1112 if (err)
1107 return 0; 1113 return err == -EINPROGRESS ? 0 : err;
1108 break; 1114 break;
1109 } 1115 }
1110 1116
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index e8e524ad8a01..50095820edb7 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -37,9 +37,9 @@ struct md_mark {
37}; 37};
38 38
39/* Metadata label for masked write to conntrack label. */ 39/* Metadata label for masked write to conntrack label. */
40struct md_label { 40struct md_labels {
41 struct ovs_key_ct_label value; 41 struct ovs_key_ct_labels value;
42 struct ovs_key_ct_label mask; 42 struct ovs_key_ct_labels mask;
43}; 43};
44 44
45/* Conntrack action context for execution. */ 45/* Conntrack action context for execution. */
@@ -47,10 +47,10 @@ struct ovs_conntrack_info {
47 struct nf_conntrack_helper *helper; 47 struct nf_conntrack_helper *helper;
48 struct nf_conntrack_zone zone; 48 struct nf_conntrack_zone zone;
49 struct nf_conn *ct; 49 struct nf_conn *ct;
50 u32 flags; 50 u8 commit : 1;
51 u16 family; 51 u16 family;
52 struct md_mark mark; 52 struct md_mark mark;
53 struct md_label label; 53 struct md_labels labels;
54}; 54};
55 55
56static u16 key_to_nfproto(const struct sw_flow_key *key) 56static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -109,21 +109,21 @@ static u32 ovs_ct_get_mark(const struct nf_conn *ct)
109#endif 109#endif
110} 110}
111 111
112static void ovs_ct_get_label(const struct nf_conn *ct, 112static void ovs_ct_get_labels(const struct nf_conn *ct,
113 struct ovs_key_ct_label *label) 113 struct ovs_key_ct_labels *labels)
114{ 114{
115 struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL; 115 struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
116 116
117 if (cl) { 117 if (cl) {
118 size_t len = cl->words * sizeof(long); 118 size_t len = cl->words * sizeof(long);
119 119
120 if (len > OVS_CT_LABEL_LEN) 120 if (len > OVS_CT_LABELS_LEN)
121 len = OVS_CT_LABEL_LEN; 121 len = OVS_CT_LABELS_LEN;
122 else if (len < OVS_CT_LABEL_LEN) 122 else if (len < OVS_CT_LABELS_LEN)
123 memset(label, 0, OVS_CT_LABEL_LEN); 123 memset(labels, 0, OVS_CT_LABELS_LEN);
124 memcpy(label, cl->bits, len); 124 memcpy(labels, cl->bits, len);
125 } else { 125 } else {
126 memset(label, 0, OVS_CT_LABEL_LEN); 126 memset(labels, 0, OVS_CT_LABELS_LEN);
127 } 127 }
128} 128}
129 129
@@ -134,7 +134,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
134 key->ct.state = state; 134 key->ct.state = state;
135 key->ct.zone = zone->id; 135 key->ct.zone = zone->id;
136 key->ct.mark = ovs_ct_get_mark(ct); 136 key->ct.mark = ovs_ct_get_mark(ct);
137 ovs_ct_get_label(ct, &key->ct.label); 137 ovs_ct_get_labels(ct, &key->ct.labels);
138} 138}
139 139
140/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has 140/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
@@ -151,6 +151,8 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
151 ct = nf_ct_get(skb, &ctinfo); 151 ct = nf_ct_get(skb, &ctinfo);
152 if (ct) { 152 if (ct) {
153 state = ovs_ct_get_state(ctinfo); 153 state = ovs_ct_get_state(ctinfo);
154 if (!nf_ct_is_confirmed(ct))
155 state |= OVS_CS_F_NEW;
154 if (ct->master) 156 if (ct->master)
155 state |= OVS_CS_F_RELATED; 157 state |= OVS_CS_F_RELATED;
156 zone = nf_ct_zone(ct); 158 zone = nf_ct_zone(ct);
@@ -167,7 +169,7 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
167 169
168int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb) 170int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
169{ 171{
170 if (nla_put_u8(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state)) 172 if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
171 return -EMSGSIZE; 173 return -EMSGSIZE;
172 174
173 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && 175 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
@@ -179,8 +181,8 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
179 return -EMSGSIZE; 181 return -EMSGSIZE;
180 182
181 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && 183 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
182 nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label), 184 nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
183 &key->ct.label)) 185 &key->ct.labels))
184 return -EMSGSIZE; 186 return -EMSGSIZE;
185 187
186 return 0; 188 return 0;
@@ -213,18 +215,15 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
213#endif 215#endif
214} 216}
215 217
216static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key, 218static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
217 const struct ovs_key_ct_label *label, 219 const struct ovs_key_ct_labels *labels,
218 const struct ovs_key_ct_label *mask) 220 const struct ovs_key_ct_labels *mask)
219{ 221{
220 enum ip_conntrack_info ctinfo; 222 enum ip_conntrack_info ctinfo;
221 struct nf_conn_labels *cl; 223 struct nf_conn_labels *cl;
222 struct nf_conn *ct; 224 struct nf_conn *ct;
223 int err; 225 int err;
224 226
225 if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS))
226 return -ENOTSUPP;
227
228 /* The connection could be invalid, in which case set_label is no-op.*/ 227 /* The connection could be invalid, in which case set_label is no-op.*/
229 ct = nf_ct_get(skb, &ctinfo); 228 ct = nf_ct_get(skb, &ctinfo);
230 if (!ct) 229 if (!ct)
@@ -235,15 +234,15 @@ static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
235 nf_ct_labels_ext_add(ct); 234 nf_ct_labels_ext_add(ct);
236 cl = nf_ct_labels_find(ct); 235 cl = nf_ct_labels_find(ct);
237 } 236 }
238 if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN) 237 if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
239 return -ENOSPC; 238 return -ENOSPC;
240 239
241 err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask, 240 err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
242 OVS_CT_LABEL_LEN / sizeof(u32)); 241 OVS_CT_LABELS_LEN / sizeof(u32));
243 if (err) 242 if (err)
244 return err; 243 return err;
245 244
246 ovs_ct_get_label(ct, &key->ct.label); 245 ovs_ct_get_labels(ct, &key->ct.labels);
247 return 0; 246 return 0;
248} 247}
249 248
@@ -275,13 +274,15 @@ static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
275 case NFPROTO_IPV6: { 274 case NFPROTO_IPV6: {
276 u8 nexthdr = ipv6_hdr(skb)->nexthdr; 275 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
277 __be16 frag_off; 276 __be16 frag_off;
277 int ofs;
278 278
279 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), 279 ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
280 &nexthdr, &frag_off); 280 &frag_off);
281 if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { 281 if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
282 pr_debug("proto header not found\n"); 282 pr_debug("proto header not found\n");
283 return NF_ACCEPT; 283 return NF_ACCEPT;
284 } 284 }
285 protoff = ofs;
285 break; 286 break;
286 } 287 }
287 default: 288 default:
@@ -292,6 +293,9 @@ static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
292 return helper->help(skb, protoff, ct, ctinfo); 293 return helper->help(skb, protoff, ct, ctinfo);
293} 294}
294 295
296/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
297 * value if 'skb' is freed.
298 */
295static int handle_fragments(struct net *net, struct sw_flow_key *key, 299static int handle_fragments(struct net *net, struct sw_flow_key *key,
296 u16 zone, struct sk_buff *skb) 300 u16 zone, struct sk_buff *skb)
297{ 301{
@@ -307,8 +311,8 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
307 return err; 311 return err;
308 312
309 ovs_cb.mru = IPCB(skb)->frag_max_size; 313 ovs_cb.mru = IPCB(skb)->frag_max_size;
310 } else if (key->eth.type == htons(ETH_P_IPV6)) {
311#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) 314#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
315 } else if (key->eth.type == htons(ETH_P_IPV6)) {
312 enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone; 316 enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
313 struct sk_buff *reasm; 317 struct sk_buff *reasm;
314 318
@@ -317,17 +321,25 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
317 if (!reasm) 321 if (!reasm)
318 return -EINPROGRESS; 322 return -EINPROGRESS;
319 323
320 if (skb == reasm) 324 if (skb == reasm) {
325 kfree_skb(skb);
321 return -EINVAL; 326 return -EINVAL;
327 }
328
329 /* Don't free 'skb' even though it is one of the original
330 * fragments, as we're going to morph it into the head.
331 */
332 skb_get(skb);
333 nf_ct_frag6_consume_orig(reasm);
322 334
323 key->ip.proto = ipv6_hdr(reasm)->nexthdr; 335 key->ip.proto = ipv6_hdr(reasm)->nexthdr;
324 skb_morph(skb, reasm); 336 skb_morph(skb, reasm);
337 skb->next = reasm->next;
325 consume_skb(reasm); 338 consume_skb(reasm);
326 ovs_cb.mru = IP6CB(skb)->frag_max_size; 339 ovs_cb.mru = IP6CB(skb)->frag_max_size;
327#else
328 return -EPFNOSUPPORT;
329#endif 340#endif
330 } else { 341 } else {
342 kfree_skb(skb);
331 return -EPFNOSUPPORT; 343 return -EPFNOSUPPORT;
332 } 344 }
333 345
@@ -375,7 +387,7 @@ static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
375 return true; 387 return true;
376} 388}
377 389
378static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key, 390static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
379 const struct ovs_conntrack_info *info, 391 const struct ovs_conntrack_info *info,
380 struct sk_buff *skb) 392 struct sk_buff *skb)
381{ 393{
@@ -406,6 +418,8 @@ static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
406 } 418 }
407 } 419 }
408 420
421 ovs_ct_update_key(skb, key, true);
422
409 return 0; 423 return 0;
410} 424}
411 425
@@ -428,8 +442,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
428 err = __ovs_ct_lookup(net, key, info, skb); 442 err = __ovs_ct_lookup(net, key, info, skb);
429 if (err) 443 if (err)
430 return err; 444 return err;
431
432 ovs_ct_update_key(skb, key, true);
433 } 445 }
434 446
435 return 0; 447 return 0;
@@ -458,22 +470,23 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
458 if (nf_conntrack_confirm(skb) != NF_ACCEPT) 470 if (nf_conntrack_confirm(skb) != NF_ACCEPT)
459 return -EINVAL; 471 return -EINVAL;
460 472
461 ovs_ct_update_key(skb, key, true);
462
463 return 0; 473 return 0;
464} 474}
465 475
466static bool label_nonzero(const struct ovs_key_ct_label *label) 476static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
467{ 477{
468 size_t i; 478 size_t i;
469 479
470 for (i = 0; i < sizeof(*label); i++) 480 for (i = 0; i < sizeof(*labels); i++)
471 if (label->ct_label[i]) 481 if (labels->ct_labels[i])
472 return true; 482 return true;
473 483
474 return false; 484 return false;
475} 485}
476 486
487/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
488 * value if 'skb' is freed.
489 */
477int ovs_ct_execute(struct net *net, struct sk_buff *skb, 490int ovs_ct_execute(struct net *net, struct sk_buff *skb,
478 struct sw_flow_key *key, 491 struct sw_flow_key *key,
479 const struct ovs_conntrack_info *info) 492 const struct ovs_conntrack_info *info)
@@ -491,7 +504,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
491 return err; 504 return err;
492 } 505 }
493 506
494 if (info->flags & OVS_CT_F_COMMIT) 507 if (info->commit)
495 err = ovs_ct_commit(net, key, info, skb); 508 err = ovs_ct_commit(net, key, info, skb);
496 else 509 else
497 err = ovs_ct_lookup(net, key, info, skb); 510 err = ovs_ct_lookup(net, key, info, skb);
@@ -504,11 +517,13 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
504 if (err) 517 if (err)
505 goto err; 518 goto err;
506 } 519 }
507 if (label_nonzero(&info->label.mask)) 520 if (labels_nonzero(&info->labels.mask))
508 err = ovs_ct_set_label(skb, key, &info->label.value, 521 err = ovs_ct_set_labels(skb, key, &info->labels.value,
509 &info->label.mask); 522 &info->labels.mask);
510err: 523err:
511 skb_push(skb, nh_ofs); 524 skb_push(skb, nh_ofs);
525 if (err)
526 kfree_skb(skb);
512 return err; 527 return err;
513} 528}
514 529
@@ -537,14 +552,13 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
537} 552}
538 553
539static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = { 554static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
540 [OVS_CT_ATTR_FLAGS] = { .minlen = sizeof(u32), 555 [OVS_CT_ATTR_COMMIT] = { .minlen = 0, .maxlen = 0 },
541 .maxlen = sizeof(u32) },
542 [OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16), 556 [OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16),
543 .maxlen = sizeof(u16) }, 557 .maxlen = sizeof(u16) },
544 [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark), 558 [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
545 .maxlen = sizeof(struct md_mark) }, 559 .maxlen = sizeof(struct md_mark) },
546 [OVS_CT_ATTR_LABEL] = { .minlen = sizeof(struct md_label), 560 [OVS_CT_ATTR_LABELS] = { .minlen = sizeof(struct md_labels),
547 .maxlen = sizeof(struct md_label) }, 561 .maxlen = sizeof(struct md_labels) },
548 [OVS_CT_ATTR_HELPER] = { .minlen = 1, 562 [OVS_CT_ATTR_HELPER] = { .minlen = 1,
549 .maxlen = NF_CT_HELPER_NAME_LEN } 563 .maxlen = NF_CT_HELPER_NAME_LEN }
550}; 564};
@@ -574,8 +588,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
574 } 588 }
575 589
576 switch (type) { 590 switch (type) {
577 case OVS_CT_ATTR_FLAGS: 591 case OVS_CT_ATTR_COMMIT:
578 info->flags = nla_get_u32(a); 592 info->commit = true;
579 break; 593 break;
580#ifdef CONFIG_NF_CONNTRACK_ZONES 594#ifdef CONFIG_NF_CONNTRACK_ZONES
581 case OVS_CT_ATTR_ZONE: 595 case OVS_CT_ATTR_ZONE:
@@ -586,15 +600,23 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
586 case OVS_CT_ATTR_MARK: { 600 case OVS_CT_ATTR_MARK: {
587 struct md_mark *mark = nla_data(a); 601 struct md_mark *mark = nla_data(a);
588 602
603 if (!mark->mask) {
604 OVS_NLERR(log, "ct_mark mask cannot be 0");
605 return -EINVAL;
606 }
589 info->mark = *mark; 607 info->mark = *mark;
590 break; 608 break;
591 } 609 }
592#endif 610#endif
593#ifdef CONFIG_NF_CONNTRACK_LABELS 611#ifdef CONFIG_NF_CONNTRACK_LABELS
594 case OVS_CT_ATTR_LABEL: { 612 case OVS_CT_ATTR_LABELS: {
595 struct md_label *label = nla_data(a); 613 struct md_labels *labels = nla_data(a);
596 614
597 info->label = *label; 615 if (!labels_nonzero(&labels->mask)) {
616 OVS_NLERR(log, "ct_labels mask cannot be 0");
617 return -EINVAL;
618 }
619 info->labels = *labels;
598 break; 620 break;
599 } 621 }
600#endif 622#endif
@@ -631,7 +653,7 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
631 attr == OVS_KEY_ATTR_CT_MARK) 653 attr == OVS_KEY_ATTR_CT_MARK)
632 return true; 654 return true;
633 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && 655 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
634 attr == OVS_KEY_ATTR_CT_LABEL) { 656 attr == OVS_KEY_ATTR_CT_LABELS) {
635 struct ovs_net *ovs_net = net_generic(net, ovs_net_id); 657 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
636 658
637 return ovs_net->xt_label; 659 return ovs_net->xt_label;
@@ -699,18 +721,19 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
699 if (!start) 721 if (!start)
700 return -EMSGSIZE; 722 return -EMSGSIZE;
701 723
702 if (nla_put_u32(skb, OVS_CT_ATTR_FLAGS, ct_info->flags)) 724 if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
703 return -EMSGSIZE; 725 return -EMSGSIZE;
704 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && 726 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
705 nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id)) 727 nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
706 return -EMSGSIZE; 728 return -EMSGSIZE;
707 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && 729 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
708 nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), 730 nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
709 &ct_info->mark)) 731 &ct_info->mark))
710 return -EMSGSIZE; 732 return -EMSGSIZE;
711 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && 733 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
712 nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label), 734 labels_nonzero(&ct_info->labels.mask) &&
713 &ct_info->label)) 735 nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
736 &ct_info->labels))
714 return -EMSGSIZE; 737 return -EMSGSIZE;
715 if (ct_info->helper) { 738 if (ct_info->helper) {
716 if (nla_put_string(skb, OVS_CT_ATTR_HELPER, 739 if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
@@ -735,7 +758,7 @@ void ovs_ct_free_action(const struct nlattr *a)
735 758
736void ovs_ct_init(struct net *net) 759void ovs_ct_init(struct net *net)
737{ 760{
738 unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE; 761 unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
739 struct ovs_net *ovs_net = net_generic(net, ovs_net_id); 762 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
740 763
741 if (nf_connlabels_get(net, n_bits)) { 764 if (nf_connlabels_get(net, n_bits)) {
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h
index 43f5dd7a5577..a7544f405c16 100644
--- a/net/openvswitch/conntrack.h
+++ b/net/openvswitch/conntrack.h
@@ -34,6 +34,10 @@ int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *,
34void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key); 34void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
35int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb); 35int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
36void ovs_ct_free_action(const struct nlattr *a); 36void ovs_ct_free_action(const struct nlattr *a);
37
38#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
39 OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \
40 OVS_CS_F_INVALID | OVS_CS_F_TRACKED)
37#else 41#else
38#include <linux/errno.h> 42#include <linux/errno.h>
39 43
@@ -63,6 +67,7 @@ static inline int ovs_ct_execute(struct net *net, struct sk_buff *skb,
63 struct sw_flow_key *key, 67 struct sw_flow_key *key,
64 const struct ovs_conntrack_info *info) 68 const struct ovs_conntrack_info *info)
65{ 69{
70 kfree_skb(skb);
66 return -ENOTSUPP; 71 return -ENOTSUPP;
67} 72}
68 73
@@ -72,7 +77,7 @@ static inline void ovs_ct_fill_key(const struct sk_buff *skb,
72 key->ct.state = 0; 77 key->ct.state = 0;
73 key->ct.zone = 0; 78 key->ct.zone = 0;
74 key->ct.mark = 0; 79 key->ct.mark = 0;
75 memset(&key->ct.label, 0, sizeof(key->ct.label)); 80 memset(&key->ct.labels, 0, sizeof(key->ct.labels));
76} 81}
77 82
78static inline int ovs_ct_put_key(const struct sw_flow_key *key, 83static inline int ovs_ct_put_key(const struct sw_flow_key *key,
@@ -82,5 +87,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key,
82} 87}
83 88
84static inline void ovs_ct_free_action(const struct nlattr *a) { } 89static inline void ovs_ct_free_action(const struct nlattr *a) { }
90
91#define CT_SUPPORTED_MASK 0
85#endif /* CONFIG_NF_CONNTRACK */ 92#endif /* CONFIG_NF_CONNTRACK */
86#endif /* ovs_conntrack.h */ 93#endif /* ovs_conntrack.h */
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 6fbd2decb19e..c5d08ee37730 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -490,9 +490,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
490 490
491 if (upcall_info->egress_tun_info) { 491 if (upcall_info->egress_tun_info) {
492 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); 492 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
493 err = ovs_nla_put_egress_tunnel_key(user_skb, 493 err = ovs_nla_put_tunnel_info(user_skb,
494 upcall_info->egress_tun_info, 494 upcall_info->egress_tun_info);
495 upcall_info->egress_tun_opts);
496 BUG_ON(err); 495 BUG_ON(err);
497 nla_nest_end(user_skb, nla); 496 nla_nest_end(user_skb, nla);
498 } 497 }
@@ -952,7 +951,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
952 if (error) 951 if (error)
953 goto err_kfree_flow; 952 goto err_kfree_flow;
954 953
955 ovs_flow_mask_key(&new_flow->key, &key, &mask); 954 ovs_flow_mask_key(&new_flow->key, &key, true, &mask);
956 955
957 /* Extract flow identifier. */ 956 /* Extract flow identifier. */
958 error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], 957 error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
@@ -1080,7 +1079,7 @@ static struct sw_flow_actions *get_flow_actions(struct net *net,
1080 struct sw_flow_key masked_key; 1079 struct sw_flow_key masked_key;
1081 int error; 1080 int error;
1082 1081
1083 ovs_flow_mask_key(&masked_key, key, mask); 1082 ovs_flow_mask_key(&masked_key, key, true, mask);
1084 error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log); 1083 error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log);
1085 if (error) { 1084 if (error) {
1086 OVS_NLERR(log, 1085 OVS_NLERR(log,
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index f88038a99f44..67bdecd9fdc1 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -117,7 +117,6 @@ struct ovs_skb_cb {
117 */ 117 */
118struct dp_upcall_info { 118struct dp_upcall_info {
119 struct ip_tunnel_info *egress_tun_info; 119 struct ip_tunnel_info *egress_tun_info;
120 const void *egress_tun_opts;
121 const struct nlattr *userdata; 120 const struct nlattr *userdata;
122 const struct nlattr *actions; 121 const struct nlattr *actions;
123 int actions_len; 122 int actions_len;
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index fe527d2dd4b7..8cfa15a08668 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -116,7 +116,7 @@ struct sw_flow_key {
116 u16 zone; 116 u16 zone;
117 u32 mark; 117 u32 mark;
118 u8 state; 118 u8 state;
119 struct ovs_key_ct_label label; 119 struct ovs_key_ct_labels labels;
120 } ct; 120 } ct;
121 121
122} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */ 122} __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index c92d6a262bc5..38536c137c54 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -57,6 +57,7 @@ struct ovs_len_tbl {
57}; 57};
58 58
59#define OVS_ATTR_NESTED -1 59#define OVS_ATTR_NESTED -1
60#define OVS_ATTR_VARIABLE -2
60 61
61static void update_range(struct sw_flow_match *match, 62static void update_range(struct sw_flow_match *match,
62 size_t offset, size_t size, bool is_mask) 63 size_t offset, size_t size, bool is_mask)
@@ -290,10 +291,10 @@ size_t ovs_key_attr_size(void)
290 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */ 291 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
291 + nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */ 292 + nla_total_size(4) /* OVS_KEY_ATTR_DP_HASH */
292 + nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */ 293 + nla_total_size(4) /* OVS_KEY_ATTR_RECIRC_ID */
293 + nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */ 294 + nla_total_size(4) /* OVS_KEY_ATTR_CT_STATE */
294 + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */ 295 + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
295 + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */ 296 + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
296 + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABEL */ 297 + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
297 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ 298 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
298 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */ 299 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
299 + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */ 300 + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
@@ -304,6 +305,10 @@ size_t ovs_key_attr_size(void)
304 + nla_total_size(28); /* OVS_KEY_ATTR_ND */ 305 + nla_total_size(28); /* OVS_KEY_ATTR_ND */
305} 306}
306 307
308static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
309 [OVS_VXLAN_EXT_GBP] = { .len = sizeof(u32) },
310};
311
307static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = { 312static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
308 [OVS_TUNNEL_KEY_ATTR_ID] = { .len = sizeof(u64) }, 313 [OVS_TUNNEL_KEY_ATTR_ID] = { .len = sizeof(u64) },
309 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = { .len = sizeof(u32) }, 314 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = { .len = sizeof(u32) },
@@ -315,8 +320,9 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
315 [OVS_TUNNEL_KEY_ATTR_TP_SRC] = { .len = sizeof(u16) }, 320 [OVS_TUNNEL_KEY_ATTR_TP_SRC] = { .len = sizeof(u16) },
316 [OVS_TUNNEL_KEY_ATTR_TP_DST] = { .len = sizeof(u16) }, 321 [OVS_TUNNEL_KEY_ATTR_TP_DST] = { .len = sizeof(u16) },
317 [OVS_TUNNEL_KEY_ATTR_OAM] = { .len = 0 }, 322 [OVS_TUNNEL_KEY_ATTR_OAM] = { .len = 0 },
318 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_NESTED }, 323 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_VARIABLE },
319 [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED }, 324 [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED,
325 .next = ovs_vxlan_ext_key_lens },
320}; 326};
321 327
322/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */ 328/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
@@ -343,12 +349,19 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
343 [OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED, 349 [OVS_KEY_ATTR_TUNNEL] = { .len = OVS_ATTR_NESTED,
344 .next = ovs_tunnel_key_lens, }, 350 .next = ovs_tunnel_key_lens, },
345 [OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) }, 351 [OVS_KEY_ATTR_MPLS] = { .len = sizeof(struct ovs_key_mpls) },
346 [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) }, 352 [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u32) },
347 [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) }, 353 [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
348 [OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) }, 354 [OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) },
349 [OVS_KEY_ATTR_CT_LABEL] = { .len = sizeof(struct ovs_key_ct_label) }, 355 [OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
350}; 356};
351 357
358static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
359{
360 return expected_len == attr_len ||
361 expected_len == OVS_ATTR_NESTED ||
362 expected_len == OVS_ATTR_VARIABLE;
363}
364
352static bool is_all_zero(const u8 *fp, size_t size) 365static bool is_all_zero(const u8 *fp, size_t size)
353{ 366{
354 int i; 367 int i;
@@ -388,7 +401,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
388 } 401 }
389 402
390 expected_len = ovs_key_lens[type].len; 403 expected_len = ovs_key_lens[type].len;
391 if (nla_len(nla) != expected_len && expected_len != OVS_ATTR_NESTED) { 404 if (!check_attr_len(nla_len(nla), expected_len)) {
392 OVS_NLERR(log, "Key %d has unexpected len %d expected %d", 405 OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
393 type, nla_len(nla), expected_len); 406 type, nla_len(nla), expected_len);
394 return -EINVAL; 407 return -EINVAL;
@@ -473,29 +486,50 @@ static int genev_tun_opt_from_nlattr(const struct nlattr *a,
473 return 0; 486 return 0;
474} 487}
475 488
476static const struct nla_policy vxlan_opt_policy[OVS_VXLAN_EXT_MAX + 1] = { 489static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
477 [OVS_VXLAN_EXT_GBP] = { .type = NLA_U32 },
478};
479
480static int vxlan_tun_opt_from_nlattr(const struct nlattr *a,
481 struct sw_flow_match *match, bool is_mask, 490 struct sw_flow_match *match, bool is_mask,
482 bool log) 491 bool log)
483{ 492{
484 struct nlattr *tb[OVS_VXLAN_EXT_MAX+1]; 493 struct nlattr *a;
494 int rem;
485 unsigned long opt_key_offset; 495 unsigned long opt_key_offset;
486 struct vxlan_metadata opts; 496 struct vxlan_metadata opts;
487 int err;
488 497
489 BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts)); 498 BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
490 499
491 err = nla_parse_nested(tb, OVS_VXLAN_EXT_MAX, a, vxlan_opt_policy);
492 if (err < 0)
493 return err;
494
495 memset(&opts, 0, sizeof(opts)); 500 memset(&opts, 0, sizeof(opts));
501 nla_for_each_nested(a, attr, rem) {
502 int type = nla_type(a);
496 503
497 if (tb[OVS_VXLAN_EXT_GBP]) 504 if (type > OVS_VXLAN_EXT_MAX) {
498 opts.gbp = nla_get_u32(tb[OVS_VXLAN_EXT_GBP]); 505 OVS_NLERR(log, "VXLAN extension %d out of range max %d",
506 type, OVS_VXLAN_EXT_MAX);
507 return -EINVAL;
508 }
509
510 if (!check_attr_len(nla_len(a),
511 ovs_vxlan_ext_key_lens[type].len)) {
512 OVS_NLERR(log, "VXLAN extension %d has unexpected len %d expected %d",
513 type, nla_len(a),
514 ovs_vxlan_ext_key_lens[type].len);
515 return -EINVAL;
516 }
517
518 switch (type) {
519 case OVS_VXLAN_EXT_GBP:
520 opts.gbp = nla_get_u32(a);
521 break;
522 default:
523 OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
524 type);
525 return -EINVAL;
526 }
527 }
528 if (rem) {
529 OVS_NLERR(log, "VXLAN extension message has %d unknown bytes.",
530 rem);
531 return -EINVAL;
532 }
499 533
500 if (!is_mask) 534 if (!is_mask)
501 SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false); 535 SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false);
@@ -528,8 +562,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
528 return -EINVAL; 562 return -EINVAL;
529 } 563 }
530 564
531 if (ovs_tunnel_key_lens[type].len != nla_len(a) && 565 if (!check_attr_len(nla_len(a),
532 ovs_tunnel_key_lens[type].len != OVS_ATTR_NESTED) { 566 ovs_tunnel_key_lens[type].len)) {
533 OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d", 567 OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
534 type, nla_len(a), ovs_tunnel_key_lens[type].len); 568 type, nla_len(a), ovs_tunnel_key_lens[type].len);
535 return -EINVAL; 569 return -EINVAL;
@@ -683,7 +717,7 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
683 if ((output->tun_flags & TUNNEL_OAM) && 717 if ((output->tun_flags & TUNNEL_OAM) &&
684 nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) 718 nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
685 return -EMSGSIZE; 719 return -EMSGSIZE;
686 if (tun_opts) { 720 if (swkey_tun_opts_len) {
687 if (output->tun_flags & TUNNEL_GENEVE_OPT && 721 if (output->tun_flags & TUNNEL_GENEVE_OPT &&
688 nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, 722 nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
689 swkey_tun_opts_len, tun_opts)) 723 swkey_tun_opts_len, tun_opts))
@@ -715,13 +749,12 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
715 return 0; 749 return 0;
716} 750}
717 751
718int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb, 752int ovs_nla_put_tunnel_info(struct sk_buff *skb,
719 const struct ip_tunnel_info *egress_tun_info, 753 struct ip_tunnel_info *tun_info)
720 const void *egress_tun_opts)
721{ 754{
722 return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key, 755 return __ipv4_tun_to_nlattr(skb, &tun_info->key,
723 egress_tun_opts, 756 ip_tunnel_info_opts(tun_info),
724 egress_tun_info->options_len); 757 tun_info->options_len);
725} 758}
726 759
727static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, 760static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -780,7 +813,13 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
780 813
781 if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) && 814 if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
782 ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) { 815 ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
783 u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]); 816 u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
817
818 if (ct_state & ~CT_SUPPORTED_MASK) {
819 OVS_NLERR(log, "ct_state flags %08x unsupported",
820 ct_state);
821 return -EINVAL;
822 }
784 823
785 SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask); 824 SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
786 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE); 825 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
@@ -799,14 +838,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
799 SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask); 838 SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
800 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK); 839 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
801 } 840 }
802 if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) && 841 if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
803 ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) { 842 ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
804 const struct ovs_key_ct_label *cl; 843 const struct ovs_key_ct_labels *cl;
805 844
806 cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]); 845 cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
807 SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label, 846 SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
808 sizeof(*cl), is_mask); 847 sizeof(*cl), is_mask);
809 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL); 848 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
810 } 849 }
811 return 0; 850 return 0;
812} 851}
@@ -1052,10 +1091,16 @@ static void nlattr_set(struct nlattr *attr, u8 val,
1052 1091
1053 /* The nlattr stream should already have been validated */ 1092 /* The nlattr stream should already have been validated */
1054 nla_for_each_nested(nla, attr, rem) { 1093 nla_for_each_nested(nla, attr, rem) {
1055 if (tbl && tbl[nla_type(nla)].len == OVS_ATTR_NESTED) 1094 if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) {
1056 nlattr_set(nla, val, tbl[nla_type(nla)].next); 1095 if (tbl[nla_type(nla)].next)
1057 else 1096 tbl = tbl[nla_type(nla)].next;
1097 nlattr_set(nla, val, tbl);
1098 } else {
1058 memset(nla_data(nla), val, nla_len(nla)); 1099 memset(nla_data(nla), val, nla_len(nla));
1100 }
1101
1102 if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
1103 *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
1059 } 1104 }
1060} 1105}
1061 1106
@@ -1922,8 +1967,7 @@ static int validate_set(const struct nlattr *a,
1922 key_len /= 2; 1967 key_len /= 2;
1923 1968
1924 if (key_type > OVS_KEY_ATTR_MAX || 1969 if (key_type > OVS_KEY_ATTR_MAX ||
1925 (ovs_key_lens[key_type].len != key_len && 1970 !check_attr_len(key_len, ovs_key_lens[key_type].len))
1926 ovs_key_lens[key_type].len != OVS_ATTR_NESTED))
1927 return -EINVAL; 1971 return -EINVAL;
1928 1972
1929 if (masked && !validate_masked(nla_data(ovs_key), key_len)) 1973 if (masked && !validate_masked(nla_data(ovs_key), key_len))
@@ -1937,7 +1981,7 @@ static int validate_set(const struct nlattr *a,
1937 case OVS_KEY_ATTR_PRIORITY: 1981 case OVS_KEY_ATTR_PRIORITY:
1938 case OVS_KEY_ATTR_SKB_MARK: 1982 case OVS_KEY_ATTR_SKB_MARK:
1939 case OVS_KEY_ATTR_CT_MARK: 1983 case OVS_KEY_ATTR_CT_MARK:
1940 case OVS_KEY_ATTR_CT_LABEL: 1984 case OVS_KEY_ATTR_CT_LABELS:
1941 case OVS_KEY_ATTR_ETHERNET: 1985 case OVS_KEY_ATTR_ETHERNET:
1942 break; 1986 break;
1943 1987
@@ -2338,10 +2382,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
2338 if (!start) 2382 if (!start)
2339 return -EMSGSIZE; 2383 return -EMSGSIZE;
2340 2384
2341 err = ipv4_tun_to_nlattr(skb, &tun_info->key, 2385 err = ovs_nla_put_tunnel_info(skb, tun_info);
2342 tun_info->options_len ?
2343 ip_tunnel_info_opts(tun_info) : NULL,
2344 tun_info->options_len);
2345 if (err) 2386 if (err)
2346 return err; 2387 return err;
2347 nla_nest_end(skb, start); 2388 nla_nest_end(skb, start);
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 6ca3f0baf449..47dd142eca1c 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -55,9 +55,9 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
55int ovs_nla_get_match(struct net *, struct sw_flow_match *, 55int ovs_nla_get_match(struct net *, struct sw_flow_match *,
56 const struct nlattr *key, const struct nlattr *mask, 56 const struct nlattr *key, const struct nlattr *mask,
57 bool log); 57 bool log);
58int ovs_nla_put_egress_tunnel_key(struct sk_buff *, 58
59 const struct ip_tunnel_info *, 59int ovs_nla_put_tunnel_info(struct sk_buff *skb,
60 const void *egress_tun_opts); 60 struct ip_tunnel_info *tun_info);
61 61
62bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log); 62bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log);
63int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid, 63int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index d22d8e948d0f..c7f74aab34b9 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -57,20 +57,21 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range)
57} 57}
58 58
59void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, 59void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
60 const struct sw_flow_mask *mask) 60 bool full, const struct sw_flow_mask *mask)
61{ 61{
62 const long *m = (const long *)((const u8 *)&mask->key + 62 int start = full ? 0 : mask->range.start;
63 mask->range.start); 63 int len = full ? sizeof *dst : range_n_bytes(&mask->range);
64 const long *s = (const long *)((const u8 *)src + 64 const long *m = (const long *)((const u8 *)&mask->key + start);
65 mask->range.start); 65 const long *s = (const long *)((const u8 *)src + start);
66 long *d = (long *)((u8 *)dst + mask->range.start); 66 long *d = (long *)((u8 *)dst + start);
67 int i; 67 int i;
68 68
69 /* The memory outside of the 'mask->range' are not set since 69 /* If 'full' is true then all of 'dst' is fully initialized. Otherwise,
70 * further operations on 'dst' only uses contents within 70 * if 'full' is false the memory outside of the 'mask->range' is left
71 * 'mask->range'. 71 * uninitialized. This can be used as an optimization when further
72 * operations on 'dst' only use contents within 'mask->range'.
72 */ 73 */
73 for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long)) 74 for (i = 0; i < len; i += sizeof(long))
74 *d++ = *s++ & *m++; 75 *d++ = *s++ & *m++;
75} 76}
76 77
@@ -92,7 +93,8 @@ struct sw_flow *ovs_flow_alloc(void)
92 93
93 /* Initialize the default stat node. */ 94 /* Initialize the default stat node. */
94 stats = kmem_cache_alloc_node(flow_stats_cache, 95 stats = kmem_cache_alloc_node(flow_stats_cache,
95 GFP_KERNEL | __GFP_ZERO, 0); 96 GFP_KERNEL | __GFP_ZERO,
97 node_online(0) ? 0 : NUMA_NO_NODE);
96 if (!stats) 98 if (!stats)
97 goto err; 99 goto err;
98 100
@@ -475,7 +477,7 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
475 u32 hash; 477 u32 hash;
476 struct sw_flow_key masked_key; 478 struct sw_flow_key masked_key;
477 479
478 ovs_flow_mask_key(&masked_key, unmasked, mask); 480 ovs_flow_mask_key(&masked_key, unmasked, false, mask);
479 hash = flow_hash(&masked_key, &mask->range); 481 hash = flow_hash(&masked_key, &mask->range);
480 head = find_bucket(ti, hash); 482 head = find_bucket(ti, hash);
481 hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) { 483 hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) {
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h
index 616eda10d955..2dd9900f533d 100644
--- a/net/openvswitch/flow_table.h
+++ b/net/openvswitch/flow_table.h
@@ -86,5 +86,5 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *,
86bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *); 86bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *);
87 87
88void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src, 88void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
89 const struct sw_flow_mask *mask); 89 bool full, const struct sw_flow_mask *mask);
90#endif /* flow_table.h */ 90#endif /* flow_table.h */
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c
index 2735e9c4a3b8..5f8aaaaa0785 100644
--- a/net/openvswitch/vport-geneve.c
+++ b/net/openvswitch/vport-geneve.c
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport,
52 return 0; 52 return 0;
53} 53}
54 54
55static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
56 struct dp_upcall_info *upcall)
57{
58 struct geneve_port *geneve_port = geneve_vport(vport);
59 struct net *net = ovs_dp_get_net(vport->dp);
60 __be16 dport = htons(geneve_port->port_no);
61 __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
62
63 return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
64 skb, IPPROTO_UDP, sport, dport);
65}
66
67static struct vport *geneve_tnl_create(const struct vport_parms *parms) 55static struct vport *geneve_tnl_create(const struct vport_parms *parms)
68{ 56{
69 struct net *net = ovs_dp_get_net(parms->dp); 57 struct net *net = ovs_dp_get_net(parms->dp);
@@ -130,7 +118,6 @@ static struct vport_ops ovs_geneve_vport_ops = {
130 .get_options = geneve_get_options, 118 .get_options = geneve_get_options,
131 .send = ovs_netdev_send, 119 .send = ovs_netdev_send,
132 .owner = THIS_MODULE, 120 .owner = THIS_MODULE,
133 .get_egress_tun_info = geneve_get_egress_tun_info,
134}; 121};
135 122
136static int __init ovs_geneve_tnl_init(void) 123static int __init ovs_geneve_tnl_init(void)
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index 4d24481669c9..64225bf5eb40 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -84,18 +84,10 @@ static struct vport *gre_create(const struct vport_parms *parms)
84 return ovs_netdev_link(vport, parms->name); 84 return ovs_netdev_link(vport, parms->name);
85} 85}
86 86
87static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
88 struct dp_upcall_info *upcall)
89{
90 return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
91 skb, IPPROTO_GRE, 0, 0);
92}
93
94static struct vport_ops ovs_gre_vport_ops = { 87static struct vport_ops ovs_gre_vport_ops = {
95 .type = OVS_VPORT_TYPE_GRE, 88 .type = OVS_VPORT_TYPE_GRE,
96 .create = gre_create, 89 .create = gre_create,
97 .send = ovs_netdev_send, 90 .send = ovs_netdev_send,
98 .get_egress_tun_info = gre_get_egress_tun_info,
99 .destroy = ovs_netdev_tunnel_destroy, 91 .destroy = ovs_netdev_tunnel_destroy,
100 .owner = THIS_MODULE, 92 .owner = THIS_MODULE,
101}; 93};
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 388b8a6bf112..b3934126daa8 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev)
106 free_netdev(dev); 106 free_netdev(dev);
107} 107}
108 108
109static struct rtnl_link_stats64 *
110internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
111{
112 int i;
113
114 memset(stats, 0, sizeof(*stats));
115 stats->rx_errors = dev->stats.rx_errors;
116 stats->tx_errors = dev->stats.tx_errors;
117 stats->tx_dropped = dev->stats.tx_dropped;
118 stats->rx_dropped = dev->stats.rx_dropped;
119
120 for_each_possible_cpu(i) {
121 const struct pcpu_sw_netstats *percpu_stats;
122 struct pcpu_sw_netstats local_stats;
123 unsigned int start;
124
125 percpu_stats = per_cpu_ptr(dev->tstats, i);
126
127 do {
128 start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
129 local_stats = *percpu_stats;
130 } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
131
132 stats->rx_bytes += local_stats.rx_bytes;
133 stats->rx_packets += local_stats.rx_packets;
134 stats->tx_bytes += local_stats.tx_bytes;
135 stats->tx_packets += local_stats.tx_packets;
136 }
137
138 return stats;
139}
140
109static const struct net_device_ops internal_dev_netdev_ops = { 141static const struct net_device_ops internal_dev_netdev_ops = {
110 .ndo_open = internal_dev_open, 142 .ndo_open = internal_dev_open,
111 .ndo_stop = internal_dev_stop, 143 .ndo_stop = internal_dev_stop,
112 .ndo_start_xmit = internal_dev_xmit, 144 .ndo_start_xmit = internal_dev_xmit,
113 .ndo_set_mac_address = eth_mac_addr, 145 .ndo_set_mac_address = eth_mac_addr,
114 .ndo_change_mtu = internal_dev_change_mtu, 146 .ndo_change_mtu = internal_dev_change_mtu,
147 .ndo_get_stats64 = internal_get_stats,
115}; 148};
116 149
117static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { 150static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
161 err = -ENOMEM; 194 err = -ENOMEM;
162 goto error_free_vport; 195 goto error_free_vport;
163 } 196 }
197 vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
198 if (!vport->dev->tstats) {
199 err = -ENOMEM;
200 goto error_free_netdev;
201 }
164 202
165 dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); 203 dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
166 internal_dev = internal_dev_priv(vport->dev); 204 internal_dev = internal_dev_priv(vport->dev);
@@ -173,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
173 rtnl_lock(); 211 rtnl_lock();
174 err = register_netdevice(vport->dev); 212 err = register_netdevice(vport->dev);
175 if (err) 213 if (err)
176 goto error_free_netdev; 214 goto error_unlock;
177 215
178 dev_set_promiscuity(vport->dev, 1); 216 dev_set_promiscuity(vport->dev, 1);
179 rtnl_unlock(); 217 rtnl_unlock();
@@ -181,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
181 219
182 return vport; 220 return vport;
183 221
184error_free_netdev: 222error_unlock:
185 rtnl_unlock(); 223 rtnl_unlock();
224 free_percpu(vport->dev->tstats);
225error_free_netdev:
186 free_netdev(vport->dev); 226 free_netdev(vport->dev);
187error_free_vport: 227error_free_vport:
188 ovs_vport_free(vport); 228 ovs_vport_free(vport);
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport)
198 238
199 /* unregister_netdevice() waits for an RCU grace period. */ 239 /* unregister_netdevice() waits for an RCU grace period. */
200 unregister_netdevice(vport->dev); 240 unregister_netdevice(vport->dev);
201 241 free_percpu(vport->dev->tstats);
202 rtnl_unlock(); 242 rtnl_unlock();
203} 243}
204 244
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index c11413d5075f..e1c9c0888037 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -146,31 +146,12 @@ static struct vport *vxlan_create(const struct vport_parms *parms)
146 return ovs_netdev_link(vport, parms->name); 146 return ovs_netdev_link(vport, parms->name);
147} 147}
148 148
149static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
150 struct dp_upcall_info *upcall)
151{
152 struct vxlan_dev *vxlan = netdev_priv(vport->dev);
153 struct net *net = ovs_dp_get_net(vport->dp);
154 __be16 dst_port = vxlan_dev_dst_port(vxlan);
155 __be16 src_port;
156 int port_min;
157 int port_max;
158
159 inet_get_local_port_range(net, &port_min, &port_max);
160 src_port = udp_flow_src_port(net, skb, 0, 0, true);
161
162 return ovs_tunnel_get_egress_info(upcall, net,
163 skb, IPPROTO_UDP,
164 src_port, dst_port);
165}
166
167static struct vport_ops ovs_vxlan_netdev_vport_ops = { 149static struct vport_ops ovs_vxlan_netdev_vport_ops = {
168 .type = OVS_VPORT_TYPE_VXLAN, 150 .type = OVS_VPORT_TYPE_VXLAN,
169 .create = vxlan_create, 151 .create = vxlan_create,
170 .destroy = ovs_netdev_tunnel_destroy, 152 .destroy = ovs_netdev_tunnel_destroy,
171 .get_options = vxlan_get_options, 153 .get_options = vxlan_get_options,
172 .send = ovs_netdev_send, 154 .send = ovs_netdev_send,
173 .get_egress_tun_info = vxlan_get_egress_tun_info,
174}; 155};
175 156
176static int __init ovs_vxlan_tnl_init(void) 157static int __init ovs_vxlan_tnl_init(void)
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index dc81dc619aa2..320c765ce44a 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -280,35 +280,19 @@ void ovs_vport_del(struct vport *vport)
280 */ 280 */
281void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats) 281void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
282{ 282{
283 struct net_device *dev = vport->dev; 283 const struct rtnl_link_stats64 *dev_stats;
284 int i; 284 struct rtnl_link_stats64 temp;
285 285
286 memset(stats, 0, sizeof(*stats)); 286 dev_stats = dev_get_stats(vport->dev, &temp);
287 stats->rx_errors = dev->stats.rx_errors; 287 stats->rx_errors = dev_stats->rx_errors;
288 stats->tx_errors = dev->stats.tx_errors; 288 stats->tx_errors = dev_stats->tx_errors;
289 stats->tx_dropped = dev->stats.tx_dropped; 289 stats->tx_dropped = dev_stats->tx_dropped;
290 stats->rx_dropped = dev->stats.rx_dropped; 290 stats->rx_dropped = dev_stats->rx_dropped;
291 291
292 stats->rx_dropped += atomic_long_read(&dev->rx_dropped); 292 stats->rx_bytes = dev_stats->rx_bytes;
293 stats->tx_dropped += atomic_long_read(&dev->tx_dropped); 293 stats->rx_packets = dev_stats->rx_packets;
294 294 stats->tx_bytes = dev_stats->tx_bytes;
295 for_each_possible_cpu(i) { 295 stats->tx_packets = dev_stats->tx_packets;
296 const struct pcpu_sw_netstats *percpu_stats;
297 struct pcpu_sw_netstats local_stats;
298 unsigned int start;
299
300 percpu_stats = per_cpu_ptr(dev->tstats, i);
301
302 do {
303 start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
304 local_stats = *percpu_stats;
305 } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
306
307 stats->rx_bytes += local_stats.rx_bytes;
308 stats->rx_packets += local_stats.rx_packets;
309 stats->tx_bytes += local_stats.tx_bytes;
310 stats->tx_packets += local_stats.tx_packets;
311 }
312} 296}
313 297
314/** 298/**
@@ -460,6 +444,15 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
460 444
461 OVS_CB(skb)->input_vport = vport; 445 OVS_CB(skb)->input_vport = vport;
462 OVS_CB(skb)->mru = 0; 446 OVS_CB(skb)->mru = 0;
447 if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
448 u32 mark;
449
450 mark = skb->mark;
451 skb_scrub_packet(skb, true);
452 skb->mark = mark;
453 tun_info = NULL;
454 }
455
463 /* Extract flow from 'skb' into 'key'. */ 456 /* Extract flow from 'skb' into 'key'. */
464 error = ovs_flow_key_extract(tun_info, skb, &key); 457 error = ovs_flow_key_extract(tun_info, skb, &key);
465 if (unlikely(error)) { 458 if (unlikely(error)) {
@@ -486,61 +479,3 @@ void ovs_vport_deferred_free(struct vport *vport)
486 call_rcu(&vport->rcu, free_vport_rcu); 479 call_rcu(&vport->rcu, free_vport_rcu);
487} 480}
488EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); 481EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
489
490int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
491 struct net *net,
492 struct sk_buff *skb,
493 u8 ipproto,
494 __be16 tp_src,
495 __be16 tp_dst)
496{
497 struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info;
498 const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb);
499 const struct ip_tunnel_key *tun_key;
500 u32 skb_mark = skb->mark;
501 struct rtable *rt;
502 struct flowi4 fl;
503
504 if (unlikely(!tun_info))
505 return -EINVAL;
506 if (ip_tunnel_info_af(tun_info) != AF_INET)
507 return -EINVAL;
508
509 tun_key = &tun_info->key;
510
511 /* Route lookup to get srouce IP address.
512 * The process may need to be changed if the corresponding process
513 * in vports ops changed.
514 */
515 rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto);
516 if (IS_ERR(rt))
517 return PTR_ERR(rt);
518
519 ip_rt_put(rt);
520
521 /* Generate egress_tun_info based on tun_info,
522 * saddr, tp_src and tp_dst
523 */
524 ip_tunnel_key_init(&egress_tun_info->key,
525 fl.saddr, tun_key->u.ipv4.dst,
526 tun_key->tos,
527 tun_key->ttl,
528 tp_src, tp_dst,
529 tun_key->tun_id,
530 tun_key->tun_flags);
531 egress_tun_info->options_len = tun_info->options_len;
532 egress_tun_info->mode = tun_info->mode;
533 upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info);
534 return 0;
535}
536EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info);
537
538int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
539 struct dp_upcall_info *upcall)
540{
541 /* get_egress_tun_info() is only implemented on tunnel ports. */
542 if (unlikely(!vport->ops->get_egress_tun_info))
543 return -EINVAL;
544
545 return vport->ops->get_egress_tun_info(vport, skb, upcall);
546}
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index a413f3ae6a7b..d341ad6f3afe 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -27,7 +27,6 @@
27#include <linux/skbuff.h> 27#include <linux/skbuff.h>
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29#include <linux/u64_stats_sync.h> 29#include <linux/u64_stats_sync.h>
30#include <net/route.h>
31 30
32#include "datapath.h" 31#include "datapath.h"
33 32
@@ -53,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids);
53int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); 52int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
54u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); 53u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
55 54
56int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
57 struct net *net,
58 struct sk_buff *,
59 u8 ipproto,
60 __be16 tp_src,
61 __be16 tp_dst);
62
63int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
64 struct dp_upcall_info *upcall);
65
66/** 55/**
67 * struct vport_portids - array of netlink portids of a vport. 56 * struct vport_portids - array of netlink portids of a vport.
68 * must be protected by rcu. 57 * must be protected by rcu.
@@ -140,8 +129,6 @@ struct vport_parms {
140 * have any configuration. 129 * have any configuration.
141 * @send: Send a packet on the device. 130 * @send: Send a packet on the device.
142 * zero for dropped packets or negative for error. 131 * zero for dropped packets or negative for error.
143 * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
144 * a packet.
145 */ 132 */
146struct vport_ops { 133struct vport_ops {
147 enum ovs_vport_type type; 134 enum ovs_vport_type type;
@@ -154,9 +141,6 @@ struct vport_ops {
154 int (*get_options)(const struct vport *, struct sk_buff *); 141 int (*get_options)(const struct vport *, struct sk_buff *);
155 142
156 void (*send)(struct vport *, struct sk_buff *); 143 void (*send)(struct vport *, struct sk_buff *);
157 int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
158 struct dp_upcall_info *upcall);
159
160 struct module *owner; 144 struct module *owner;
161 struct list_head list; 145 struct list_head list;
162}; 146};
@@ -215,25 +199,6 @@ static inline const char *ovs_vport_name(struct vport *vport)
215int ovs_vport_ops_register(struct vport_ops *ops); 199int ovs_vport_ops_register(struct vport_ops *ops);
216void ovs_vport_ops_unregister(struct vport_ops *ops); 200void ovs_vport_ops_unregister(struct vport_ops *ops);
217 201
218static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,
219 const struct ip_tunnel_key *key,
220 u32 mark,
221 struct flowi4 *fl,
222 u8 protocol)
223{
224 struct rtable *rt;
225
226 memset(fl, 0, sizeof(*fl));
227 fl->daddr = key->u.ipv4.dst;
228 fl->saddr = key->u.ipv4.src;
229 fl->flowi4_tos = RT_TOS(key->tos);
230 fl->flowi4_mark = mark;
231 fl->flowi4_proto = protocol;
232
233 rt = ip_route_output_key(net, fl);
234 return rt;
235}
236
237static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb) 202static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
238{ 203{
239 vport->ops->send(vport, skb); 204 vport->ops->send(vport, skb);