xref: /linux/net/openvswitch/conntrack.c (revision 3c2f85b8ce8acee0502d61fb53015eabd7d4c8fb)
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 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_labels(const struct nf_conn *ct,
113 			      struct ovs_key_ct_labels *labels)
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_LABELS_LEN)
121 			len = OVS_CT_LABELS_LEN;
122 		else if (len < OVS_CT_LABELS_LEN)
123 			memset(labels, 0, OVS_CT_LABELS_LEN);
124 		memcpy(labels, cl->bits, len);
125 	} else {
126 		memset(labels, 0, OVS_CT_LABELS_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_labels(ct, &key->ct.labels);
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_u32(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_LABELS, sizeof(key->ct.labels),
183 		    &key->ct.labels))
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_labels(struct sk_buff *skb, struct sw_flow_key *key,
217 			     const struct ovs_key_ct_labels *labels,
218 			     const struct ovs_key_ct_labels *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_LABELS_LEN)
239 		return -ENOSPC;
240 
241 	err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
242 				    OVS_CT_LABELS_LEN / sizeof(u32));
243 	if (err)
244 		return err;
245 
246 	ovs_ct_get_labels(ct, &key->ct.labels);
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 labels_nonzero(const struct ovs_key_ct_labels *labels)
469 {
470 	size_t i;
471 
472 	for (i = 0; i < sizeof(*labels); i++)
473 		if (labels->ct_labels[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->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 (labels_nonzero(&info->labels.mask))
510 		err = ovs_ct_set_labels(skb, key, &info->labels.value,
511 					&info->labels.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_COMMIT]	= { .minlen = 0, .maxlen = 0 },
543 	[OVS_CT_ATTR_ZONE]	= { .minlen = sizeof(u16),
544 				    .maxlen = sizeof(u16) },
545 	[OVS_CT_ATTR_MARK]	= { .minlen = sizeof(struct md_mark),
546 				    .maxlen = sizeof(struct md_mark) },
547 	[OVS_CT_ATTR_LABELS]	= { .minlen = sizeof(struct md_labels),
548 				    .maxlen = sizeof(struct md_labels) },
549 	[OVS_CT_ATTR_HELPER]	= { .minlen = 1,
550 				    .maxlen = NF_CT_HELPER_NAME_LEN }
551 };
552 
553 static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
554 		    const char **helper, bool log)
555 {
556 	struct nlattr *a;
557 	int rem;
558 
559 	nla_for_each_nested(a, attr, rem) {
560 		int type = nla_type(a);
561 		int maxlen = ovs_ct_attr_lens[type].maxlen;
562 		int minlen = ovs_ct_attr_lens[type].minlen;
563 
564 		if (type > OVS_CT_ATTR_MAX) {
565 			OVS_NLERR(log,
566 				  "Unknown conntrack attr (type=%d, max=%d)",
567 				  type, OVS_CT_ATTR_MAX);
568 			return -EINVAL;
569 		}
570 		if (nla_len(a) < minlen || nla_len(a) > maxlen) {
571 			OVS_NLERR(log,
572 				  "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
573 				  type, nla_len(a), maxlen);
574 			return -EINVAL;
575 		}
576 
577 		switch (type) {
578 		case OVS_CT_ATTR_COMMIT:
579 			info->commit = true;
580 			break;
581 #ifdef CONFIG_NF_CONNTRACK_ZONES
582 		case OVS_CT_ATTR_ZONE:
583 			info->zone.id = nla_get_u16(a);
584 			break;
585 #endif
586 #ifdef CONFIG_NF_CONNTRACK_MARK
587 		case OVS_CT_ATTR_MARK: {
588 			struct md_mark *mark = nla_data(a);
589 
590 			info->mark = *mark;
591 			break;
592 		}
593 #endif
594 #ifdef CONFIG_NF_CONNTRACK_LABELS
595 		case OVS_CT_ATTR_LABELS: {
596 			struct md_labels *labels = nla_data(a);
597 
598 			info->labels = *labels;
599 			break;
600 		}
601 #endif
602 		case OVS_CT_ATTR_HELPER:
603 			*helper = nla_data(a);
604 			if (!memchr(*helper, '\0', nla_len(a))) {
605 				OVS_NLERR(log, "Invalid conntrack helper");
606 				return -EINVAL;
607 			}
608 			break;
609 		default:
610 			OVS_NLERR(log, "Unknown conntrack attr (%d)",
611 				  type);
612 			return -EINVAL;
613 		}
614 	}
615 
616 	if (rem > 0) {
617 		OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
618 		return -EINVAL;
619 	}
620 
621 	return 0;
622 }
623 
624 bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
625 {
626 	if (attr == OVS_KEY_ATTR_CT_STATE)
627 		return true;
628 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
629 	    attr == OVS_KEY_ATTR_CT_ZONE)
630 		return true;
631 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
632 	    attr == OVS_KEY_ATTR_CT_MARK)
633 		return true;
634 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
635 	    attr == OVS_KEY_ATTR_CT_LABELS) {
636 		struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
637 
638 		return ovs_net->xt_label;
639 	}
640 
641 	return false;
642 }
643 
644 int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
645 		       const struct sw_flow_key *key,
646 		       struct sw_flow_actions **sfa,  bool log)
647 {
648 	struct ovs_conntrack_info ct_info;
649 	const char *helper = NULL;
650 	u16 family;
651 	int err;
652 
653 	family = key_to_nfproto(key);
654 	if (family == NFPROTO_UNSPEC) {
655 		OVS_NLERR(log, "ct family unspecified");
656 		return -EINVAL;
657 	}
658 
659 	memset(&ct_info, 0, sizeof(ct_info));
660 	ct_info.family = family;
661 
662 	nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
663 			NF_CT_DEFAULT_ZONE_DIR, 0);
664 
665 	err = parse_ct(attr, &ct_info, &helper, log);
666 	if (err)
667 		return err;
668 
669 	/* Set up template for tracking connections in specific zones. */
670 	ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
671 	if (!ct_info.ct) {
672 		OVS_NLERR(log, "Failed to allocate conntrack template");
673 		return -ENOMEM;
674 	}
675 	if (helper) {
676 		err = ovs_ct_add_helper(&ct_info, helper, key, log);
677 		if (err)
678 			goto err_free_ct;
679 	}
680 
681 	err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
682 				 sizeof(ct_info), log);
683 	if (err)
684 		goto err_free_ct;
685 
686 	__set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
687 	nf_conntrack_get(&ct_info.ct->ct_general);
688 	return 0;
689 err_free_ct:
690 	nf_conntrack_free(ct_info.ct);
691 	return err;
692 }
693 
694 int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
695 			  struct sk_buff *skb)
696 {
697 	struct nlattr *start;
698 
699 	start = nla_nest_start(skb, OVS_ACTION_ATTR_CT);
700 	if (!start)
701 		return -EMSGSIZE;
702 
703 	if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
704 		return -EMSGSIZE;
705 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
706 	    nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
707 		return -EMSGSIZE;
708 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
709 	    nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
710 		    &ct_info->mark))
711 		return -EMSGSIZE;
712 	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
713 	    nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
714 		    &ct_info->labels))
715 		return -EMSGSIZE;
716 	if (ct_info->helper) {
717 		if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
718 				   ct_info->helper->name))
719 			return -EMSGSIZE;
720 	}
721 
722 	nla_nest_end(skb, start);
723 
724 	return 0;
725 }
726 
727 void ovs_ct_free_action(const struct nlattr *a)
728 {
729 	struct ovs_conntrack_info *ct_info = nla_data(a);
730 
731 	if (ct_info->helper)
732 		module_put(ct_info->helper->me);
733 	if (ct_info->ct)
734 		nf_ct_put(ct_info->ct);
735 }
736 
737 void ovs_ct_init(struct net *net)
738 {
739 	unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
740 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
741 
742 	if (nf_connlabels_get(net, n_bits)) {
743 		ovs_net->xt_label = false;
744 		OVS_NLERR(true, "Failed to set connlabel length");
745 	} else {
746 		ovs_net->xt_label = true;
747 	}
748 }
749 
750 void ovs_ct_exit(struct net *net)
751 {
752 	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
753 
754 	if (ovs_net->xt_label)
755 		nf_connlabels_put(net);
756 }
757