xref: /openbmc/linux/net/ipv6/ioam6.c (revision 2326f3cd)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  IPv6 IOAM implementation
4  *
5  *  Author:
6  *  Justin Iurman <justin.iurman@uliege.be>
7  */
8 
9 #include <linux/errno.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/net.h>
13 #include <linux/ioam6.h>
14 #include <linux/ioam6_genl.h>
15 #include <linux/rhashtable.h>
16 
17 #include <net/addrconf.h>
18 #include <net/genetlink.h>
19 #include <net/ioam6.h>
20 
21 static void ioam6_ns_release(struct ioam6_namespace *ns)
22 {
23 	kfree_rcu(ns, rcu);
24 }
25 
26 static void ioam6_sc_release(struct ioam6_schema *sc)
27 {
28 	kfree_rcu(sc, rcu);
29 }
30 
31 static void ioam6_free_ns(void *ptr, void *arg)
32 {
33 	struct ioam6_namespace *ns = (struct ioam6_namespace *)ptr;
34 
35 	if (ns)
36 		ioam6_ns_release(ns);
37 }
38 
39 static void ioam6_free_sc(void *ptr, void *arg)
40 {
41 	struct ioam6_schema *sc = (struct ioam6_schema *)ptr;
42 
43 	if (sc)
44 		ioam6_sc_release(sc);
45 }
46 
47 static int ioam6_ns_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
48 {
49 	const struct ioam6_namespace *ns = obj;
50 
51 	return (ns->id != *(__be16 *)arg->key);
52 }
53 
54 static int ioam6_sc_cmpfn(struct rhashtable_compare_arg *arg, const void *obj)
55 {
56 	const struct ioam6_schema *sc = obj;
57 
58 	return (sc->id != *(u32 *)arg->key);
59 }
60 
61 static const struct rhashtable_params rht_ns_params = {
62 	.key_len		= sizeof(__be16),
63 	.key_offset		= offsetof(struct ioam6_namespace, id),
64 	.head_offset		= offsetof(struct ioam6_namespace, head),
65 	.automatic_shrinking	= true,
66 	.obj_cmpfn		= ioam6_ns_cmpfn,
67 };
68 
69 static const struct rhashtable_params rht_sc_params = {
70 	.key_len		= sizeof(u32),
71 	.key_offset		= offsetof(struct ioam6_schema, id),
72 	.head_offset		= offsetof(struct ioam6_schema, head),
73 	.automatic_shrinking	= true,
74 	.obj_cmpfn		= ioam6_sc_cmpfn,
75 };
76 
77 static struct genl_family ioam6_genl_family;
78 
79 static const struct nla_policy ioam6_genl_policy_addns[] = {
80 	[IOAM6_ATTR_NS_ID]	= { .type = NLA_U16 },
81 	[IOAM6_ATTR_NS_DATA]	= { .type = NLA_U32 },
82 	[IOAM6_ATTR_NS_DATA_WIDE] = { .type = NLA_U64 },
83 };
84 
85 static const struct nla_policy ioam6_genl_policy_delns[] = {
86 	[IOAM6_ATTR_NS_ID]	= { .type = NLA_U16 },
87 };
88 
89 static const struct nla_policy ioam6_genl_policy_addsc[] = {
90 	[IOAM6_ATTR_SC_ID]	= { .type = NLA_U32 },
91 	[IOAM6_ATTR_SC_DATA]	= { .type = NLA_BINARY,
92 				    .len = IOAM6_MAX_SCHEMA_DATA_LEN },
93 };
94 
95 static const struct nla_policy ioam6_genl_policy_delsc[] = {
96 	[IOAM6_ATTR_SC_ID]	= { .type = NLA_U32 },
97 };
98 
99 static const struct nla_policy ioam6_genl_policy_ns_sc[] = {
100 	[IOAM6_ATTR_NS_ID]	= { .type = NLA_U16 },
101 	[IOAM6_ATTR_SC_ID]	= { .type = NLA_U32 },
102 	[IOAM6_ATTR_SC_NONE]	= { .type = NLA_FLAG },
103 };
104 
105 static int ioam6_genl_addns(struct sk_buff *skb, struct genl_info *info)
106 {
107 	struct ioam6_pernet_data *nsdata;
108 	struct ioam6_namespace *ns;
109 	u64 data64;
110 	u32 data32;
111 	__be16 id;
112 	int err;
113 
114 	if (!info->attrs[IOAM6_ATTR_NS_ID])
115 		return -EINVAL;
116 
117 	id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID]));
118 	nsdata = ioam6_pernet(genl_info_net(info));
119 
120 	mutex_lock(&nsdata->lock);
121 
122 	ns = rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params);
123 	if (ns) {
124 		err = -EEXIST;
125 		goto out_unlock;
126 	}
127 
128 	ns = kzalloc(sizeof(*ns), GFP_KERNEL);
129 	if (!ns) {
130 		err = -ENOMEM;
131 		goto out_unlock;
132 	}
133 
134 	ns->id = id;
135 
136 	if (!info->attrs[IOAM6_ATTR_NS_DATA])
137 		data32 = IOAM6_U32_UNAVAILABLE;
138 	else
139 		data32 = nla_get_u32(info->attrs[IOAM6_ATTR_NS_DATA]);
140 
141 	if (!info->attrs[IOAM6_ATTR_NS_DATA_WIDE])
142 		data64 = IOAM6_U64_UNAVAILABLE;
143 	else
144 		data64 = nla_get_u64(info->attrs[IOAM6_ATTR_NS_DATA_WIDE]);
145 
146 	ns->data = cpu_to_be32(data32);
147 	ns->data_wide = cpu_to_be64(data64);
148 
149 	err = rhashtable_lookup_insert_fast(&nsdata->namespaces, &ns->head,
150 					    rht_ns_params);
151 	if (err)
152 		kfree(ns);
153 
154 out_unlock:
155 	mutex_unlock(&nsdata->lock);
156 	return err;
157 }
158 
159 static int ioam6_genl_delns(struct sk_buff *skb, struct genl_info *info)
160 {
161 	struct ioam6_pernet_data *nsdata;
162 	struct ioam6_namespace *ns;
163 	struct ioam6_schema *sc;
164 	__be16 id;
165 	int err;
166 
167 	if (!info->attrs[IOAM6_ATTR_NS_ID])
168 		return -EINVAL;
169 
170 	id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID]));
171 	nsdata = ioam6_pernet(genl_info_net(info));
172 
173 	mutex_lock(&nsdata->lock);
174 
175 	ns = rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params);
176 	if (!ns) {
177 		err = -ENOENT;
178 		goto out_unlock;
179 	}
180 
181 	sc = rcu_dereference_protected(ns->schema,
182 				       lockdep_is_held(&nsdata->lock));
183 
184 	err = rhashtable_remove_fast(&nsdata->namespaces, &ns->head,
185 				     rht_ns_params);
186 	if (err)
187 		goto out_unlock;
188 
189 	if (sc)
190 		rcu_assign_pointer(sc->ns, NULL);
191 
192 	ioam6_ns_release(ns);
193 
194 out_unlock:
195 	mutex_unlock(&nsdata->lock);
196 	return err;
197 }
198 
199 static int __ioam6_genl_dumpns_element(struct ioam6_namespace *ns,
200 				       u32 portid,
201 				       u32 seq,
202 				       u32 flags,
203 				       struct sk_buff *skb,
204 				       u8 cmd)
205 {
206 	struct ioam6_schema *sc;
207 	u64 data64;
208 	u32 data32;
209 	void *hdr;
210 
211 	hdr = genlmsg_put(skb, portid, seq, &ioam6_genl_family, flags, cmd);
212 	if (!hdr)
213 		return -ENOMEM;
214 
215 	data32 = be32_to_cpu(ns->data);
216 	data64 = be64_to_cpu(ns->data_wide);
217 
218 	if (nla_put_u16(skb, IOAM6_ATTR_NS_ID, be16_to_cpu(ns->id)) ||
219 	    (data32 != IOAM6_U32_UNAVAILABLE &&
220 	     nla_put_u32(skb, IOAM6_ATTR_NS_DATA, data32)) ||
221 	    (data64 != IOAM6_U64_UNAVAILABLE &&
222 	     nla_put_u64_64bit(skb, IOAM6_ATTR_NS_DATA_WIDE,
223 			       data64, IOAM6_ATTR_PAD)))
224 		goto nla_put_failure;
225 
226 	rcu_read_lock();
227 
228 	sc = rcu_dereference(ns->schema);
229 	if (sc && nla_put_u32(skb, IOAM6_ATTR_SC_ID, sc->id)) {
230 		rcu_read_unlock();
231 		goto nla_put_failure;
232 	}
233 
234 	rcu_read_unlock();
235 
236 	genlmsg_end(skb, hdr);
237 	return 0;
238 
239 nla_put_failure:
240 	genlmsg_cancel(skb, hdr);
241 	return -EMSGSIZE;
242 }
243 
244 static int ioam6_genl_dumpns_start(struct netlink_callback *cb)
245 {
246 	struct ioam6_pernet_data *nsdata = ioam6_pernet(sock_net(cb->skb->sk));
247 	struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
248 
249 	if (!iter) {
250 		iter = kmalloc(sizeof(*iter), GFP_KERNEL);
251 		if (!iter)
252 			return -ENOMEM;
253 
254 		cb->args[0] = (long)iter;
255 	}
256 
257 	rhashtable_walk_enter(&nsdata->namespaces, iter);
258 
259 	return 0;
260 }
261 
262 static int ioam6_genl_dumpns_done(struct netlink_callback *cb)
263 {
264 	struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
265 
266 	rhashtable_walk_exit(iter);
267 	kfree(iter);
268 
269 	return 0;
270 }
271 
272 static int ioam6_genl_dumpns(struct sk_buff *skb, struct netlink_callback *cb)
273 {
274 	struct rhashtable_iter *iter;
275 	struct ioam6_namespace *ns;
276 	int err;
277 
278 	iter = (struct rhashtable_iter *)cb->args[0];
279 	rhashtable_walk_start(iter);
280 
281 	for (;;) {
282 		ns = rhashtable_walk_next(iter);
283 
284 		if (IS_ERR(ns)) {
285 			if (PTR_ERR(ns) == -EAGAIN)
286 				continue;
287 			err = PTR_ERR(ns);
288 			goto done;
289 		} else if (!ns) {
290 			break;
291 		}
292 
293 		err = __ioam6_genl_dumpns_element(ns,
294 						  NETLINK_CB(cb->skb).portid,
295 						  cb->nlh->nlmsg_seq,
296 						  NLM_F_MULTI,
297 						  skb,
298 						  IOAM6_CMD_DUMP_NAMESPACES);
299 		if (err)
300 			goto done;
301 	}
302 
303 	err = skb->len;
304 
305 done:
306 	rhashtable_walk_stop(iter);
307 	return err;
308 }
309 
310 static int ioam6_genl_addsc(struct sk_buff *skb, struct genl_info *info)
311 {
312 	struct ioam6_pernet_data *nsdata;
313 	int len, len_aligned, err;
314 	struct ioam6_schema *sc;
315 	u32 id;
316 
317 	if (!info->attrs[IOAM6_ATTR_SC_ID] || !info->attrs[IOAM6_ATTR_SC_DATA])
318 		return -EINVAL;
319 
320 	id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]);
321 	nsdata = ioam6_pernet(genl_info_net(info));
322 
323 	mutex_lock(&nsdata->lock);
324 
325 	sc = rhashtable_lookup_fast(&nsdata->schemas, &id, rht_sc_params);
326 	if (sc) {
327 		err = -EEXIST;
328 		goto out_unlock;
329 	}
330 
331 	len = nla_len(info->attrs[IOAM6_ATTR_SC_DATA]);
332 	len_aligned = ALIGN(len, 4);
333 
334 	sc = kzalloc(sizeof(*sc) + len_aligned, GFP_KERNEL);
335 	if (!sc) {
336 		err = -ENOMEM;
337 		goto out_unlock;
338 	}
339 
340 	sc->id = id;
341 	sc->len = len_aligned;
342 	sc->hdr = cpu_to_be32(sc->id | ((u8)(sc->len / 4) << 24));
343 	nla_memcpy(sc->data, info->attrs[IOAM6_ATTR_SC_DATA], len);
344 
345 	err = rhashtable_lookup_insert_fast(&nsdata->schemas, &sc->head,
346 					    rht_sc_params);
347 	if (err)
348 		goto free_sc;
349 
350 out_unlock:
351 	mutex_unlock(&nsdata->lock);
352 	return err;
353 free_sc:
354 	kfree(sc);
355 	goto out_unlock;
356 }
357 
358 static int ioam6_genl_delsc(struct sk_buff *skb, struct genl_info *info)
359 {
360 	struct ioam6_pernet_data *nsdata;
361 	struct ioam6_namespace *ns;
362 	struct ioam6_schema *sc;
363 	int err;
364 	u32 id;
365 
366 	if (!info->attrs[IOAM6_ATTR_SC_ID])
367 		return -EINVAL;
368 
369 	id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]);
370 	nsdata = ioam6_pernet(genl_info_net(info));
371 
372 	mutex_lock(&nsdata->lock);
373 
374 	sc = rhashtable_lookup_fast(&nsdata->schemas, &id, rht_sc_params);
375 	if (!sc) {
376 		err = -ENOENT;
377 		goto out_unlock;
378 	}
379 
380 	ns = rcu_dereference_protected(sc->ns, lockdep_is_held(&nsdata->lock));
381 
382 	err = rhashtable_remove_fast(&nsdata->schemas, &sc->head,
383 				     rht_sc_params);
384 	if (err)
385 		goto out_unlock;
386 
387 	if (ns)
388 		rcu_assign_pointer(ns->schema, NULL);
389 
390 	ioam6_sc_release(sc);
391 
392 out_unlock:
393 	mutex_unlock(&nsdata->lock);
394 	return err;
395 }
396 
397 static int __ioam6_genl_dumpsc_element(struct ioam6_schema *sc,
398 				       u32 portid, u32 seq, u32 flags,
399 				       struct sk_buff *skb, u8 cmd)
400 {
401 	struct ioam6_namespace *ns;
402 	void *hdr;
403 
404 	hdr = genlmsg_put(skb, portid, seq, &ioam6_genl_family, flags, cmd);
405 	if (!hdr)
406 		return -ENOMEM;
407 
408 	if (nla_put_u32(skb, IOAM6_ATTR_SC_ID, sc->id) ||
409 	    nla_put(skb, IOAM6_ATTR_SC_DATA, sc->len, sc->data))
410 		goto nla_put_failure;
411 
412 	rcu_read_lock();
413 
414 	ns = rcu_dereference(sc->ns);
415 	if (ns && nla_put_u16(skb, IOAM6_ATTR_NS_ID, be16_to_cpu(ns->id))) {
416 		rcu_read_unlock();
417 		goto nla_put_failure;
418 	}
419 
420 	rcu_read_unlock();
421 
422 	genlmsg_end(skb, hdr);
423 	return 0;
424 
425 nla_put_failure:
426 	genlmsg_cancel(skb, hdr);
427 	return -EMSGSIZE;
428 }
429 
430 static int ioam6_genl_dumpsc_start(struct netlink_callback *cb)
431 {
432 	struct ioam6_pernet_data *nsdata = ioam6_pernet(sock_net(cb->skb->sk));
433 	struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
434 
435 	if (!iter) {
436 		iter = kmalloc(sizeof(*iter), GFP_KERNEL);
437 		if (!iter)
438 			return -ENOMEM;
439 
440 		cb->args[0] = (long)iter;
441 	}
442 
443 	rhashtable_walk_enter(&nsdata->schemas, iter);
444 
445 	return 0;
446 }
447 
448 static int ioam6_genl_dumpsc_done(struct netlink_callback *cb)
449 {
450 	struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0];
451 
452 	rhashtable_walk_exit(iter);
453 	kfree(iter);
454 
455 	return 0;
456 }
457 
458 static int ioam6_genl_dumpsc(struct sk_buff *skb, struct netlink_callback *cb)
459 {
460 	struct rhashtable_iter *iter;
461 	struct ioam6_schema *sc;
462 	int err;
463 
464 	iter = (struct rhashtable_iter *)cb->args[0];
465 	rhashtable_walk_start(iter);
466 
467 	for (;;) {
468 		sc = rhashtable_walk_next(iter);
469 
470 		if (IS_ERR(sc)) {
471 			if (PTR_ERR(sc) == -EAGAIN)
472 				continue;
473 			err = PTR_ERR(sc);
474 			goto done;
475 		} else if (!sc) {
476 			break;
477 		}
478 
479 		err = __ioam6_genl_dumpsc_element(sc,
480 						  NETLINK_CB(cb->skb).portid,
481 						  cb->nlh->nlmsg_seq,
482 						  NLM_F_MULTI,
483 						  skb,
484 						  IOAM6_CMD_DUMP_SCHEMAS);
485 		if (err)
486 			goto done;
487 	}
488 
489 	err = skb->len;
490 
491 done:
492 	rhashtable_walk_stop(iter);
493 	return err;
494 }
495 
496 static int ioam6_genl_ns_set_schema(struct sk_buff *skb, struct genl_info *info)
497 {
498 	struct ioam6_namespace *ns, *ns_ref;
499 	struct ioam6_schema *sc, *sc_ref;
500 	struct ioam6_pernet_data *nsdata;
501 	__be16 ns_id;
502 	u32 sc_id;
503 	int err;
504 
505 	if (!info->attrs[IOAM6_ATTR_NS_ID] ||
506 	    (!info->attrs[IOAM6_ATTR_SC_ID] &&
507 	     !info->attrs[IOAM6_ATTR_SC_NONE]))
508 		return -EINVAL;
509 
510 	ns_id = cpu_to_be16(nla_get_u16(info->attrs[IOAM6_ATTR_NS_ID]));
511 	nsdata = ioam6_pernet(genl_info_net(info));
512 
513 	mutex_lock(&nsdata->lock);
514 
515 	ns = rhashtable_lookup_fast(&nsdata->namespaces, &ns_id, rht_ns_params);
516 	if (!ns) {
517 		err = -ENOENT;
518 		goto out_unlock;
519 	}
520 
521 	if (info->attrs[IOAM6_ATTR_SC_NONE]) {
522 		sc = NULL;
523 	} else {
524 		sc_id = nla_get_u32(info->attrs[IOAM6_ATTR_SC_ID]);
525 		sc = rhashtable_lookup_fast(&nsdata->schemas, &sc_id,
526 					    rht_sc_params);
527 		if (!sc) {
528 			err = -ENOENT;
529 			goto out_unlock;
530 		}
531 	}
532 
533 	sc_ref = rcu_dereference_protected(ns->schema,
534 					   lockdep_is_held(&nsdata->lock));
535 	if (sc_ref)
536 		rcu_assign_pointer(sc_ref->ns, NULL);
537 	rcu_assign_pointer(ns->schema, sc);
538 
539 	if (sc) {
540 		ns_ref = rcu_dereference_protected(sc->ns,
541 						   lockdep_is_held(&nsdata->lock));
542 		if (ns_ref)
543 			rcu_assign_pointer(ns_ref->schema, NULL);
544 		rcu_assign_pointer(sc->ns, ns);
545 	}
546 
547 	err = 0;
548 
549 out_unlock:
550 	mutex_unlock(&nsdata->lock);
551 	return err;
552 }
553 
554 static const struct genl_ops ioam6_genl_ops[] = {
555 	{
556 		.cmd	= IOAM6_CMD_ADD_NAMESPACE,
557 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
558 		.doit	= ioam6_genl_addns,
559 		.flags	= GENL_ADMIN_PERM,
560 		.policy	= ioam6_genl_policy_addns,
561 		.maxattr = ARRAY_SIZE(ioam6_genl_policy_addns) - 1,
562 	},
563 	{
564 		.cmd	= IOAM6_CMD_DEL_NAMESPACE,
565 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
566 		.doit	= ioam6_genl_delns,
567 		.flags	= GENL_ADMIN_PERM,
568 		.policy	= ioam6_genl_policy_delns,
569 		.maxattr = ARRAY_SIZE(ioam6_genl_policy_delns) - 1,
570 	},
571 	{
572 		.cmd	= IOAM6_CMD_DUMP_NAMESPACES,
573 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
574 		.start	= ioam6_genl_dumpns_start,
575 		.dumpit	= ioam6_genl_dumpns,
576 		.done	= ioam6_genl_dumpns_done,
577 		.flags	= GENL_ADMIN_PERM,
578 	},
579 	{
580 		.cmd	= IOAM6_CMD_ADD_SCHEMA,
581 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
582 		.doit	= ioam6_genl_addsc,
583 		.flags	= GENL_ADMIN_PERM,
584 		.policy	= ioam6_genl_policy_addsc,
585 		.maxattr = ARRAY_SIZE(ioam6_genl_policy_addsc) - 1,
586 	},
587 	{
588 		.cmd	= IOAM6_CMD_DEL_SCHEMA,
589 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
590 		.doit	= ioam6_genl_delsc,
591 		.flags	= GENL_ADMIN_PERM,
592 		.policy	= ioam6_genl_policy_delsc,
593 		.maxattr = ARRAY_SIZE(ioam6_genl_policy_delsc) - 1,
594 	},
595 	{
596 		.cmd	= IOAM6_CMD_DUMP_SCHEMAS,
597 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
598 		.start	= ioam6_genl_dumpsc_start,
599 		.dumpit	= ioam6_genl_dumpsc,
600 		.done	= ioam6_genl_dumpsc_done,
601 		.flags	= GENL_ADMIN_PERM,
602 	},
603 	{
604 		.cmd	= IOAM6_CMD_NS_SET_SCHEMA,
605 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
606 		.doit	= ioam6_genl_ns_set_schema,
607 		.flags	= GENL_ADMIN_PERM,
608 		.policy	= ioam6_genl_policy_ns_sc,
609 		.maxattr = ARRAY_SIZE(ioam6_genl_policy_ns_sc) - 1,
610 	},
611 };
612 
613 static struct genl_family ioam6_genl_family __ro_after_init = {
614 	.name		= IOAM6_GENL_NAME,
615 	.version	= IOAM6_GENL_VERSION,
616 	.netnsok	= true,
617 	.parallel_ops	= true,
618 	.ops		= ioam6_genl_ops,
619 	.n_ops		= ARRAY_SIZE(ioam6_genl_ops),
620 	.module		= THIS_MODULE,
621 };
622 
623 struct ioam6_namespace *ioam6_namespace(struct net *net, __be16 id)
624 {
625 	struct ioam6_pernet_data *nsdata = ioam6_pernet(net);
626 
627 	return rhashtable_lookup_fast(&nsdata->namespaces, &id, rht_ns_params);
628 }
629 
630 static void __ioam6_fill_trace_data(struct sk_buff *skb,
631 				    struct ioam6_namespace *ns,
632 				    struct ioam6_trace_hdr *trace,
633 				    struct ioam6_schema *sc,
634 				    u8 sclen)
635 {
636 	struct __kernel_sock_timeval ts;
637 	u64 raw64;
638 	u32 raw32;
639 	u16 raw16;
640 	u8 *data;
641 	u8 byte;
642 
643 	data = trace->data + trace->remlen * 4 - trace->nodelen * 4 - sclen * 4;
644 
645 	/* hop_lim and node_id */
646 	if (trace->type.bit0) {
647 		byte = ipv6_hdr(skb)->hop_limit;
648 		if (skb->dev)
649 			byte--;
650 
651 		raw32 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id;
652 
653 		*(__be32 *)data = cpu_to_be32((byte << 24) | raw32);
654 		data += sizeof(__be32);
655 	}
656 
657 	/* ingress_if_id and egress_if_id */
658 	if (trace->type.bit1) {
659 		if (!skb->dev)
660 			raw16 = IOAM6_U16_UNAVAILABLE;
661 		else
662 			raw16 = (__force u16)__in6_dev_get(skb->dev)->cnf.ioam6_id;
663 
664 		*(__be16 *)data = cpu_to_be16(raw16);
665 		data += sizeof(__be16);
666 
667 		if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
668 			raw16 = IOAM6_U16_UNAVAILABLE;
669 		else
670 			raw16 = (__force u16)__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id;
671 
672 		*(__be16 *)data = cpu_to_be16(raw16);
673 		data += sizeof(__be16);
674 	}
675 
676 	/* timestamp seconds */
677 	if (trace->type.bit2) {
678 		if (!skb->dev) {
679 			*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
680 		} else {
681 			if (!skb->tstamp)
682 				__net_timestamp(skb);
683 
684 			skb_get_new_timestamp(skb, &ts);
685 			*(__be32 *)data = cpu_to_be32((u32)ts.tv_sec);
686 		}
687 		data += sizeof(__be32);
688 	}
689 
690 	/* timestamp subseconds */
691 	if (trace->type.bit3) {
692 		if (!skb->dev) {
693 			*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
694 		} else {
695 			if (!skb->tstamp)
696 				__net_timestamp(skb);
697 
698 			if (!trace->type.bit2)
699 				skb_get_new_timestamp(skb, &ts);
700 
701 			*(__be32 *)data = cpu_to_be32((u32)ts.tv_usec);
702 		}
703 		data += sizeof(__be32);
704 	}
705 
706 	/* transit delay */
707 	if (trace->type.bit4) {
708 		*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
709 		data += sizeof(__be32);
710 	}
711 
712 	/* namespace data */
713 	if (trace->type.bit5) {
714 		*(__be32 *)data = ns->data;
715 		data += sizeof(__be32);
716 	}
717 
718 	/* queue depth */
719 	if (trace->type.bit6) {
720 		*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
721 		data += sizeof(__be32);
722 	}
723 
724 	/* checksum complement */
725 	if (trace->type.bit7) {
726 		*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
727 		data += sizeof(__be32);
728 	}
729 
730 	/* hop_lim and node_id (wide) */
731 	if (trace->type.bit8) {
732 		byte = ipv6_hdr(skb)->hop_limit;
733 		if (skb->dev)
734 			byte--;
735 
736 		raw64 = dev_net(skb_dst(skb)->dev)->ipv6.sysctl.ioam6_id_wide;
737 
738 		*(__be64 *)data = cpu_to_be64(((u64)byte << 56) | raw64);
739 		data += sizeof(__be64);
740 	}
741 
742 	/* ingress_if_id and egress_if_id (wide) */
743 	if (trace->type.bit9) {
744 		if (!skb->dev)
745 			raw32 = IOAM6_U32_UNAVAILABLE;
746 		else
747 			raw32 = __in6_dev_get(skb->dev)->cnf.ioam6_id_wide;
748 
749 		*(__be32 *)data = cpu_to_be32(raw32);
750 		data += sizeof(__be32);
751 
752 		if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
753 			raw32 = IOAM6_U32_UNAVAILABLE;
754 		else
755 			raw32 = __in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide;
756 
757 		*(__be32 *)data = cpu_to_be32(raw32);
758 		data += sizeof(__be32);
759 	}
760 
761 	/* namespace data (wide) */
762 	if (trace->type.bit10) {
763 		*(__be64 *)data = ns->data_wide;
764 		data += sizeof(__be64);
765 	}
766 
767 	/* buffer occupancy */
768 	if (trace->type.bit11) {
769 		*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE);
770 		data += sizeof(__be32);
771 	}
772 
773 	/* opaque state snapshot */
774 	if (trace->type.bit22) {
775 		if (!sc) {
776 			*(__be32 *)data = cpu_to_be32(IOAM6_U32_UNAVAILABLE >> 8);
777 		} else {
778 			*(__be32 *)data = sc->hdr;
779 			data += sizeof(__be32);
780 
781 			memcpy(data, sc->data, sc->len);
782 		}
783 	}
784 }
785 
786 /* called with rcu_read_lock() */
787 void ioam6_fill_trace_data(struct sk_buff *skb,
788 			   struct ioam6_namespace *ns,
789 			   struct ioam6_trace_hdr *trace)
790 {
791 	struct ioam6_schema *sc;
792 	u8 sclen = 0;
793 
794 	/* Skip if Overflow flag is set OR
795 	 * if an unknown type (bit 12-21) is set
796 	 */
797 	if (trace->overflow ||
798 	    trace->type.bit12 | trace->type.bit13 | trace->type.bit14 |
799 	    trace->type.bit15 | trace->type.bit16 | trace->type.bit17 |
800 	    trace->type.bit18 | trace->type.bit19 | trace->type.bit20 |
801 	    trace->type.bit21) {
802 		return;
803 	}
804 
805 	/* NodeLen does not include Opaque State Snapshot length. We need to
806 	 * take it into account if the corresponding bit is set (bit 22) and
807 	 * if the current IOAM namespace has an active schema attached to it
808 	 */
809 	sc = rcu_dereference(ns->schema);
810 	if (trace->type.bit22) {
811 		sclen = sizeof_field(struct ioam6_schema, hdr) / 4;
812 
813 		if (sc)
814 			sclen += sc->len / 4;
815 	}
816 
817 	/* If there is no space remaining, we set the Overflow flag and we
818 	 * skip without filling the trace
819 	 */
820 	if (!trace->remlen || trace->remlen < trace->nodelen + sclen) {
821 		trace->overflow = 1;
822 		return;
823 	}
824 
825 	__ioam6_fill_trace_data(skb, ns, trace, sc, sclen);
826 	trace->remlen -= trace->nodelen + sclen;
827 }
828 
829 static int __net_init ioam6_net_init(struct net *net)
830 {
831 	struct ioam6_pernet_data *nsdata;
832 	int err = -ENOMEM;
833 
834 	nsdata = kzalloc(sizeof(*nsdata), GFP_KERNEL);
835 	if (!nsdata)
836 		goto out;
837 
838 	mutex_init(&nsdata->lock);
839 	net->ipv6.ioam6_data = nsdata;
840 
841 	err = rhashtable_init(&nsdata->namespaces, &rht_ns_params);
842 	if (err)
843 		goto free_nsdata;
844 
845 	err = rhashtable_init(&nsdata->schemas, &rht_sc_params);
846 	if (err)
847 		goto free_rht_ns;
848 
849 out:
850 	return err;
851 free_rht_ns:
852 	rhashtable_destroy(&nsdata->namespaces);
853 free_nsdata:
854 	kfree(nsdata);
855 	net->ipv6.ioam6_data = NULL;
856 	goto out;
857 }
858 
859 static void __net_exit ioam6_net_exit(struct net *net)
860 {
861 	struct ioam6_pernet_data *nsdata = ioam6_pernet(net);
862 
863 	rhashtable_free_and_destroy(&nsdata->namespaces, ioam6_free_ns, NULL);
864 	rhashtable_free_and_destroy(&nsdata->schemas, ioam6_free_sc, NULL);
865 
866 	kfree(nsdata);
867 }
868 
869 static struct pernet_operations ioam6_net_ops = {
870 	.init = ioam6_net_init,
871 	.exit = ioam6_net_exit,
872 };
873 
874 int __init ioam6_init(void)
875 {
876 	int err = register_pernet_subsys(&ioam6_net_ops);
877 	if (err)
878 		goto out;
879 
880 	err = genl_register_family(&ioam6_genl_family);
881 	if (err)
882 		goto out_unregister_pernet_subsys;
883 
884 #ifdef CONFIG_IPV6_IOAM6_LWTUNNEL
885 	err = ioam6_iptunnel_init();
886 	if (err)
887 		goto out_unregister_genl;
888 #endif
889 
890 	pr_info("In-situ OAM (IOAM) with IPv6\n");
891 
892 out:
893 	return err;
894 #ifdef CONFIG_IPV6_IOAM6_LWTUNNEL
895 out_unregister_genl:
896 	genl_unregister_family(&ioam6_genl_family);
897 #endif
898 out_unregister_pernet_subsys:
899 	unregister_pernet_subsys(&ioam6_net_ops);
900 	goto out;
901 }
902 
903 void ioam6_exit(void)
904 {
905 #ifdef CONFIG_IPV6_IOAM6_LWTUNNEL
906 	ioam6_iptunnel_exit();
907 #endif
908 	genl_unregister_family(&ioam6_genl_family);
909 	unregister_pernet_subsys(&ioam6_net_ops);
910 }
911