1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */ 3 4 #include <linux/kernel.h> 5 #include <linux/types.h> 6 #include <linux/inetdevice.h> 7 #include <net/inet_dscp.h> 8 #include <net/switchdev.h> 9 #include <linux/rhashtable.h> 10 #include <net/nexthop.h> 11 #include <net/netevent.h> 12 13 #include "prestera.h" 14 #include "prestera_router_hw.h" 15 16 struct prestera_kern_fib_cache_key { 17 struct prestera_ip_addr addr; 18 u32 prefix_len; 19 u32 kern_tb_id; /* tb_id from kernel (not fixed) */ 20 }; 21 22 /* Subscribing on neighbours in kernel */ 23 struct prestera_kern_fib_cache { 24 struct prestera_kern_fib_cache_key key; 25 struct { 26 struct prestera_fib_key fib_key; 27 enum prestera_fib_type fib_type; 28 } lpm_info; /* hold prepared lpm info */ 29 /* Indicate if route is not overlapped by another table */ 30 struct rhash_head ht_node; /* node of prestera_router */ 31 union { 32 struct fib_notifier_info info; /* point to any of 4/6 */ 33 struct fib_entry_notifier_info fen4_info; 34 }; 35 bool reachable; 36 }; 37 38 static const struct rhashtable_params __prestera_kern_fib_cache_ht_params = { 39 .key_offset = offsetof(struct prestera_kern_fib_cache, key), 40 .head_offset = offsetof(struct prestera_kern_fib_cache, ht_node), 41 .key_len = sizeof(struct prestera_kern_fib_cache_key), 42 .automatic_shrinking = true, 43 }; 44 45 /* This util to be used, to convert kernel rules for default vr in hw_vr */ 46 static u32 prestera_fix_tb_id(u32 tb_id) 47 { 48 if (tb_id == RT_TABLE_UNSPEC || 49 tb_id == RT_TABLE_LOCAL || 50 tb_id == RT_TABLE_DEFAULT) 51 tb_id = RT_TABLE_MAIN; 52 53 return tb_id; 54 } 55 56 static void 57 prestera_util_fen_info2fib_cache_key(struct fib_notifier_info *info, 58 struct prestera_kern_fib_cache_key *key) 59 { 60 struct fib_entry_notifier_info *fen_info = 61 container_of(info, struct fib_entry_notifier_info, info); 62 63 memset(key, 0, sizeof(*key)); 64 key->addr.v = PRESTERA_IPV4; 65 key->addr.u.ipv4 = cpu_to_be32(fen_info->dst); 66 key->prefix_len = fen_info->dst_len; 67 key->kern_tb_id = fen_info->tb_id; 68 } 69 70 static unsigned char 71 prestera_kern_fib_info_type(struct fib_notifier_info *info) 72 { 73 struct fib6_entry_notifier_info *fen6_info; 74 struct fib_entry_notifier_info *fen4_info; 75 76 if (info->family == AF_INET) { 77 fen4_info = container_of(info, struct fib_entry_notifier_info, 78 info); 79 return fen4_info->fi->fib_type; 80 } else if (info->family == AF_INET6) { 81 fen6_info = container_of(info, struct fib6_entry_notifier_info, 82 info); 83 /* TODO: ECMP in ipv6 is several routes. 84 * Every route has single nh. 85 */ 86 return fen6_info->rt->fib6_type; 87 } 88 89 return RTN_UNSPEC; 90 } 91 92 static struct prestera_kern_fib_cache * 93 prestera_kern_fib_cache_find(struct prestera_switch *sw, 94 struct prestera_kern_fib_cache_key *key) 95 { 96 struct prestera_kern_fib_cache *fib_cache; 97 98 fib_cache = 99 rhashtable_lookup_fast(&sw->router->kern_fib_cache_ht, key, 100 __prestera_kern_fib_cache_ht_params); 101 return fib_cache; 102 } 103 104 static void 105 __prestera_kern_fib_cache_destruct(struct prestera_switch *sw, 106 struct prestera_kern_fib_cache *fib_cache) 107 { 108 fib_info_put(fib_cache->fen4_info.fi); 109 } 110 111 static void 112 prestera_kern_fib_cache_destroy(struct prestera_switch *sw, 113 struct prestera_kern_fib_cache *fib_cache) 114 { 115 rhashtable_remove_fast(&sw->router->kern_fib_cache_ht, 116 &fib_cache->ht_node, 117 __prestera_kern_fib_cache_ht_params); 118 __prestera_kern_fib_cache_destruct(sw, fib_cache); 119 kfree(fib_cache); 120 } 121 122 /* Operations on fi (offload, etc) must be wrapped in utils. 123 * This function just create storage. 124 */ 125 static struct prestera_kern_fib_cache * 126 prestera_kern_fib_cache_create(struct prestera_switch *sw, 127 struct prestera_kern_fib_cache_key *key, 128 struct fib_notifier_info *info) 129 { 130 struct fib_entry_notifier_info *fen_info = 131 container_of(info, struct fib_entry_notifier_info, info); 132 struct prestera_kern_fib_cache *fib_cache; 133 int err; 134 135 fib_cache = kzalloc(sizeof(*fib_cache), GFP_KERNEL); 136 if (!fib_cache) 137 goto err_kzalloc; 138 139 memcpy(&fib_cache->key, key, sizeof(*key)); 140 fib_info_hold(fen_info->fi); 141 memcpy(&fib_cache->fen4_info, fen_info, sizeof(*fen_info)); 142 143 err = rhashtable_insert_fast(&sw->router->kern_fib_cache_ht, 144 &fib_cache->ht_node, 145 __prestera_kern_fib_cache_ht_params); 146 if (err) 147 goto err_ht_insert; 148 149 return fib_cache; 150 151 err_ht_insert: 152 fib_info_put(fen_info->fi); 153 kfree(fib_cache); 154 err_kzalloc: 155 return NULL; 156 } 157 158 static void 159 __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw, 160 struct prestera_kern_fib_cache *fc, 161 bool fail, bool offload, bool trap) 162 { 163 struct fib_rt_info fri; 164 165 switch (fc->key.addr.v) { 166 case PRESTERA_IPV4: 167 fri.fi = fc->fen4_info.fi; 168 fri.tb_id = fc->key.kern_tb_id; 169 fri.dst = fc->key.addr.u.ipv4; 170 fri.dst_len = fc->key.prefix_len; 171 fri.dscp = fc->fen4_info.dscp; 172 fri.type = fc->fen4_info.type; 173 /* flags begin */ 174 fri.offload = offload; 175 fri.trap = trap; 176 fri.offload_failed = fail; 177 /* flags end */ 178 fib_alias_hw_flags_set(&init_net, &fri); 179 return; 180 case PRESTERA_IPV6: 181 /* TODO */ 182 return; 183 } 184 } 185 186 static int 187 __prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw, 188 struct prestera_kern_fib_cache *fc) 189 { 190 memset(&fc->lpm_info, 0, sizeof(fc->lpm_info)); 191 192 switch (prestera_kern_fib_info_type(&fc->info)) { 193 case RTN_UNICAST: 194 fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_TRAP; 195 break; 196 /* Unsupported. Leave it for kernel: */ 197 case RTN_BROADCAST: 198 case RTN_MULTICAST: 199 /* Routes we must trap by design: */ 200 case RTN_LOCAL: 201 case RTN_UNREACHABLE: 202 case RTN_PROHIBIT: 203 fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_TRAP; 204 break; 205 case RTN_BLACKHOLE: 206 fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_DROP; 207 break; 208 default: 209 dev_err(sw->dev->dev, "Unsupported fib_type"); 210 return -EOPNOTSUPP; 211 } 212 213 fc->lpm_info.fib_key.addr = fc->key.addr; 214 fc->lpm_info.fib_key.prefix_len = fc->key.prefix_len; 215 fc->lpm_info.fib_key.tb_id = prestera_fix_tb_id(fc->key.kern_tb_id); 216 217 return 0; 218 } 219 220 static int __prestera_k_arb_f_lpm_set(struct prestera_switch *sw, 221 struct prestera_kern_fib_cache *fc, 222 bool enabled) 223 { 224 struct prestera_fib_node *fib_node; 225 226 fib_node = prestera_fib_node_find(sw, &fc->lpm_info.fib_key); 227 if (fib_node) 228 prestera_fib_node_destroy(sw, fib_node); 229 230 if (!enabled) 231 return 0; 232 233 fib_node = prestera_fib_node_create(sw, &fc->lpm_info.fib_key, 234 fc->lpm_info.fib_type, NULL); 235 236 if (!fib_node) { 237 dev_err(sw->dev->dev, "fib_node=NULL %pI4n/%d kern_tb_id = %d", 238 &fc->key.addr.u.ipv4, fc->key.prefix_len, 239 fc->key.kern_tb_id); 240 return -ENOENT; 241 } 242 243 return 0; 244 } 245 246 static int __prestera_k_arb_fc_apply(struct prestera_switch *sw, 247 struct prestera_kern_fib_cache *fc) 248 { 249 int err; 250 251 err = __prestera_pr_k_arb_fc_lpm_info_calc(sw, fc); 252 if (err) 253 return err; 254 255 err = __prestera_k_arb_f_lpm_set(sw, fc, fc->reachable); 256 if (err) { 257 __prestera_k_arb_fib_lpm_offload_set(sw, fc, 258 true, false, false); 259 return err; 260 } 261 262 switch (fc->lpm_info.fib_type) { 263 case PRESTERA_FIB_TYPE_UC_NH: 264 break; 265 case PRESTERA_FIB_TYPE_TRAP: 266 __prestera_k_arb_fib_lpm_offload_set(sw, fc, false, 267 false, fc->reachable); 268 break; 269 case PRESTERA_FIB_TYPE_DROP: 270 __prestera_k_arb_fib_lpm_offload_set(sw, fc, false, true, 271 fc->reachable); 272 break; 273 case PRESTERA_FIB_TYPE_INVALID: 274 break; 275 } 276 277 return 0; 278 } 279 280 static struct prestera_kern_fib_cache * 281 __prestera_k_arb_util_fib_overlaps(struct prestera_switch *sw, 282 struct prestera_kern_fib_cache *fc) 283 { 284 struct prestera_kern_fib_cache_key fc_key; 285 struct prestera_kern_fib_cache *rfc; 286 287 /* TODO: parse kernel rules */ 288 rfc = NULL; 289 if (fc->key.kern_tb_id == RT_TABLE_LOCAL) { 290 memcpy(&fc_key, &fc->key, sizeof(fc_key)); 291 fc_key.kern_tb_id = RT_TABLE_MAIN; 292 rfc = prestera_kern_fib_cache_find(sw, &fc_key); 293 } 294 295 return rfc; 296 } 297 298 static struct prestera_kern_fib_cache * 299 __prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw, 300 struct prestera_kern_fib_cache *fc) 301 { 302 struct prestera_kern_fib_cache_key fc_key; 303 struct prestera_kern_fib_cache *rfc; 304 305 /* TODO: parse kernel rules */ 306 rfc = NULL; 307 if (fc->key.kern_tb_id == RT_TABLE_MAIN) { 308 memcpy(&fc_key, &fc->key, sizeof(fc_key)); 309 fc_key.kern_tb_id = RT_TABLE_LOCAL; 310 rfc = prestera_kern_fib_cache_find(sw, &fc_key); 311 } 312 313 return rfc; 314 } 315 316 static int 317 prestera_k_arb_fib_evt(struct prestera_switch *sw, 318 bool replace, /* replace or del */ 319 struct fib_notifier_info *info) 320 { 321 struct prestera_kern_fib_cache *tfib_cache, *bfib_cache; /* top/btm */ 322 struct prestera_kern_fib_cache_key fc_key; 323 struct prestera_kern_fib_cache *fib_cache; 324 int err; 325 326 prestera_util_fen_info2fib_cache_key(info, &fc_key); 327 fib_cache = prestera_kern_fib_cache_find(sw, &fc_key); 328 if (fib_cache) { 329 fib_cache->reachable = false; 330 err = __prestera_k_arb_fc_apply(sw, fib_cache); 331 if (err) 332 dev_err(sw->dev->dev, 333 "Applying destroyed fib_cache failed"); 334 335 bfib_cache = __prestera_k_arb_util_fib_overlaps(sw, fib_cache); 336 tfib_cache = __prestera_k_arb_util_fib_overlapped(sw, fib_cache); 337 if (!tfib_cache && bfib_cache) { 338 bfib_cache->reachable = true; 339 err = __prestera_k_arb_fc_apply(sw, bfib_cache); 340 if (err) 341 dev_err(sw->dev->dev, 342 "Applying fib_cache btm failed"); 343 } 344 345 prestera_kern_fib_cache_destroy(sw, fib_cache); 346 } 347 348 if (replace) { 349 fib_cache = prestera_kern_fib_cache_create(sw, &fc_key, info); 350 if (!fib_cache) { 351 dev_err(sw->dev->dev, "fib_cache == NULL"); 352 return -ENOENT; 353 } 354 355 bfib_cache = __prestera_k_arb_util_fib_overlaps(sw, fib_cache); 356 tfib_cache = __prestera_k_arb_util_fib_overlapped(sw, fib_cache); 357 if (!tfib_cache) 358 fib_cache->reachable = true; 359 360 if (bfib_cache) { 361 bfib_cache->reachable = false; 362 err = __prestera_k_arb_fc_apply(sw, bfib_cache); 363 if (err) 364 dev_err(sw->dev->dev, 365 "Applying fib_cache btm failed"); 366 } 367 368 err = __prestera_k_arb_fc_apply(sw, fib_cache); 369 if (err) 370 dev_err(sw->dev->dev, "Applying fib_cache failed"); 371 } 372 373 return 0; 374 } 375 376 static void __prestera_k_arb_abort_fib_ht_cb(void *ptr, void *arg) 377 { 378 struct prestera_kern_fib_cache *fib_cache = ptr; 379 struct prestera_switch *sw = arg; 380 381 __prestera_k_arb_fib_lpm_offload_set(sw, fib_cache, 382 false, false, 383 false); 384 /* No need to destroy lpm. 385 * It will be aborted by destroy_ht 386 */ 387 __prestera_kern_fib_cache_destruct(sw, fib_cache); 388 kfree(fib_cache); 389 } 390 391 static void prestera_k_arb_abort(struct prestera_switch *sw) 392 { 393 /* Function to remove all arbiter entries and related hw objects. */ 394 /* Sequence: 395 * 1) Clear arbiter tables, but don't touch hw 396 * 2) Clear hw 397 * We use such approach, because arbiter object is not directly mapped 398 * to hw. So deletion of one arbiter object may even lead to creation of 399 * hw object (e.g. in case of overlapped routes). 400 */ 401 rhashtable_free_and_destroy(&sw->router->kern_fib_cache_ht, 402 __prestera_k_arb_abort_fib_ht_cb, 403 sw); 404 } 405 406 static int __prestera_inetaddr_port_event(struct net_device *port_dev, 407 unsigned long event, 408 struct netlink_ext_ack *extack) 409 { 410 struct prestera_port *port = netdev_priv(port_dev); 411 struct prestera_rif_entry_key re_key = {}; 412 struct prestera_rif_entry *re; 413 u32 kern_tb_id; 414 int err; 415 416 err = prestera_is_valid_mac_addr(port, port_dev->dev_addr); 417 if (err) { 418 NL_SET_ERR_MSG_MOD(extack, "RIF MAC must have the same prefix"); 419 return err; 420 } 421 422 kern_tb_id = l3mdev_fib_table(port_dev); 423 re_key.iface.type = PRESTERA_IF_PORT_E; 424 re_key.iface.dev_port.hw_dev_num = port->dev_id; 425 re_key.iface.dev_port.port_num = port->hw_id; 426 re = prestera_rif_entry_find(port->sw, &re_key); 427 428 switch (event) { 429 case NETDEV_UP: 430 if (re) { 431 NL_SET_ERR_MSG_MOD(extack, "RIF already exist"); 432 return -EEXIST; 433 } 434 re = prestera_rif_entry_create(port->sw, &re_key, 435 prestera_fix_tb_id(kern_tb_id), 436 port_dev->dev_addr); 437 if (!re) { 438 NL_SET_ERR_MSG_MOD(extack, "Can't create RIF"); 439 return -EINVAL; 440 } 441 dev_hold(port_dev); 442 break; 443 case NETDEV_DOWN: 444 if (!re) { 445 NL_SET_ERR_MSG_MOD(extack, "Can't find RIF"); 446 return -EEXIST; 447 } 448 prestera_rif_entry_destroy(port->sw, re); 449 dev_put(port_dev); 450 break; 451 } 452 453 return 0; 454 } 455 456 static int __prestera_inetaddr_event(struct prestera_switch *sw, 457 struct net_device *dev, 458 unsigned long event, 459 struct netlink_ext_ack *extack) 460 { 461 if (!prestera_netdev_check(dev) || netif_is_any_bridge_port(dev) || 462 netif_is_lag_port(dev)) 463 return 0; 464 465 return __prestera_inetaddr_port_event(dev, event, extack); 466 } 467 468 static int __prestera_inetaddr_cb(struct notifier_block *nb, 469 unsigned long event, void *ptr) 470 { 471 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; 472 struct net_device *dev = ifa->ifa_dev->dev; 473 struct prestera_router *router = container_of(nb, 474 struct prestera_router, 475 inetaddr_nb); 476 struct in_device *idev; 477 int err = 0; 478 479 if (event != NETDEV_DOWN) 480 goto out; 481 482 /* Ignore if this is not latest address */ 483 idev = __in_dev_get_rtnl(dev); 484 if (idev && idev->ifa_list) 485 goto out; 486 487 err = __prestera_inetaddr_event(router->sw, dev, event, NULL); 488 out: 489 return notifier_from_errno(err); 490 } 491 492 static int __prestera_inetaddr_valid_cb(struct notifier_block *nb, 493 unsigned long event, void *ptr) 494 { 495 struct in_validator_info *ivi = (struct in_validator_info *)ptr; 496 struct net_device *dev = ivi->ivi_dev->dev; 497 struct prestera_router *router = container_of(nb, 498 struct prestera_router, 499 inetaddr_valid_nb); 500 struct in_device *idev; 501 int err = 0; 502 503 if (event != NETDEV_UP) 504 goto out; 505 506 /* Ignore if this is not first address */ 507 idev = __in_dev_get_rtnl(dev); 508 if (idev && idev->ifa_list) 509 goto out; 510 511 if (ipv4_is_multicast(ivi->ivi_addr)) { 512 NL_SET_ERR_MSG_MOD(ivi->extack, 513 "Multicast addr on RIF is not supported"); 514 err = -EINVAL; 515 goto out; 516 } 517 518 err = __prestera_inetaddr_event(router->sw, dev, event, ivi->extack); 519 out: 520 return notifier_from_errno(err); 521 } 522 523 struct prestera_fib_event_work { 524 struct work_struct work; 525 struct prestera_switch *sw; 526 struct fib_entry_notifier_info fen_info; 527 unsigned long event; 528 }; 529 530 static void __prestera_router_fib_event_work(struct work_struct *work) 531 { 532 struct prestera_fib_event_work *fib_work = 533 container_of(work, struct prestera_fib_event_work, work); 534 struct prestera_switch *sw = fib_work->sw; 535 int err; 536 537 rtnl_lock(); 538 539 switch (fib_work->event) { 540 case FIB_EVENT_ENTRY_REPLACE: 541 err = prestera_k_arb_fib_evt(sw, true, 542 &fib_work->fen_info.info); 543 if (err) 544 goto err_out; 545 546 break; 547 case FIB_EVENT_ENTRY_DEL: 548 err = prestera_k_arb_fib_evt(sw, false, 549 &fib_work->fen_info.info); 550 if (err) 551 goto err_out; 552 553 break; 554 } 555 556 goto out; 557 558 err_out: 559 dev_err(sw->dev->dev, "Error when processing %pI4h/%d", 560 &fib_work->fen_info.dst, 561 fib_work->fen_info.dst_len); 562 out: 563 fib_info_put(fib_work->fen_info.fi); 564 rtnl_unlock(); 565 kfree(fib_work); 566 } 567 568 /* Called with rcu_read_lock() */ 569 static int __prestera_router_fib_event(struct notifier_block *nb, 570 unsigned long event, void *ptr) 571 { 572 struct prestera_fib_event_work *fib_work; 573 struct fib_entry_notifier_info *fen_info; 574 struct fib_notifier_info *info = ptr; 575 struct prestera_router *router; 576 577 if (info->family != AF_INET) 578 return NOTIFY_DONE; 579 580 router = container_of(nb, struct prestera_router, fib_nb); 581 582 switch (event) { 583 case FIB_EVENT_ENTRY_REPLACE: 584 case FIB_EVENT_ENTRY_DEL: 585 fen_info = container_of(info, struct fib_entry_notifier_info, 586 info); 587 if (!fen_info->fi) 588 return NOTIFY_DONE; 589 590 fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); 591 if (WARN_ON(!fib_work)) 592 return NOTIFY_BAD; 593 594 fib_info_hold(fen_info->fi); 595 fib_work->fen_info = *fen_info; 596 fib_work->event = event; 597 fib_work->sw = router->sw; 598 INIT_WORK(&fib_work->work, __prestera_router_fib_event_work); 599 prestera_queue_work(&fib_work->work); 600 break; 601 default: 602 return NOTIFY_DONE; 603 } 604 605 return NOTIFY_DONE; 606 } 607 608 struct prestera_netevent_work { 609 struct work_struct work; 610 struct prestera_switch *sw; 611 struct neighbour *n; 612 }; 613 614 static void prestera_router_neigh_event_work(struct work_struct *work) 615 { 616 struct prestera_netevent_work *net_work = 617 container_of(work, struct prestera_netevent_work, work); 618 struct neighbour *n = net_work->n; 619 620 /* neigh - its not hw related object. It stored only in kernel. So... */ 621 rtnl_lock(); 622 623 /* TODO: handler */ 624 625 neigh_release(n); 626 rtnl_unlock(); 627 kfree(net_work); 628 } 629 630 static int prestera_router_netevent_event(struct notifier_block *nb, 631 unsigned long event, void *ptr) 632 { 633 struct prestera_netevent_work *net_work; 634 struct prestera_router *router; 635 struct neighbour *n = ptr; 636 637 router = container_of(nb, struct prestera_router, netevent_nb); 638 639 switch (event) { 640 case NETEVENT_NEIGH_UPDATE: 641 if (n->tbl->family != AF_INET) 642 return NOTIFY_DONE; 643 644 net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); 645 if (WARN_ON(!net_work)) 646 return NOTIFY_BAD; 647 648 neigh_clone(n); 649 net_work->n = n; 650 net_work->sw = router->sw; 651 INIT_WORK(&net_work->work, prestera_router_neigh_event_work); 652 prestera_queue_work(&net_work->work); 653 } 654 655 return NOTIFY_DONE; 656 } 657 658 int prestera_router_init(struct prestera_switch *sw) 659 { 660 struct prestera_router *router; 661 int err, nhgrp_cache_bytes; 662 663 router = kzalloc(sizeof(*sw->router), GFP_KERNEL); 664 if (!router) 665 return -ENOMEM; 666 667 sw->router = router; 668 router->sw = sw; 669 670 err = prestera_router_hw_init(sw); 671 if (err) 672 goto err_router_lib_init; 673 674 err = rhashtable_init(&router->kern_fib_cache_ht, 675 &__prestera_kern_fib_cache_ht_params); 676 if (err) 677 goto err_kern_fib_cache_ht_init; 678 679 nhgrp_cache_bytes = sw->size_tbl_router_nexthop / 8 + 1; 680 router->nhgrp_hw_state_cache = kzalloc(nhgrp_cache_bytes, GFP_KERNEL); 681 if (!router->nhgrp_hw_state_cache) { 682 err = -ENOMEM; 683 goto err_nh_state_cache_alloc; 684 } 685 686 router->inetaddr_valid_nb.notifier_call = __prestera_inetaddr_valid_cb; 687 err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb); 688 if (err) 689 goto err_register_inetaddr_validator_notifier; 690 691 router->inetaddr_nb.notifier_call = __prestera_inetaddr_cb; 692 err = register_inetaddr_notifier(&router->inetaddr_nb); 693 if (err) 694 goto err_register_inetaddr_notifier; 695 696 router->netevent_nb.notifier_call = prestera_router_netevent_event; 697 err = register_netevent_notifier(&router->netevent_nb); 698 if (err) 699 goto err_register_netevent_notifier; 700 701 router->fib_nb.notifier_call = __prestera_router_fib_event; 702 err = register_fib_notifier(&init_net, &router->fib_nb, 703 /* TODO: flush fib entries */ NULL, NULL); 704 if (err) 705 goto err_register_fib_notifier; 706 707 return 0; 708 709 err_register_fib_notifier: 710 unregister_netevent_notifier(&router->netevent_nb); 711 err_register_netevent_notifier: 712 unregister_inetaddr_notifier(&router->inetaddr_nb); 713 err_register_inetaddr_notifier: 714 unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb); 715 err_register_inetaddr_validator_notifier: 716 kfree(router->nhgrp_hw_state_cache); 717 err_nh_state_cache_alloc: 718 rhashtable_destroy(&router->kern_fib_cache_ht); 719 err_kern_fib_cache_ht_init: 720 prestera_router_hw_fini(sw); 721 err_router_lib_init: 722 kfree(sw->router); 723 return err; 724 } 725 726 void prestera_router_fini(struct prestera_switch *sw) 727 { 728 unregister_fib_notifier(&init_net, &sw->router->fib_nb); 729 unregister_netevent_notifier(&sw->router->netevent_nb); 730 unregister_inetaddr_notifier(&sw->router->inetaddr_nb); 731 unregister_inetaddr_validator_notifier(&sw->router->inetaddr_valid_nb); 732 prestera_queue_drain(); 733 734 prestera_k_arb_abort(sw); 735 736 kfree(sw->router->nhgrp_hw_state_cache); 737 rhashtable_destroy(&sw->router->kern_fib_cache_ht); 738 prestera_router_hw_fini(sw); 739 kfree(sw->router); 740 sw->router = NULL; 741 } 742