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