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