aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe Stringer <joestringer@nicira.com>2015-08-26 14:31:52 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-27 14:40:43 -0400
commitc2ac667358708d7cce64c78f58af6adf4c1e848b (patch)
treef24ccd3b0e54fe0ba09ecadb837eef3ecaa014c8
parent86ca02e77408bb58ba596c1a411ec7f631733690 (diff)
openvswitch: Allow matching on conntrack label
Allow matching and setting the ct_label field. As with ct_mark, this is populated by executing the CT action. The label field may be modified by specifying a label and mask nested under the CT action. It is stored as metadata attached to the connection. Label modification occurs after lookup, and will only persist when the conntrack entry is committed by providing the COMMIT flag to the CT action. Labels are currently fixed to 128 bits in size. Signed-off-by: Joe Stringer <joestringer@nicira.com> Acked-by: Thomas Graf <tgraf@suug.ch> Acked-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/openvswitch.h10
-rw-r--r--net/openvswitch/actions.c1
-rw-r--r--net/openvswitch/conntrack.c128
-rw-r--r--net/openvswitch/conntrack.h11
-rw-r--r--net/openvswitch/datapath.c18
-rw-r--r--net/openvswitch/datapath.h3
-rw-r--r--net/openvswitch/flow.c4
-rw-r--r--net/openvswitch/flow.h3
-rw-r--r--net/openvswitch/flow_netlink.c46
-rw-r--r--net/openvswitch/flow_netlink.h9
10 files changed, 199 insertions, 34 deletions
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 7a185b554343..9d52058a9330 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -326,6 +326,7 @@ enum ovs_key_attr {
326 OVS_KEY_ATTR_CT_STATE, /* u8 bitmask of OVS_CS_F_* */ 326 OVS_KEY_ATTR_CT_STATE, /* u8 bitmask of OVS_CS_F_* */
327 OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */ 327 OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */
328 OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */ 328 OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */
329 OVS_KEY_ATTR_CT_LABEL, /* 16-octet connection tracking label */
329 330
330#ifdef __KERNEL__ 331#ifdef __KERNEL__
331 OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */ 332 OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */
@@ -438,6 +439,11 @@ struct ovs_key_nd {
438 __u8 nd_tll[ETH_ALEN]; 439 __u8 nd_tll[ETH_ALEN];
439}; 440};
440 441
442#define OVS_CT_LABEL_LEN 16
443struct ovs_key_ct_label {
444 __u8 ct_label[OVS_CT_LABEL_LEN];
445};
446
441/* OVS_KEY_ATTR_CT_STATE flags */ 447/* OVS_KEY_ATTR_CT_STATE flags */
442#define OVS_CS_F_NEW 0x01 /* Beginning of a new connection. */ 448#define OVS_CS_F_NEW 0x01 /* Beginning of a new connection. */
443#define OVS_CS_F_ESTABLISHED 0x02 /* Part of an existing connection. */ 449#define OVS_CS_F_ESTABLISHED 0x02 /* Part of an existing connection. */
@@ -617,12 +623,16 @@ struct ovs_action_hash {
617 * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the 623 * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
618 * mask, the corresponding bit in the value is copied to the connection 624 * mask, the corresponding bit in the value is copied to the connection
619 * tracking mark field in the connection. 625 * tracking mark field in the connection.
626 * @OVS_CT_ATTR_LABEL: %OVS_CT_LABEL_LEN value followed by %OVS_CT_LABEL_LEN
627 * mask. For each bit set in the mask, the corresponding bit in the value is
628 * copied to the connection tracking label field in the connection.
620 */ 629 */
621enum ovs_ct_attr { 630enum ovs_ct_attr {
622 OVS_CT_ATTR_UNSPEC, 631 OVS_CT_ATTR_UNSPEC,
623 OVS_CT_ATTR_FLAGS, /* u8 bitmask of OVS_CT_F_*. */ 632 OVS_CT_ATTR_FLAGS, /* u8 bitmask of OVS_CT_F_*. */
624 OVS_CT_ATTR_ZONE, /* u16 zone id. */ 633 OVS_CT_ATTR_ZONE, /* u16 zone id. */
625 OVS_CT_ATTR_MARK, /* mark to associate with this connection. */ 634 OVS_CT_ATTR_MARK, /* mark to associate with this connection. */
635 OVS_CT_ATTR_LABEL, /* label to associate with this connection. */
626 __OVS_CT_ATTR_MAX 636 __OVS_CT_ATTR_MAX
627}; 637};
628 638
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 9741d2c703df..736a113a75c3 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -969,6 +969,7 @@ static int execute_masked_set_action(struct sk_buff *skb,
969 case OVS_KEY_ATTR_CT_STATE: 969 case OVS_KEY_ATTR_CT_STATE:
970 case OVS_KEY_ATTR_CT_ZONE: 970 case OVS_KEY_ATTR_CT_ZONE:
971 case OVS_KEY_ATTR_CT_MARK: 971 case OVS_KEY_ATTR_CT_MARK:
972 case OVS_KEY_ATTR_CT_LABEL:
972 err = -EINVAL; 973 err = -EINVAL;
973 break; 974 break;
974 } 975 }
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index e53dafccf21f..a0417fb33d1d 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -15,6 +15,7 @@
15#include <linux/openvswitch.h> 15#include <linux/openvswitch.h>
16#include <net/ip.h> 16#include <net/ip.h>
17#include <net/netfilter/nf_conntrack_core.h> 17#include <net/netfilter/nf_conntrack_core.h>
18#include <net/netfilter/nf_conntrack_labels.h>
18#include <net/netfilter/nf_conntrack_zones.h> 19#include <net/netfilter/nf_conntrack_zones.h>
19#include <net/netfilter/ipv6/nf_defrag_ipv6.h> 20#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
20 21
@@ -34,6 +35,12 @@ struct md_mark {
34 u32 mask; 35 u32 mask;
35}; 36};
36 37
38/* Metadata label for masked write to conntrack label. */
39struct md_label {
40 struct ovs_key_ct_label value;
41 struct ovs_key_ct_label mask;
42};
43
37/* Conntrack action context for execution. */ 44/* Conntrack action context for execution. */
38struct ovs_conntrack_info { 45struct ovs_conntrack_info {
39 struct nf_conntrack_zone zone; 46 struct nf_conntrack_zone zone;
@@ -41,6 +48,7 @@ struct ovs_conntrack_info {
41 u32 flags; 48 u32 flags;
42 u16 family; 49 u16 family;
43 struct md_mark mark; 50 struct md_mark mark;
51 struct md_label label;
44}; 52};
45 53
46static u16 key_to_nfproto(const struct sw_flow_key *key) 54static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -90,6 +98,24 @@ static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
90 return ct_state; 98 return ct_state;
91} 99}
92 100
101static void ovs_ct_get_label(const struct nf_conn *ct,
102 struct ovs_key_ct_label *label)
103{
104 struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
105
106 if (cl) {
107 size_t len = cl->words * sizeof(long);
108
109 if (len > OVS_CT_LABEL_LEN)
110 len = OVS_CT_LABEL_LEN;
111 else if (len < OVS_CT_LABEL_LEN)
112 memset(label, 0, OVS_CT_LABEL_LEN);
113 memcpy(label, cl->bits, len);
114 } else {
115 memset(label, 0, OVS_CT_LABEL_LEN);
116 }
117}
118
93static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state, 119static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
94 const struct nf_conntrack_zone *zone, 120 const struct nf_conntrack_zone *zone,
95 const struct nf_conn *ct) 121 const struct nf_conn *ct)
@@ -97,6 +123,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
97 key->ct.state = state; 123 key->ct.state = state;
98 key->ct.zone = zone->id; 124 key->ct.zone = zone->id;
99 key->ct.mark = ct ? ct->mark : 0; 125 key->ct.mark = ct ? ct->mark : 0;
126 ovs_ct_get_label(ct, &key->ct.label);
100} 127}
101 128
102/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has 129/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
@@ -140,6 +167,11 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
140 nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, key->ct.mark)) 167 nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, key->ct.mark))
141 return -EMSGSIZE; 168 return -EMSGSIZE;
142 169
170 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABEL) &&
171 nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label),
172 &key->ct.label))
173 return -EMSGSIZE;
174
143 return 0; 175 return 0;
144} 176}
145 177
@@ -168,6 +200,40 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
168 return 0; 200 return 0;
169} 201}
170 202
203static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
204 const struct ovs_key_ct_label *label,
205 const struct ovs_key_ct_label *mask)
206{
207 enum ip_conntrack_info ctinfo;
208 struct nf_conn_labels *cl;
209 struct nf_conn *ct;
210 int err;
211
212 if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS))
213 return -ENOTSUPP;
214
215 /* The connection could be invalid, in which case set_label is no-op.*/
216 ct = nf_ct_get(skb, &ctinfo);
217 if (!ct)
218 return 0;
219
220 cl = nf_ct_labels_find(ct);
221 if (!cl) {
222 nf_ct_labels_ext_add(ct);
223 cl = nf_ct_labels_find(ct);
224 }
225 if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN)
226 return -ENOSPC;
227
228 err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask,
229 OVS_CT_LABEL_LEN / sizeof(u32));
230 if (err)
231 return err;
232
233 ovs_ct_get_label(ct, &key->ct.label);
234 return 0;
235}
236
171static int handle_fragments(struct net *net, struct sw_flow_key *key, 237static int handle_fragments(struct net *net, struct sw_flow_key *key,
172 u16 zone, struct sk_buff *skb) 238 u16 zone, struct sk_buff *skb)
173{ 239{
@@ -327,6 +393,17 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
327 return 0; 393 return 0;
328} 394}
329 395
396static bool label_nonzero(const struct ovs_key_ct_label *label)
397{
398 size_t i;
399
400 for (i = 0; i < sizeof(*label); i++)
401 if (label->ct_label[i])
402 return true;
403
404 return false;
405}
406
330int ovs_ct_execute(struct net *net, struct sk_buff *skb, 407int ovs_ct_execute(struct net *net, struct sk_buff *skb,
331 struct sw_flow_key *key, 408 struct sw_flow_key *key,
332 const struct ovs_conntrack_info *info) 409 const struct ovs_conntrack_info *info)
@@ -351,9 +428,15 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
351 if (err) 428 if (err)
352 goto err; 429 goto err;
353 430
354 if (info->mark.mask) 431 if (info->mark.mask) {
355 err = ovs_ct_set_mark(skb, key, info->mark.value, 432 err = ovs_ct_set_mark(skb, key, info->mark.value,
356 info->mark.mask); 433 info->mark.mask);
434 if (err)
435 goto err;
436 }
437 if (label_nonzero(&info->label.mask))
438 err = ovs_ct_set_label(skb, key, &info->label.value,
439 &info->label.mask);
357err: 440err:
358 skb_push(skb, nh_ofs); 441 skb_push(skb, nh_ofs);
359 return err; 442 return err;
@@ -366,6 +449,8 @@ static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
366 .maxlen = sizeof(u16) }, 449 .maxlen = sizeof(u16) },
367 [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark), 450 [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
368 .maxlen = sizeof(struct md_mark) }, 451 .maxlen = sizeof(struct md_mark) },
452 [OVS_CT_ATTR_LABEL] = { .minlen = sizeof(struct md_label),
453 .maxlen = sizeof(struct md_label) },
369}; 454};
370 455
371static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, 456static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
@@ -409,6 +494,14 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
409 break; 494 break;
410 } 495 }
411#endif 496#endif
497#ifdef CONFIG_NF_CONNTRACK_LABELS
498 case OVS_CT_ATTR_LABEL: {
499 struct md_label *label = nla_data(a);
500
501 info->label = *label;
502 break;
503 }
504#endif
412 default: 505 default:
413 OVS_NLERR(log, "Unknown conntrack attr (%d)", 506 OVS_NLERR(log, "Unknown conntrack attr (%d)",
414 type); 507 type);
@@ -424,7 +517,7 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
424 return 0; 517 return 0;
425} 518}
426 519
427bool ovs_ct_verify(enum ovs_key_attr attr) 520bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
428{ 521{
429 if (attr == OVS_KEY_ATTR_CT_STATE) 522 if (attr == OVS_KEY_ATTR_CT_STATE)
430 return true; 523 return true;
@@ -434,6 +527,12 @@ bool ovs_ct_verify(enum ovs_key_attr attr)
434 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && 527 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
435 attr == OVS_KEY_ATTR_CT_MARK) 528 attr == OVS_KEY_ATTR_CT_MARK)
436 return true; 529 return true;
530 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
531 attr == OVS_KEY_ATTR_CT_LABEL) {
532 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
533
534 return ovs_net->xt_label;
535 }
437 536
438 return false; 537 return false;
439} 538}
@@ -500,6 +599,10 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
500 nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), 599 nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
501 &ct_info->mark)) 600 &ct_info->mark))
502 return -EMSGSIZE; 601 return -EMSGSIZE;
602 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
603 nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label),
604 &ct_info->label))
605 return -EMSGSIZE;
503 606
504 nla_nest_end(skb, start); 607 nla_nest_end(skb, start);
505 608
@@ -513,3 +616,24 @@ void ovs_ct_free_action(const struct nlattr *a)
513 if (ct_info->ct) 616 if (ct_info->ct)
514 nf_ct_put(ct_info->ct); 617 nf_ct_put(ct_info->ct);
515} 618}
619
620void ovs_ct_init(struct net *net)
621{
622 unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE;
623 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
624
625 if (nf_connlabels_get(net, n_bits)) {
626 ovs_net->xt_label = false;
627 OVS_NLERR(true, "Failed to set connlabel length");
628 } else {
629 ovs_net->xt_label = true;
630 }
631}
632
633void ovs_ct_exit(struct net *net)
634{
635 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
636
637 if (ovs_net->xt_label)
638 nf_connlabels_put(net);
639}
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h
index 87b289c58978..3cb30667a7dc 100644
--- a/net/openvswitch/conntrack.h
+++ b/net/openvswitch/conntrack.h
@@ -20,7 +20,9 @@ struct ovs_conntrack_info;
20enum ovs_key_attr; 20enum ovs_key_attr;
21 21
22#if defined(CONFIG_OPENVSWITCH_CONNTRACK) 22#if defined(CONFIG_OPENVSWITCH_CONNTRACK)
23bool ovs_ct_verify(enum ovs_key_attr attr); 23void ovs_ct_init(struct net *);
24void ovs_ct_exit(struct net *);
25bool ovs_ct_verify(struct net *, enum ovs_key_attr attr);
24int ovs_ct_copy_action(struct net *, const struct nlattr *, 26int ovs_ct_copy_action(struct net *, const struct nlattr *,
25 const struct sw_flow_key *, struct sw_flow_actions **, 27 const struct sw_flow_key *, struct sw_flow_actions **,
26 bool log); 28 bool log);
@@ -35,7 +37,11 @@ void ovs_ct_free_action(const struct nlattr *a);
35#else 37#else
36#include <linux/errno.h> 38#include <linux/errno.h>
37 39
38static inline bool ovs_ct_verify(int attr) 40static inline void ovs_ct_init(struct net *net) { }
41
42static inline void ovs_ct_exit(struct net *net) { }
43
44static inline bool ovs_ct_verify(struct net *net, int attr)
39{ 45{
40 return false; 46 return false;
41} 47}
@@ -66,6 +72,7 @@ static inline void ovs_ct_fill_key(const struct sk_buff *skb,
66 key->ct.state = 0; 72 key->ct.state = 0;
67 key->ct.zone = 0; 73 key->ct.zone = 0;
68 key->ct.mark = 0; 74 key->ct.mark = 0;
75 memset(&key->ct.label, 0, sizeof(key->ct.label));
69} 76}
70 77
71static inline int ovs_ct_put_key(const struct sw_flow_key *key, 78static inline int ovs_ct_put_key(const struct sw_flow_key *key,
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 72e63726efa0..ec0f8d9cee73 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -599,8 +599,8 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
599 if (IS_ERR(flow)) 599 if (IS_ERR(flow))
600 goto err_kfree_skb; 600 goto err_kfree_skb;
601 601
602 err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet, 602 err = ovs_flow_key_extract_userspace(net, a[OVS_PACKET_ATTR_KEY],
603 &flow->key, log); 603 packet, &flow->key, log);
604 if (err) 604 if (err)
605 goto err_flow_free; 605 goto err_flow_free;
606 606
@@ -947,7 +947,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
947 947
948 /* Extract key. */ 948 /* Extract key. */
949 ovs_match_init(&match, &key, &mask); 949 ovs_match_init(&match, &key, &mask);
950 error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], 950 error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
951 a[OVS_FLOW_ATTR_MASK], log); 951 a[OVS_FLOW_ATTR_MASK], log);
952 if (error) 952 if (error)
953 goto err_kfree_flow; 953 goto err_kfree_flow;
@@ -1118,7 +1118,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
1118 1118
1119 ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log); 1119 ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);
1120 ovs_match_init(&match, &key, &mask); 1120 ovs_match_init(&match, &key, &mask);
1121 error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], 1121 error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
1122 a[OVS_FLOW_ATTR_MASK], log); 1122 a[OVS_FLOW_ATTR_MASK], log);
1123 if (error) 1123 if (error)
1124 goto error; 1124 goto error;
@@ -1208,6 +1208,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
1208{ 1208{
1209 struct nlattr **a = info->attrs; 1209 struct nlattr **a = info->attrs;
1210 struct ovs_header *ovs_header = info->userhdr; 1210 struct ovs_header *ovs_header = info->userhdr;
1211 struct net *net = sock_net(skb->sk);
1211 struct sw_flow_key key; 1212 struct sw_flow_key key;
1212 struct sk_buff *reply; 1213 struct sk_buff *reply;
1213 struct sw_flow *flow; 1214 struct sw_flow *flow;
@@ -1222,7 +1223,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
1222 ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log); 1223 ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
1223 if (a[OVS_FLOW_ATTR_KEY]) { 1224 if (a[OVS_FLOW_ATTR_KEY]) {
1224 ovs_match_init(&match, &key, NULL); 1225 ovs_match_init(&match, &key, NULL);
1225 err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, 1226 err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,
1226 log); 1227 log);
1227 } else if (!ufid_present) { 1228 } else if (!ufid_present) {
1228 OVS_NLERR(log, 1229 OVS_NLERR(log,
@@ -1266,6 +1267,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1266{ 1267{
1267 struct nlattr **a = info->attrs; 1268 struct nlattr **a = info->attrs;
1268 struct ovs_header *ovs_header = info->userhdr; 1269 struct ovs_header *ovs_header = info->userhdr;
1270 struct net *net = sock_net(skb->sk);
1269 struct sw_flow_key key; 1271 struct sw_flow_key key;
1270 struct sk_buff *reply; 1272 struct sk_buff *reply;
1271 struct sw_flow *flow = NULL; 1273 struct sw_flow *flow = NULL;
@@ -1280,8 +1282,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
1280 ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log); 1282 ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
1281 if (a[OVS_FLOW_ATTR_KEY]) { 1283 if (a[OVS_FLOW_ATTR_KEY]) {
1282 ovs_match_init(&match, &key, NULL); 1284 ovs_match_init(&match, &key, NULL);
1283 err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, 1285 err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
1284 log); 1286 NULL, log);
1285 if (unlikely(err)) 1287 if (unlikely(err))
1286 return err; 1288 return err;
1287 } 1289 }
@@ -2237,6 +2239,7 @@ static int __net_init ovs_init_net(struct net *net)
2237 2239
2238 INIT_LIST_HEAD(&ovs_net->dps); 2240 INIT_LIST_HEAD(&ovs_net->dps);
2239 INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq); 2241 INIT_WORK(&ovs_net->dp_notify_work, ovs_dp_notify_wq);
2242 ovs_ct_init(net);
2240 return 0; 2243 return 0;
2241} 2244}
2242 2245
@@ -2271,6 +2274,7 @@ static void __net_exit ovs_exit_net(struct net *dnet)
2271 struct net *net; 2274 struct net *net;
2272 LIST_HEAD(head); 2275 LIST_HEAD(head);
2273 2276
2277 ovs_ct_exit(dnet);
2274 ovs_lock(); 2278 ovs_lock();
2275 list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node) 2279 list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
2276 __dp_destroy(dp); 2280 __dp_destroy(dp);
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index d24ba98024be..4e785ab88973 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -138,6 +138,9 @@ struct ovs_net {
138 struct list_head dps; 138 struct list_head dps;
139 struct work_struct dp_notify_work; 139 struct work_struct dp_notify_work;
140 struct vport_net vport_net; 140 struct vport_net vport_net;
141
142 /* Module reference for configuring conntrack. */
143 bool xt_label;
141}; 144};
142 145
143extern int ovs_net_id; 146extern int ovs_net_id;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 376ca8738fd4..5a3195e538ce 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -715,7 +715,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
715 return key_extract(skb, key); 715 return key_extract(skb, key);
716} 716}
717 717
718int ovs_flow_key_extract_userspace(const struct nlattr *attr, 718int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
719 struct sk_buff *skb, 719 struct sk_buff *skb,
720 struct sw_flow_key *key, bool log) 720 struct sw_flow_key *key, bool log)
721{ 721{
@@ -724,7 +724,7 @@ int ovs_flow_key_extract_userspace(const struct nlattr *attr,
724 memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE); 724 memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE);
725 725
726 /* Extract metadata from netlink attributes. */ 726 /* Extract metadata from netlink attributes. */
727 err = ovs_nla_get_flow_metadata(attr, key, log); 727 err = ovs_nla_get_flow_metadata(net, attr, key, log);
728 if (err) 728 if (err)
729 return err; 729 return err;
730 730
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index e05e69711ce1..fe527d2dd4b7 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -116,6 +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 } ct; 120 } ct;
120 121
121} __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. */
@@ -220,7 +221,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
220 struct sk_buff *skb, 221 struct sk_buff *skb,
221 struct sw_flow_key *key); 222 struct sw_flow_key *key);
222/* Extract key from packet coming from userspace. */ 223/* Extract key from packet coming from userspace. */
223int ovs_flow_key_extract_userspace(const struct nlattr *attr, 224int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
224 struct sk_buff *skb, 225 struct sk_buff *skb,
225 struct sw_flow_key *key, bool log); 226 struct sw_flow_key *key, bool log);
226 227
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index b17a4ec348f9..e22c5bfe8575 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -281,7 +281,7 @@ size_t ovs_key_attr_size(void)
281 /* Whenever adding new OVS_KEY_ FIELDS, we should consider 281 /* Whenever adding new OVS_KEY_ FIELDS, we should consider
282 * updating this function. 282 * updating this function.
283 */ 283 */
284 BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 25); 284 BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26);
285 285
286 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */ 286 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
287 + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */ 287 + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
@@ -293,6 +293,7 @@ size_t ovs_key_attr_size(void)
293 + nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */ 293 + nla_total_size(1) /* OVS_KEY_ATTR_CT_STATE */
294 + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */ 294 + nla_total_size(2) /* OVS_KEY_ATTR_CT_ZONE */
295 + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */ 295 + nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
296 + nla_total_size(16) /* OVS_KEY_ATTR_CT_LABEL */
296 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ 297 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
297 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */ 298 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
298 + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */ 299 + nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
@@ -345,6 +346,7 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
345 [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) }, 346 [OVS_KEY_ATTR_CT_STATE] = { .len = sizeof(u8) },
346 [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) }, 347 [OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
347 [OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) }, 348 [OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) },
349 [OVS_KEY_ATTR_CT_LABEL] = { .len = sizeof(struct ovs_key_ct_label) },
348}; 350};
349 351
350static bool is_all_zero(const u8 *fp, size_t size) 352static bool is_all_zero(const u8 *fp, size_t size)
@@ -721,9 +723,9 @@ int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
721 egress_tun_info->options_len); 723 egress_tun_info->options_len);
722} 724}
723 725
724static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs, 726static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
725 const struct nlattr **a, bool is_mask, 727 u64 *attrs, const struct nlattr **a,
726 bool log) 728 bool is_mask, bool log)
727{ 729{
728 if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) { 730 if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
729 u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]); 731 u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
@@ -776,36 +778,45 @@ static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
776 } 778 }
777 779
778 if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) && 780 if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
779 ovs_ct_verify(OVS_KEY_ATTR_CT_STATE)) { 781 ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
780 u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]); 782 u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
781 783
782 SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask); 784 SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
783 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE); 785 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
784 } 786 }
785 if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) && 787 if (*attrs & (1 << OVS_KEY_ATTR_CT_ZONE) &&
786 ovs_ct_verify(OVS_KEY_ATTR_CT_ZONE)) { 788 ovs_ct_verify(net, OVS_KEY_ATTR_CT_ZONE)) {
787 u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]); 789 u16 ct_zone = nla_get_u16(a[OVS_KEY_ATTR_CT_ZONE]);
788 790
789 SW_FLOW_KEY_PUT(match, ct.zone, ct_zone, is_mask); 791 SW_FLOW_KEY_PUT(match, ct.zone, ct_zone, is_mask);
790 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE); 792 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_ZONE);
791 } 793 }
792 if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) && 794 if (*attrs & (1 << OVS_KEY_ATTR_CT_MARK) &&
793 ovs_ct_verify(OVS_KEY_ATTR_CT_MARK)) { 795 ovs_ct_verify(net, OVS_KEY_ATTR_CT_MARK)) {
794 u32 mark = nla_get_u32(a[OVS_KEY_ATTR_CT_MARK]); 796 u32 mark = nla_get_u32(a[OVS_KEY_ATTR_CT_MARK]);
795 797
796 SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask); 798 SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
797 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK); 799 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
798 } 800 }
801 if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) &&
802 ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) {
803 const struct ovs_key_ct_label *cl;
804
805 cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]);
806 SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label,
807 sizeof(*cl), is_mask);
808 *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL);
809 }
799 return 0; 810 return 0;
800} 811}
801 812
802static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs, 813static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
803 const struct nlattr **a, bool is_mask, 814 u64 attrs, const struct nlattr **a,
804 bool log) 815 bool is_mask, bool log)
805{ 816{
806 int err; 817 int err;
807 818
808 err = metadata_from_nlattrs(match, &attrs, a, is_mask, log); 819 err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
809 if (err) 820 if (err)
810 return err; 821 return err;
811 822
@@ -1057,6 +1068,7 @@ static void mask_set_nlattr(struct nlattr *attr, u8 val)
1057 * mask. In case the 'mask' is NULL, the flow is treated as exact match 1068 * mask. In case the 'mask' is NULL, the flow is treated as exact match
1058 * flow. Otherwise, it is treated as a wildcarded flow, except the mask 1069 * flow. Otherwise, it is treated as a wildcarded flow, except the mask
1059 * does not include any don't care bit. 1070 * does not include any don't care bit.
1071 * @net: Used to determine per-namespace field support.
1060 * @match: receives the extracted flow match information. 1072 * @match: receives the extracted flow match information.
1061 * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute 1073 * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
1062 * sequence. The fields should of the packet that triggered the creation 1074 * sequence. The fields should of the packet that triggered the creation
@@ -1067,7 +1079,7 @@ static void mask_set_nlattr(struct nlattr *attr, u8 val)
1067 * probing for feature compatibility this should be passed in as false to 1079 * probing for feature compatibility this should be passed in as false to
1068 * suppress unnecessary error logging. 1080 * suppress unnecessary error logging.
1069 */ 1081 */
1070int ovs_nla_get_match(struct sw_flow_match *match, 1082int ovs_nla_get_match(struct net *net, struct sw_flow_match *match,
1071 const struct nlattr *nla_key, 1083 const struct nlattr *nla_key,
1072 const struct nlattr *nla_mask, 1084 const struct nlattr *nla_mask,
1073 bool log) 1085 bool log)
@@ -1117,7 +1129,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
1117 } 1129 }
1118 } 1130 }
1119 1131
1120 err = ovs_key_from_nlattrs(match, key_attrs, a, false, log); 1132 err = ovs_key_from_nlattrs(net, match, key_attrs, a, false, log);
1121 if (err) 1133 if (err)
1122 return err; 1134 return err;
1123 1135
@@ -1197,7 +1209,8 @@ int ovs_nla_get_match(struct sw_flow_match *match,
1197 } 1209 }
1198 } 1210 }
1199 1211
1200 err = ovs_key_from_nlattrs(match, mask_attrs, a, true, log); 1212 err = ovs_key_from_nlattrs(net, match, mask_attrs, a, true,
1213 log);
1201 if (err) 1214 if (err)
1202 goto free_newmask; 1215 goto free_newmask;
1203 } 1216 }
@@ -1278,7 +1291,7 @@ u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
1278 * extracted from the packet itself. 1291 * extracted from the packet itself.
1279 */ 1292 */
1280 1293
1281int ovs_nla_get_flow_metadata(const struct nlattr *attr, 1294int ovs_nla_get_flow_metadata(struct net *net, const struct nlattr *attr,
1282 struct sw_flow_key *key, 1295 struct sw_flow_key *key,
1283 bool log) 1296 bool log)
1284{ 1297{
@@ -1297,7 +1310,7 @@ int ovs_nla_get_flow_metadata(const struct nlattr *attr,
1297 memset(&key->ct, 0, sizeof(key->ct)); 1310 memset(&key->ct, 0, sizeof(key->ct));
1298 key->phy.in_port = DP_MAX_PORTS; 1311 key->phy.in_port = DP_MAX_PORTS;
1299 1312
1300 return metadata_from_nlattrs(&match, &attrs, a, false, log); 1313 return metadata_from_nlattrs(net, &match, &attrs, a, false, log);
1301} 1314}
1302 1315
1303static int __ovs_nla_put_key(const struct sw_flow_key *swkey, 1316static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
@@ -1929,6 +1942,7 @@ static int validate_set(const struct nlattr *a,
1929 case OVS_KEY_ATTR_PRIORITY: 1942 case OVS_KEY_ATTR_PRIORITY:
1930 case OVS_KEY_ATTR_SKB_MARK: 1943 case OVS_KEY_ATTR_SKB_MARK:
1931 case OVS_KEY_ATTR_CT_MARK: 1944 case OVS_KEY_ATTR_CT_MARK:
1945 case OVS_KEY_ATTR_CT_LABEL:
1932 case OVS_KEY_ATTR_ETHERNET: 1946 case OVS_KEY_ATTR_ETHERNET:
1933 break; 1947 break;
1934 1948
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index c0b484b237c9..07878e22e783 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -45,15 +45,16 @@ void ovs_match_init(struct sw_flow_match *match,
45 45
46int ovs_nla_put_key(const struct sw_flow_key *, const struct sw_flow_key *, 46int ovs_nla_put_key(const struct sw_flow_key *, const struct sw_flow_key *,
47 int attr, bool is_mask, struct sk_buff *); 47 int attr, bool is_mask, struct sk_buff *);
48int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *, 48int ovs_nla_get_flow_metadata(struct net *, const struct nlattr *,
49 bool log); 49 struct sw_flow_key *, bool log);
50 50
51int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb); 51int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb);
52int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb); 52int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb);
53int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb); 53int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
54 54
55int ovs_nla_get_match(struct sw_flow_match *, const struct nlattr *key, 55int ovs_nla_get_match(struct net *, struct sw_flow_match *,
56 const struct nlattr *mask, bool log); 56 const struct nlattr *key, const struct nlattr *mask,
57 bool log);
57int ovs_nla_put_egress_tunnel_key(struct sk_buff *, 58int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
58 const struct ip_tunnel_info *); 59 const struct ip_tunnel_info *);
59 60