xref: /openbmc/linux/net/openvswitch/conntrack.c (revision 9b9c2cd4)
1 /*
2  * Copyright (c) 2015 Nicira, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of version 2 of the GNU General Public
6  * License as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * General Public License for more details.
12  */
13 
14 #include <linux/module.h>
15 #include <linux/openvswitch.h>
16 #include <net/ip.h>
17 #include <net/netfilter/nf_conntrack_core.h>
18 #include <net/netfilter/nf_conntrack_helper.h>
19 #include <net/netfilter/nf_conntrack_labels.h>
20 #include <net/netfilter/nf_conntrack_zones.h>
21 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
22 
23 #include "datapath.h"
24 #include "conntrack.h"
25 #include "flow.h"
26 #include "flow_netlink.h"
27 
28 struct ovs_ct_len_tbl {
29 	size_t maxlen;
30 	size_t minlen;
31 };
32 
33 /* Metadata mark for masked write to conntrack mark */
34 struct md_mark {
35 	u32 value;
36 	u32 mask;
37 };
38 
39 /* Metadata label for masked write to conntrack label. */
40 struct md_labels {
41 	struct ovs_key_ct_labels value;
42 	struct ovs_key_ct_labels mask;
43 };
44 
45 /* Conntrack action context for execution. */
46 struct ovs_conntrack_info {
47 	struct nf_conntrack_helper *helper;
48 	struct nf_conntrack_zone zone;
49 	struct nf_conn *ct;
50 	u8 commit : 1;
51 	u16 family;
52 	struct md_mark mark;
53 	struct md_labels labels;
54 };
55 
56 static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
57 
58 static u16 key_to_nfproto(const struct sw_flow_key *key)
59 {
60 	switch (ntohs(key->eth.type)) {
61 	case ETH_P_IP:
62 		return NFPROTO_IPV4;
63 	case ETH_P_IPV6:
64 		return NFPROTO_IPV6;
65 	default:
66 		return NFPROTO_UNSPEC;
67 	}
68 }
69 
70 /* Map SKB connection state into the values used by flow definition. */
71 static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
72 {
73 	u8 ct_state = OVS_CS_F_TRACKED;
74 
75 	switch (ctinfo) {
76 	case IP_CT_ESTABLISHED_REPLY:
77 	case IP_CT_RELATED_REPLY:
78 	case IP_CT_NEW_REPLY:
79 		ct_state |= OVS_CS_F_REPLY_DIR;
80 		break;
81 	default:
82 		break;
83 	}
84 
85 	switch (ctinfo) {
86 	case IP_CT_ESTABLISHED:
87 	case IP_CT_ESTABLISHED_REPLY:
88 		ct_state |= OVS_CS_F_ESTABLISHED;
89 		break;
90 	case IP_CT_RELATED:
91 	case IP_CT_RELATED_REPLY:
92 		ct_state |= OVS_CS_F_RELATED;
93 		break;
94 	case IP_CT_NEW:
95 	case IP_CT_NEW_REPLY:
96 		ct_state |= OVS_CS_F_NEW;
97 		break;
98 	default:
99 		break;
100 	}
101 
102 	return ct_state;
103 }
104 
105 static u32 ovs_ct_get_mark(const struct nf_conn *ct)
106 {
107 #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
108 	return ct ? ct->mark : 0;
109 #else
110 	return 0;
111 #endif
112 }
113 
114 static void ovs_ct_get_labels(const struct nf_conn *ct,
115 			      struct ovs_key_ct_labels *labels)
116 {
117 	struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
118 
119 	if (cl) {
120 		size_t len = cl->words * sizeof(long);
121 
122 		if (len > OVS_CT_LABELS_LEN)
123 			len = OVS_CT_LABELS_LEN;
124 		else if (len < OVS_CT_LABELS_LEN)
125 			memset(labels, 0, OVS_CT_LABELS_LEN);
126 		memcpy(labels, cl->bits, len);
127 	} else {
128 		memset(labels, 0, OVS_CT_LABELS_LEN);
129 	}
130 }
131 
132 static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
133 				const struct nf_conntrack_zone *zone,
134 				const struct nf_conn *ct)
135 {
136 	key->ct.state = state;
137 	key->ct.zone = zone->id;
138 	key->ct.mark = ovs_ct_get_mark(ct);
139 	ovs_ct_get_labels(ct, &key->ct.labels);
140 }
141 
142 /* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
143  * previously sent the packet to conntrack via the ct action.
144  */
145 static void ovs_ct_update_key(const struct sk_buff *skb,
146 			      const struct ovs_conntrack_info *info,
147 			      struct sw_flow_key *key, bool post_ct)
148 {
149 	const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
150 	enum ip_conntrack_info ctinfo;
151 	struct nf_conn *ct;
152 	u8 state = 0;
153 
154 	ct = nf_ct_get(skb, &ctinfo);
155 	if (ct) {
156 		state = ovs_ct_get_state(ctinfo);
157 		if (!nf_ct_is_confirmed(ct))
158 			state |= OVS_CS_F_NEW;
159 		if (ct->master)
160 			state |= OVS_CS_F_RELATED;
161 		zone = nf_ct_zone(ct);
162 	} else if (post_ct) {
163 		state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
164 		if (info)
165 			zone = &info->zone;
166 	}
167 	__ovs_ct_update_key(key, state, zone, ct);
168 }
169 
170 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
171 {
172 	ovs_ct_update_key(skb, NULL, key, false);
173 }
174 
175 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
176 {
177 	if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
178 		return -EMSGSIZE;
179 
180 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
181 	    nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, key->ct.zone))
182 		return -EMSGSIZE;
183 
184 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
185 	    nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, key->ct.mark))
186 		return -EMSGSIZE;
187 
188 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
189 	    nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
190 		    &key->ct.labels))
191 		return -EMSGSIZE;
192 
193 	return 0;
194 }
195 
196 static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
197 			   u32 ct_mark, u32 mask)
198 {
199 #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
200 	enum ip_conntrack_info ctinfo;
201 	struct nf_conn *ct;
202 	u32 new_mark;
203 
204 
205 	/* The connection could be invalid, in which case set_mark is no-op. */
206 	ct = nf_ct_get(skb, &ctinfo);
207 	if (!ct)
208 		return 0;
209 
210 	new_mark = ct_mark | (ct->mark & ~(mask));
211 	if (ct->mark != new_mark) {
212 		ct->mark = new_mark;
213 		nf_conntrack_event_cache(IPCT_MARK, ct);
214 		key->ct.mark = new_mark;
215 	}
216 
217 	return 0;
218 #else
219 	return -ENOTSUPP;
220 #endif
221 }
222 
223 static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
224 			     const struct ovs_key_ct_labels *labels,
225 			     const struct ovs_key_ct_labels *mask)
226 {
227 	enum ip_conntrack_info ctinfo;
228 	struct nf_conn_labels *cl;
229 	struct nf_conn *ct;
230 	int err;
231 
232 	/* The connection could be invalid, in which case set_label is no-op.*/
233 	ct = nf_ct_get(skb, &ctinfo);
234 	if (!ct)
235 		return 0;
236 
237 	cl = nf_ct_labels_find(ct);
238 	if (!cl) {
239 		nf_ct_labels_ext_add(ct);
240 		cl = nf_ct_labels_find(ct);
241 	}
242 	if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
243 		return -ENOSPC;
244 
245 	err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
246 				    OVS_CT_LABELS_LEN / sizeof(u32));
247 	if (err)
248 		return err;
249 
250 	ovs_ct_get_labels(ct, &key->ct.labels);
251 	return 0;
252 }
253 
254 /* 'skb' should already be pulled to nh_ofs. */
255 static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
256 {
257 	const struct nf_conntrack_helper *helper;
258 	const struct nf_conn_help *help;
259 	enum ip_conntrack_info ctinfo;
260 	unsigned int protoff;
261 	struct nf_conn *ct;
262 
263 	ct = nf_ct_get(skb, &ctinfo);
264 	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
265 		return NF_ACCEPT;
266 
267 	help = nfct_help(ct);
268 	if (!help)
269 		return NF_ACCEPT;
270 
271 	helper = rcu_dereference(help->helper);
272 	if (!helper)
273 		return NF_ACCEPT;
274 
275 	switch (proto) {
276 	case NFPROTO_IPV4:
277 		protoff = ip_hdrlen(skb);
278 		break;
279 	case NFPROTO_IPV6: {
280 		u8 nexthdr = ipv6_hdr(skb)->nexthdr;
281 		__be16 frag_off;
282 		int ofs;
283 
284 		ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
285 				       &frag_off);
286 		if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
287 			pr_debug("proto header not found\n");
288 			return NF_ACCEPT;
289 		}
290 		protoff = ofs;
291 		break;
292 	}
293 	default:
294 		WARN_ONCE(1, "helper invoked on non-IP family!");
295 		return NF_DROP;
296 	}
297 
298 	return helper->help(skb, protoff, ct, ctinfo);
299 }
300 
301 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
302  * value if 'skb' is freed.
303  */
304 static int handle_fragments(struct net *net, struct sw_flow_key *key,
305 			    u16 zone, struct sk_buff *skb)
306 {
307 	struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
308 
309 	if (key->eth.type == htons(ETH_P_IP)) {
310 		enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
311 		int err;
312 
313 		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
314 		err = ip_defrag(net, skb, user);
315 		if (err)
316 			return err;
317 
318 		ovs_cb.mru = IPCB(skb)->frag_max_size;
319 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
320 	} else if (key->eth.type == htons(ETH_P_IPV6)) {
321 		enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
322 		struct sk_buff *reasm;
323 
324 		memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
325 		reasm = nf_ct_frag6_gather(net, skb, user);
326 		if (!reasm)
327 			return -EINPROGRESS;
328 
329 		if (skb == reasm) {
330 			kfree_skb(skb);
331 			return -EINVAL;
332 		}
333 
334 		/* Don't free 'skb' even though it is one of the original
335 		 * fragments, as we're going to morph it into the head.
336 		 */
337 		skb_get(skb);
338 		nf_ct_frag6_consume_orig(reasm);
339 
340 		key->ip.proto = ipv6_hdr(reasm)->nexthdr;
341 		skb_morph(skb, reasm);
342 		skb->next = reasm->next;
343 		consume_skb(reasm);
344 		ovs_cb.mru = IP6CB(skb)->frag_max_size;
345 #endif
346 	} else {
347 		kfree_skb(skb);
348 		return -EPFNOSUPPORT;
349 	}
350 
351 	key->ip.frag = OVS_FRAG_TYPE_NONE;
352 	skb_clear_hash(skb);
353 	skb->ignore_df = 1;
354 	*OVS_CB(skb) = ovs_cb;
355 
356 	return 0;
357 }
358 
359 static struct nf_conntrack_expect *
360 ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
361 		   u16 proto, const struct sk_buff *skb)
362 {
363 	struct nf_conntrack_tuple tuple;
364 
365 	if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
366 		return NULL;
367 	return __nf_ct_expect_find(net, zone, &tuple);
368 }
369 
370 /* Determine whether skb->nfct is equal to the result of conntrack lookup. */
371 static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
372 			    const struct ovs_conntrack_info *info)
373 {
374 	enum ip_conntrack_info ctinfo;
375 	struct nf_conn *ct;
376 
377 	ct = nf_ct_get(skb, &ctinfo);
378 	if (!ct)
379 		return false;
380 	if (!net_eq(net, read_pnet(&ct->ct_net)))
381 		return false;
382 	if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
383 		return false;
384 	if (info->helper) {
385 		struct nf_conn_help *help;
386 
387 		help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
388 		if (help && rcu_access_pointer(help->helper) != info->helper)
389 			return false;
390 	}
391 
392 	return true;
393 }
394 
395 static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
396 			   const struct ovs_conntrack_info *info,
397 			   struct sk_buff *skb)
398 {
399 	/* If we are recirculating packets to match on conntrack fields and
400 	 * committing with a separate conntrack action,  then we don't need to
401 	 * actually run the packet through conntrack twice unless it's for a
402 	 * different zone.
403 	 */
404 	if (!skb_nfct_cached(net, skb, info)) {
405 		struct nf_conn *tmpl = info->ct;
406 
407 		/* Associate skb with specified zone. */
408 		if (tmpl) {
409 			if (skb->nfct)
410 				nf_conntrack_put(skb->nfct);
411 			nf_conntrack_get(&tmpl->ct_general);
412 			skb->nfct = &tmpl->ct_general;
413 			skb->nfctinfo = IP_CT_NEW;
414 		}
415 
416 		if (nf_conntrack_in(net, info->family, NF_INET_PRE_ROUTING,
417 				    skb) != NF_ACCEPT)
418 			return -ENOENT;
419 
420 		if (ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
421 			WARN_ONCE(1, "helper rejected packet");
422 			return -EINVAL;
423 		}
424 	}
425 
426 	ovs_ct_update_key(skb, info, key, true);
427 
428 	return 0;
429 }
430 
431 /* Lookup connection and read fields into key. */
432 static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
433 			 const struct ovs_conntrack_info *info,
434 			 struct sk_buff *skb)
435 {
436 	struct nf_conntrack_expect *exp;
437 
438 	exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
439 	if (exp) {
440 		u8 state;
441 
442 		state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
443 		__ovs_ct_update_key(key, state, &info->zone, exp->master);
444 	} else {
445 		int err;
446 
447 		err = __ovs_ct_lookup(net, key, info, skb);
448 		if (err)
449 			return err;
450 	}
451 
452 	return 0;
453 }
454 
455 /* Lookup connection and confirm if unconfirmed. */
456 static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
457 			 const struct ovs_conntrack_info *info,
458 			 struct sk_buff *skb)
459 {
460 	u8 state;
461 	int err;
462 
463 	state = key->ct.state;
464 	if (key->ct.zone == info->zone.id &&
465 	    ((state & OVS_CS_F_TRACKED) && !(state & OVS_CS_F_NEW))) {
466 		/* Previous lookup has shown that this connection is already
467 		 * tracked and committed. Skip committing.
468 		 */
469 		return 0;
470 	}
471 
472 	err = __ovs_ct_lookup(net, key, info, skb);
473 	if (err)
474 		return err;
475 	if (nf_conntrack_confirm(skb) != NF_ACCEPT)
476 		return -EINVAL;
477 
478 	return 0;
479 }
480 
481 static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
482 {
483 	size_t i;
484 
485 	for (i = 0; i < sizeof(*labels); i++)
486 		if (labels->ct_labels[i])
487 			return true;
488 
489 	return false;
490 }
491 
492 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
493  * value if 'skb' is freed.
494  */
495 int ovs_ct_execute(struct net *net, struct sk_buff *skb,
496 		   struct sw_flow_key *key,
497 		   const struct ovs_conntrack_info *info)
498 {
499 	int nh_ofs;
500 	int err;
501 
502 	/* The conntrack module expects to be working at L3. */
503 	nh_ofs = skb_network_offset(skb);
504 	skb_pull(skb, nh_ofs);
505 
506 	if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
507 		err = handle_fragments(net, key, info->zone.id, skb);
508 		if (err)
509 			return err;
510 	}
511 
512 	if (info->commit)
513 		err = ovs_ct_commit(net, key, info, skb);
514 	else
515 		err = ovs_ct_lookup(net, key, info, skb);
516 	if (err)
517 		goto err;
518 
519 	if (info->mark.mask) {
520 		err = ovs_ct_set_mark(skb, key, info->mark.value,
521 				      info->mark.mask);
522 		if (err)
523 			goto err;
524 	}
525 	if (labels_nonzero(&info->labels.mask))
526 		err = ovs_ct_set_labels(skb, key, &info->labels.value,
527 					&info->labels.mask);
528 err:
529 	skb_push(skb, nh_ofs);
530 	if (err)
531 		kfree_skb(skb);
532 	return err;
533 }
534 
535 static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
536 			     const struct sw_flow_key *key, bool log)
537 {
538 	struct nf_conntrack_helper *helper;
539 	struct nf_conn_help *help;
540 
541 	helper = nf_conntrack_helper_try_module_get(name, info->family,
542 						    key->ip.proto);
543 	if (!helper) {
544 		OVS_NLERR(log, "Unknown helper \"%s\"", name);
545 		return -EINVAL;
546 	}
547 
548 	help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
549 	if (!help) {
550 		module_put(helper->me);
551 		return -ENOMEM;
552 	}
553 
554 	rcu_assign_pointer(help->helper, helper);
555 	info->helper = helper;
556 	return 0;
557 }
558 
559 static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
560 	[OVS_CT_ATTR_COMMIT]	= { .minlen = 0, .maxlen = 0 },
561 	[OVS_CT_ATTR_ZONE]	= { .minlen = sizeof(u16),
562 				    .maxlen = sizeof(u16) },
563 	[OVS_CT_ATTR_MARK]	= { .minlen = sizeof(struct md_mark),
564 				    .maxlen = sizeof(struct md_mark) },
565 	[OVS_CT_ATTR_LABELS]	= { .minlen = sizeof(struct md_labels),
566 				    .maxlen = sizeof(struct md_labels) },
567 	[OVS_CT_ATTR_HELPER]	= { .minlen = 1,
568 				    .maxlen = NF_CT_HELPER_NAME_LEN }
569 };
570 
571 static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
572 		    const char **helper, bool log)
573 {
574 	struct nlattr *a;
575 	int rem;
576 
577 	nla_for_each_nested(a, attr, rem) {
578 		int type = nla_type(a);
579 		int maxlen = ovs_ct_attr_lens[type].maxlen;
580 		int minlen = ovs_ct_attr_lens[type].minlen;
581 
582 		if (type > OVS_CT_ATTR_MAX) {
583 			OVS_NLERR(log,
584 				  "Unknown conntrack attr (type=%d, max=%d)",
585 				  type, OVS_CT_ATTR_MAX);
586 			return -EINVAL;
587 		}
588 		if (nla_len(a) < minlen || nla_len(a) > maxlen) {
589 			OVS_NLERR(log,
590 				  "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
591 				  type, nla_len(a), maxlen);
592 			return -EINVAL;
593 		}
594 
595 		switch (type) {
596 		case OVS_CT_ATTR_COMMIT:
597 			info->commit = true;
598 			break;
599 #ifdef CONFIG_NF_CONNTRACK_ZONES
600 		case OVS_CT_ATTR_ZONE:
601 			info->zone.id = nla_get_u16(a);
602 			break;
603 #endif
604 #ifdef CONFIG_NF_CONNTRACK_MARK
605 		case OVS_CT_ATTR_MARK: {
606 			struct md_mark *mark = nla_data(a);
607 
608 			if (!mark->mask) {
609 				OVS_NLERR(log, "ct_mark mask cannot be 0");
610 				return -EINVAL;
611 			}
612 			info->mark = *mark;
613 			break;
614 		}
615 #endif
616 #ifdef CONFIG_NF_CONNTRACK_LABELS
617 		case OVS_CT_ATTR_LABELS: {
618 			struct md_labels *labels = nla_data(a);
619 
620 			if (!labels_nonzero(&labels->mask)) {
621 				OVS_NLERR(log, "ct_labels mask cannot be 0");
622 				return -EINVAL;
623 			}
624 			info->labels = *labels;
625 			break;
626 		}
627 #endif
628 		case OVS_CT_ATTR_HELPER:
629 			*helper = nla_data(a);
630 			if (!memchr(*helper, '\0', nla_len(a))) {
631 				OVS_NLERR(log, "Invalid conntrack helper");
632 				return -EINVAL;
633 			}
634 			break;
635 		default:
636 			OVS_NLERR(log, "Unknown conntrack attr (%d)",
637 				  type);
638 			return -EINVAL;
639 		}
640 	}
641 
642 	if (rem > 0) {
643 		OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
644 		return -EINVAL;
645 	}
646 
647 	return 0;
648 }
649 
650 bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
651 {
652 	if (attr == OVS_KEY_ATTR_CT_STATE)
653 		return true;
654 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
655 	    attr == OVS_KEY_ATTR_CT_ZONE)
656 		return true;
657 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
658 	    attr == OVS_KEY_ATTR_CT_MARK)
659 		return true;
660 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
661 	    attr == OVS_KEY_ATTR_CT_LABELS) {
662 		struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
663 
664 		return ovs_net->xt_label;
665 	}
666 
667 	return false;
668 }
669 
670 int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
671 		       const struct sw_flow_key *key,
672 		       struct sw_flow_actions **sfa,  bool log)
673 {
674 	struct ovs_conntrack_info ct_info;
675 	const char *helper = NULL;
676 	u16 family;
677 	int err;
678 
679 	family = key_to_nfproto(key);
680 	if (family == NFPROTO_UNSPEC) {
681 		OVS_NLERR(log, "ct family unspecified");
682 		return -EINVAL;
683 	}
684 
685 	memset(&ct_info, 0, sizeof(ct_info));
686 	ct_info.family = family;
687 
688 	nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
689 			NF_CT_DEFAULT_ZONE_DIR, 0);
690 
691 	err = parse_ct(attr, &ct_info, &helper, log);
692 	if (err)
693 		return err;
694 
695 	/* Set up template for tracking connections in specific zones. */
696 	ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
697 	if (!ct_info.ct) {
698 		OVS_NLERR(log, "Failed to allocate conntrack template");
699 		return -ENOMEM;
700 	}
701 
702 	__set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
703 	nf_conntrack_get(&ct_info.ct->ct_general);
704 
705 	if (helper) {
706 		err = ovs_ct_add_helper(&ct_info, helper, key, log);
707 		if (err)
708 			goto err_free_ct;
709 	}
710 
711 	err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
712 				 sizeof(ct_info), log);
713 	if (err)
714 		goto err_free_ct;
715 
716 	return 0;
717 err_free_ct:
718 	__ovs_ct_free_action(&ct_info);
719 	return err;
720 }
721 
722 int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
723 			  struct sk_buff *skb)
724 {
725 	struct nlattr *start;
726 
727 	start = nla_nest_start(skb, OVS_ACTION_ATTR_CT);
728 	if (!start)
729 		return -EMSGSIZE;
730 
731 	if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
732 		return -EMSGSIZE;
733 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
734 	    nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
735 		return -EMSGSIZE;
736 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
737 	    nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
738 		    &ct_info->mark))
739 		return -EMSGSIZE;
740 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
741 	    labels_nonzero(&ct_info->labels.mask) &&
742 	    nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
743 		    &ct_info->labels))
744 		return -EMSGSIZE;
745 	if (ct_info->helper) {
746 		if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
747 				   ct_info->helper->name))
748 			return -EMSGSIZE;
749 	}
750 
751 	nla_nest_end(skb, start);
752 
753 	return 0;
754 }
755 
756 void ovs_ct_free_action(const struct nlattr *a)
757 {
758 	struct ovs_conntrack_info *ct_info = nla_data(a);
759 
760 	__ovs_ct_free_action(ct_info);
761 }
762 
763 static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
764 {
765 	if (ct_info->helper)
766 		module_put(ct_info->helper->me);
767 	if (ct_info->ct)
768 		nf_ct_put(ct_info->ct);
769 }
770 
771 void ovs_ct_init(struct net *net)
772 {
773 	unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
774 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
775 
776 	if (nf_connlabels_get(net, n_bits)) {
777 		ovs_net->xt_label = false;
778 		OVS_NLERR(true, "Failed to set connlabel length");
779 	} else {
780 		ovs_net->xt_label = true;
781 	}
782 }
783 
784 void ovs_ct_exit(struct net *net)
785 {
786 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
787 
788 	if (ovs_net->xt_label)
789 		nf_connlabels_put(net);
790 }
791