1 #include <linux/jhash.h> 2 #include <linux/netfilter.h> 3 #include <linux/rcupdate.h> 4 #include <linux/rhashtable.h> 5 #include <linux/vmalloc.h> 6 #include <net/genetlink.h> 7 #include <net/ila.h> 8 #include <net/netns/generic.h> 9 #include <uapi/linux/genetlink.h> 10 #include "ila.h" 11 12 struct ila_xlat_params { 13 struct ila_params ip; 14 int ifindex; 15 }; 16 17 struct ila_map { 18 struct ila_xlat_params xp; 19 struct rhash_head node; 20 struct ila_map __rcu *next; 21 struct rcu_head rcu; 22 }; 23 24 static unsigned int ila_net_id; 25 26 struct ila_net { 27 struct rhashtable rhash_table; 28 spinlock_t *locks; /* Bucket locks for entry manipulation */ 29 unsigned int locks_mask; 30 bool hooks_registered; 31 }; 32 33 #define LOCKS_PER_CPU 10 34 35 static int alloc_ila_locks(struct ila_net *ilan) 36 { 37 unsigned int i, size; 38 unsigned int nr_pcpus = num_possible_cpus(); 39 40 nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL); 41 size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU); 42 43 if (sizeof(spinlock_t) != 0) { 44 #ifdef CONFIG_NUMA 45 if (size * sizeof(spinlock_t) > PAGE_SIZE) 46 ilan->locks = vmalloc(size * sizeof(spinlock_t)); 47 else 48 #endif 49 ilan->locks = kmalloc_array(size, sizeof(spinlock_t), 50 GFP_KERNEL); 51 if (!ilan->locks) 52 return -ENOMEM; 53 for (i = 0; i < size; i++) 54 spin_lock_init(&ilan->locks[i]); 55 } 56 ilan->locks_mask = size - 1; 57 58 return 0; 59 } 60 61 static u32 hashrnd __read_mostly; 62 static __always_inline void __ila_hash_secret_init(void) 63 { 64 net_get_random_once(&hashrnd, sizeof(hashrnd)); 65 } 66 67 static inline u32 ila_locator_hash(struct ila_locator loc) 68 { 69 u32 *v = (u32 *)loc.v32; 70 71 return jhash_2words(v[0], v[1], hashrnd); 72 } 73 74 static inline spinlock_t *ila_get_lock(struct ila_net *ilan, 75 struct ila_locator loc) 76 { 77 return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask]; 78 } 79 80 static inline int ila_cmp_wildcards(struct ila_map *ila, 81 struct ila_addr *iaddr, int ifindex) 82 { 83 return (ila->xp.ifindex && ila->xp.ifindex != ifindex); 84 } 85 86 static inline int ila_cmp_params(struct ila_map *ila, 87 struct ila_xlat_params *xp) 88 { 89 return (ila->xp.ifindex != xp->ifindex); 90 } 91 92 static int ila_cmpfn(struct rhashtable_compare_arg *arg, 93 const void *obj) 94 { 95 const struct ila_map *ila = obj; 96 97 return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key); 98 } 99 100 static inline int ila_order(struct ila_map *ila) 101 { 102 int score = 0; 103 104 if (ila->xp.ifindex) 105 score += 1 << 1; 106 107 return score; 108 } 109 110 static const struct rhashtable_params rht_params = { 111 .nelem_hint = 1024, 112 .head_offset = offsetof(struct ila_map, node), 113 .key_offset = offsetof(struct ila_map, xp.ip.locator_match), 114 .key_len = sizeof(u64), /* identifier */ 115 .max_size = 1048576, 116 .min_size = 256, 117 .automatic_shrinking = true, 118 .obj_cmpfn = ila_cmpfn, 119 }; 120 121 static struct genl_family ila_nl_family = { 122 .id = GENL_ID_GENERATE, 123 .hdrsize = 0, 124 .name = ILA_GENL_NAME, 125 .version = ILA_GENL_VERSION, 126 .maxattr = ILA_ATTR_MAX, 127 .netnsok = true, 128 .parallel_ops = true, 129 }; 130 131 static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = { 132 [ILA_ATTR_LOCATOR] = { .type = NLA_U64, }, 133 [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, }, 134 [ILA_ATTR_IFINDEX] = { .type = NLA_U32, }, 135 [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, }, 136 }; 137 138 static int parse_nl_config(struct genl_info *info, 139 struct ila_xlat_params *xp) 140 { 141 memset(xp, 0, sizeof(*xp)); 142 143 if (info->attrs[ILA_ATTR_LOCATOR]) 144 xp->ip.locator.v64 = (__force __be64)nla_get_u64( 145 info->attrs[ILA_ATTR_LOCATOR]); 146 147 if (info->attrs[ILA_ATTR_LOCATOR_MATCH]) 148 xp->ip.locator_match.v64 = (__force __be64)nla_get_u64( 149 info->attrs[ILA_ATTR_LOCATOR_MATCH]); 150 151 if (info->attrs[ILA_ATTR_CSUM_MODE]) 152 xp->ip.csum_mode = nla_get_u8(info->attrs[ILA_ATTR_CSUM_MODE]); 153 154 if (info->attrs[ILA_ATTR_IFINDEX]) 155 xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]); 156 157 return 0; 158 } 159 160 /* Must be called with rcu readlock */ 161 static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr, 162 int ifindex, 163 struct ila_net *ilan) 164 { 165 struct ila_map *ila; 166 167 ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc, 168 rht_params); 169 while (ila) { 170 if (!ila_cmp_wildcards(ila, iaddr, ifindex)) 171 return ila; 172 ila = rcu_access_pointer(ila->next); 173 } 174 175 return NULL; 176 } 177 178 /* Must be called with rcu readlock */ 179 static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp, 180 struct ila_net *ilan) 181 { 182 struct ila_map *ila; 183 184 ila = rhashtable_lookup_fast(&ilan->rhash_table, 185 &xp->ip.locator_match, 186 rht_params); 187 while (ila) { 188 if (!ila_cmp_params(ila, xp)) 189 return ila; 190 ila = rcu_access_pointer(ila->next); 191 } 192 193 return NULL; 194 } 195 196 static inline void ila_release(struct ila_map *ila) 197 { 198 kfree_rcu(ila, rcu); 199 } 200 201 static void ila_free_cb(void *ptr, void *arg) 202 { 203 struct ila_map *ila = (struct ila_map *)ptr, *next; 204 205 /* Assume rcu_readlock held */ 206 while (ila) { 207 next = rcu_access_pointer(ila->next); 208 ila_release(ila); 209 ila = next; 210 } 211 } 212 213 static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral); 214 215 static unsigned int 216 ila_nf_input(void *priv, 217 struct sk_buff *skb, 218 const struct nf_hook_state *state) 219 { 220 ila_xlat_addr(skb, false); 221 return NF_ACCEPT; 222 } 223 224 static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = { 225 { 226 .hook = ila_nf_input, 227 .pf = NFPROTO_IPV6, 228 .hooknum = NF_INET_PRE_ROUTING, 229 .priority = -1, 230 }, 231 }; 232 233 static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp) 234 { 235 struct ila_net *ilan = net_generic(net, ila_net_id); 236 struct ila_map *ila, *head; 237 spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); 238 int err = 0, order; 239 240 if (!ilan->hooks_registered) { 241 /* We defer registering net hooks in the namespace until the 242 * first mapping is added. 243 */ 244 err = nf_register_net_hooks(net, ila_nf_hook_ops, 245 ARRAY_SIZE(ila_nf_hook_ops)); 246 if (err) 247 return err; 248 249 ilan->hooks_registered = true; 250 } 251 252 ila = kzalloc(sizeof(*ila), GFP_KERNEL); 253 if (!ila) 254 return -ENOMEM; 255 256 ila_init_saved_csum(&xp->ip); 257 258 ila->xp = *xp; 259 260 order = ila_order(ila); 261 262 spin_lock(lock); 263 264 head = rhashtable_lookup_fast(&ilan->rhash_table, 265 &xp->ip.locator_match, 266 rht_params); 267 if (!head) { 268 /* New entry for the rhash_table */ 269 err = rhashtable_lookup_insert_fast(&ilan->rhash_table, 270 &ila->node, rht_params); 271 } else { 272 struct ila_map *tila = head, *prev = NULL; 273 274 do { 275 if (!ila_cmp_params(tila, xp)) { 276 err = -EEXIST; 277 goto out; 278 } 279 280 if (order > ila_order(tila)) 281 break; 282 283 prev = tila; 284 tila = rcu_dereference_protected(tila->next, 285 lockdep_is_held(lock)); 286 } while (tila); 287 288 if (prev) { 289 /* Insert in sub list of head */ 290 RCU_INIT_POINTER(ila->next, tila); 291 rcu_assign_pointer(prev->next, ila); 292 } else { 293 /* Make this ila new head */ 294 RCU_INIT_POINTER(ila->next, head); 295 err = rhashtable_replace_fast(&ilan->rhash_table, 296 &head->node, 297 &ila->node, rht_params); 298 if (err) 299 goto out; 300 } 301 } 302 303 out: 304 spin_unlock(lock); 305 306 if (err) 307 kfree(ila); 308 309 return err; 310 } 311 312 static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp) 313 { 314 struct ila_net *ilan = net_generic(net, ila_net_id); 315 struct ila_map *ila, *head, *prev; 316 spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match); 317 int err = -ENOENT; 318 319 spin_lock(lock); 320 321 head = rhashtable_lookup_fast(&ilan->rhash_table, 322 &xp->ip.locator_match, rht_params); 323 ila = head; 324 325 prev = NULL; 326 327 while (ila) { 328 if (ila_cmp_params(ila, xp)) { 329 prev = ila; 330 ila = rcu_dereference_protected(ila->next, 331 lockdep_is_held(lock)); 332 continue; 333 } 334 335 err = 0; 336 337 if (prev) { 338 /* Not head, just delete from list */ 339 rcu_assign_pointer(prev->next, ila->next); 340 } else { 341 /* It is the head. If there is something in the 342 * sublist we need to make a new head. 343 */ 344 head = rcu_dereference_protected(ila->next, 345 lockdep_is_held(lock)); 346 if (head) { 347 /* Put first entry in the sublist into the 348 * table 349 */ 350 err = rhashtable_replace_fast( 351 &ilan->rhash_table, &ila->node, 352 &head->node, rht_params); 353 if (err) 354 goto out; 355 } else { 356 /* Entry no longer used */ 357 err = rhashtable_remove_fast(&ilan->rhash_table, 358 &ila->node, 359 rht_params); 360 } 361 } 362 363 ila_release(ila); 364 365 break; 366 } 367 368 out: 369 spin_unlock(lock); 370 371 return err; 372 } 373 374 static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info) 375 { 376 struct net *net = genl_info_net(info); 377 struct ila_xlat_params p; 378 int err; 379 380 err = parse_nl_config(info, &p); 381 if (err) 382 return err; 383 384 return ila_add_mapping(net, &p); 385 } 386 387 static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info) 388 { 389 struct net *net = genl_info_net(info); 390 struct ila_xlat_params xp; 391 int err; 392 393 err = parse_nl_config(info, &xp); 394 if (err) 395 return err; 396 397 ila_del_mapping(net, &xp); 398 399 return 0; 400 } 401 402 static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg) 403 { 404 if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR, 405 (__force u64)ila->xp.ip.locator.v64, 406 ILA_ATTR_PAD) || 407 nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH, 408 (__force u64)ila->xp.ip.locator_match.v64, 409 ILA_ATTR_PAD) || 410 nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) || 411 nla_put_u32(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode)) 412 return -1; 413 414 return 0; 415 } 416 417 static int ila_dump_info(struct ila_map *ila, 418 u32 portid, u32 seq, u32 flags, 419 struct sk_buff *skb, u8 cmd) 420 { 421 void *hdr; 422 423 hdr = genlmsg_put(skb, portid, seq, &ila_nl_family, flags, cmd); 424 if (!hdr) 425 return -ENOMEM; 426 427 if (ila_fill_info(ila, skb) < 0) 428 goto nla_put_failure; 429 430 genlmsg_end(skb, hdr); 431 return 0; 432 433 nla_put_failure: 434 genlmsg_cancel(skb, hdr); 435 return -EMSGSIZE; 436 } 437 438 static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info) 439 { 440 struct net *net = genl_info_net(info); 441 struct ila_net *ilan = net_generic(net, ila_net_id); 442 struct sk_buff *msg; 443 struct ila_xlat_params xp; 444 struct ila_map *ila; 445 int ret; 446 447 ret = parse_nl_config(info, &xp); 448 if (ret) 449 return ret; 450 451 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 452 if (!msg) 453 return -ENOMEM; 454 455 rcu_read_lock(); 456 457 ila = ila_lookup_by_params(&xp, ilan); 458 if (ila) { 459 ret = ila_dump_info(ila, 460 info->snd_portid, 461 info->snd_seq, 0, msg, 462 info->genlhdr->cmd); 463 } 464 465 rcu_read_unlock(); 466 467 if (ret < 0) 468 goto out_free; 469 470 return genlmsg_reply(msg, info); 471 472 out_free: 473 nlmsg_free(msg); 474 return ret; 475 } 476 477 struct ila_dump_iter { 478 struct rhashtable_iter rhiter; 479 }; 480 481 static int ila_nl_dump_start(struct netlink_callback *cb) 482 { 483 struct net *net = sock_net(cb->skb->sk); 484 struct ila_net *ilan = net_generic(net, ila_net_id); 485 struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; 486 487 return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter, 488 GFP_KERNEL); 489 } 490 491 static int ila_nl_dump_done(struct netlink_callback *cb) 492 { 493 struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; 494 495 rhashtable_walk_exit(&iter->rhiter); 496 497 return 0; 498 } 499 500 static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb) 501 { 502 struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args; 503 struct rhashtable_iter *rhiter = &iter->rhiter; 504 struct ila_map *ila; 505 int ret; 506 507 ret = rhashtable_walk_start(rhiter); 508 if (ret && ret != -EAGAIN) 509 goto done; 510 511 for (;;) { 512 ila = rhashtable_walk_next(rhiter); 513 514 if (IS_ERR(ila)) { 515 if (PTR_ERR(ila) == -EAGAIN) 516 continue; 517 ret = PTR_ERR(ila); 518 goto done; 519 } else if (!ila) { 520 break; 521 } 522 523 while (ila) { 524 ret = ila_dump_info(ila, NETLINK_CB(cb->skb).portid, 525 cb->nlh->nlmsg_seq, NLM_F_MULTI, 526 skb, ILA_CMD_GET); 527 if (ret) 528 goto done; 529 530 ila = rcu_access_pointer(ila->next); 531 } 532 } 533 534 ret = skb->len; 535 536 done: 537 rhashtable_walk_stop(rhiter); 538 return ret; 539 } 540 541 static const struct genl_ops ila_nl_ops[] = { 542 { 543 .cmd = ILA_CMD_ADD, 544 .doit = ila_nl_cmd_add_mapping, 545 .policy = ila_nl_policy, 546 .flags = GENL_ADMIN_PERM, 547 }, 548 { 549 .cmd = ILA_CMD_DEL, 550 .doit = ila_nl_cmd_del_mapping, 551 .policy = ila_nl_policy, 552 .flags = GENL_ADMIN_PERM, 553 }, 554 { 555 .cmd = ILA_CMD_GET, 556 .doit = ila_nl_cmd_get_mapping, 557 .start = ila_nl_dump_start, 558 .dumpit = ila_nl_dump, 559 .done = ila_nl_dump_done, 560 .policy = ila_nl_policy, 561 }, 562 }; 563 564 #define ILA_HASH_TABLE_SIZE 1024 565 566 static __net_init int ila_init_net(struct net *net) 567 { 568 int err; 569 struct ila_net *ilan = net_generic(net, ila_net_id); 570 571 err = alloc_ila_locks(ilan); 572 if (err) 573 return err; 574 575 rhashtable_init(&ilan->rhash_table, &rht_params); 576 577 return 0; 578 } 579 580 static __net_exit void ila_exit_net(struct net *net) 581 { 582 struct ila_net *ilan = net_generic(net, ila_net_id); 583 584 rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL); 585 586 kvfree(ilan->locks); 587 588 if (ilan->hooks_registered) 589 nf_unregister_net_hooks(net, ila_nf_hook_ops, 590 ARRAY_SIZE(ila_nf_hook_ops)); 591 } 592 593 static struct pernet_operations ila_net_ops = { 594 .init = ila_init_net, 595 .exit = ila_exit_net, 596 .id = &ila_net_id, 597 .size = sizeof(struct ila_net), 598 }; 599 600 static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral) 601 { 602 struct ila_map *ila; 603 struct ipv6hdr *ip6h = ipv6_hdr(skb); 604 struct net *net = dev_net(skb->dev); 605 struct ila_net *ilan = net_generic(net, ila_net_id); 606 struct ila_addr *iaddr = ila_a2i(&ip6h->daddr); 607 608 /* Assumes skb contains a valid IPv6 header that is pulled */ 609 610 if (!ila_addr_is_ila(iaddr)) { 611 /* Type indicates this is not an ILA address */ 612 return 0; 613 } 614 615 rcu_read_lock(); 616 617 ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan); 618 if (ila) 619 ila_update_ipv6_locator(skb, &ila->xp.ip, set_csum_neutral); 620 621 rcu_read_unlock(); 622 623 return 0; 624 } 625 626 int ila_xlat_init(void) 627 { 628 int ret; 629 630 ret = register_pernet_device(&ila_net_ops); 631 if (ret) 632 goto exit; 633 634 ret = genl_register_family_with_ops(&ila_nl_family, 635 ila_nl_ops); 636 if (ret < 0) 637 goto unregister; 638 639 return 0; 640 641 unregister: 642 unregister_pernet_device(&ila_net_ops); 643 exit: 644 return ret; 645 } 646 647 void ila_xlat_fini(void) 648 { 649 genl_unregister_family(&ila_nl_family); 650 unregister_pernet_device(&ila_net_ops); 651 } 652