1 /* 2 * drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c 3 * Copyright (c) 2016-2017 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 * Copyright (c) 2016 Ido Schimmel <idosch@mellanox.com> 6 * Copyright (c) 2016 Yotam Gigi <yotamg@mellanox.com> 7 * Copyright (c) 2017 Petr Machata <petrm@mellanox.com> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the names of the copyright holders nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * Alternatively, this software may be distributed under the terms of the 22 * GNU General Public License ("GPL") version 2 as published by the Free 23 * Software Foundation. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <linux/kernel.h> 39 #include <linux/types.h> 40 #include <linux/rhashtable.h> 41 #include <linux/bitops.h> 42 #include <linux/in6.h> 43 #include <linux/notifier.h> 44 #include <linux/inetdevice.h> 45 #include <linux/netdevice.h> 46 #include <linux/if_bridge.h> 47 #include <linux/socket.h> 48 #include <linux/route.h> 49 #include <net/netevent.h> 50 #include <net/neighbour.h> 51 #include <net/arp.h> 52 #include <net/ip_fib.h> 53 #include <net/ip6_fib.h> 54 #include <net/fib_rules.h> 55 #include <net/ip_tunnels.h> 56 #include <net/l3mdev.h> 57 #include <net/addrconf.h> 58 #include <net/ndisc.h> 59 #include <net/ipv6.h> 60 #include <net/fib_notifier.h> 61 62 #include "spectrum.h" 63 #include "core.h" 64 #include "reg.h" 65 #include "spectrum_cnt.h" 66 #include "spectrum_dpipe.h" 67 #include "spectrum_ipip.h" 68 #include "spectrum_router.h" 69 70 struct mlxsw_sp_vr; 71 struct mlxsw_sp_lpm_tree; 72 struct mlxsw_sp_rif_ops; 73 74 struct mlxsw_sp_router { 75 struct mlxsw_sp *mlxsw_sp; 76 struct mlxsw_sp_rif **rifs; 77 struct mlxsw_sp_vr *vrs; 78 struct rhashtable neigh_ht; 79 struct rhashtable nexthop_group_ht; 80 struct rhashtable nexthop_ht; 81 struct { 82 struct mlxsw_sp_lpm_tree *trees; 83 unsigned int tree_count; 84 } lpm; 85 struct { 86 struct delayed_work dw; 87 unsigned long interval; /* ms */ 88 } neighs_update; 89 struct delayed_work nexthop_probe_dw; 90 #define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */ 91 struct list_head nexthop_neighs_list; 92 struct list_head ipip_list; 93 bool aborted; 94 struct notifier_block fib_nb; 95 const struct mlxsw_sp_rif_ops **rif_ops_arr; 96 const struct mlxsw_sp_ipip_ops **ipip_ops_arr; 97 }; 98 99 struct mlxsw_sp_rif { 100 struct list_head nexthop_list; 101 struct list_head neigh_list; 102 struct net_device *dev; 103 struct mlxsw_sp_fid *fid; 104 unsigned char addr[ETH_ALEN]; 105 int mtu; 106 u16 rif_index; 107 u16 vr_id; 108 const struct mlxsw_sp_rif_ops *ops; 109 struct mlxsw_sp *mlxsw_sp; 110 111 unsigned int counter_ingress; 112 bool counter_ingress_valid; 113 unsigned int counter_egress; 114 bool counter_egress_valid; 115 }; 116 117 struct mlxsw_sp_rif_params { 118 struct net_device *dev; 119 union { 120 u16 system_port; 121 u16 lag_id; 122 }; 123 u16 vid; 124 bool lag; 125 }; 126 127 struct mlxsw_sp_rif_subport { 128 struct mlxsw_sp_rif common; 129 union { 130 u16 system_port; 131 u16 lag_id; 132 }; 133 u16 vid; 134 bool lag; 135 }; 136 137 struct mlxsw_sp_rif_ipip_lb { 138 struct mlxsw_sp_rif common; 139 struct mlxsw_sp_rif_ipip_lb_config lb_config; 140 u16 ul_vr_id; /* Reserved for Spectrum-2. */ 141 }; 142 143 struct mlxsw_sp_rif_params_ipip_lb { 144 struct mlxsw_sp_rif_params common; 145 struct mlxsw_sp_rif_ipip_lb_config lb_config; 146 }; 147 148 struct mlxsw_sp_rif_ops { 149 enum mlxsw_sp_rif_type type; 150 size_t rif_size; 151 152 void (*setup)(struct mlxsw_sp_rif *rif, 153 const struct mlxsw_sp_rif_params *params); 154 int (*configure)(struct mlxsw_sp_rif *rif); 155 void (*deconfigure)(struct mlxsw_sp_rif *rif); 156 struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif); 157 }; 158 159 static unsigned int * 160 mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif, 161 enum mlxsw_sp_rif_counter_dir dir) 162 { 163 switch (dir) { 164 case MLXSW_SP_RIF_COUNTER_EGRESS: 165 return &rif->counter_egress; 166 case MLXSW_SP_RIF_COUNTER_INGRESS: 167 return &rif->counter_ingress; 168 } 169 return NULL; 170 } 171 172 static bool 173 mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif *rif, 174 enum mlxsw_sp_rif_counter_dir dir) 175 { 176 switch (dir) { 177 case MLXSW_SP_RIF_COUNTER_EGRESS: 178 return rif->counter_egress_valid; 179 case MLXSW_SP_RIF_COUNTER_INGRESS: 180 return rif->counter_ingress_valid; 181 } 182 return false; 183 } 184 185 static void 186 mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif, 187 enum mlxsw_sp_rif_counter_dir dir, 188 bool valid) 189 { 190 switch (dir) { 191 case MLXSW_SP_RIF_COUNTER_EGRESS: 192 rif->counter_egress_valid = valid; 193 break; 194 case MLXSW_SP_RIF_COUNTER_INGRESS: 195 rif->counter_ingress_valid = valid; 196 break; 197 } 198 } 199 200 static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, 201 unsigned int counter_index, bool enable, 202 enum mlxsw_sp_rif_counter_dir dir) 203 { 204 char ritr_pl[MLXSW_REG_RITR_LEN]; 205 bool is_egress = false; 206 int err; 207 208 if (dir == MLXSW_SP_RIF_COUNTER_EGRESS) 209 is_egress = true; 210 mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index); 211 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 212 if (err) 213 return err; 214 215 mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable, 216 is_egress); 217 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 218 } 219 220 int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp, 221 struct mlxsw_sp_rif *rif, 222 enum mlxsw_sp_rif_counter_dir dir, u64 *cnt) 223 { 224 char ricnt_pl[MLXSW_REG_RICNT_LEN]; 225 unsigned int *p_counter_index; 226 bool valid; 227 int err; 228 229 valid = mlxsw_sp_rif_counter_valid_get(rif, dir); 230 if (!valid) 231 return -EINVAL; 232 233 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir); 234 if (!p_counter_index) 235 return -EINVAL; 236 mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index, 237 MLXSW_REG_RICNT_OPCODE_NOP); 238 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl); 239 if (err) 240 return err; 241 *cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl); 242 return 0; 243 } 244 245 static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp, 246 unsigned int counter_index) 247 { 248 char ricnt_pl[MLXSW_REG_RICNT_LEN]; 249 250 mlxsw_reg_ricnt_pack(ricnt_pl, counter_index, 251 MLXSW_REG_RICNT_OPCODE_CLEAR); 252 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl); 253 } 254 255 int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp, 256 struct mlxsw_sp_rif *rif, 257 enum mlxsw_sp_rif_counter_dir dir) 258 { 259 unsigned int *p_counter_index; 260 int err; 261 262 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir); 263 if (!p_counter_index) 264 return -EINVAL; 265 err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF, 266 p_counter_index); 267 if (err) 268 return err; 269 270 err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index); 271 if (err) 272 goto err_counter_clear; 273 274 err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index, 275 *p_counter_index, true, dir); 276 if (err) 277 goto err_counter_edit; 278 mlxsw_sp_rif_counter_valid_set(rif, dir, true); 279 return 0; 280 281 err_counter_edit: 282 err_counter_clear: 283 mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF, 284 *p_counter_index); 285 return err; 286 } 287 288 void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp, 289 struct mlxsw_sp_rif *rif, 290 enum mlxsw_sp_rif_counter_dir dir) 291 { 292 unsigned int *p_counter_index; 293 294 if (!mlxsw_sp_rif_counter_valid_get(rif, dir)) 295 return; 296 297 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir); 298 if (WARN_ON(!p_counter_index)) 299 return; 300 mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index, 301 *p_counter_index, false, dir); 302 mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF, 303 *p_counter_index); 304 mlxsw_sp_rif_counter_valid_set(rif, dir, false); 305 } 306 307 static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif *rif) 308 { 309 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 310 struct devlink *devlink; 311 312 devlink = priv_to_devlink(mlxsw_sp->core); 313 if (!devlink_dpipe_table_counter_enabled(devlink, 314 MLXSW_SP_DPIPE_TABLE_NAME_ERIF)) 315 return; 316 mlxsw_sp_rif_counter_alloc(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS); 317 } 318 319 static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif *rif) 320 { 321 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 322 323 mlxsw_sp_rif_counter_free(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS); 324 } 325 326 static struct mlxsw_sp_rif * 327 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp, 328 const struct net_device *dev); 329 330 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1) 331 332 struct mlxsw_sp_prefix_usage { 333 DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT); 334 }; 335 336 #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \ 337 for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT) 338 339 static bool 340 mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1, 341 struct mlxsw_sp_prefix_usage *prefix_usage2) 342 { 343 return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1)); 344 } 345 346 static bool 347 mlxsw_sp_prefix_usage_none(struct mlxsw_sp_prefix_usage *prefix_usage) 348 { 349 struct mlxsw_sp_prefix_usage prefix_usage_none = {{ 0 } }; 350 351 return mlxsw_sp_prefix_usage_eq(prefix_usage, &prefix_usage_none); 352 } 353 354 static void 355 mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1, 356 struct mlxsw_sp_prefix_usage *prefix_usage2) 357 { 358 memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1)); 359 } 360 361 static void 362 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage, 363 unsigned char prefix_len) 364 { 365 set_bit(prefix_len, prefix_usage->b); 366 } 367 368 static void 369 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage, 370 unsigned char prefix_len) 371 { 372 clear_bit(prefix_len, prefix_usage->b); 373 } 374 375 struct mlxsw_sp_fib_key { 376 unsigned char addr[sizeof(struct in6_addr)]; 377 unsigned char prefix_len; 378 }; 379 380 enum mlxsw_sp_fib_entry_type { 381 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE, 382 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL, 383 MLXSW_SP_FIB_ENTRY_TYPE_TRAP, 384 385 /* This is a special case of local delivery, where a packet should be 386 * decapsulated on reception. Note that there is no corresponding ENCAP, 387 * because that's a type of next hop, not of FIB entry. (There can be 388 * several next hops in a REMOTE entry, and some of them may be 389 * encapsulating entries.) 390 */ 391 MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP, 392 }; 393 394 struct mlxsw_sp_nexthop_group; 395 struct mlxsw_sp_fib; 396 397 struct mlxsw_sp_fib_node { 398 struct list_head entry_list; 399 struct list_head list; 400 struct rhash_head ht_node; 401 struct mlxsw_sp_fib *fib; 402 struct mlxsw_sp_fib_key key; 403 }; 404 405 struct mlxsw_sp_fib_entry_decap { 406 struct mlxsw_sp_ipip_entry *ipip_entry; 407 u32 tunnel_index; 408 }; 409 410 struct mlxsw_sp_fib_entry { 411 struct list_head list; 412 struct mlxsw_sp_fib_node *fib_node; 413 enum mlxsw_sp_fib_entry_type type; 414 struct list_head nexthop_group_node; 415 struct mlxsw_sp_nexthop_group *nh_group; 416 struct mlxsw_sp_fib_entry_decap decap; /* Valid for decap entries. */ 417 }; 418 419 struct mlxsw_sp_fib4_entry { 420 struct mlxsw_sp_fib_entry common; 421 u32 tb_id; 422 u32 prio; 423 u8 tos; 424 u8 type; 425 }; 426 427 struct mlxsw_sp_fib6_entry { 428 struct mlxsw_sp_fib_entry common; 429 struct list_head rt6_list; 430 unsigned int nrt6; 431 }; 432 433 struct mlxsw_sp_rt6 { 434 struct list_head list; 435 struct rt6_info *rt; 436 }; 437 438 struct mlxsw_sp_lpm_tree { 439 u8 id; /* tree ID */ 440 unsigned int ref_count; 441 enum mlxsw_sp_l3proto proto; 442 struct mlxsw_sp_prefix_usage prefix_usage; 443 }; 444 445 struct mlxsw_sp_fib { 446 struct rhashtable ht; 447 struct list_head node_list; 448 struct mlxsw_sp_vr *vr; 449 struct mlxsw_sp_lpm_tree *lpm_tree; 450 unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT]; 451 struct mlxsw_sp_prefix_usage prefix_usage; 452 enum mlxsw_sp_l3proto proto; 453 }; 454 455 struct mlxsw_sp_vr { 456 u16 id; /* virtual router ID */ 457 u32 tb_id; /* kernel fib table id */ 458 unsigned int rif_count; 459 struct mlxsw_sp_fib *fib4; 460 struct mlxsw_sp_fib *fib6; 461 }; 462 463 static const struct rhashtable_params mlxsw_sp_fib_ht_params; 464 465 static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp_vr *vr, 466 enum mlxsw_sp_l3proto proto) 467 { 468 struct mlxsw_sp_fib *fib; 469 int err; 470 471 fib = kzalloc(sizeof(*fib), GFP_KERNEL); 472 if (!fib) 473 return ERR_PTR(-ENOMEM); 474 err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params); 475 if (err) 476 goto err_rhashtable_init; 477 INIT_LIST_HEAD(&fib->node_list); 478 fib->proto = proto; 479 fib->vr = vr; 480 return fib; 481 482 err_rhashtable_init: 483 kfree(fib); 484 return ERR_PTR(err); 485 } 486 487 static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib *fib) 488 { 489 WARN_ON(!list_empty(&fib->node_list)); 490 WARN_ON(fib->lpm_tree); 491 rhashtable_destroy(&fib->ht); 492 kfree(fib); 493 } 494 495 static struct mlxsw_sp_lpm_tree * 496 mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp) 497 { 498 static struct mlxsw_sp_lpm_tree *lpm_tree; 499 int i; 500 501 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) { 502 lpm_tree = &mlxsw_sp->router->lpm.trees[i]; 503 if (lpm_tree->ref_count == 0) 504 return lpm_tree; 505 } 506 return NULL; 507 } 508 509 static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp, 510 struct mlxsw_sp_lpm_tree *lpm_tree) 511 { 512 char ralta_pl[MLXSW_REG_RALTA_LEN]; 513 514 mlxsw_reg_ralta_pack(ralta_pl, true, 515 (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, 516 lpm_tree->id); 517 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl); 518 } 519 520 static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp, 521 struct mlxsw_sp_lpm_tree *lpm_tree) 522 { 523 char ralta_pl[MLXSW_REG_RALTA_LEN]; 524 525 mlxsw_reg_ralta_pack(ralta_pl, false, 526 (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto, 527 lpm_tree->id); 528 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl); 529 } 530 531 static int 532 mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp, 533 struct mlxsw_sp_prefix_usage *prefix_usage, 534 struct mlxsw_sp_lpm_tree *lpm_tree) 535 { 536 char ralst_pl[MLXSW_REG_RALST_LEN]; 537 u8 root_bin = 0; 538 u8 prefix; 539 u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD; 540 541 mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) 542 root_bin = prefix; 543 544 mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id); 545 mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) { 546 if (prefix == 0) 547 continue; 548 mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix, 549 MLXSW_REG_RALST_BIN_NO_CHILD); 550 last_prefix = prefix; 551 } 552 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl); 553 } 554 555 static struct mlxsw_sp_lpm_tree * 556 mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp, 557 struct mlxsw_sp_prefix_usage *prefix_usage, 558 enum mlxsw_sp_l3proto proto) 559 { 560 struct mlxsw_sp_lpm_tree *lpm_tree; 561 int err; 562 563 lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp); 564 if (!lpm_tree) 565 return ERR_PTR(-EBUSY); 566 lpm_tree->proto = proto; 567 err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree); 568 if (err) 569 return ERR_PTR(err); 570 571 err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage, 572 lpm_tree); 573 if (err) 574 goto err_left_struct_set; 575 memcpy(&lpm_tree->prefix_usage, prefix_usage, 576 sizeof(lpm_tree->prefix_usage)); 577 return lpm_tree; 578 579 err_left_struct_set: 580 mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree); 581 return ERR_PTR(err); 582 } 583 584 static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp, 585 struct mlxsw_sp_lpm_tree *lpm_tree) 586 { 587 mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree); 588 } 589 590 static struct mlxsw_sp_lpm_tree * 591 mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp, 592 struct mlxsw_sp_prefix_usage *prefix_usage, 593 enum mlxsw_sp_l3proto proto) 594 { 595 struct mlxsw_sp_lpm_tree *lpm_tree; 596 int i; 597 598 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) { 599 lpm_tree = &mlxsw_sp->router->lpm.trees[i]; 600 if (lpm_tree->ref_count != 0 && 601 lpm_tree->proto == proto && 602 mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage, 603 prefix_usage)) 604 return lpm_tree; 605 } 606 return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto); 607 } 608 609 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree) 610 { 611 lpm_tree->ref_count++; 612 } 613 614 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp, 615 struct mlxsw_sp_lpm_tree *lpm_tree) 616 { 617 if (--lpm_tree->ref_count == 0) 618 mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree); 619 } 620 621 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */ 622 623 static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp) 624 { 625 struct mlxsw_sp_lpm_tree *lpm_tree; 626 u64 max_trees; 627 int i; 628 629 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES)) 630 return -EIO; 631 632 max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES); 633 mlxsw_sp->router->lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN; 634 mlxsw_sp->router->lpm.trees = kcalloc(mlxsw_sp->router->lpm.tree_count, 635 sizeof(struct mlxsw_sp_lpm_tree), 636 GFP_KERNEL); 637 if (!mlxsw_sp->router->lpm.trees) 638 return -ENOMEM; 639 640 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) { 641 lpm_tree = &mlxsw_sp->router->lpm.trees[i]; 642 lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN; 643 } 644 645 return 0; 646 } 647 648 static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp) 649 { 650 kfree(mlxsw_sp->router->lpm.trees); 651 } 652 653 static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr) 654 { 655 return !!vr->fib4 || !!vr->fib6; 656 } 657 658 static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) 659 { 660 struct mlxsw_sp_vr *vr; 661 int i; 662 663 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 664 vr = &mlxsw_sp->router->vrs[i]; 665 if (!mlxsw_sp_vr_is_used(vr)) 666 return vr; 667 } 668 return NULL; 669 } 670 671 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp, 672 const struct mlxsw_sp_fib *fib, u8 tree_id) 673 { 674 char raltb_pl[MLXSW_REG_RALTB_LEN]; 675 676 mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id, 677 (enum mlxsw_reg_ralxx_protocol) fib->proto, 678 tree_id); 679 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl); 680 } 681 682 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp, 683 const struct mlxsw_sp_fib *fib) 684 { 685 char raltb_pl[MLXSW_REG_RALTB_LEN]; 686 687 /* Bind to tree 0 which is default */ 688 mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id, 689 (enum mlxsw_reg_ralxx_protocol) fib->proto, 0); 690 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl); 691 } 692 693 static u32 mlxsw_sp_fix_tb_id(u32 tb_id) 694 { 695 /* For our purpose, squash main and local table into one */ 696 if (tb_id == RT_TABLE_LOCAL) 697 tb_id = RT_TABLE_MAIN; 698 return tb_id; 699 } 700 701 static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp, 702 u32 tb_id) 703 { 704 struct mlxsw_sp_vr *vr; 705 int i; 706 707 tb_id = mlxsw_sp_fix_tb_id(tb_id); 708 709 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 710 vr = &mlxsw_sp->router->vrs[i]; 711 if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id) 712 return vr; 713 } 714 return NULL; 715 } 716 717 static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr, 718 enum mlxsw_sp_l3proto proto) 719 { 720 switch (proto) { 721 case MLXSW_SP_L3_PROTO_IPV4: 722 return vr->fib4; 723 case MLXSW_SP_L3_PROTO_IPV6: 724 return vr->fib6; 725 } 726 return NULL; 727 } 728 729 static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, 730 u32 tb_id) 731 { 732 struct mlxsw_sp_vr *vr; 733 int err; 734 735 vr = mlxsw_sp_vr_find_unused(mlxsw_sp); 736 if (!vr) 737 return ERR_PTR(-EBUSY); 738 vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4); 739 if (IS_ERR(vr->fib4)) 740 return ERR_CAST(vr->fib4); 741 vr->fib6 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV6); 742 if (IS_ERR(vr->fib6)) { 743 err = PTR_ERR(vr->fib6); 744 goto err_fib6_create; 745 } 746 vr->tb_id = tb_id; 747 return vr; 748 749 err_fib6_create: 750 mlxsw_sp_fib_destroy(vr->fib4); 751 vr->fib4 = NULL; 752 return ERR_PTR(err); 753 } 754 755 static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr *vr) 756 { 757 mlxsw_sp_fib_destroy(vr->fib6); 758 vr->fib6 = NULL; 759 mlxsw_sp_fib_destroy(vr->fib4); 760 vr->fib4 = NULL; 761 } 762 763 static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id) 764 { 765 struct mlxsw_sp_vr *vr; 766 767 tb_id = mlxsw_sp_fix_tb_id(tb_id); 768 vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id); 769 if (!vr) 770 vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id); 771 return vr; 772 } 773 774 static void mlxsw_sp_vr_put(struct mlxsw_sp_vr *vr) 775 { 776 if (!vr->rif_count && list_empty(&vr->fib4->node_list) && 777 list_empty(&vr->fib6->node_list)) 778 mlxsw_sp_vr_destroy(vr); 779 } 780 781 static bool 782 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr *vr, 783 enum mlxsw_sp_l3proto proto, u8 tree_id) 784 { 785 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto); 786 787 if (!mlxsw_sp_vr_is_used(vr)) 788 return false; 789 if (fib->lpm_tree && fib->lpm_tree->id == tree_id) 790 return true; 791 return false; 792 } 793 794 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, 795 struct mlxsw_sp_fib *fib, 796 struct mlxsw_sp_lpm_tree *new_tree) 797 { 798 struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree; 799 int err; 800 801 err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); 802 if (err) 803 return err; 804 fib->lpm_tree = new_tree; 805 mlxsw_sp_lpm_tree_hold(new_tree); 806 mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree); 807 return 0; 808 } 809 810 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, 811 struct mlxsw_sp_fib *fib, 812 struct mlxsw_sp_lpm_tree *new_tree) 813 { 814 struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree; 815 enum mlxsw_sp_l3proto proto = fib->proto; 816 u8 old_id, new_id = new_tree->id; 817 struct mlxsw_sp_vr *vr; 818 int i, err; 819 820 if (!old_tree) 821 goto no_replace; 822 old_id = old_tree->id; 823 824 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 825 vr = &mlxsw_sp->router->vrs[i]; 826 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id)) 827 continue; 828 err = mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp, 829 mlxsw_sp_vr_fib(vr, proto), 830 new_tree); 831 if (err) 832 goto err_tree_replace; 833 } 834 835 return 0; 836 837 err_tree_replace: 838 for (i--; i >= 0; i--) { 839 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id)) 840 continue; 841 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp, 842 mlxsw_sp_vr_fib(vr, proto), 843 old_tree); 844 } 845 return err; 846 847 no_replace: 848 err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); 849 if (err) 850 return err; 851 fib->lpm_tree = new_tree; 852 mlxsw_sp_lpm_tree_hold(new_tree); 853 return 0; 854 } 855 856 static void 857 mlxsw_sp_vrs_prefixes(struct mlxsw_sp *mlxsw_sp, 858 enum mlxsw_sp_l3proto proto, 859 struct mlxsw_sp_prefix_usage *req_prefix_usage) 860 { 861 int i; 862 863 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 864 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; 865 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto); 866 unsigned char prefix; 867 868 if (!mlxsw_sp_vr_is_used(vr)) 869 continue; 870 mlxsw_sp_prefix_usage_for_each(prefix, &fib->prefix_usage) 871 mlxsw_sp_prefix_usage_set(req_prefix_usage, prefix); 872 } 873 } 874 875 static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp) 876 { 877 struct mlxsw_sp_vr *vr; 878 u64 max_vrs; 879 int i; 880 881 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS)) 882 return -EIO; 883 884 max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); 885 mlxsw_sp->router->vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr), 886 GFP_KERNEL); 887 if (!mlxsw_sp->router->vrs) 888 return -ENOMEM; 889 890 for (i = 0; i < max_vrs; i++) { 891 vr = &mlxsw_sp->router->vrs[i]; 892 vr->id = i; 893 } 894 895 return 0; 896 } 897 898 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp); 899 900 static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp) 901 { 902 /* At this stage we're guaranteed not to have new incoming 903 * FIB notifications and the work queue is free from FIBs 904 * sitting on top of mlxsw netdevs. However, we can still 905 * have other FIBs queued. Flush the queue before flushing 906 * the device's tables. No need for locks, as we're the only 907 * writer. 908 */ 909 mlxsw_core_flush_owq(); 910 mlxsw_sp_router_fib_flush(mlxsw_sp); 911 kfree(mlxsw_sp->router->vrs); 912 } 913 914 static struct net_device * 915 __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev) 916 { 917 struct ip_tunnel *tun = netdev_priv(ol_dev); 918 struct net *net = dev_net(ol_dev); 919 920 return __dev_get_by_index(net, tun->parms.link); 921 } 922 923 static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev) 924 { 925 struct net_device *d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev); 926 927 if (d) 928 return l3mdev_fib_table(d) ? : RT_TABLE_MAIN; 929 else 930 return l3mdev_fib_table(ol_dev) ? : RT_TABLE_MAIN; 931 } 932 933 static struct mlxsw_sp_rif * 934 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, 935 const struct mlxsw_sp_rif_params *params); 936 937 static struct mlxsw_sp_rif_ipip_lb * 938 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp, 939 enum mlxsw_sp_ipip_type ipipt, 940 struct net_device *ol_dev) 941 { 942 struct mlxsw_sp_rif_params_ipip_lb lb_params; 943 const struct mlxsw_sp_ipip_ops *ipip_ops; 944 struct mlxsw_sp_rif *rif; 945 946 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt]; 947 lb_params = (struct mlxsw_sp_rif_params_ipip_lb) { 948 .common.dev = ol_dev, 949 .common.lag = false, 950 .lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev), 951 }; 952 953 rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common); 954 if (IS_ERR(rif)) 955 return ERR_CAST(rif); 956 return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common); 957 } 958 959 static struct mlxsw_sp_ipip_entry * 960 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp *mlxsw_sp, 961 enum mlxsw_sp_ipip_type ipipt, 962 struct net_device *ol_dev) 963 { 964 struct mlxsw_sp_ipip_entry *ipip_entry; 965 struct mlxsw_sp_ipip_entry *ret = NULL; 966 967 ipip_entry = kzalloc(sizeof(*ipip_entry), GFP_KERNEL); 968 if (!ipip_entry) 969 return ERR_PTR(-ENOMEM); 970 971 ipip_entry->ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipipt, 972 ol_dev); 973 if (IS_ERR(ipip_entry->ol_lb)) { 974 ret = ERR_CAST(ipip_entry->ol_lb); 975 goto err_ol_ipip_lb_create; 976 } 977 978 ipip_entry->ipipt = ipipt; 979 ipip_entry->ol_dev = ol_dev; 980 981 return ipip_entry; 982 983 err_ol_ipip_lb_create: 984 kfree(ipip_entry); 985 return ret; 986 } 987 988 static void 989 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp_ipip_entry *ipip_entry) 990 { 991 WARN_ON(ipip_entry->ref_count > 0); 992 mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common); 993 kfree(ipip_entry); 994 } 995 996 static __be32 997 mlxsw_sp_ipip_netdev_saddr4(const struct net_device *ol_dev) 998 { 999 struct ip_tunnel *tun = netdev_priv(ol_dev); 1000 1001 return tun->parms.iph.saddr; 1002 } 1003 1004 union mlxsw_sp_l3addr 1005 mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto, 1006 const struct net_device *ol_dev) 1007 { 1008 switch (proto) { 1009 case MLXSW_SP_L3_PROTO_IPV4: 1010 return (union mlxsw_sp_l3addr) { 1011 .addr4 = mlxsw_sp_ipip_netdev_saddr4(ol_dev), 1012 }; 1013 case MLXSW_SP_L3_PROTO_IPV6: 1014 break; 1015 }; 1016 1017 WARN_ON(1); 1018 return (union mlxsw_sp_l3addr) { 1019 .addr4 = 0, 1020 }; 1021 } 1022 1023 __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev) 1024 { 1025 struct ip_tunnel *tun = netdev_priv(ol_dev); 1026 1027 return tun->parms.iph.daddr; 1028 } 1029 1030 union mlxsw_sp_l3addr 1031 mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto, 1032 const struct net_device *ol_dev) 1033 { 1034 switch (proto) { 1035 case MLXSW_SP_L3_PROTO_IPV4: 1036 return (union mlxsw_sp_l3addr) { 1037 .addr4 = mlxsw_sp_ipip_netdev_daddr4(ol_dev), 1038 }; 1039 case MLXSW_SP_L3_PROTO_IPV6: 1040 break; 1041 }; 1042 1043 WARN_ON(1); 1044 return (union mlxsw_sp_l3addr) { 1045 .addr4 = 0, 1046 }; 1047 } 1048 1049 static bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1, 1050 const union mlxsw_sp_l3addr *addr2) 1051 { 1052 return !memcmp(addr1, addr2, sizeof(*addr1)); 1053 } 1054 1055 static bool 1056 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp, 1057 const enum mlxsw_sp_l3proto ul_proto, 1058 union mlxsw_sp_l3addr saddr, 1059 u32 ul_tb_id, 1060 struct mlxsw_sp_ipip_entry *ipip_entry) 1061 { 1062 u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev); 1063 enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt; 1064 union mlxsw_sp_l3addr tun_saddr; 1065 1066 if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto) 1067 return false; 1068 1069 tun_saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev); 1070 return tun_ul_tb_id == ul_tb_id && 1071 mlxsw_sp_l3addr_eq(&tun_saddr, &saddr); 1072 } 1073 1074 static int 1075 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp *mlxsw_sp, 1076 struct mlxsw_sp_fib_entry *fib_entry, 1077 struct mlxsw_sp_ipip_entry *ipip_entry) 1078 { 1079 u32 tunnel_index; 1080 int err; 1081 1082 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, 1, &tunnel_index); 1083 if (err) 1084 return err; 1085 1086 ipip_entry->decap_fib_entry = fib_entry; 1087 fib_entry->decap.ipip_entry = ipip_entry; 1088 fib_entry->decap.tunnel_index = tunnel_index; 1089 return 0; 1090 } 1091 1092 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp, 1093 struct mlxsw_sp_fib_entry *fib_entry) 1094 { 1095 /* Unlink this node from the IPIP entry that it's the decap entry of. */ 1096 fib_entry->decap.ipip_entry->decap_fib_entry = NULL; 1097 fib_entry->decap.ipip_entry = NULL; 1098 mlxsw_sp_kvdl_free(mlxsw_sp, fib_entry->decap.tunnel_index); 1099 } 1100 1101 static struct mlxsw_sp_fib_node * 1102 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr, 1103 size_t addr_len, unsigned char prefix_len); 1104 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, 1105 struct mlxsw_sp_fib_entry *fib_entry); 1106 1107 static void 1108 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp, 1109 struct mlxsw_sp_ipip_entry *ipip_entry) 1110 { 1111 struct mlxsw_sp_fib_entry *fib_entry = ipip_entry->decap_fib_entry; 1112 1113 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry); 1114 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; 1115 1116 mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); 1117 } 1118 1119 static void 1120 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp, 1121 struct mlxsw_sp_ipip_entry *ipip_entry, 1122 struct mlxsw_sp_fib_entry *decap_fib_entry) 1123 { 1124 if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry, 1125 ipip_entry)) 1126 return; 1127 decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP; 1128 1129 if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry)) 1130 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry); 1131 } 1132 1133 /* Given an IPIP entry, find the corresponding decap route. */ 1134 static struct mlxsw_sp_fib_entry * 1135 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp, 1136 struct mlxsw_sp_ipip_entry *ipip_entry) 1137 { 1138 static struct mlxsw_sp_fib_node *fib_node; 1139 const struct mlxsw_sp_ipip_ops *ipip_ops; 1140 struct mlxsw_sp_fib_entry *fib_entry; 1141 unsigned char saddr_prefix_len; 1142 union mlxsw_sp_l3addr saddr; 1143 struct mlxsw_sp_fib *ul_fib; 1144 struct mlxsw_sp_vr *ul_vr; 1145 const void *saddrp; 1146 size_t saddr_len; 1147 u32 ul_tb_id; 1148 u32 saddr4; 1149 1150 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]; 1151 1152 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev); 1153 ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id); 1154 if (!ul_vr) 1155 return NULL; 1156 1157 ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto); 1158 saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto, 1159 ipip_entry->ol_dev); 1160 1161 switch (ipip_ops->ul_proto) { 1162 case MLXSW_SP_L3_PROTO_IPV4: 1163 saddr4 = be32_to_cpu(saddr.addr4); 1164 saddrp = &saddr4; 1165 saddr_len = 4; 1166 saddr_prefix_len = 32; 1167 break; 1168 case MLXSW_SP_L3_PROTO_IPV6: 1169 WARN_ON(1); 1170 return NULL; 1171 } 1172 1173 fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len, 1174 saddr_prefix_len); 1175 if (!fib_node || list_empty(&fib_node->entry_list)) 1176 return NULL; 1177 1178 fib_entry = list_first_entry(&fib_node->entry_list, 1179 struct mlxsw_sp_fib_entry, list); 1180 if (fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP) 1181 return NULL; 1182 1183 return fib_entry; 1184 } 1185 1186 static struct mlxsw_sp_ipip_entry * 1187 mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp, 1188 enum mlxsw_sp_ipip_type ipipt, 1189 struct net_device *ol_dev) 1190 { 1191 u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev); 1192 struct mlxsw_sp_router *router = mlxsw_sp->router; 1193 struct mlxsw_sp_fib_entry *decap_fib_entry; 1194 struct mlxsw_sp_ipip_entry *ipip_entry; 1195 enum mlxsw_sp_l3proto ul_proto; 1196 union mlxsw_sp_l3addr saddr; 1197 1198 list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list, 1199 ipip_list_node) { 1200 if (ipip_entry->ol_dev == ol_dev) 1201 goto inc_ref_count; 1202 1203 /* The configuration where several tunnels have the same local 1204 * address in the same underlay table needs special treatment in 1205 * the HW. That is currently not implemented in the driver. 1206 */ 1207 ul_proto = router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto; 1208 saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev); 1209 if (mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, saddr, 1210 ul_tb_id, ipip_entry)) 1211 return ERR_PTR(-EEXIST); 1212 } 1213 1214 ipip_entry = mlxsw_sp_ipip_entry_alloc(mlxsw_sp, ipipt, ol_dev); 1215 if (IS_ERR(ipip_entry)) 1216 return ipip_entry; 1217 1218 decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry); 1219 if (decap_fib_entry) 1220 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry, 1221 decap_fib_entry); 1222 1223 list_add_tail(&ipip_entry->ipip_list_node, 1224 &mlxsw_sp->router->ipip_list); 1225 1226 inc_ref_count: 1227 ++ipip_entry->ref_count; 1228 return ipip_entry; 1229 } 1230 1231 static void 1232 mlxsw_sp_ipip_entry_put(struct mlxsw_sp *mlxsw_sp, 1233 struct mlxsw_sp_ipip_entry *ipip_entry) 1234 { 1235 if (--ipip_entry->ref_count == 0) { 1236 list_del(&ipip_entry->ipip_list_node); 1237 if (ipip_entry->decap_fib_entry) 1238 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry); 1239 mlxsw_sp_ipip_entry_destroy(ipip_entry); 1240 } 1241 } 1242 1243 static bool 1244 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp *mlxsw_sp, 1245 const struct net_device *ul_dev, 1246 enum mlxsw_sp_l3proto ul_proto, 1247 union mlxsw_sp_l3addr ul_dip, 1248 struct mlxsw_sp_ipip_entry *ipip_entry) 1249 { 1250 u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN; 1251 enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt; 1252 struct net_device *ipip_ul_dev; 1253 1254 if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto) 1255 return false; 1256 1257 ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry->ol_dev); 1258 return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, ul_dip, 1259 ul_tb_id, ipip_entry) && 1260 (!ipip_ul_dev || ipip_ul_dev == ul_dev); 1261 } 1262 1263 /* Given decap parameters, find the corresponding IPIP entry. */ 1264 static struct mlxsw_sp_ipip_entry * 1265 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp *mlxsw_sp, 1266 const struct net_device *ul_dev, 1267 enum mlxsw_sp_l3proto ul_proto, 1268 union mlxsw_sp_l3addr ul_dip) 1269 { 1270 struct mlxsw_sp_ipip_entry *ipip_entry; 1271 1272 list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list, 1273 ipip_list_node) 1274 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp, ul_dev, 1275 ul_proto, ul_dip, 1276 ipip_entry)) 1277 return ipip_entry; 1278 1279 return NULL; 1280 } 1281 1282 struct mlxsw_sp_neigh_key { 1283 struct neighbour *n; 1284 }; 1285 1286 struct mlxsw_sp_neigh_entry { 1287 struct list_head rif_list_node; 1288 struct rhash_head ht_node; 1289 struct mlxsw_sp_neigh_key key; 1290 u16 rif; 1291 bool connected; 1292 unsigned char ha[ETH_ALEN]; 1293 struct list_head nexthop_list; /* list of nexthops using 1294 * this neigh entry 1295 */ 1296 struct list_head nexthop_neighs_list_node; 1297 unsigned int counter_index; 1298 bool counter_valid; 1299 }; 1300 1301 static const struct rhashtable_params mlxsw_sp_neigh_ht_params = { 1302 .key_offset = offsetof(struct mlxsw_sp_neigh_entry, key), 1303 .head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node), 1304 .key_len = sizeof(struct mlxsw_sp_neigh_key), 1305 }; 1306 1307 struct mlxsw_sp_neigh_entry * 1308 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif, 1309 struct mlxsw_sp_neigh_entry *neigh_entry) 1310 { 1311 if (!neigh_entry) { 1312 if (list_empty(&rif->neigh_list)) 1313 return NULL; 1314 else 1315 return list_first_entry(&rif->neigh_list, 1316 typeof(*neigh_entry), 1317 rif_list_node); 1318 } 1319 if (neigh_entry->rif_list_node.next == &rif->neigh_list) 1320 return NULL; 1321 return list_next_entry(neigh_entry, rif_list_node); 1322 } 1323 1324 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry) 1325 { 1326 return neigh_entry->key.n->tbl->family; 1327 } 1328 1329 unsigned char * 1330 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry) 1331 { 1332 return neigh_entry->ha; 1333 } 1334 1335 u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry) 1336 { 1337 struct neighbour *n; 1338 1339 n = neigh_entry->key.n; 1340 return ntohl(*((__be32 *) n->primary_key)); 1341 } 1342 1343 struct in6_addr * 1344 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry) 1345 { 1346 struct neighbour *n; 1347 1348 n = neigh_entry->key.n; 1349 return (struct in6_addr *) &n->primary_key; 1350 } 1351 1352 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp, 1353 struct mlxsw_sp_neigh_entry *neigh_entry, 1354 u64 *p_counter) 1355 { 1356 if (!neigh_entry->counter_valid) 1357 return -EINVAL; 1358 1359 return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index, 1360 p_counter, NULL); 1361 } 1362 1363 static struct mlxsw_sp_neigh_entry * 1364 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n, 1365 u16 rif) 1366 { 1367 struct mlxsw_sp_neigh_entry *neigh_entry; 1368 1369 neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL); 1370 if (!neigh_entry) 1371 return NULL; 1372 1373 neigh_entry->key.n = n; 1374 neigh_entry->rif = rif; 1375 INIT_LIST_HEAD(&neigh_entry->nexthop_list); 1376 1377 return neigh_entry; 1378 } 1379 1380 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry) 1381 { 1382 kfree(neigh_entry); 1383 } 1384 1385 static int 1386 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp, 1387 struct mlxsw_sp_neigh_entry *neigh_entry) 1388 { 1389 return rhashtable_insert_fast(&mlxsw_sp->router->neigh_ht, 1390 &neigh_entry->ht_node, 1391 mlxsw_sp_neigh_ht_params); 1392 } 1393 1394 static void 1395 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp, 1396 struct mlxsw_sp_neigh_entry *neigh_entry) 1397 { 1398 rhashtable_remove_fast(&mlxsw_sp->router->neigh_ht, 1399 &neigh_entry->ht_node, 1400 mlxsw_sp_neigh_ht_params); 1401 } 1402 1403 static bool 1404 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp, 1405 struct mlxsw_sp_neigh_entry *neigh_entry) 1406 { 1407 struct devlink *devlink; 1408 const char *table_name; 1409 1410 switch (mlxsw_sp_neigh_entry_type(neigh_entry)) { 1411 case AF_INET: 1412 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4; 1413 break; 1414 case AF_INET6: 1415 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6; 1416 break; 1417 default: 1418 WARN_ON(1); 1419 return false; 1420 } 1421 1422 devlink = priv_to_devlink(mlxsw_sp->core); 1423 return devlink_dpipe_table_counter_enabled(devlink, table_name); 1424 } 1425 1426 static void 1427 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp, 1428 struct mlxsw_sp_neigh_entry *neigh_entry) 1429 { 1430 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry)) 1431 return; 1432 1433 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index)) 1434 return; 1435 1436 neigh_entry->counter_valid = true; 1437 } 1438 1439 static void 1440 mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp, 1441 struct mlxsw_sp_neigh_entry *neigh_entry) 1442 { 1443 if (!neigh_entry->counter_valid) 1444 return; 1445 mlxsw_sp_flow_counter_free(mlxsw_sp, 1446 neigh_entry->counter_index); 1447 neigh_entry->counter_valid = false; 1448 } 1449 1450 static struct mlxsw_sp_neigh_entry * 1451 mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n) 1452 { 1453 struct mlxsw_sp_neigh_entry *neigh_entry; 1454 struct mlxsw_sp_rif *rif; 1455 int err; 1456 1457 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev); 1458 if (!rif) 1459 return ERR_PTR(-EINVAL); 1460 1461 neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index); 1462 if (!neigh_entry) 1463 return ERR_PTR(-ENOMEM); 1464 1465 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry); 1466 if (err) 1467 goto err_neigh_entry_insert; 1468 1469 mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry); 1470 list_add(&neigh_entry->rif_list_node, &rif->neigh_list); 1471 1472 return neigh_entry; 1473 1474 err_neigh_entry_insert: 1475 mlxsw_sp_neigh_entry_free(neigh_entry); 1476 return ERR_PTR(err); 1477 } 1478 1479 static void 1480 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp, 1481 struct mlxsw_sp_neigh_entry *neigh_entry) 1482 { 1483 list_del(&neigh_entry->rif_list_node); 1484 mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry); 1485 mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry); 1486 mlxsw_sp_neigh_entry_free(neigh_entry); 1487 } 1488 1489 static struct mlxsw_sp_neigh_entry * 1490 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n) 1491 { 1492 struct mlxsw_sp_neigh_key key; 1493 1494 key.n = n; 1495 return rhashtable_lookup_fast(&mlxsw_sp->router->neigh_ht, 1496 &key, mlxsw_sp_neigh_ht_params); 1497 } 1498 1499 static void 1500 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp) 1501 { 1502 unsigned long interval; 1503 1504 #if IS_ENABLED(CONFIG_IPV6) 1505 interval = min_t(unsigned long, 1506 NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME), 1507 NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME)); 1508 #else 1509 interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME); 1510 #endif 1511 mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval); 1512 } 1513 1514 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp, 1515 char *rauhtd_pl, 1516 int ent_index) 1517 { 1518 struct net_device *dev; 1519 struct neighbour *n; 1520 __be32 dipn; 1521 u32 dip; 1522 u16 rif; 1523 1524 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip); 1525 1526 if (!mlxsw_sp->router->rifs[rif]) { 1527 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n"); 1528 return; 1529 } 1530 1531 dipn = htonl(dip); 1532 dev = mlxsw_sp->router->rifs[rif]->dev; 1533 n = neigh_lookup(&arp_tbl, &dipn, dev); 1534 if (!n) { 1535 netdev_err(dev, "Failed to find matching neighbour for IP=%pI4h\n", 1536 &dip); 1537 return; 1538 } 1539 1540 netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip); 1541 neigh_event_send(n, NULL); 1542 neigh_release(n); 1543 } 1544 1545 #if IS_ENABLED(CONFIG_IPV6) 1546 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, 1547 char *rauhtd_pl, 1548 int rec_index) 1549 { 1550 struct net_device *dev; 1551 struct neighbour *n; 1552 struct in6_addr dip; 1553 u16 rif; 1554 1555 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif, 1556 (char *) &dip); 1557 1558 if (!mlxsw_sp->router->rifs[rif]) { 1559 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n"); 1560 return; 1561 } 1562 1563 dev = mlxsw_sp->router->rifs[rif]->dev; 1564 n = neigh_lookup(&nd_tbl, &dip, dev); 1565 if (!n) { 1566 netdev_err(dev, "Failed to find matching neighbour for IP=%pI6c\n", 1567 &dip); 1568 return; 1569 } 1570 1571 netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip); 1572 neigh_event_send(n, NULL); 1573 neigh_release(n); 1574 } 1575 #else 1576 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp, 1577 char *rauhtd_pl, 1578 int rec_index) 1579 { 1580 } 1581 #endif 1582 1583 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp, 1584 char *rauhtd_pl, 1585 int rec_index) 1586 { 1587 u8 num_entries; 1588 int i; 1589 1590 num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl, 1591 rec_index); 1592 /* Hardware starts counting at 0, so add 1. */ 1593 num_entries++; 1594 1595 /* Each record consists of several neighbour entries. */ 1596 for (i = 0; i < num_entries; i++) { 1597 int ent_index; 1598 1599 ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i; 1600 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl, 1601 ent_index); 1602 } 1603 1604 } 1605 1606 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp, 1607 char *rauhtd_pl, 1608 int rec_index) 1609 { 1610 /* One record contains one entry. */ 1611 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl, 1612 rec_index); 1613 } 1614 1615 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp, 1616 char *rauhtd_pl, int rec_index) 1617 { 1618 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) { 1619 case MLXSW_REG_RAUHTD_TYPE_IPV4: 1620 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl, 1621 rec_index); 1622 break; 1623 case MLXSW_REG_RAUHTD_TYPE_IPV6: 1624 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl, 1625 rec_index); 1626 break; 1627 } 1628 } 1629 1630 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl) 1631 { 1632 u8 num_rec, last_rec_index, num_entries; 1633 1634 num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl); 1635 last_rec_index = num_rec - 1; 1636 1637 if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM) 1638 return false; 1639 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) == 1640 MLXSW_REG_RAUHTD_TYPE_IPV6) 1641 return true; 1642 1643 num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl, 1644 last_rec_index); 1645 if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC) 1646 return true; 1647 return false; 1648 } 1649 1650 static int 1651 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp, 1652 char *rauhtd_pl, 1653 enum mlxsw_reg_rauhtd_type type) 1654 { 1655 int i, num_rec; 1656 int err; 1657 1658 /* Make sure the neighbour's netdev isn't removed in the 1659 * process. 1660 */ 1661 rtnl_lock(); 1662 do { 1663 mlxsw_reg_rauhtd_pack(rauhtd_pl, type); 1664 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd), 1665 rauhtd_pl); 1666 if (err) { 1667 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour talbe\n"); 1668 break; 1669 } 1670 num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl); 1671 for (i = 0; i < num_rec; i++) 1672 mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl, 1673 i); 1674 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl)); 1675 rtnl_unlock(); 1676 1677 return err; 1678 } 1679 1680 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp) 1681 { 1682 enum mlxsw_reg_rauhtd_type type; 1683 char *rauhtd_pl; 1684 int err; 1685 1686 rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL); 1687 if (!rauhtd_pl) 1688 return -ENOMEM; 1689 1690 type = MLXSW_REG_RAUHTD_TYPE_IPV4; 1691 err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type); 1692 if (err) 1693 goto out; 1694 1695 type = MLXSW_REG_RAUHTD_TYPE_IPV6; 1696 err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type); 1697 out: 1698 kfree(rauhtd_pl); 1699 return err; 1700 } 1701 1702 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp) 1703 { 1704 struct mlxsw_sp_neigh_entry *neigh_entry; 1705 1706 /* Take RTNL mutex here to prevent lists from changes */ 1707 rtnl_lock(); 1708 list_for_each_entry(neigh_entry, &mlxsw_sp->router->nexthop_neighs_list, 1709 nexthop_neighs_list_node) 1710 /* If this neigh have nexthops, make the kernel think this neigh 1711 * is active regardless of the traffic. 1712 */ 1713 neigh_event_send(neigh_entry->key.n, NULL); 1714 rtnl_unlock(); 1715 } 1716 1717 static void 1718 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp) 1719 { 1720 unsigned long interval = mlxsw_sp->router->neighs_update.interval; 1721 1722 mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 1723 msecs_to_jiffies(interval)); 1724 } 1725 1726 static void mlxsw_sp_router_neighs_update_work(struct work_struct *work) 1727 { 1728 struct mlxsw_sp_router *router; 1729 int err; 1730 1731 router = container_of(work, struct mlxsw_sp_router, 1732 neighs_update.dw.work); 1733 err = mlxsw_sp_router_neighs_update_rauhtd(router->mlxsw_sp); 1734 if (err) 1735 dev_err(router->mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity"); 1736 1737 mlxsw_sp_router_neighs_update_nh(router->mlxsw_sp); 1738 1739 mlxsw_sp_router_neighs_update_work_schedule(router->mlxsw_sp); 1740 } 1741 1742 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work) 1743 { 1744 struct mlxsw_sp_neigh_entry *neigh_entry; 1745 struct mlxsw_sp_router *router; 1746 1747 router = container_of(work, struct mlxsw_sp_router, 1748 nexthop_probe_dw.work); 1749 /* Iterate over nexthop neighbours, find those who are unresolved and 1750 * send arp on them. This solves the chicken-egg problem when 1751 * the nexthop wouldn't get offloaded until the neighbor is resolved 1752 * but it wouldn't get resolved ever in case traffic is flowing in HW 1753 * using different nexthop. 1754 * 1755 * Take RTNL mutex here to prevent lists from changes. 1756 */ 1757 rtnl_lock(); 1758 list_for_each_entry(neigh_entry, &router->nexthop_neighs_list, 1759 nexthop_neighs_list_node) 1760 if (!neigh_entry->connected) 1761 neigh_event_send(neigh_entry->key.n, NULL); 1762 rtnl_unlock(); 1763 1764 mlxsw_core_schedule_dw(&router->nexthop_probe_dw, 1765 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL); 1766 } 1767 1768 static void 1769 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp, 1770 struct mlxsw_sp_neigh_entry *neigh_entry, 1771 bool removing); 1772 1773 static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding) 1774 { 1775 return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD : 1776 MLXSW_REG_RAUHT_OP_WRITE_DELETE; 1777 } 1778 1779 static void 1780 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp, 1781 struct mlxsw_sp_neigh_entry *neigh_entry, 1782 enum mlxsw_reg_rauht_op op) 1783 { 1784 struct neighbour *n = neigh_entry->key.n; 1785 u32 dip = ntohl(*((__be32 *) n->primary_key)); 1786 char rauht_pl[MLXSW_REG_RAUHT_LEN]; 1787 1788 mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha, 1789 dip); 1790 if (neigh_entry->counter_valid) 1791 mlxsw_reg_rauht_pack_counter(rauht_pl, 1792 neigh_entry->counter_index); 1793 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl); 1794 } 1795 1796 static void 1797 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp, 1798 struct mlxsw_sp_neigh_entry *neigh_entry, 1799 enum mlxsw_reg_rauht_op op) 1800 { 1801 struct neighbour *n = neigh_entry->key.n; 1802 char rauht_pl[MLXSW_REG_RAUHT_LEN]; 1803 const char *dip = n->primary_key; 1804 1805 mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha, 1806 dip); 1807 if (neigh_entry->counter_valid) 1808 mlxsw_reg_rauht_pack_counter(rauht_pl, 1809 neigh_entry->counter_index); 1810 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl); 1811 } 1812 1813 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry) 1814 { 1815 struct neighbour *n = neigh_entry->key.n; 1816 1817 /* Packets with a link-local destination address are trapped 1818 * after LPM lookup and never reach the neighbour table, so 1819 * there is no need to program such neighbours to the device. 1820 */ 1821 if (ipv6_addr_type((struct in6_addr *) &n->primary_key) & 1822 IPV6_ADDR_LINKLOCAL) 1823 return true; 1824 return false; 1825 } 1826 1827 static void 1828 mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp, 1829 struct mlxsw_sp_neigh_entry *neigh_entry, 1830 bool adding) 1831 { 1832 if (!adding && !neigh_entry->connected) 1833 return; 1834 neigh_entry->connected = adding; 1835 if (neigh_entry->key.n->tbl->family == AF_INET) { 1836 mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry, 1837 mlxsw_sp_rauht_op(adding)); 1838 } else if (neigh_entry->key.n->tbl->family == AF_INET6) { 1839 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry)) 1840 return; 1841 mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry, 1842 mlxsw_sp_rauht_op(adding)); 1843 } else { 1844 WARN_ON_ONCE(1); 1845 } 1846 } 1847 1848 void 1849 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp, 1850 struct mlxsw_sp_neigh_entry *neigh_entry, 1851 bool adding) 1852 { 1853 if (adding) 1854 mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry); 1855 else 1856 mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry); 1857 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true); 1858 } 1859 1860 struct mlxsw_sp_neigh_event_work { 1861 struct work_struct work; 1862 struct mlxsw_sp *mlxsw_sp; 1863 struct neighbour *n; 1864 }; 1865 1866 static void mlxsw_sp_router_neigh_event_work(struct work_struct *work) 1867 { 1868 struct mlxsw_sp_neigh_event_work *neigh_work = 1869 container_of(work, struct mlxsw_sp_neigh_event_work, work); 1870 struct mlxsw_sp *mlxsw_sp = neigh_work->mlxsw_sp; 1871 struct mlxsw_sp_neigh_entry *neigh_entry; 1872 struct neighbour *n = neigh_work->n; 1873 unsigned char ha[ETH_ALEN]; 1874 bool entry_connected; 1875 u8 nud_state, dead; 1876 1877 /* If these parameters are changed after we release the lock, 1878 * then we are guaranteed to receive another event letting us 1879 * know about it. 1880 */ 1881 read_lock_bh(&n->lock); 1882 memcpy(ha, n->ha, ETH_ALEN); 1883 nud_state = n->nud_state; 1884 dead = n->dead; 1885 read_unlock_bh(&n->lock); 1886 1887 rtnl_lock(); 1888 entry_connected = nud_state & NUD_VALID && !dead; 1889 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 1890 if (!entry_connected && !neigh_entry) 1891 goto out; 1892 if (!neigh_entry) { 1893 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n); 1894 if (IS_ERR(neigh_entry)) 1895 goto out; 1896 } 1897 1898 memcpy(neigh_entry->ha, ha, ETH_ALEN); 1899 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected); 1900 mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected); 1901 1902 if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) 1903 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); 1904 1905 out: 1906 rtnl_unlock(); 1907 neigh_release(n); 1908 kfree(neigh_work); 1909 } 1910 1911 int mlxsw_sp_router_netevent_event(struct notifier_block *unused, 1912 unsigned long event, void *ptr) 1913 { 1914 struct mlxsw_sp_neigh_event_work *neigh_work; 1915 struct mlxsw_sp_port *mlxsw_sp_port; 1916 struct mlxsw_sp *mlxsw_sp; 1917 unsigned long interval; 1918 struct neigh_parms *p; 1919 struct neighbour *n; 1920 1921 switch (event) { 1922 case NETEVENT_DELAY_PROBE_TIME_UPDATE: 1923 p = ptr; 1924 1925 /* We don't care about changes in the default table. */ 1926 if (!p->dev || (p->tbl->family != AF_INET && 1927 p->tbl->family != AF_INET6)) 1928 return NOTIFY_DONE; 1929 1930 /* We are in atomic context and can't take RTNL mutex, 1931 * so use RCU variant to walk the device chain. 1932 */ 1933 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev); 1934 if (!mlxsw_sp_port) 1935 return NOTIFY_DONE; 1936 1937 mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1938 interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME)); 1939 mlxsw_sp->router->neighs_update.interval = interval; 1940 1941 mlxsw_sp_port_dev_put(mlxsw_sp_port); 1942 break; 1943 case NETEVENT_NEIGH_UPDATE: 1944 n = ptr; 1945 1946 if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6) 1947 return NOTIFY_DONE; 1948 1949 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev); 1950 if (!mlxsw_sp_port) 1951 return NOTIFY_DONE; 1952 1953 neigh_work = kzalloc(sizeof(*neigh_work), GFP_ATOMIC); 1954 if (!neigh_work) { 1955 mlxsw_sp_port_dev_put(mlxsw_sp_port); 1956 return NOTIFY_BAD; 1957 } 1958 1959 INIT_WORK(&neigh_work->work, mlxsw_sp_router_neigh_event_work); 1960 neigh_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1961 neigh_work->n = n; 1962 1963 /* Take a reference to ensure the neighbour won't be 1964 * destructed until we drop the reference in delayed 1965 * work. 1966 */ 1967 neigh_clone(n); 1968 mlxsw_core_schedule_work(&neigh_work->work); 1969 mlxsw_sp_port_dev_put(mlxsw_sp_port); 1970 break; 1971 } 1972 1973 return NOTIFY_DONE; 1974 } 1975 1976 static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp) 1977 { 1978 int err; 1979 1980 err = rhashtable_init(&mlxsw_sp->router->neigh_ht, 1981 &mlxsw_sp_neigh_ht_params); 1982 if (err) 1983 return err; 1984 1985 /* Initialize the polling interval according to the default 1986 * table. 1987 */ 1988 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp); 1989 1990 /* Create the delayed works for the activity_update */ 1991 INIT_DELAYED_WORK(&mlxsw_sp->router->neighs_update.dw, 1992 mlxsw_sp_router_neighs_update_work); 1993 INIT_DELAYED_WORK(&mlxsw_sp->router->nexthop_probe_dw, 1994 mlxsw_sp_router_probe_unresolved_nexthops); 1995 mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 0); 1996 mlxsw_core_schedule_dw(&mlxsw_sp->router->nexthop_probe_dw, 0); 1997 return 0; 1998 } 1999 2000 static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp) 2001 { 2002 cancel_delayed_work_sync(&mlxsw_sp->router->neighs_update.dw); 2003 cancel_delayed_work_sync(&mlxsw_sp->router->nexthop_probe_dw); 2004 rhashtable_destroy(&mlxsw_sp->router->neigh_ht); 2005 } 2006 2007 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, 2008 struct mlxsw_sp_rif *rif) 2009 { 2010 struct mlxsw_sp_neigh_entry *neigh_entry, *tmp; 2011 2012 list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list, 2013 rif_list_node) { 2014 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, false); 2015 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); 2016 } 2017 } 2018 2019 enum mlxsw_sp_nexthop_type { 2020 MLXSW_SP_NEXTHOP_TYPE_ETH, 2021 MLXSW_SP_NEXTHOP_TYPE_IPIP, 2022 }; 2023 2024 struct mlxsw_sp_nexthop_key { 2025 struct fib_nh *fib_nh; 2026 }; 2027 2028 struct mlxsw_sp_nexthop { 2029 struct list_head neigh_list_node; /* member of neigh entry list */ 2030 struct list_head rif_list_node; 2031 struct mlxsw_sp_nexthop_group *nh_grp; /* pointer back to the group 2032 * this belongs to 2033 */ 2034 struct rhash_head ht_node; 2035 struct mlxsw_sp_nexthop_key key; 2036 unsigned char gw_addr[sizeof(struct in6_addr)]; 2037 int ifindex; 2038 struct mlxsw_sp_rif *rif; 2039 u8 should_offload:1, /* set indicates this neigh is connected and 2040 * should be put to KVD linear area of this group. 2041 */ 2042 offloaded:1, /* set in case the neigh is actually put into 2043 * KVD linear area of this group. 2044 */ 2045 update:1; /* set indicates that MAC of this neigh should be 2046 * updated in HW 2047 */ 2048 enum mlxsw_sp_nexthop_type type; 2049 union { 2050 struct mlxsw_sp_neigh_entry *neigh_entry; 2051 struct mlxsw_sp_ipip_entry *ipip_entry; 2052 }; 2053 }; 2054 2055 struct mlxsw_sp_nexthop_group { 2056 void *priv; 2057 struct rhash_head ht_node; 2058 struct list_head fib_list; /* list of fib entries that use this group */ 2059 struct neigh_table *neigh_tbl; 2060 u8 adj_index_valid:1, 2061 gateway:1; /* routes using the group use a gateway */ 2062 u32 adj_index; 2063 u16 ecmp_size; 2064 u16 count; 2065 struct mlxsw_sp_nexthop nexthops[0]; 2066 #define nh_rif nexthops[0].rif 2067 }; 2068 2069 static struct fib_info * 2070 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group *nh_grp) 2071 { 2072 return nh_grp->priv; 2073 } 2074 2075 struct mlxsw_sp_nexthop_group_cmp_arg { 2076 enum mlxsw_sp_l3proto proto; 2077 union { 2078 struct fib_info *fi; 2079 struct mlxsw_sp_fib6_entry *fib6_entry; 2080 }; 2081 }; 2082 2083 static bool 2084 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group *nh_grp, 2085 const struct in6_addr *gw, int ifindex) 2086 { 2087 int i; 2088 2089 for (i = 0; i < nh_grp->count; i++) { 2090 const struct mlxsw_sp_nexthop *nh; 2091 2092 nh = &nh_grp->nexthops[i]; 2093 if (nh->ifindex == ifindex && 2094 ipv6_addr_equal(gw, (struct in6_addr *) nh->gw_addr)) 2095 return true; 2096 } 2097 2098 return false; 2099 } 2100 2101 static bool 2102 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp, 2103 const struct mlxsw_sp_fib6_entry *fib6_entry) 2104 { 2105 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 2106 2107 if (nh_grp->count != fib6_entry->nrt6) 2108 return false; 2109 2110 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { 2111 struct in6_addr *gw; 2112 int ifindex; 2113 2114 ifindex = mlxsw_sp_rt6->rt->dst.dev->ifindex; 2115 gw = &mlxsw_sp_rt6->rt->rt6i_gateway; 2116 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex)) 2117 return false; 2118 } 2119 2120 return true; 2121 } 2122 2123 static int 2124 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg *arg, const void *ptr) 2125 { 2126 const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = arg->key; 2127 const struct mlxsw_sp_nexthop_group *nh_grp = ptr; 2128 2129 switch (cmp_arg->proto) { 2130 case MLXSW_SP_L3_PROTO_IPV4: 2131 return cmp_arg->fi != mlxsw_sp_nexthop4_group_fi(nh_grp); 2132 case MLXSW_SP_L3_PROTO_IPV6: 2133 return !mlxsw_sp_nexthop6_group_cmp(nh_grp, 2134 cmp_arg->fib6_entry); 2135 default: 2136 WARN_ON(1); 2137 return 1; 2138 } 2139 } 2140 2141 static int 2142 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group *nh_grp) 2143 { 2144 return nh_grp->neigh_tbl->family; 2145 } 2146 2147 static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed) 2148 { 2149 const struct mlxsw_sp_nexthop_group *nh_grp = data; 2150 const struct mlxsw_sp_nexthop *nh; 2151 struct fib_info *fi; 2152 unsigned int val; 2153 int i; 2154 2155 switch (mlxsw_sp_nexthop_group_type(nh_grp)) { 2156 case AF_INET: 2157 fi = mlxsw_sp_nexthop4_group_fi(nh_grp); 2158 return jhash(&fi, sizeof(fi), seed); 2159 case AF_INET6: 2160 val = nh_grp->count; 2161 for (i = 0; i < nh_grp->count; i++) { 2162 nh = &nh_grp->nexthops[i]; 2163 val ^= nh->ifindex; 2164 } 2165 return jhash(&val, sizeof(val), seed); 2166 default: 2167 WARN_ON(1); 2168 return 0; 2169 } 2170 } 2171 2172 static u32 2173 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed) 2174 { 2175 unsigned int val = fib6_entry->nrt6; 2176 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 2177 struct net_device *dev; 2178 2179 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { 2180 dev = mlxsw_sp_rt6->rt->dst.dev; 2181 val ^= dev->ifindex; 2182 } 2183 2184 return jhash(&val, sizeof(val), seed); 2185 } 2186 2187 static u32 2188 mlxsw_sp_nexthop_group_hash(const void *data, u32 len, u32 seed) 2189 { 2190 const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = data; 2191 2192 switch (cmp_arg->proto) { 2193 case MLXSW_SP_L3_PROTO_IPV4: 2194 return jhash(&cmp_arg->fi, sizeof(cmp_arg->fi), seed); 2195 case MLXSW_SP_L3_PROTO_IPV6: 2196 return mlxsw_sp_nexthop6_group_hash(cmp_arg->fib6_entry, seed); 2197 default: 2198 WARN_ON(1); 2199 return 0; 2200 } 2201 } 2202 2203 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = { 2204 .head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node), 2205 .hashfn = mlxsw_sp_nexthop_group_hash, 2206 .obj_hashfn = mlxsw_sp_nexthop_group_hash_obj, 2207 .obj_cmpfn = mlxsw_sp_nexthop_group_cmp, 2208 }; 2209 2210 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp, 2211 struct mlxsw_sp_nexthop_group *nh_grp) 2212 { 2213 if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 && 2214 !nh_grp->gateway) 2215 return 0; 2216 2217 return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_group_ht, 2218 &nh_grp->ht_node, 2219 mlxsw_sp_nexthop_group_ht_params); 2220 } 2221 2222 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp, 2223 struct mlxsw_sp_nexthop_group *nh_grp) 2224 { 2225 if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 && 2226 !nh_grp->gateway) 2227 return; 2228 2229 rhashtable_remove_fast(&mlxsw_sp->router->nexthop_group_ht, 2230 &nh_grp->ht_node, 2231 mlxsw_sp_nexthop_group_ht_params); 2232 } 2233 2234 static struct mlxsw_sp_nexthop_group * 2235 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp *mlxsw_sp, 2236 struct fib_info *fi) 2237 { 2238 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg; 2239 2240 cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV4; 2241 cmp_arg.fi = fi; 2242 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht, 2243 &cmp_arg, 2244 mlxsw_sp_nexthop_group_ht_params); 2245 } 2246 2247 static struct mlxsw_sp_nexthop_group * 2248 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp *mlxsw_sp, 2249 struct mlxsw_sp_fib6_entry *fib6_entry) 2250 { 2251 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg; 2252 2253 cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV6; 2254 cmp_arg.fib6_entry = fib6_entry; 2255 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht, 2256 &cmp_arg, 2257 mlxsw_sp_nexthop_group_ht_params); 2258 } 2259 2260 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = { 2261 .key_offset = offsetof(struct mlxsw_sp_nexthop, key), 2262 .head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node), 2263 .key_len = sizeof(struct mlxsw_sp_nexthop_key), 2264 }; 2265 2266 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp, 2267 struct mlxsw_sp_nexthop *nh) 2268 { 2269 return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_ht, 2270 &nh->ht_node, mlxsw_sp_nexthop_ht_params); 2271 } 2272 2273 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp, 2274 struct mlxsw_sp_nexthop *nh) 2275 { 2276 rhashtable_remove_fast(&mlxsw_sp->router->nexthop_ht, &nh->ht_node, 2277 mlxsw_sp_nexthop_ht_params); 2278 } 2279 2280 static struct mlxsw_sp_nexthop * 2281 mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp, 2282 struct mlxsw_sp_nexthop_key key) 2283 { 2284 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_ht, &key, 2285 mlxsw_sp_nexthop_ht_params); 2286 } 2287 2288 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp, 2289 const struct mlxsw_sp_fib *fib, 2290 u32 adj_index, u16 ecmp_size, 2291 u32 new_adj_index, 2292 u16 new_ecmp_size) 2293 { 2294 char raleu_pl[MLXSW_REG_RALEU_LEN]; 2295 2296 mlxsw_reg_raleu_pack(raleu_pl, 2297 (enum mlxsw_reg_ralxx_protocol) fib->proto, 2298 fib->vr->id, adj_index, ecmp_size, new_adj_index, 2299 new_ecmp_size); 2300 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl); 2301 } 2302 2303 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp, 2304 struct mlxsw_sp_nexthop_group *nh_grp, 2305 u32 old_adj_index, u16 old_ecmp_size) 2306 { 2307 struct mlxsw_sp_fib_entry *fib_entry; 2308 struct mlxsw_sp_fib *fib = NULL; 2309 int err; 2310 2311 list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) { 2312 if (fib == fib_entry->fib_node->fib) 2313 continue; 2314 fib = fib_entry->fib_node->fib; 2315 err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, fib, 2316 old_adj_index, 2317 old_ecmp_size, 2318 nh_grp->adj_index, 2319 nh_grp->ecmp_size); 2320 if (err) 2321 return err; 2322 } 2323 return 0; 2324 } 2325 2326 static int mlxsw_sp_nexthop_mac_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index, 2327 struct mlxsw_sp_nexthop *nh) 2328 { 2329 struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; 2330 char ratr_pl[MLXSW_REG_RATR_LEN]; 2331 2332 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, 2333 true, MLXSW_REG_RATR_TYPE_ETHERNET, 2334 adj_index, neigh_entry->rif); 2335 mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha); 2336 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); 2337 } 2338 2339 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp, 2340 u32 adj_index, 2341 struct mlxsw_sp_nexthop *nh) 2342 { 2343 const struct mlxsw_sp_ipip_ops *ipip_ops; 2344 2345 ipip_ops = mlxsw_sp->router->ipip_ops_arr[nh->ipip_entry->ipipt]; 2346 return ipip_ops->nexthop_update(mlxsw_sp, adj_index, nh->ipip_entry); 2347 } 2348 2349 static int 2350 mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp, 2351 struct mlxsw_sp_nexthop_group *nh_grp, 2352 bool reallocate) 2353 { 2354 u32 adj_index = nh_grp->adj_index; /* base */ 2355 struct mlxsw_sp_nexthop *nh; 2356 int i; 2357 int err; 2358 2359 for (i = 0; i < nh_grp->count; i++) { 2360 nh = &nh_grp->nexthops[i]; 2361 2362 if (!nh->should_offload) { 2363 nh->offloaded = 0; 2364 continue; 2365 } 2366 2367 if (nh->update || reallocate) { 2368 switch (nh->type) { 2369 case MLXSW_SP_NEXTHOP_TYPE_ETH: 2370 err = mlxsw_sp_nexthop_mac_update 2371 (mlxsw_sp, adj_index, nh); 2372 break; 2373 case MLXSW_SP_NEXTHOP_TYPE_IPIP: 2374 err = mlxsw_sp_nexthop_ipip_update 2375 (mlxsw_sp, adj_index, nh); 2376 break; 2377 } 2378 if (err) 2379 return err; 2380 nh->update = 0; 2381 nh->offloaded = 1; 2382 } 2383 adj_index++; 2384 } 2385 return 0; 2386 } 2387 2388 static bool 2389 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node, 2390 const struct mlxsw_sp_fib_entry *fib_entry); 2391 2392 static int 2393 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp, 2394 struct mlxsw_sp_nexthop_group *nh_grp) 2395 { 2396 struct mlxsw_sp_fib_entry *fib_entry; 2397 int err; 2398 2399 list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) { 2400 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node, 2401 fib_entry)) 2402 continue; 2403 err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); 2404 if (err) 2405 return err; 2406 } 2407 return 0; 2408 } 2409 2410 static void 2411 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry, 2412 enum mlxsw_reg_ralue_op op, int err); 2413 2414 static void 2415 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group *nh_grp) 2416 { 2417 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_WRITE; 2418 struct mlxsw_sp_fib_entry *fib_entry; 2419 2420 list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) { 2421 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node, 2422 fib_entry)) 2423 continue; 2424 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0); 2425 } 2426 } 2427 2428 static void 2429 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp, 2430 struct mlxsw_sp_nexthop_group *nh_grp) 2431 { 2432 struct mlxsw_sp_nexthop *nh; 2433 bool offload_change = false; 2434 u32 adj_index; 2435 u16 ecmp_size = 0; 2436 bool old_adj_index_valid; 2437 u32 old_adj_index; 2438 u16 old_ecmp_size; 2439 int i; 2440 int err; 2441 2442 if (!nh_grp->gateway) { 2443 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp); 2444 return; 2445 } 2446 2447 for (i = 0; i < nh_grp->count; i++) { 2448 nh = &nh_grp->nexthops[i]; 2449 2450 if (nh->should_offload != nh->offloaded) { 2451 offload_change = true; 2452 if (nh->should_offload) 2453 nh->update = 1; 2454 } 2455 if (nh->should_offload) 2456 ecmp_size++; 2457 } 2458 if (!offload_change) { 2459 /* Nothing was added or removed, so no need to reallocate. Just 2460 * update MAC on existing adjacency indexes. 2461 */ 2462 err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, false); 2463 if (err) { 2464 dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n"); 2465 goto set_trap; 2466 } 2467 return; 2468 } 2469 if (!ecmp_size) 2470 /* No neigh of this group is connected so we just set 2471 * the trap and let everthing flow through kernel. 2472 */ 2473 goto set_trap; 2474 2475 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, ecmp_size, &adj_index); 2476 if (err) { 2477 /* We ran out of KVD linear space, just set the 2478 * trap and let everything flow through kernel. 2479 */ 2480 dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n"); 2481 goto set_trap; 2482 } 2483 old_adj_index_valid = nh_grp->adj_index_valid; 2484 old_adj_index = nh_grp->adj_index; 2485 old_ecmp_size = nh_grp->ecmp_size; 2486 nh_grp->adj_index_valid = 1; 2487 nh_grp->adj_index = adj_index; 2488 nh_grp->ecmp_size = ecmp_size; 2489 err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, true); 2490 if (err) { 2491 dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n"); 2492 goto set_trap; 2493 } 2494 2495 if (!old_adj_index_valid) { 2496 /* The trap was set for fib entries, so we have to call 2497 * fib entry update to unset it and use adjacency index. 2498 */ 2499 err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp); 2500 if (err) { 2501 dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n"); 2502 goto set_trap; 2503 } 2504 return; 2505 } 2506 2507 err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp, 2508 old_adj_index, old_ecmp_size); 2509 mlxsw_sp_kvdl_free(mlxsw_sp, old_adj_index); 2510 if (err) { 2511 dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n"); 2512 goto set_trap; 2513 } 2514 2515 /* Offload state within the group changed, so update the flags. */ 2516 mlxsw_sp_nexthop_fib_entries_refresh(nh_grp); 2517 2518 return; 2519 2520 set_trap: 2521 old_adj_index_valid = nh_grp->adj_index_valid; 2522 nh_grp->adj_index_valid = 0; 2523 for (i = 0; i < nh_grp->count; i++) { 2524 nh = &nh_grp->nexthops[i]; 2525 nh->offloaded = 0; 2526 } 2527 err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp); 2528 if (err) 2529 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n"); 2530 if (old_adj_index_valid) 2531 mlxsw_sp_kvdl_free(mlxsw_sp, nh_grp->adj_index); 2532 } 2533 2534 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh, 2535 bool removing) 2536 { 2537 if (!removing) 2538 nh->should_offload = 1; 2539 else if (nh->offloaded) 2540 nh->should_offload = 0; 2541 nh->update = 1; 2542 } 2543 2544 static void 2545 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp, 2546 struct mlxsw_sp_neigh_entry *neigh_entry, 2547 bool removing) 2548 { 2549 struct mlxsw_sp_nexthop *nh; 2550 2551 list_for_each_entry(nh, &neigh_entry->nexthop_list, 2552 neigh_list_node) { 2553 __mlxsw_sp_nexthop_neigh_update(nh, removing); 2554 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp); 2555 } 2556 } 2557 2558 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh, 2559 struct mlxsw_sp_rif *rif) 2560 { 2561 if (nh->rif) 2562 return; 2563 2564 nh->rif = rif; 2565 list_add(&nh->rif_list_node, &rif->nexthop_list); 2566 } 2567 2568 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh) 2569 { 2570 if (!nh->rif) 2571 return; 2572 2573 list_del(&nh->rif_list_node); 2574 nh->rif = NULL; 2575 } 2576 2577 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp, 2578 struct mlxsw_sp_nexthop *nh) 2579 { 2580 struct mlxsw_sp_neigh_entry *neigh_entry; 2581 struct neighbour *n; 2582 u8 nud_state, dead; 2583 int err; 2584 2585 if (!nh->nh_grp->gateway || nh->neigh_entry) 2586 return 0; 2587 2588 /* Take a reference of neigh here ensuring that neigh would 2589 * not be destructed before the nexthop entry is finished. 2590 * The reference is taken either in neigh_lookup() or 2591 * in neigh_create() in case n is not found. 2592 */ 2593 n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev); 2594 if (!n) { 2595 n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr, 2596 nh->rif->dev); 2597 if (IS_ERR(n)) 2598 return PTR_ERR(n); 2599 neigh_event_send(n, NULL); 2600 } 2601 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n); 2602 if (!neigh_entry) { 2603 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n); 2604 if (IS_ERR(neigh_entry)) { 2605 err = -EINVAL; 2606 goto err_neigh_entry_create; 2607 } 2608 } 2609 2610 /* If that is the first nexthop connected to that neigh, add to 2611 * nexthop_neighs_list 2612 */ 2613 if (list_empty(&neigh_entry->nexthop_list)) 2614 list_add_tail(&neigh_entry->nexthop_neighs_list_node, 2615 &mlxsw_sp->router->nexthop_neighs_list); 2616 2617 nh->neigh_entry = neigh_entry; 2618 list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list); 2619 read_lock_bh(&n->lock); 2620 nud_state = n->nud_state; 2621 dead = n->dead; 2622 read_unlock_bh(&n->lock); 2623 __mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead)); 2624 2625 return 0; 2626 2627 err_neigh_entry_create: 2628 neigh_release(n); 2629 return err; 2630 } 2631 2632 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp, 2633 struct mlxsw_sp_nexthop *nh) 2634 { 2635 struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry; 2636 struct neighbour *n; 2637 2638 if (!neigh_entry) 2639 return; 2640 n = neigh_entry->key.n; 2641 2642 __mlxsw_sp_nexthop_neigh_update(nh, true); 2643 list_del(&nh->neigh_list_node); 2644 nh->neigh_entry = NULL; 2645 2646 /* If that is the last nexthop connected to that neigh, remove from 2647 * nexthop_neighs_list 2648 */ 2649 if (list_empty(&neigh_entry->nexthop_list)) 2650 list_del(&neigh_entry->nexthop_neighs_list_node); 2651 2652 if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list)) 2653 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry); 2654 2655 neigh_release(n); 2656 } 2657 2658 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp, 2659 const struct net_device *dev, 2660 enum mlxsw_sp_ipip_type *p_type) 2661 { 2662 struct mlxsw_sp_router *router = mlxsw_sp->router; 2663 const struct mlxsw_sp_ipip_ops *ipip_ops; 2664 enum mlxsw_sp_ipip_type ipipt; 2665 2666 for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) { 2667 ipip_ops = router->ipip_ops_arr[ipipt]; 2668 if (dev->type == ipip_ops->dev_type) { 2669 if (p_type) 2670 *p_type = ipipt; 2671 return true; 2672 } 2673 } 2674 return false; 2675 } 2676 2677 static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp, 2678 enum mlxsw_sp_ipip_type ipipt, 2679 struct mlxsw_sp_nexthop *nh, 2680 struct net_device *ol_dev) 2681 { 2682 if (!nh->nh_grp->gateway || nh->ipip_entry) 2683 return 0; 2684 2685 nh->ipip_entry = mlxsw_sp_ipip_entry_get(mlxsw_sp, ipipt, ol_dev); 2686 if (IS_ERR(nh->ipip_entry)) 2687 return PTR_ERR(nh->ipip_entry); 2688 2689 __mlxsw_sp_nexthop_neigh_update(nh, false); 2690 return 0; 2691 } 2692 2693 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp, 2694 struct mlxsw_sp_nexthop *nh) 2695 { 2696 struct mlxsw_sp_ipip_entry *ipip_entry = nh->ipip_entry; 2697 2698 if (!ipip_entry) 2699 return; 2700 2701 __mlxsw_sp_nexthop_neigh_update(nh, true); 2702 mlxsw_sp_ipip_entry_put(mlxsw_sp, ipip_entry); 2703 nh->ipip_entry = NULL; 2704 } 2705 2706 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp, 2707 const struct fib_nh *fib_nh, 2708 enum mlxsw_sp_ipip_type *p_ipipt) 2709 { 2710 struct net_device *dev = fib_nh->nh_dev; 2711 2712 return dev && 2713 fib_nh->nh_parent->fib_type == RTN_UNICAST && 2714 mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, p_ipipt); 2715 } 2716 2717 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp, 2718 struct mlxsw_sp_nexthop *nh) 2719 { 2720 switch (nh->type) { 2721 case MLXSW_SP_NEXTHOP_TYPE_ETH: 2722 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh); 2723 mlxsw_sp_nexthop_rif_fini(nh); 2724 break; 2725 case MLXSW_SP_NEXTHOP_TYPE_IPIP: 2726 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh); 2727 break; 2728 } 2729 } 2730 2731 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp, 2732 struct mlxsw_sp_nexthop *nh, 2733 struct fib_nh *fib_nh) 2734 { 2735 struct mlxsw_sp_router *router = mlxsw_sp->router; 2736 struct net_device *dev = fib_nh->nh_dev; 2737 enum mlxsw_sp_ipip_type ipipt; 2738 struct mlxsw_sp_rif *rif; 2739 int err; 2740 2741 if (mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fib_nh, &ipipt) && 2742 router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev, 2743 MLXSW_SP_L3_PROTO_IPV4)) { 2744 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP; 2745 return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); 2746 } 2747 2748 nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH; 2749 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); 2750 if (!rif) 2751 return 0; 2752 2753 mlxsw_sp_nexthop_rif_init(nh, rif); 2754 err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh); 2755 if (err) 2756 goto err_neigh_init; 2757 2758 return 0; 2759 2760 err_neigh_init: 2761 mlxsw_sp_nexthop_rif_fini(nh); 2762 return err; 2763 } 2764 2765 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp *mlxsw_sp, 2766 struct mlxsw_sp_nexthop *nh) 2767 { 2768 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh); 2769 } 2770 2771 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp, 2772 struct mlxsw_sp_nexthop_group *nh_grp, 2773 struct mlxsw_sp_nexthop *nh, 2774 struct fib_nh *fib_nh) 2775 { 2776 struct net_device *dev = fib_nh->nh_dev; 2777 struct in_device *in_dev; 2778 int err; 2779 2780 nh->nh_grp = nh_grp; 2781 nh->key.fib_nh = fib_nh; 2782 memcpy(&nh->gw_addr, &fib_nh->nh_gw, sizeof(fib_nh->nh_gw)); 2783 err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh); 2784 if (err) 2785 return err; 2786 2787 if (!dev) 2788 return 0; 2789 2790 in_dev = __in_dev_get_rtnl(dev); 2791 if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) && 2792 fib_nh->nh_flags & RTNH_F_LINKDOWN) 2793 return 0; 2794 2795 err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh); 2796 if (err) 2797 goto err_nexthop_neigh_init; 2798 2799 return 0; 2800 2801 err_nexthop_neigh_init: 2802 mlxsw_sp_nexthop_remove(mlxsw_sp, nh); 2803 return err; 2804 } 2805 2806 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp, 2807 struct mlxsw_sp_nexthop *nh) 2808 { 2809 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh); 2810 mlxsw_sp_nexthop_remove(mlxsw_sp, nh); 2811 } 2812 2813 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp, 2814 unsigned long event, struct fib_nh *fib_nh) 2815 { 2816 struct mlxsw_sp_nexthop_key key; 2817 struct mlxsw_sp_nexthop *nh; 2818 2819 if (mlxsw_sp->router->aborted) 2820 return; 2821 2822 key.fib_nh = fib_nh; 2823 nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key); 2824 if (WARN_ON_ONCE(!nh)) 2825 return; 2826 2827 switch (event) { 2828 case FIB_EVENT_NH_ADD: 2829 mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh); 2830 break; 2831 case FIB_EVENT_NH_DEL: 2832 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh); 2833 break; 2834 } 2835 2836 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp); 2837 } 2838 2839 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, 2840 struct mlxsw_sp_rif *rif) 2841 { 2842 struct mlxsw_sp_nexthop *nh, *tmp; 2843 2844 list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) { 2845 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh); 2846 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp); 2847 } 2848 } 2849 2850 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp, 2851 const struct fib_info *fi) 2852 { 2853 return fi->fib_nh->nh_scope == RT_SCOPE_LINK || 2854 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fi->fib_nh, NULL); 2855 } 2856 2857 static struct mlxsw_sp_nexthop_group * 2858 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi) 2859 { 2860 struct mlxsw_sp_nexthop_group *nh_grp; 2861 struct mlxsw_sp_nexthop *nh; 2862 struct fib_nh *fib_nh; 2863 size_t alloc_size; 2864 int i; 2865 int err; 2866 2867 alloc_size = sizeof(*nh_grp) + 2868 fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop); 2869 nh_grp = kzalloc(alloc_size, GFP_KERNEL); 2870 if (!nh_grp) 2871 return ERR_PTR(-ENOMEM); 2872 nh_grp->priv = fi; 2873 INIT_LIST_HEAD(&nh_grp->fib_list); 2874 nh_grp->neigh_tbl = &arp_tbl; 2875 2876 nh_grp->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, fi); 2877 nh_grp->count = fi->fib_nhs; 2878 fib_info_hold(fi); 2879 for (i = 0; i < nh_grp->count; i++) { 2880 nh = &nh_grp->nexthops[i]; 2881 fib_nh = &fi->fib_nh[i]; 2882 err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh); 2883 if (err) 2884 goto err_nexthop4_init; 2885 } 2886 err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp); 2887 if (err) 2888 goto err_nexthop_group_insert; 2889 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp); 2890 return nh_grp; 2891 2892 err_nexthop_group_insert: 2893 err_nexthop4_init: 2894 for (i--; i >= 0; i--) { 2895 nh = &nh_grp->nexthops[i]; 2896 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh); 2897 } 2898 fib_info_put(fi); 2899 kfree(nh_grp); 2900 return ERR_PTR(err); 2901 } 2902 2903 static void 2904 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp, 2905 struct mlxsw_sp_nexthop_group *nh_grp) 2906 { 2907 struct mlxsw_sp_nexthop *nh; 2908 int i; 2909 2910 mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp); 2911 for (i = 0; i < nh_grp->count; i++) { 2912 nh = &nh_grp->nexthops[i]; 2913 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh); 2914 } 2915 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp); 2916 WARN_ON_ONCE(nh_grp->adj_index_valid); 2917 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp)); 2918 kfree(nh_grp); 2919 } 2920 2921 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp, 2922 struct mlxsw_sp_fib_entry *fib_entry, 2923 struct fib_info *fi) 2924 { 2925 struct mlxsw_sp_nexthop_group *nh_grp; 2926 2927 nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi); 2928 if (!nh_grp) { 2929 nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi); 2930 if (IS_ERR(nh_grp)) 2931 return PTR_ERR(nh_grp); 2932 } 2933 list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list); 2934 fib_entry->nh_group = nh_grp; 2935 return 0; 2936 } 2937 2938 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp, 2939 struct mlxsw_sp_fib_entry *fib_entry) 2940 { 2941 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; 2942 2943 list_del(&fib_entry->nexthop_group_node); 2944 if (!list_empty(&nh_grp->fib_list)) 2945 return; 2946 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp); 2947 } 2948 2949 static bool 2950 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry) 2951 { 2952 struct mlxsw_sp_fib4_entry *fib4_entry; 2953 2954 fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry, 2955 common); 2956 return !fib4_entry->tos; 2957 } 2958 2959 static bool 2960 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry) 2961 { 2962 struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group; 2963 2964 switch (fib_entry->fib_node->fib->proto) { 2965 case MLXSW_SP_L3_PROTO_IPV4: 2966 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry)) 2967 return false; 2968 break; 2969 case MLXSW_SP_L3_PROTO_IPV6: 2970 break; 2971 } 2972 2973 switch (fib_entry->type) { 2974 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE: 2975 return !!nh_group->adj_index_valid; 2976 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: 2977 return !!nh_group->nh_rif; 2978 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: 2979 return true; 2980 default: 2981 return false; 2982 } 2983 } 2984 2985 static struct mlxsw_sp_nexthop * 2986 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp, 2987 const struct mlxsw_sp_rt6 *mlxsw_sp_rt6) 2988 { 2989 int i; 2990 2991 for (i = 0; i < nh_grp->count; i++) { 2992 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i]; 2993 struct rt6_info *rt = mlxsw_sp_rt6->rt; 2994 2995 if (nh->rif && nh->rif->dev == rt->dst.dev && 2996 ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr, 2997 &rt->rt6i_gateway)) 2998 return nh; 2999 continue; 3000 } 3001 3002 return NULL; 3003 } 3004 3005 static void 3006 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) 3007 { 3008 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; 3009 int i; 3010 3011 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL || 3012 fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP) { 3013 nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD; 3014 return; 3015 } 3016 3017 for (i = 0; i < nh_grp->count; i++) { 3018 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i]; 3019 3020 if (nh->offloaded) 3021 nh->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD; 3022 else 3023 nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD; 3024 } 3025 } 3026 3027 static void 3028 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry) 3029 { 3030 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; 3031 int i; 3032 3033 for (i = 0; i < nh_grp->count; i++) { 3034 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i]; 3035 3036 nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD; 3037 } 3038 } 3039 3040 static void 3041 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) 3042 { 3043 struct mlxsw_sp_fib6_entry *fib6_entry; 3044 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 3045 3046 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry, 3047 common); 3048 3049 if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) { 3050 list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6, 3051 list)->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD; 3052 return; 3053 } 3054 3055 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { 3056 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; 3057 struct mlxsw_sp_nexthop *nh; 3058 3059 nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6); 3060 if (nh && nh->offloaded) 3061 mlxsw_sp_rt6->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD; 3062 else 3063 mlxsw_sp_rt6->rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD; 3064 } 3065 } 3066 3067 static void 3068 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry) 3069 { 3070 struct mlxsw_sp_fib6_entry *fib6_entry; 3071 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 3072 3073 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry, 3074 common); 3075 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { 3076 struct rt6_info *rt = mlxsw_sp_rt6->rt; 3077 3078 rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD; 3079 } 3080 } 3081 3082 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) 3083 { 3084 switch (fib_entry->fib_node->fib->proto) { 3085 case MLXSW_SP_L3_PROTO_IPV4: 3086 mlxsw_sp_fib4_entry_offload_set(fib_entry); 3087 break; 3088 case MLXSW_SP_L3_PROTO_IPV6: 3089 mlxsw_sp_fib6_entry_offload_set(fib_entry); 3090 break; 3091 } 3092 } 3093 3094 static void 3095 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry) 3096 { 3097 switch (fib_entry->fib_node->fib->proto) { 3098 case MLXSW_SP_L3_PROTO_IPV4: 3099 mlxsw_sp_fib4_entry_offload_unset(fib_entry); 3100 break; 3101 case MLXSW_SP_L3_PROTO_IPV6: 3102 mlxsw_sp_fib6_entry_offload_unset(fib_entry); 3103 break; 3104 } 3105 } 3106 3107 static void 3108 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry, 3109 enum mlxsw_reg_ralue_op op, int err) 3110 { 3111 switch (op) { 3112 case MLXSW_REG_RALUE_OP_WRITE_DELETE: 3113 return mlxsw_sp_fib_entry_offload_unset(fib_entry); 3114 case MLXSW_REG_RALUE_OP_WRITE_WRITE: 3115 if (err) 3116 return; 3117 if (mlxsw_sp_fib_entry_should_offload(fib_entry)) 3118 mlxsw_sp_fib_entry_offload_set(fib_entry); 3119 else if (!mlxsw_sp_fib_entry_should_offload(fib_entry)) 3120 mlxsw_sp_fib_entry_offload_unset(fib_entry); 3121 return; 3122 default: 3123 return; 3124 } 3125 } 3126 3127 static void 3128 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl, 3129 const struct mlxsw_sp_fib_entry *fib_entry, 3130 enum mlxsw_reg_ralue_op op) 3131 { 3132 struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib; 3133 enum mlxsw_reg_ralxx_protocol proto; 3134 u32 *p_dip; 3135 3136 proto = (enum mlxsw_reg_ralxx_protocol) fib->proto; 3137 3138 switch (fib->proto) { 3139 case MLXSW_SP_L3_PROTO_IPV4: 3140 p_dip = (u32 *) fib_entry->fib_node->key.addr; 3141 mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id, 3142 fib_entry->fib_node->key.prefix_len, 3143 *p_dip); 3144 break; 3145 case MLXSW_SP_L3_PROTO_IPV6: 3146 mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id, 3147 fib_entry->fib_node->key.prefix_len, 3148 fib_entry->fib_node->key.addr); 3149 break; 3150 } 3151 } 3152 3153 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp, 3154 struct mlxsw_sp_fib_entry *fib_entry, 3155 enum mlxsw_reg_ralue_op op) 3156 { 3157 char ralue_pl[MLXSW_REG_RALUE_LEN]; 3158 enum mlxsw_reg_ralue_trap_action trap_action; 3159 u16 trap_id = 0; 3160 u32 adjacency_index = 0; 3161 u16 ecmp_size = 0; 3162 3163 /* In case the nexthop group adjacency index is valid, use it 3164 * with provided ECMP size. Otherwise, setup trap and pass 3165 * traffic to kernel. 3166 */ 3167 if (mlxsw_sp_fib_entry_should_offload(fib_entry)) { 3168 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; 3169 adjacency_index = fib_entry->nh_group->adj_index; 3170 ecmp_size = fib_entry->nh_group->ecmp_size; 3171 } else { 3172 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP; 3173 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0; 3174 } 3175 3176 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); 3177 mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id, 3178 adjacency_index, ecmp_size); 3179 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 3180 } 3181 3182 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp, 3183 struct mlxsw_sp_fib_entry *fib_entry, 3184 enum mlxsw_reg_ralue_op op) 3185 { 3186 struct mlxsw_sp_rif *rif = fib_entry->nh_group->nh_rif; 3187 enum mlxsw_reg_ralue_trap_action trap_action; 3188 char ralue_pl[MLXSW_REG_RALUE_LEN]; 3189 u16 trap_id = 0; 3190 u16 rif_index = 0; 3191 3192 if (mlxsw_sp_fib_entry_should_offload(fib_entry)) { 3193 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP; 3194 rif_index = rif->rif_index; 3195 } else { 3196 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP; 3197 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0; 3198 } 3199 3200 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); 3201 mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 3202 rif_index); 3203 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 3204 } 3205 3206 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp, 3207 struct mlxsw_sp_fib_entry *fib_entry, 3208 enum mlxsw_reg_ralue_op op) 3209 { 3210 char ralue_pl[MLXSW_REG_RALUE_LEN]; 3211 3212 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); 3213 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl); 3214 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 3215 } 3216 3217 static int 3218 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, 3219 struct mlxsw_sp_fib_entry *fib_entry, 3220 enum mlxsw_reg_ralue_op op) 3221 { 3222 struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry; 3223 const struct mlxsw_sp_ipip_ops *ipip_ops; 3224 3225 if (WARN_ON(!ipip_entry)) 3226 return -EINVAL; 3227 3228 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]; 3229 return ipip_ops->fib_entry_op(mlxsw_sp, ipip_entry, op, 3230 fib_entry->decap.tunnel_index); 3231 } 3232 3233 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, 3234 struct mlxsw_sp_fib_entry *fib_entry, 3235 enum mlxsw_reg_ralue_op op) 3236 { 3237 switch (fib_entry->type) { 3238 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE: 3239 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op); 3240 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: 3241 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op); 3242 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP: 3243 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op); 3244 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: 3245 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp, 3246 fib_entry, op); 3247 } 3248 return -EINVAL; 3249 } 3250 3251 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, 3252 struct mlxsw_sp_fib_entry *fib_entry, 3253 enum mlxsw_reg_ralue_op op) 3254 { 3255 int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op); 3256 3257 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, err); 3258 3259 return err; 3260 } 3261 3262 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, 3263 struct mlxsw_sp_fib_entry *fib_entry) 3264 { 3265 return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, 3266 MLXSW_REG_RALUE_OP_WRITE_WRITE); 3267 } 3268 3269 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp, 3270 struct mlxsw_sp_fib_entry *fib_entry) 3271 { 3272 return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, 3273 MLXSW_REG_RALUE_OP_WRITE_DELETE); 3274 } 3275 3276 static int 3277 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp, 3278 const struct fib_entry_notifier_info *fen_info, 3279 struct mlxsw_sp_fib_entry *fib_entry) 3280 { 3281 union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) }; 3282 struct net_device *dev = fen_info->fi->fib_dev; 3283 struct mlxsw_sp_ipip_entry *ipip_entry; 3284 struct fib_info *fi = fen_info->fi; 3285 3286 switch (fen_info->type) { 3287 case RTN_LOCAL: 3288 ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, dev, 3289 MLXSW_SP_L3_PROTO_IPV4, dip); 3290 if (ipip_entry) { 3291 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP; 3292 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp, 3293 fib_entry, 3294 ipip_entry); 3295 } 3296 /* fall through */ 3297 case RTN_BROADCAST: 3298 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; 3299 return 0; 3300 case RTN_UNREACHABLE: /* fall through */ 3301 case RTN_BLACKHOLE: /* fall through */ 3302 case RTN_PROHIBIT: 3303 /* Packets hitting these routes need to be trapped, but 3304 * can do so with a lower priority than packets directed 3305 * at the host, so use action type local instead of trap. 3306 */ 3307 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; 3308 return 0; 3309 case RTN_UNICAST: 3310 if (mlxsw_sp_fi_is_gateway(mlxsw_sp, fi)) 3311 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE; 3312 else 3313 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; 3314 return 0; 3315 default: 3316 return -EINVAL; 3317 } 3318 } 3319 3320 static struct mlxsw_sp_fib4_entry * 3321 mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp, 3322 struct mlxsw_sp_fib_node *fib_node, 3323 const struct fib_entry_notifier_info *fen_info) 3324 { 3325 struct mlxsw_sp_fib4_entry *fib4_entry; 3326 struct mlxsw_sp_fib_entry *fib_entry; 3327 int err; 3328 3329 fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL); 3330 if (!fib4_entry) 3331 return ERR_PTR(-ENOMEM); 3332 fib_entry = &fib4_entry->common; 3333 3334 err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry); 3335 if (err) 3336 goto err_fib4_entry_type_set; 3337 3338 err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi); 3339 if (err) 3340 goto err_nexthop4_group_get; 3341 3342 fib4_entry->prio = fen_info->fi->fib_priority; 3343 fib4_entry->tb_id = fen_info->tb_id; 3344 fib4_entry->type = fen_info->type; 3345 fib4_entry->tos = fen_info->tos; 3346 3347 fib_entry->fib_node = fib_node; 3348 3349 return fib4_entry; 3350 3351 err_nexthop4_group_get: 3352 err_fib4_entry_type_set: 3353 kfree(fib4_entry); 3354 return ERR_PTR(err); 3355 } 3356 3357 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp, 3358 struct mlxsw_sp_fib4_entry *fib4_entry) 3359 { 3360 mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common); 3361 kfree(fib4_entry); 3362 } 3363 3364 static struct mlxsw_sp_fib4_entry * 3365 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp, 3366 const struct fib_entry_notifier_info *fen_info) 3367 { 3368 struct mlxsw_sp_fib4_entry *fib4_entry; 3369 struct mlxsw_sp_fib_node *fib_node; 3370 struct mlxsw_sp_fib *fib; 3371 struct mlxsw_sp_vr *vr; 3372 3373 vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id); 3374 if (!vr) 3375 return NULL; 3376 fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4); 3377 3378 fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst, 3379 sizeof(fen_info->dst), 3380 fen_info->dst_len); 3381 if (!fib_node) 3382 return NULL; 3383 3384 list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) { 3385 if (fib4_entry->tb_id == fen_info->tb_id && 3386 fib4_entry->tos == fen_info->tos && 3387 fib4_entry->type == fen_info->type && 3388 mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) == 3389 fen_info->fi) { 3390 return fib4_entry; 3391 } 3392 } 3393 3394 return NULL; 3395 } 3396 3397 static const struct rhashtable_params mlxsw_sp_fib_ht_params = { 3398 .key_offset = offsetof(struct mlxsw_sp_fib_node, key), 3399 .head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node), 3400 .key_len = sizeof(struct mlxsw_sp_fib_key), 3401 .automatic_shrinking = true, 3402 }; 3403 3404 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib, 3405 struct mlxsw_sp_fib_node *fib_node) 3406 { 3407 return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node, 3408 mlxsw_sp_fib_ht_params); 3409 } 3410 3411 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib, 3412 struct mlxsw_sp_fib_node *fib_node) 3413 { 3414 rhashtable_remove_fast(&fib->ht, &fib_node->ht_node, 3415 mlxsw_sp_fib_ht_params); 3416 } 3417 3418 static struct mlxsw_sp_fib_node * 3419 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr, 3420 size_t addr_len, unsigned char prefix_len) 3421 { 3422 struct mlxsw_sp_fib_key key; 3423 3424 memset(&key, 0, sizeof(key)); 3425 memcpy(key.addr, addr, addr_len); 3426 key.prefix_len = prefix_len; 3427 return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params); 3428 } 3429 3430 static struct mlxsw_sp_fib_node * 3431 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr, 3432 size_t addr_len, unsigned char prefix_len) 3433 { 3434 struct mlxsw_sp_fib_node *fib_node; 3435 3436 fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL); 3437 if (!fib_node) 3438 return NULL; 3439 3440 INIT_LIST_HEAD(&fib_node->entry_list); 3441 list_add(&fib_node->list, &fib->node_list); 3442 memcpy(fib_node->key.addr, addr, addr_len); 3443 fib_node->key.prefix_len = prefix_len; 3444 3445 return fib_node; 3446 } 3447 3448 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node) 3449 { 3450 list_del(&fib_node->list); 3451 WARN_ON(!list_empty(&fib_node->entry_list)); 3452 kfree(fib_node); 3453 } 3454 3455 static bool 3456 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node, 3457 const struct mlxsw_sp_fib_entry *fib_entry) 3458 { 3459 return list_first_entry(&fib_node->entry_list, 3460 struct mlxsw_sp_fib_entry, list) == fib_entry; 3461 } 3462 3463 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp, 3464 struct mlxsw_sp_fib *fib, 3465 struct mlxsw_sp_fib_node *fib_node) 3466 { 3467 struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } }; 3468 struct mlxsw_sp_lpm_tree *lpm_tree; 3469 int err; 3470 3471 /* Since the tree is shared between all virtual routers we must 3472 * make sure it contains all the required prefix lengths. This 3473 * can be computed by either adding the new prefix length to the 3474 * existing prefix usage of a bound tree, or by aggregating the 3475 * prefix lengths across all virtual routers and adding the new 3476 * one as well. 3477 */ 3478 if (fib->lpm_tree) 3479 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, 3480 &fib->lpm_tree->prefix_usage); 3481 else 3482 mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage); 3483 mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len); 3484 3485 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage, 3486 fib->proto); 3487 if (IS_ERR(lpm_tree)) 3488 return PTR_ERR(lpm_tree); 3489 3490 if (fib->lpm_tree && fib->lpm_tree->id == lpm_tree->id) 3491 return 0; 3492 3493 err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree); 3494 if (err) 3495 return err; 3496 3497 return 0; 3498 } 3499 3500 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp, 3501 struct mlxsw_sp_fib *fib) 3502 { 3503 struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } }; 3504 struct mlxsw_sp_lpm_tree *lpm_tree; 3505 3506 /* Aggregate prefix lengths across all virtual routers to make 3507 * sure we only have used prefix lengths in the LPM tree. 3508 */ 3509 mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage); 3510 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage, 3511 fib->proto); 3512 if (IS_ERR(lpm_tree)) 3513 goto err_tree_get; 3514 mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree); 3515 3516 err_tree_get: 3517 if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage)) 3518 return; 3519 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib); 3520 mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree); 3521 fib->lpm_tree = NULL; 3522 } 3523 3524 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node *fib_node) 3525 { 3526 unsigned char prefix_len = fib_node->key.prefix_len; 3527 struct mlxsw_sp_fib *fib = fib_node->fib; 3528 3529 if (fib->prefix_ref_count[prefix_len]++ == 0) 3530 mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len); 3531 } 3532 3533 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node *fib_node) 3534 { 3535 unsigned char prefix_len = fib_node->key.prefix_len; 3536 struct mlxsw_sp_fib *fib = fib_node->fib; 3537 3538 if (--fib->prefix_ref_count[prefix_len] == 0) 3539 mlxsw_sp_prefix_usage_clear(&fib->prefix_usage, prefix_len); 3540 } 3541 3542 static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp, 3543 struct mlxsw_sp_fib_node *fib_node, 3544 struct mlxsw_sp_fib *fib) 3545 { 3546 int err; 3547 3548 err = mlxsw_sp_fib_node_insert(fib, fib_node); 3549 if (err) 3550 return err; 3551 fib_node->fib = fib; 3552 3553 err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib, fib_node); 3554 if (err) 3555 goto err_fib_lpm_tree_link; 3556 3557 mlxsw_sp_fib_node_prefix_inc(fib_node); 3558 3559 return 0; 3560 3561 err_fib_lpm_tree_link: 3562 fib_node->fib = NULL; 3563 mlxsw_sp_fib_node_remove(fib, fib_node); 3564 return err; 3565 } 3566 3567 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp, 3568 struct mlxsw_sp_fib_node *fib_node) 3569 { 3570 struct mlxsw_sp_fib *fib = fib_node->fib; 3571 3572 mlxsw_sp_fib_node_prefix_dec(fib_node); 3573 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib); 3574 fib_node->fib = NULL; 3575 mlxsw_sp_fib_node_remove(fib, fib_node); 3576 } 3577 3578 static struct mlxsw_sp_fib_node * 3579 mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr, 3580 size_t addr_len, unsigned char prefix_len, 3581 enum mlxsw_sp_l3proto proto) 3582 { 3583 struct mlxsw_sp_fib_node *fib_node; 3584 struct mlxsw_sp_fib *fib; 3585 struct mlxsw_sp_vr *vr; 3586 int err; 3587 3588 vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id); 3589 if (IS_ERR(vr)) 3590 return ERR_CAST(vr); 3591 fib = mlxsw_sp_vr_fib(vr, proto); 3592 3593 fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len); 3594 if (fib_node) 3595 return fib_node; 3596 3597 fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len); 3598 if (!fib_node) { 3599 err = -ENOMEM; 3600 goto err_fib_node_create; 3601 } 3602 3603 err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib); 3604 if (err) 3605 goto err_fib_node_init; 3606 3607 return fib_node; 3608 3609 err_fib_node_init: 3610 mlxsw_sp_fib_node_destroy(fib_node); 3611 err_fib_node_create: 3612 mlxsw_sp_vr_put(vr); 3613 return ERR_PTR(err); 3614 } 3615 3616 static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp, 3617 struct mlxsw_sp_fib_node *fib_node) 3618 { 3619 struct mlxsw_sp_vr *vr = fib_node->fib->vr; 3620 3621 if (!list_empty(&fib_node->entry_list)) 3622 return; 3623 mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node); 3624 mlxsw_sp_fib_node_destroy(fib_node); 3625 mlxsw_sp_vr_put(vr); 3626 } 3627 3628 static struct mlxsw_sp_fib4_entry * 3629 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node, 3630 const struct mlxsw_sp_fib4_entry *new4_entry) 3631 { 3632 struct mlxsw_sp_fib4_entry *fib4_entry; 3633 3634 list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) { 3635 if (fib4_entry->tb_id > new4_entry->tb_id) 3636 continue; 3637 if (fib4_entry->tb_id != new4_entry->tb_id) 3638 break; 3639 if (fib4_entry->tos > new4_entry->tos) 3640 continue; 3641 if (fib4_entry->prio >= new4_entry->prio || 3642 fib4_entry->tos < new4_entry->tos) 3643 return fib4_entry; 3644 } 3645 3646 return NULL; 3647 } 3648 3649 static int 3650 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry *fib4_entry, 3651 struct mlxsw_sp_fib4_entry *new4_entry) 3652 { 3653 struct mlxsw_sp_fib_node *fib_node; 3654 3655 if (WARN_ON(!fib4_entry)) 3656 return -EINVAL; 3657 3658 fib_node = fib4_entry->common.fib_node; 3659 list_for_each_entry_from(fib4_entry, &fib_node->entry_list, 3660 common.list) { 3661 if (fib4_entry->tb_id != new4_entry->tb_id || 3662 fib4_entry->tos != new4_entry->tos || 3663 fib4_entry->prio != new4_entry->prio) 3664 break; 3665 } 3666 3667 list_add_tail(&new4_entry->common.list, &fib4_entry->common.list); 3668 return 0; 3669 } 3670 3671 static int 3672 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry *new4_entry, 3673 bool replace, bool append) 3674 { 3675 struct mlxsw_sp_fib_node *fib_node = new4_entry->common.fib_node; 3676 struct mlxsw_sp_fib4_entry *fib4_entry; 3677 3678 fib4_entry = mlxsw_sp_fib4_node_entry_find(fib_node, new4_entry); 3679 3680 if (append) 3681 return mlxsw_sp_fib4_node_list_append(fib4_entry, new4_entry); 3682 if (replace && WARN_ON(!fib4_entry)) 3683 return -EINVAL; 3684 3685 /* Insert new entry before replaced one, so that we can later 3686 * remove the second. 3687 */ 3688 if (fib4_entry) { 3689 list_add_tail(&new4_entry->common.list, 3690 &fib4_entry->common.list); 3691 } else { 3692 struct mlxsw_sp_fib4_entry *last; 3693 3694 list_for_each_entry(last, &fib_node->entry_list, common.list) { 3695 if (new4_entry->tb_id > last->tb_id) 3696 break; 3697 fib4_entry = last; 3698 } 3699 3700 if (fib4_entry) 3701 list_add(&new4_entry->common.list, 3702 &fib4_entry->common.list); 3703 else 3704 list_add(&new4_entry->common.list, 3705 &fib_node->entry_list); 3706 } 3707 3708 return 0; 3709 } 3710 3711 static void 3712 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry *fib4_entry) 3713 { 3714 list_del(&fib4_entry->common.list); 3715 } 3716 3717 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp, 3718 struct mlxsw_sp_fib_entry *fib_entry) 3719 { 3720 struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node; 3721 3722 if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry)) 3723 return 0; 3724 3725 /* To prevent packet loss, overwrite the previously offloaded 3726 * entry. 3727 */ 3728 if (!list_is_singular(&fib_node->entry_list)) { 3729 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE; 3730 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list); 3731 3732 mlxsw_sp_fib_entry_offload_refresh(n, op, 0); 3733 } 3734 3735 return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); 3736 } 3737 3738 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp, 3739 struct mlxsw_sp_fib_entry *fib_entry) 3740 { 3741 struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node; 3742 3743 if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry)) 3744 return; 3745 3746 /* Promote the next entry by overwriting the deleted entry */ 3747 if (!list_is_singular(&fib_node->entry_list)) { 3748 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list); 3749 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE; 3750 3751 mlxsw_sp_fib_entry_update(mlxsw_sp, n); 3752 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0); 3753 return; 3754 } 3755 3756 mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry); 3757 } 3758 3759 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp, 3760 struct mlxsw_sp_fib4_entry *fib4_entry, 3761 bool replace, bool append) 3762 { 3763 int err; 3764 3765 err = mlxsw_sp_fib4_node_list_insert(fib4_entry, replace, append); 3766 if (err) 3767 return err; 3768 3769 err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common); 3770 if (err) 3771 goto err_fib_node_entry_add; 3772 3773 return 0; 3774 3775 err_fib_node_entry_add: 3776 mlxsw_sp_fib4_node_list_remove(fib4_entry); 3777 return err; 3778 } 3779 3780 static void 3781 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, 3782 struct mlxsw_sp_fib4_entry *fib4_entry) 3783 { 3784 mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common); 3785 mlxsw_sp_fib4_node_list_remove(fib4_entry); 3786 3787 if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP) 3788 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common); 3789 } 3790 3791 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp, 3792 struct mlxsw_sp_fib4_entry *fib4_entry, 3793 bool replace) 3794 { 3795 struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node; 3796 struct mlxsw_sp_fib4_entry *replaced; 3797 3798 if (!replace) 3799 return; 3800 3801 /* We inserted the new entry before replaced one */ 3802 replaced = list_next_entry(fib4_entry, common.list); 3803 3804 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, replaced); 3805 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced); 3806 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 3807 } 3808 3809 static int 3810 mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp, 3811 const struct fib_entry_notifier_info *fen_info, 3812 bool replace, bool append) 3813 { 3814 struct mlxsw_sp_fib4_entry *fib4_entry; 3815 struct mlxsw_sp_fib_node *fib_node; 3816 int err; 3817 3818 if (mlxsw_sp->router->aborted) 3819 return 0; 3820 3821 fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id, 3822 &fen_info->dst, sizeof(fen_info->dst), 3823 fen_info->dst_len, 3824 MLXSW_SP_L3_PROTO_IPV4); 3825 if (IS_ERR(fib_node)) { 3826 dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n"); 3827 return PTR_ERR(fib_node); 3828 } 3829 3830 fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info); 3831 if (IS_ERR(fib4_entry)) { 3832 dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n"); 3833 err = PTR_ERR(fib4_entry); 3834 goto err_fib4_entry_create; 3835 } 3836 3837 err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry, replace, 3838 append); 3839 if (err) { 3840 dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n"); 3841 goto err_fib4_node_entry_link; 3842 } 3843 3844 mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry, replace); 3845 3846 return 0; 3847 3848 err_fib4_node_entry_link: 3849 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); 3850 err_fib4_entry_create: 3851 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 3852 return err; 3853 } 3854 3855 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp, 3856 struct fib_entry_notifier_info *fen_info) 3857 { 3858 struct mlxsw_sp_fib4_entry *fib4_entry; 3859 struct mlxsw_sp_fib_node *fib_node; 3860 3861 if (mlxsw_sp->router->aborted) 3862 return; 3863 3864 fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info); 3865 if (WARN_ON(!fib4_entry)) 3866 return; 3867 fib_node = fib4_entry->common.fib_node; 3868 3869 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry); 3870 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); 3871 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 3872 } 3873 3874 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info *rt) 3875 { 3876 /* Packets with link-local destination IP arriving to the router 3877 * are trapped to the CPU, so no need to program specific routes 3878 * for them. 3879 */ 3880 if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL) 3881 return true; 3882 3883 /* Multicast routes aren't supported, so ignore them. Neighbour 3884 * Discovery packets are specifically trapped. 3885 */ 3886 if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST) 3887 return true; 3888 3889 /* Cloned routes are irrelevant in the forwarding path. */ 3890 if (rt->rt6i_flags & RTF_CACHE) 3891 return true; 3892 3893 return false; 3894 } 3895 3896 static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct rt6_info *rt) 3897 { 3898 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 3899 3900 mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL); 3901 if (!mlxsw_sp_rt6) 3902 return ERR_PTR(-ENOMEM); 3903 3904 /* In case of route replace, replaced route is deleted with 3905 * no notification. Take reference to prevent accessing freed 3906 * memory. 3907 */ 3908 mlxsw_sp_rt6->rt = rt; 3909 rt6_hold(rt); 3910 3911 return mlxsw_sp_rt6; 3912 } 3913 3914 #if IS_ENABLED(CONFIG_IPV6) 3915 static void mlxsw_sp_rt6_release(struct rt6_info *rt) 3916 { 3917 rt6_release(rt); 3918 } 3919 #else 3920 static void mlxsw_sp_rt6_release(struct rt6_info *rt) 3921 { 3922 } 3923 #endif 3924 3925 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6) 3926 { 3927 mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt); 3928 kfree(mlxsw_sp_rt6); 3929 } 3930 3931 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info *rt) 3932 { 3933 /* RTF_CACHE routes are ignored */ 3934 return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY; 3935 } 3936 3937 static struct rt6_info * 3938 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry) 3939 { 3940 return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6, 3941 list)->rt; 3942 } 3943 3944 static struct mlxsw_sp_fib6_entry * 3945 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node, 3946 const struct rt6_info *nrt, bool replace) 3947 { 3948 struct mlxsw_sp_fib6_entry *fib6_entry; 3949 3950 if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace) 3951 return NULL; 3952 3953 list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) { 3954 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry); 3955 3956 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same 3957 * virtual router. 3958 */ 3959 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id) 3960 continue; 3961 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id) 3962 break; 3963 if (rt->rt6i_metric < nrt->rt6i_metric) 3964 continue; 3965 if (rt->rt6i_metric == nrt->rt6i_metric && 3966 mlxsw_sp_fib6_rt_can_mp(rt)) 3967 return fib6_entry; 3968 if (rt->rt6i_metric > nrt->rt6i_metric) 3969 break; 3970 } 3971 3972 return NULL; 3973 } 3974 3975 static struct mlxsw_sp_rt6 * 3976 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry, 3977 const struct rt6_info *rt) 3978 { 3979 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 3980 3981 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) { 3982 if (mlxsw_sp_rt6->rt == rt) 3983 return mlxsw_sp_rt6; 3984 } 3985 3986 return NULL; 3987 } 3988 3989 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp, 3990 const struct rt6_info *rt, 3991 enum mlxsw_sp_ipip_type *ret) 3992 { 3993 return rt->dst.dev && 3994 mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->dst.dev, ret); 3995 } 3996 3997 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp, 3998 struct mlxsw_sp_nexthop_group *nh_grp, 3999 struct mlxsw_sp_nexthop *nh, 4000 const struct rt6_info *rt) 4001 { 4002 struct mlxsw_sp_router *router = mlxsw_sp->router; 4003 struct net_device *dev = rt->dst.dev; 4004 enum mlxsw_sp_ipip_type ipipt; 4005 struct mlxsw_sp_rif *rif; 4006 int err; 4007 4008 if (mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, &ipipt) && 4009 router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev, 4010 MLXSW_SP_L3_PROTO_IPV6)) { 4011 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP; 4012 return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); 4013 } 4014 4015 nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH; 4016 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); 4017 if (!rif) 4018 return 0; 4019 mlxsw_sp_nexthop_rif_init(nh, rif); 4020 4021 err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh); 4022 if (err) 4023 goto err_nexthop_neigh_init; 4024 4025 return 0; 4026 4027 err_nexthop_neigh_init: 4028 mlxsw_sp_nexthop_rif_fini(nh); 4029 return err; 4030 } 4031 4032 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp *mlxsw_sp, 4033 struct mlxsw_sp_nexthop *nh) 4034 { 4035 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh); 4036 } 4037 4038 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp, 4039 struct mlxsw_sp_nexthop_group *nh_grp, 4040 struct mlxsw_sp_nexthop *nh, 4041 const struct rt6_info *rt) 4042 { 4043 struct net_device *dev = rt->dst.dev; 4044 4045 nh->nh_grp = nh_grp; 4046 memcpy(&nh->gw_addr, &rt->rt6i_gateway, sizeof(nh->gw_addr)); 4047 4048 if (!dev) 4049 return 0; 4050 nh->ifindex = dev->ifindex; 4051 4052 return mlxsw_sp_nexthop6_type_init(mlxsw_sp, nh_grp, nh, rt); 4053 } 4054 4055 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp, 4056 struct mlxsw_sp_nexthop *nh) 4057 { 4058 mlxsw_sp_nexthop6_type_fini(mlxsw_sp, nh); 4059 } 4060 4061 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp, 4062 const struct rt6_info *rt) 4063 { 4064 return rt->rt6i_flags & RTF_GATEWAY || 4065 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL); 4066 } 4067 4068 static struct mlxsw_sp_nexthop_group * 4069 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp, 4070 struct mlxsw_sp_fib6_entry *fib6_entry) 4071 { 4072 struct mlxsw_sp_nexthop_group *nh_grp; 4073 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 4074 struct mlxsw_sp_nexthop *nh; 4075 size_t alloc_size; 4076 int i = 0; 4077 int err; 4078 4079 alloc_size = sizeof(*nh_grp) + 4080 fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop); 4081 nh_grp = kzalloc(alloc_size, GFP_KERNEL); 4082 if (!nh_grp) 4083 return ERR_PTR(-ENOMEM); 4084 INIT_LIST_HEAD(&nh_grp->fib_list); 4085 #if IS_ENABLED(CONFIG_IPV6) 4086 nh_grp->neigh_tbl = &nd_tbl; 4087 #endif 4088 mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list, 4089 struct mlxsw_sp_rt6, list); 4090 nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt); 4091 nh_grp->count = fib6_entry->nrt6; 4092 for (i = 0; i < nh_grp->count; i++) { 4093 struct rt6_info *rt = mlxsw_sp_rt6->rt; 4094 4095 nh = &nh_grp->nexthops[i]; 4096 err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt); 4097 if (err) 4098 goto err_nexthop6_init; 4099 mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list); 4100 } 4101 4102 err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp); 4103 if (err) 4104 goto err_nexthop_group_insert; 4105 4106 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp); 4107 return nh_grp; 4108 4109 err_nexthop_group_insert: 4110 err_nexthop6_init: 4111 for (i--; i >= 0; i--) { 4112 nh = &nh_grp->nexthops[i]; 4113 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh); 4114 } 4115 kfree(nh_grp); 4116 return ERR_PTR(err); 4117 } 4118 4119 static void 4120 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp, 4121 struct mlxsw_sp_nexthop_group *nh_grp) 4122 { 4123 struct mlxsw_sp_nexthop *nh; 4124 int i = nh_grp->count; 4125 4126 mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp); 4127 for (i--; i >= 0; i--) { 4128 nh = &nh_grp->nexthops[i]; 4129 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh); 4130 } 4131 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp); 4132 WARN_ON(nh_grp->adj_index_valid); 4133 kfree(nh_grp); 4134 } 4135 4136 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp, 4137 struct mlxsw_sp_fib6_entry *fib6_entry) 4138 { 4139 struct mlxsw_sp_nexthop_group *nh_grp; 4140 4141 nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry); 4142 if (!nh_grp) { 4143 nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry); 4144 if (IS_ERR(nh_grp)) 4145 return PTR_ERR(nh_grp); 4146 } 4147 4148 list_add_tail(&fib6_entry->common.nexthop_group_node, 4149 &nh_grp->fib_list); 4150 fib6_entry->common.nh_group = nh_grp; 4151 4152 return 0; 4153 } 4154 4155 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp, 4156 struct mlxsw_sp_fib_entry *fib_entry) 4157 { 4158 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group; 4159 4160 list_del(&fib_entry->nexthop_group_node); 4161 if (!list_empty(&nh_grp->fib_list)) 4162 return; 4163 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp); 4164 } 4165 4166 static int 4167 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp, 4168 struct mlxsw_sp_fib6_entry *fib6_entry) 4169 { 4170 struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group; 4171 int err; 4172 4173 fib6_entry->common.nh_group = NULL; 4174 list_del(&fib6_entry->common.nexthop_group_node); 4175 4176 err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry); 4177 if (err) 4178 goto err_nexthop6_group_get; 4179 4180 /* In case this entry is offloaded, then the adjacency index 4181 * currently associated with it in the device's table is that 4182 * of the old group. Start using the new one instead. 4183 */ 4184 err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common); 4185 if (err) 4186 goto err_fib_node_entry_add; 4187 4188 if (list_empty(&old_nh_grp->fib_list)) 4189 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp); 4190 4191 return 0; 4192 4193 err_fib_node_entry_add: 4194 mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common); 4195 err_nexthop6_group_get: 4196 list_add_tail(&fib6_entry->common.nexthop_group_node, 4197 &old_nh_grp->fib_list); 4198 fib6_entry->common.nh_group = old_nh_grp; 4199 return err; 4200 } 4201 4202 static int 4203 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp, 4204 struct mlxsw_sp_fib6_entry *fib6_entry, 4205 struct rt6_info *rt) 4206 { 4207 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 4208 int err; 4209 4210 mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt); 4211 if (IS_ERR(mlxsw_sp_rt6)) 4212 return PTR_ERR(mlxsw_sp_rt6); 4213 4214 list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list); 4215 fib6_entry->nrt6++; 4216 4217 err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry); 4218 if (err) 4219 goto err_nexthop6_group_update; 4220 4221 return 0; 4222 4223 err_nexthop6_group_update: 4224 fib6_entry->nrt6--; 4225 list_del(&mlxsw_sp_rt6->list); 4226 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); 4227 return err; 4228 } 4229 4230 static void 4231 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp, 4232 struct mlxsw_sp_fib6_entry *fib6_entry, 4233 struct rt6_info *rt) 4234 { 4235 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 4236 4237 mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt); 4238 if (WARN_ON(!mlxsw_sp_rt6)) 4239 return; 4240 4241 fib6_entry->nrt6--; 4242 list_del(&mlxsw_sp_rt6->list); 4243 mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry); 4244 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); 4245 } 4246 4247 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp, 4248 struct mlxsw_sp_fib_entry *fib_entry, 4249 const struct rt6_info *rt) 4250 { 4251 /* Packets hitting RTF_REJECT routes need to be discarded by the 4252 * stack. We can rely on their destination device not having a 4253 * RIF (it's the loopback device) and can thus use action type 4254 * local, which will cause them to be trapped with a lower 4255 * priority than packets that need to be locally received. 4256 */ 4257 if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) 4258 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; 4259 else if (rt->rt6i_flags & RTF_REJECT) 4260 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; 4261 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt)) 4262 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE; 4263 else 4264 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; 4265 } 4266 4267 static void 4268 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry) 4269 { 4270 struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp; 4271 4272 list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list, 4273 list) { 4274 fib6_entry->nrt6--; 4275 list_del(&mlxsw_sp_rt6->list); 4276 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); 4277 } 4278 } 4279 4280 static struct mlxsw_sp_fib6_entry * 4281 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp, 4282 struct mlxsw_sp_fib_node *fib_node, 4283 struct rt6_info *rt) 4284 { 4285 struct mlxsw_sp_fib6_entry *fib6_entry; 4286 struct mlxsw_sp_fib_entry *fib_entry; 4287 struct mlxsw_sp_rt6 *mlxsw_sp_rt6; 4288 int err; 4289 4290 fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL); 4291 if (!fib6_entry) 4292 return ERR_PTR(-ENOMEM); 4293 fib_entry = &fib6_entry->common; 4294 4295 mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt); 4296 if (IS_ERR(mlxsw_sp_rt6)) { 4297 err = PTR_ERR(mlxsw_sp_rt6); 4298 goto err_rt6_create; 4299 } 4300 4301 mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt); 4302 4303 INIT_LIST_HEAD(&fib6_entry->rt6_list); 4304 list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list); 4305 fib6_entry->nrt6 = 1; 4306 err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry); 4307 if (err) 4308 goto err_nexthop6_group_get; 4309 4310 fib_entry->fib_node = fib_node; 4311 4312 return fib6_entry; 4313 4314 err_nexthop6_group_get: 4315 list_del(&mlxsw_sp_rt6->list); 4316 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6); 4317 err_rt6_create: 4318 kfree(fib6_entry); 4319 return ERR_PTR(err); 4320 } 4321 4322 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp, 4323 struct mlxsw_sp_fib6_entry *fib6_entry) 4324 { 4325 mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common); 4326 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry); 4327 WARN_ON(fib6_entry->nrt6); 4328 kfree(fib6_entry); 4329 } 4330 4331 static struct mlxsw_sp_fib6_entry * 4332 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node, 4333 const struct rt6_info *nrt, bool replace) 4334 { 4335 struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL; 4336 4337 list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) { 4338 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry); 4339 4340 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id) 4341 continue; 4342 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id) 4343 break; 4344 if (replace && rt->rt6i_metric == nrt->rt6i_metric) { 4345 if (mlxsw_sp_fib6_rt_can_mp(rt) == 4346 mlxsw_sp_fib6_rt_can_mp(nrt)) 4347 return fib6_entry; 4348 if (mlxsw_sp_fib6_rt_can_mp(nrt)) 4349 fallback = fallback ?: fib6_entry; 4350 } 4351 if (rt->rt6i_metric > nrt->rt6i_metric) 4352 return fallback ?: fib6_entry; 4353 } 4354 4355 return fallback; 4356 } 4357 4358 static int 4359 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry, 4360 bool replace) 4361 { 4362 struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node; 4363 struct rt6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry); 4364 struct mlxsw_sp_fib6_entry *fib6_entry; 4365 4366 fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, replace); 4367 4368 if (replace && WARN_ON(!fib6_entry)) 4369 return -EINVAL; 4370 4371 if (fib6_entry) { 4372 list_add_tail(&new6_entry->common.list, 4373 &fib6_entry->common.list); 4374 } else { 4375 struct mlxsw_sp_fib6_entry *last; 4376 4377 list_for_each_entry(last, &fib_node->entry_list, common.list) { 4378 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(last); 4379 4380 if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id) 4381 break; 4382 fib6_entry = last; 4383 } 4384 4385 if (fib6_entry) 4386 list_add(&new6_entry->common.list, 4387 &fib6_entry->common.list); 4388 else 4389 list_add(&new6_entry->common.list, 4390 &fib_node->entry_list); 4391 } 4392 4393 return 0; 4394 } 4395 4396 static void 4397 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry) 4398 { 4399 list_del(&fib6_entry->common.list); 4400 } 4401 4402 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp, 4403 struct mlxsw_sp_fib6_entry *fib6_entry, 4404 bool replace) 4405 { 4406 int err; 4407 4408 err = mlxsw_sp_fib6_node_list_insert(fib6_entry, replace); 4409 if (err) 4410 return err; 4411 4412 err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common); 4413 if (err) 4414 goto err_fib_node_entry_add; 4415 4416 return 0; 4417 4418 err_fib_node_entry_add: 4419 mlxsw_sp_fib6_node_list_remove(fib6_entry); 4420 return err; 4421 } 4422 4423 static void 4424 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp, 4425 struct mlxsw_sp_fib6_entry *fib6_entry) 4426 { 4427 mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common); 4428 mlxsw_sp_fib6_node_list_remove(fib6_entry); 4429 } 4430 4431 static struct mlxsw_sp_fib6_entry * 4432 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp, 4433 const struct rt6_info *rt) 4434 { 4435 struct mlxsw_sp_fib6_entry *fib6_entry; 4436 struct mlxsw_sp_fib_node *fib_node; 4437 struct mlxsw_sp_fib *fib; 4438 struct mlxsw_sp_vr *vr; 4439 4440 vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id); 4441 if (!vr) 4442 return NULL; 4443 fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6); 4444 4445 fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr, 4446 sizeof(rt->rt6i_dst.addr), 4447 rt->rt6i_dst.plen); 4448 if (!fib_node) 4449 return NULL; 4450 4451 list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) { 4452 struct rt6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry); 4453 4454 if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id && 4455 rt->rt6i_metric == iter_rt->rt6i_metric && 4456 mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt)) 4457 return fib6_entry; 4458 } 4459 4460 return NULL; 4461 } 4462 4463 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp, 4464 struct mlxsw_sp_fib6_entry *fib6_entry, 4465 bool replace) 4466 { 4467 struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node; 4468 struct mlxsw_sp_fib6_entry *replaced; 4469 4470 if (!replace) 4471 return; 4472 4473 replaced = list_next_entry(fib6_entry, common.list); 4474 4475 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced); 4476 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced); 4477 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4478 } 4479 4480 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp, 4481 struct rt6_info *rt, bool replace) 4482 { 4483 struct mlxsw_sp_fib6_entry *fib6_entry; 4484 struct mlxsw_sp_fib_node *fib_node; 4485 int err; 4486 4487 if (mlxsw_sp->router->aborted) 4488 return 0; 4489 4490 if (rt->rt6i_src.plen) 4491 return -EINVAL; 4492 4493 if (mlxsw_sp_fib6_rt_should_ignore(rt)) 4494 return 0; 4495 4496 fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->rt6i_table->tb6_id, 4497 &rt->rt6i_dst.addr, 4498 sizeof(rt->rt6i_dst.addr), 4499 rt->rt6i_dst.plen, 4500 MLXSW_SP_L3_PROTO_IPV6); 4501 if (IS_ERR(fib_node)) 4502 return PTR_ERR(fib_node); 4503 4504 /* Before creating a new entry, try to append route to an existing 4505 * multipath entry. 4506 */ 4507 fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace); 4508 if (fib6_entry) { 4509 err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt); 4510 if (err) 4511 goto err_fib6_entry_nexthop_add; 4512 return 0; 4513 } 4514 4515 fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt); 4516 if (IS_ERR(fib6_entry)) { 4517 err = PTR_ERR(fib6_entry); 4518 goto err_fib6_entry_create; 4519 } 4520 4521 err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, replace); 4522 if (err) 4523 goto err_fib6_node_entry_link; 4524 4525 mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace); 4526 4527 return 0; 4528 4529 err_fib6_node_entry_link: 4530 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); 4531 err_fib6_entry_create: 4532 err_fib6_entry_nexthop_add: 4533 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4534 return err; 4535 } 4536 4537 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp, 4538 struct rt6_info *rt) 4539 { 4540 struct mlxsw_sp_fib6_entry *fib6_entry; 4541 struct mlxsw_sp_fib_node *fib_node; 4542 4543 if (mlxsw_sp->router->aborted) 4544 return; 4545 4546 if (mlxsw_sp_fib6_rt_should_ignore(rt)) 4547 return; 4548 4549 fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt); 4550 if (WARN_ON(!fib6_entry)) 4551 return; 4552 4553 /* If route is part of a multipath entry, but not the last one 4554 * removed, then only reduce its nexthop group. 4555 */ 4556 if (!list_is_singular(&fib6_entry->rt6_list)) { 4557 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt); 4558 return; 4559 } 4560 4561 fib_node = fib6_entry->common.fib_node; 4562 4563 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry); 4564 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); 4565 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4566 } 4567 4568 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp, 4569 enum mlxsw_reg_ralxx_protocol proto, 4570 u8 tree_id) 4571 { 4572 char ralta_pl[MLXSW_REG_RALTA_LEN]; 4573 char ralst_pl[MLXSW_REG_RALST_LEN]; 4574 int i, err; 4575 4576 mlxsw_reg_ralta_pack(ralta_pl, true, proto, tree_id); 4577 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl); 4578 if (err) 4579 return err; 4580 4581 mlxsw_reg_ralst_pack(ralst_pl, 0xff, tree_id); 4582 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl); 4583 if (err) 4584 return err; 4585 4586 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 4587 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; 4588 char raltb_pl[MLXSW_REG_RALTB_LEN]; 4589 char ralue_pl[MLXSW_REG_RALUE_LEN]; 4590 4591 mlxsw_reg_raltb_pack(raltb_pl, vr->id, proto, tree_id); 4592 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), 4593 raltb_pl); 4594 if (err) 4595 return err; 4596 4597 mlxsw_reg_ralue_pack(ralue_pl, proto, 4598 MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0); 4599 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl); 4600 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), 4601 ralue_pl); 4602 if (err) 4603 return err; 4604 } 4605 4606 return 0; 4607 } 4608 4609 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp) 4610 { 4611 enum mlxsw_reg_ralxx_protocol proto = MLXSW_REG_RALXX_PROTOCOL_IPV4; 4612 int err; 4613 4614 err = __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto, 4615 MLXSW_SP_LPM_TREE_MIN); 4616 if (err) 4617 return err; 4618 4619 proto = MLXSW_REG_RALXX_PROTOCOL_IPV6; 4620 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto, 4621 MLXSW_SP_LPM_TREE_MIN + 1); 4622 } 4623 4624 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp, 4625 struct mlxsw_sp_fib_node *fib_node) 4626 { 4627 struct mlxsw_sp_fib4_entry *fib4_entry, *tmp; 4628 4629 list_for_each_entry_safe(fib4_entry, tmp, &fib_node->entry_list, 4630 common.list) { 4631 bool do_break = &tmp->common.list == &fib_node->entry_list; 4632 4633 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry); 4634 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry); 4635 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4636 /* Break when entry list is empty and node was freed. 4637 * Otherwise, we'll access freed memory in the next 4638 * iteration. 4639 */ 4640 if (do_break) 4641 break; 4642 } 4643 } 4644 4645 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp, 4646 struct mlxsw_sp_fib_node *fib_node) 4647 { 4648 struct mlxsw_sp_fib6_entry *fib6_entry, *tmp; 4649 4650 list_for_each_entry_safe(fib6_entry, tmp, &fib_node->entry_list, 4651 common.list) { 4652 bool do_break = &tmp->common.list == &fib_node->entry_list; 4653 4654 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry); 4655 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry); 4656 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node); 4657 if (do_break) 4658 break; 4659 } 4660 } 4661 4662 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp, 4663 struct mlxsw_sp_fib_node *fib_node) 4664 { 4665 switch (fib_node->fib->proto) { 4666 case MLXSW_SP_L3_PROTO_IPV4: 4667 mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node); 4668 break; 4669 case MLXSW_SP_L3_PROTO_IPV6: 4670 mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node); 4671 break; 4672 } 4673 } 4674 4675 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp, 4676 struct mlxsw_sp_vr *vr, 4677 enum mlxsw_sp_l3proto proto) 4678 { 4679 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto); 4680 struct mlxsw_sp_fib_node *fib_node, *tmp; 4681 4682 list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) { 4683 bool do_break = &tmp->list == &fib->node_list; 4684 4685 mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node); 4686 if (do_break) 4687 break; 4688 } 4689 } 4690 4691 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) 4692 { 4693 int i; 4694 4695 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { 4696 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; 4697 4698 if (!mlxsw_sp_vr_is_used(vr)) 4699 continue; 4700 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4); 4701 4702 /* If virtual router was only used for IPv4, then it's no 4703 * longer used. 4704 */ 4705 if (!mlxsw_sp_vr_is_used(vr)) 4706 continue; 4707 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6); 4708 } 4709 } 4710 4711 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp) 4712 { 4713 int err; 4714 4715 if (mlxsw_sp->router->aborted) 4716 return; 4717 dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n"); 4718 mlxsw_sp_router_fib_flush(mlxsw_sp); 4719 mlxsw_sp->router->aborted = true; 4720 err = mlxsw_sp_router_set_abort_trap(mlxsw_sp); 4721 if (err) 4722 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n"); 4723 } 4724 4725 struct mlxsw_sp_fib_event_work { 4726 struct work_struct work; 4727 union { 4728 struct fib6_entry_notifier_info fen6_info; 4729 struct fib_entry_notifier_info fen_info; 4730 struct fib_rule_notifier_info fr_info; 4731 struct fib_nh_notifier_info fnh_info; 4732 }; 4733 struct mlxsw_sp *mlxsw_sp; 4734 unsigned long event; 4735 }; 4736 4737 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work) 4738 { 4739 struct mlxsw_sp_fib_event_work *fib_work = 4740 container_of(work, struct mlxsw_sp_fib_event_work, work); 4741 struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp; 4742 struct fib_rule *rule; 4743 bool replace, append; 4744 int err; 4745 4746 /* Protect internal structures from changes */ 4747 rtnl_lock(); 4748 switch (fib_work->event) { 4749 case FIB_EVENT_ENTRY_REPLACE: /* fall through */ 4750 case FIB_EVENT_ENTRY_APPEND: /* fall through */ 4751 case FIB_EVENT_ENTRY_ADD: 4752 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE; 4753 append = fib_work->event == FIB_EVENT_ENTRY_APPEND; 4754 err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info, 4755 replace, append); 4756 if (err) 4757 mlxsw_sp_router_fib_abort(mlxsw_sp); 4758 fib_info_put(fib_work->fen_info.fi); 4759 break; 4760 case FIB_EVENT_ENTRY_DEL: 4761 mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info); 4762 fib_info_put(fib_work->fen_info.fi); 4763 break; 4764 case FIB_EVENT_RULE_ADD: /* fall through */ 4765 case FIB_EVENT_RULE_DEL: 4766 rule = fib_work->fr_info.rule; 4767 if (!fib4_rule_default(rule) && !rule->l3mdev) 4768 mlxsw_sp_router_fib_abort(mlxsw_sp); 4769 fib_rule_put(rule); 4770 break; 4771 case FIB_EVENT_NH_ADD: /* fall through */ 4772 case FIB_EVENT_NH_DEL: 4773 mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event, 4774 fib_work->fnh_info.fib_nh); 4775 fib_info_put(fib_work->fnh_info.fib_nh->nh_parent); 4776 break; 4777 } 4778 rtnl_unlock(); 4779 kfree(fib_work); 4780 } 4781 4782 static void mlxsw_sp_router_fib6_event_work(struct work_struct *work) 4783 { 4784 struct mlxsw_sp_fib_event_work *fib_work = 4785 container_of(work, struct mlxsw_sp_fib_event_work, work); 4786 struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp; 4787 struct fib_rule *rule; 4788 bool replace; 4789 int err; 4790 4791 rtnl_lock(); 4792 switch (fib_work->event) { 4793 case FIB_EVENT_ENTRY_REPLACE: /* fall through */ 4794 case FIB_EVENT_ENTRY_ADD: 4795 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE; 4796 err = mlxsw_sp_router_fib6_add(mlxsw_sp, 4797 fib_work->fen6_info.rt, replace); 4798 if (err) 4799 mlxsw_sp_router_fib_abort(mlxsw_sp); 4800 mlxsw_sp_rt6_release(fib_work->fen6_info.rt); 4801 break; 4802 case FIB_EVENT_ENTRY_DEL: 4803 mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt); 4804 mlxsw_sp_rt6_release(fib_work->fen6_info.rt); 4805 break; 4806 case FIB_EVENT_RULE_ADD: /* fall through */ 4807 case FIB_EVENT_RULE_DEL: 4808 rule = fib_work->fr_info.rule; 4809 if (!fib6_rule_default(rule) && !rule->l3mdev) 4810 mlxsw_sp_router_fib_abort(mlxsw_sp); 4811 fib_rule_put(rule); 4812 break; 4813 } 4814 rtnl_unlock(); 4815 kfree(fib_work); 4816 } 4817 4818 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work, 4819 struct fib_notifier_info *info) 4820 { 4821 switch (fib_work->event) { 4822 case FIB_EVENT_ENTRY_REPLACE: /* fall through */ 4823 case FIB_EVENT_ENTRY_APPEND: /* fall through */ 4824 case FIB_EVENT_ENTRY_ADD: /* fall through */ 4825 case FIB_EVENT_ENTRY_DEL: 4826 memcpy(&fib_work->fen_info, info, sizeof(fib_work->fen_info)); 4827 /* Take referece on fib_info to prevent it from being 4828 * freed while work is queued. Release it afterwards. 4829 */ 4830 fib_info_hold(fib_work->fen_info.fi); 4831 break; 4832 case FIB_EVENT_RULE_ADD: /* fall through */ 4833 case FIB_EVENT_RULE_DEL: 4834 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info)); 4835 fib_rule_get(fib_work->fr_info.rule); 4836 break; 4837 case FIB_EVENT_NH_ADD: /* fall through */ 4838 case FIB_EVENT_NH_DEL: 4839 memcpy(&fib_work->fnh_info, info, sizeof(fib_work->fnh_info)); 4840 fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent); 4841 break; 4842 } 4843 } 4844 4845 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work, 4846 struct fib_notifier_info *info) 4847 { 4848 switch (fib_work->event) { 4849 case FIB_EVENT_ENTRY_REPLACE: /* fall through */ 4850 case FIB_EVENT_ENTRY_ADD: /* fall through */ 4851 case FIB_EVENT_ENTRY_DEL: 4852 memcpy(&fib_work->fen6_info, info, sizeof(fib_work->fen6_info)); 4853 rt6_hold(fib_work->fen6_info.rt); 4854 break; 4855 case FIB_EVENT_RULE_ADD: /* fall through */ 4856 case FIB_EVENT_RULE_DEL: 4857 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info)); 4858 fib_rule_get(fib_work->fr_info.rule); 4859 break; 4860 } 4861 } 4862 4863 /* Called with rcu_read_lock() */ 4864 static int mlxsw_sp_router_fib_event(struct notifier_block *nb, 4865 unsigned long event, void *ptr) 4866 { 4867 struct mlxsw_sp_fib_event_work *fib_work; 4868 struct fib_notifier_info *info = ptr; 4869 struct mlxsw_sp_router *router; 4870 4871 if (!net_eq(info->net, &init_net) || 4872 (info->family != AF_INET && info->family != AF_INET6)) 4873 return NOTIFY_DONE; 4874 4875 fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); 4876 if (WARN_ON(!fib_work)) 4877 return NOTIFY_BAD; 4878 4879 router = container_of(nb, struct mlxsw_sp_router, fib_nb); 4880 fib_work->mlxsw_sp = router->mlxsw_sp; 4881 fib_work->event = event; 4882 4883 switch (info->family) { 4884 case AF_INET: 4885 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work); 4886 mlxsw_sp_router_fib4_event(fib_work, info); 4887 break; 4888 case AF_INET6: 4889 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work); 4890 mlxsw_sp_router_fib6_event(fib_work, info); 4891 break; 4892 } 4893 4894 mlxsw_core_schedule_work(&fib_work->work); 4895 4896 return NOTIFY_DONE; 4897 } 4898 4899 static struct mlxsw_sp_rif * 4900 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp, 4901 const struct net_device *dev) 4902 { 4903 int i; 4904 4905 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) 4906 if (mlxsw_sp->router->rifs[i] && 4907 mlxsw_sp->router->rifs[i]->dev == dev) 4908 return mlxsw_sp->router->rifs[i]; 4909 4910 return NULL; 4911 } 4912 4913 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) 4914 { 4915 char ritr_pl[MLXSW_REG_RITR_LEN]; 4916 int err; 4917 4918 mlxsw_reg_ritr_rif_pack(ritr_pl, rif); 4919 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 4920 if (WARN_ON_ONCE(err)) 4921 return err; 4922 4923 mlxsw_reg_ritr_enable_set(ritr_pl, false); 4924 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 4925 } 4926 4927 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp, 4928 struct mlxsw_sp_rif *rif) 4929 { 4930 mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index); 4931 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif); 4932 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif); 4933 } 4934 4935 static bool 4936 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev, 4937 unsigned long event) 4938 { 4939 struct inet6_dev *inet6_dev; 4940 bool addr_list_empty = true; 4941 struct in_device *idev; 4942 4943 switch (event) { 4944 case NETDEV_UP: 4945 return rif == NULL; 4946 case NETDEV_DOWN: 4947 idev = __in_dev_get_rtnl(dev); 4948 if (idev && idev->ifa_list) 4949 addr_list_empty = false; 4950 4951 inet6_dev = __in6_dev_get(dev); 4952 if (addr_list_empty && inet6_dev && 4953 !list_empty(&inet6_dev->addr_list)) 4954 addr_list_empty = false; 4955 4956 if (rif && addr_list_empty && 4957 !netif_is_l3_slave(rif->dev)) 4958 return true; 4959 /* It is possible we already removed the RIF ourselves 4960 * if it was assigned to a netdev that is now a bridge 4961 * or LAG slave. 4962 */ 4963 return false; 4964 } 4965 4966 return false; 4967 } 4968 4969 static enum mlxsw_sp_rif_type 4970 mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp, 4971 const struct net_device *dev) 4972 { 4973 enum mlxsw_sp_fid_type type; 4974 4975 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL)) 4976 return MLXSW_SP_RIF_TYPE_IPIP_LB; 4977 4978 /* Otherwise RIF type is derived from the type of the underlying FID. */ 4979 if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev))) 4980 type = MLXSW_SP_FID_TYPE_8021Q; 4981 else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev)) 4982 type = MLXSW_SP_FID_TYPE_8021Q; 4983 else if (netif_is_bridge_master(dev)) 4984 type = MLXSW_SP_FID_TYPE_8021D; 4985 else 4986 type = MLXSW_SP_FID_TYPE_RFID; 4987 4988 return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type); 4989 } 4990 4991 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index) 4992 { 4993 int i; 4994 4995 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) { 4996 if (!mlxsw_sp->router->rifs[i]) { 4997 *p_rif_index = i; 4998 return 0; 4999 } 5000 } 5001 5002 return -ENOBUFS; 5003 } 5004 5005 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index, 5006 u16 vr_id, 5007 struct net_device *l3_dev) 5008 { 5009 struct mlxsw_sp_rif *rif; 5010 5011 rif = kzalloc(rif_size, GFP_KERNEL); 5012 if (!rif) 5013 return NULL; 5014 5015 INIT_LIST_HEAD(&rif->nexthop_list); 5016 INIT_LIST_HEAD(&rif->neigh_list); 5017 ether_addr_copy(rif->addr, l3_dev->dev_addr); 5018 rif->mtu = l3_dev->mtu; 5019 rif->vr_id = vr_id; 5020 rif->dev = l3_dev; 5021 rif->rif_index = rif_index; 5022 5023 return rif; 5024 } 5025 5026 struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp, 5027 u16 rif_index) 5028 { 5029 return mlxsw_sp->router->rifs[rif_index]; 5030 } 5031 5032 u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif) 5033 { 5034 return rif->rif_index; 5035 } 5036 5037 u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif) 5038 { 5039 return lb_rif->common.rif_index; 5040 } 5041 5042 u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) 5043 { 5044 return lb_rif->ul_vr_id; 5045 } 5046 5047 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) 5048 { 5049 return rif->dev->ifindex; 5050 } 5051 5052 static struct mlxsw_sp_rif * 5053 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, 5054 const struct mlxsw_sp_rif_params *params) 5055 { 5056 u32 tb_id = l3mdev_fib_table(params->dev); 5057 const struct mlxsw_sp_rif_ops *ops; 5058 struct mlxsw_sp_fid *fid = NULL; 5059 enum mlxsw_sp_rif_type type; 5060 struct mlxsw_sp_rif *rif; 5061 struct mlxsw_sp_vr *vr; 5062 u16 rif_index; 5063 int err; 5064 5065 type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev); 5066 ops = mlxsw_sp->router->rif_ops_arr[type]; 5067 5068 vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN); 5069 if (IS_ERR(vr)) 5070 return ERR_CAST(vr); 5071 5072 err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index); 5073 if (err) 5074 goto err_rif_index_alloc; 5075 5076 rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev); 5077 if (!rif) { 5078 err = -ENOMEM; 5079 goto err_rif_alloc; 5080 } 5081 rif->mlxsw_sp = mlxsw_sp; 5082 rif->ops = ops; 5083 5084 if (ops->fid_get) { 5085 fid = ops->fid_get(rif); 5086 if (IS_ERR(fid)) { 5087 err = PTR_ERR(fid); 5088 goto err_fid_get; 5089 } 5090 rif->fid = fid; 5091 } 5092 5093 if (ops->setup) 5094 ops->setup(rif, params); 5095 5096 err = ops->configure(rif); 5097 if (err) 5098 goto err_configure; 5099 5100 mlxsw_sp_rif_counters_alloc(rif); 5101 mlxsw_sp->router->rifs[rif_index] = rif; 5102 vr->rif_count++; 5103 5104 return rif; 5105 5106 err_configure: 5107 if (fid) 5108 mlxsw_sp_fid_put(fid); 5109 err_fid_get: 5110 kfree(rif); 5111 err_rif_alloc: 5112 err_rif_index_alloc: 5113 mlxsw_sp_vr_put(vr); 5114 return ERR_PTR(err); 5115 } 5116 5117 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) 5118 { 5119 const struct mlxsw_sp_rif_ops *ops = rif->ops; 5120 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5121 struct mlxsw_sp_fid *fid = rif->fid; 5122 struct mlxsw_sp_vr *vr; 5123 5124 mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); 5125 vr = &mlxsw_sp->router->vrs[rif->vr_id]; 5126 5127 vr->rif_count--; 5128 mlxsw_sp->router->rifs[rif->rif_index] = NULL; 5129 mlxsw_sp_rif_counters_free(rif); 5130 ops->deconfigure(rif); 5131 if (fid) 5132 /* Loopback RIFs are not associated with a FID. */ 5133 mlxsw_sp_fid_put(fid); 5134 kfree(rif); 5135 mlxsw_sp_vr_put(vr); 5136 } 5137 5138 static void 5139 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params, 5140 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) 5141 { 5142 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; 5143 5144 params->vid = mlxsw_sp_port_vlan->vid; 5145 params->lag = mlxsw_sp_port->lagged; 5146 if (params->lag) 5147 params->lag_id = mlxsw_sp_port->lag_id; 5148 else 5149 params->system_port = mlxsw_sp_port->local_port; 5150 } 5151 5152 static int 5153 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, 5154 struct net_device *l3_dev) 5155 { 5156 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; 5157 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 5158 u16 vid = mlxsw_sp_port_vlan->vid; 5159 struct mlxsw_sp_rif *rif; 5160 struct mlxsw_sp_fid *fid; 5161 int err; 5162 5163 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); 5164 if (!rif) { 5165 struct mlxsw_sp_rif_params params = { 5166 .dev = l3_dev, 5167 }; 5168 5169 mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan); 5170 rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms); 5171 if (IS_ERR(rif)) 5172 return PTR_ERR(rif); 5173 } 5174 5175 /* FID was already created, just take a reference */ 5176 fid = rif->ops->fid_get(rif); 5177 err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid); 5178 if (err) 5179 goto err_fid_port_vid_map; 5180 5181 err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false); 5182 if (err) 5183 goto err_port_vid_learning_set; 5184 5185 err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, 5186 BR_STATE_FORWARDING); 5187 if (err) 5188 goto err_port_vid_stp_set; 5189 5190 mlxsw_sp_port_vlan->fid = fid; 5191 5192 return 0; 5193 5194 err_port_vid_stp_set: 5195 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true); 5196 err_port_vid_learning_set: 5197 mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid); 5198 err_fid_port_vid_map: 5199 mlxsw_sp_fid_put(fid); 5200 return err; 5201 } 5202 5203 void 5204 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) 5205 { 5206 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; 5207 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid; 5208 u16 vid = mlxsw_sp_port_vlan->vid; 5209 5210 if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID)) 5211 return; 5212 5213 mlxsw_sp_port_vlan->fid = NULL; 5214 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING); 5215 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true); 5216 mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid); 5217 /* If router port holds the last reference on the rFID, then the 5218 * associated Sub-port RIF will be destroyed. 5219 */ 5220 mlxsw_sp_fid_put(fid); 5221 } 5222 5223 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, 5224 struct net_device *port_dev, 5225 unsigned long event, u16 vid) 5226 { 5227 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev); 5228 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; 5229 5230 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid); 5231 if (WARN_ON(!mlxsw_sp_port_vlan)) 5232 return -EINVAL; 5233 5234 switch (event) { 5235 case NETDEV_UP: 5236 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, 5237 l3_dev); 5238 case NETDEV_DOWN: 5239 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); 5240 break; 5241 } 5242 5243 return 0; 5244 } 5245 5246 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev, 5247 unsigned long event) 5248 { 5249 if (netif_is_bridge_port(port_dev) || 5250 netif_is_lag_port(port_dev) || 5251 netif_is_ovs_port(port_dev)) 5252 return 0; 5253 5254 return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1); 5255 } 5256 5257 static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev, 5258 struct net_device *lag_dev, 5259 unsigned long event, u16 vid) 5260 { 5261 struct net_device *port_dev; 5262 struct list_head *iter; 5263 int err; 5264 5265 netdev_for_each_lower_dev(lag_dev, port_dev, iter) { 5266 if (mlxsw_sp_port_dev_check(port_dev)) { 5267 err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev, 5268 port_dev, 5269 event, vid); 5270 if (err) 5271 return err; 5272 } 5273 } 5274 5275 return 0; 5276 } 5277 5278 static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev, 5279 unsigned long event) 5280 { 5281 if (netif_is_bridge_port(lag_dev)) 5282 return 0; 5283 5284 return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1); 5285 } 5286 5287 static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev, 5288 unsigned long event) 5289 { 5290 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev); 5291 struct mlxsw_sp_rif_params params = { 5292 .dev = l3_dev, 5293 }; 5294 struct mlxsw_sp_rif *rif; 5295 5296 switch (event) { 5297 case NETDEV_UP: 5298 rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms); 5299 if (IS_ERR(rif)) 5300 return PTR_ERR(rif); 5301 break; 5302 case NETDEV_DOWN: 5303 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); 5304 mlxsw_sp_rif_destroy(rif); 5305 break; 5306 } 5307 5308 return 0; 5309 } 5310 5311 static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev, 5312 unsigned long event) 5313 { 5314 struct net_device *real_dev = vlan_dev_real_dev(vlan_dev); 5315 u16 vid = vlan_dev_vlan_id(vlan_dev); 5316 5317 if (netif_is_bridge_port(vlan_dev)) 5318 return 0; 5319 5320 if (mlxsw_sp_port_dev_check(real_dev)) 5321 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev, 5322 event, vid); 5323 else if (netif_is_lag_master(real_dev)) 5324 return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event, 5325 vid); 5326 else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev)) 5327 return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event); 5328 5329 return 0; 5330 } 5331 5332 static int __mlxsw_sp_inetaddr_event(struct net_device *dev, 5333 unsigned long event) 5334 { 5335 if (mlxsw_sp_port_dev_check(dev)) 5336 return mlxsw_sp_inetaddr_port_event(dev, event); 5337 else if (netif_is_lag_master(dev)) 5338 return mlxsw_sp_inetaddr_lag_event(dev, event); 5339 else if (netif_is_bridge_master(dev)) 5340 return mlxsw_sp_inetaddr_bridge_event(dev, event); 5341 else if (is_vlan_dev(dev)) 5342 return mlxsw_sp_inetaddr_vlan_event(dev, event); 5343 else 5344 return 0; 5345 } 5346 5347 int mlxsw_sp_inetaddr_event(struct notifier_block *unused, 5348 unsigned long event, void *ptr) 5349 { 5350 struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; 5351 struct net_device *dev = ifa->ifa_dev->dev; 5352 struct mlxsw_sp *mlxsw_sp; 5353 struct mlxsw_sp_rif *rif; 5354 int err = 0; 5355 5356 mlxsw_sp = mlxsw_sp_lower_get(dev); 5357 if (!mlxsw_sp) 5358 goto out; 5359 5360 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); 5361 if (!mlxsw_sp_rif_should_config(rif, dev, event)) 5362 goto out; 5363 5364 err = __mlxsw_sp_inetaddr_event(dev, event); 5365 out: 5366 return notifier_from_errno(err); 5367 } 5368 5369 struct mlxsw_sp_inet6addr_event_work { 5370 struct work_struct work; 5371 struct net_device *dev; 5372 unsigned long event; 5373 }; 5374 5375 static void mlxsw_sp_inet6addr_event_work(struct work_struct *work) 5376 { 5377 struct mlxsw_sp_inet6addr_event_work *inet6addr_work = 5378 container_of(work, struct mlxsw_sp_inet6addr_event_work, work); 5379 struct net_device *dev = inet6addr_work->dev; 5380 unsigned long event = inet6addr_work->event; 5381 struct mlxsw_sp *mlxsw_sp; 5382 struct mlxsw_sp_rif *rif; 5383 5384 rtnl_lock(); 5385 mlxsw_sp = mlxsw_sp_lower_get(dev); 5386 if (!mlxsw_sp) 5387 goto out; 5388 5389 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); 5390 if (!mlxsw_sp_rif_should_config(rif, dev, event)) 5391 goto out; 5392 5393 __mlxsw_sp_inetaddr_event(dev, event); 5394 out: 5395 rtnl_unlock(); 5396 dev_put(dev); 5397 kfree(inet6addr_work); 5398 } 5399 5400 /* Called with rcu_read_lock() */ 5401 int mlxsw_sp_inet6addr_event(struct notifier_block *unused, 5402 unsigned long event, void *ptr) 5403 { 5404 struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr; 5405 struct mlxsw_sp_inet6addr_event_work *inet6addr_work; 5406 struct net_device *dev = if6->idev->dev; 5407 5408 if (!mlxsw_sp_port_dev_lower_find_rcu(dev)) 5409 return NOTIFY_DONE; 5410 5411 inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC); 5412 if (!inet6addr_work) 5413 return NOTIFY_BAD; 5414 5415 INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work); 5416 inet6addr_work->dev = dev; 5417 inet6addr_work->event = event; 5418 dev_hold(dev); 5419 mlxsw_core_schedule_work(&inet6addr_work->work); 5420 5421 return NOTIFY_DONE; 5422 } 5423 5424 static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index, 5425 const char *mac, int mtu) 5426 { 5427 char ritr_pl[MLXSW_REG_RITR_LEN]; 5428 int err; 5429 5430 mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index); 5431 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 5432 if (err) 5433 return err; 5434 5435 mlxsw_reg_ritr_mtu_set(ritr_pl, mtu); 5436 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac); 5437 mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE); 5438 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 5439 } 5440 5441 int mlxsw_sp_netdevice_router_port_event(struct net_device *dev) 5442 { 5443 struct mlxsw_sp *mlxsw_sp; 5444 struct mlxsw_sp_rif *rif; 5445 u16 fid_index; 5446 int err; 5447 5448 mlxsw_sp = mlxsw_sp_lower_get(dev); 5449 if (!mlxsw_sp) 5450 return 0; 5451 5452 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev); 5453 if (!rif) 5454 return 0; 5455 fid_index = mlxsw_sp_fid_index(rif->fid); 5456 5457 err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false); 5458 if (err) 5459 return err; 5460 5461 err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr, 5462 dev->mtu); 5463 if (err) 5464 goto err_rif_edit; 5465 5466 err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true); 5467 if (err) 5468 goto err_rif_fdb_op; 5469 5470 ether_addr_copy(rif->addr, dev->dev_addr); 5471 rif->mtu = dev->mtu; 5472 5473 netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index); 5474 5475 return 0; 5476 5477 err_rif_fdb_op: 5478 mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu); 5479 err_rif_edit: 5480 mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true); 5481 return err; 5482 } 5483 5484 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp, 5485 struct net_device *l3_dev) 5486 { 5487 struct mlxsw_sp_rif *rif; 5488 5489 /* If netdev is already associated with a RIF, then we need to 5490 * destroy it and create a new one with the new virtual router ID. 5491 */ 5492 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); 5493 if (rif) 5494 __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN); 5495 5496 return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP); 5497 } 5498 5499 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp, 5500 struct net_device *l3_dev) 5501 { 5502 struct mlxsw_sp_rif *rif; 5503 5504 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev); 5505 if (!rif) 5506 return; 5507 __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN); 5508 } 5509 5510 int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event, 5511 struct netdev_notifier_changeupper_info *info) 5512 { 5513 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev); 5514 int err = 0; 5515 5516 if (!mlxsw_sp) 5517 return 0; 5518 5519 switch (event) { 5520 case NETDEV_PRECHANGEUPPER: 5521 return 0; 5522 case NETDEV_CHANGEUPPER: 5523 if (info->linking) 5524 err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev); 5525 else 5526 mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev); 5527 break; 5528 } 5529 5530 return err; 5531 } 5532 5533 static struct mlxsw_sp_rif_subport * 5534 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif) 5535 { 5536 return container_of(rif, struct mlxsw_sp_rif_subport, common); 5537 } 5538 5539 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif, 5540 const struct mlxsw_sp_rif_params *params) 5541 { 5542 struct mlxsw_sp_rif_subport *rif_subport; 5543 5544 rif_subport = mlxsw_sp_rif_subport_rif(rif); 5545 rif_subport->vid = params->vid; 5546 rif_subport->lag = params->lag; 5547 if (params->lag) 5548 rif_subport->lag_id = params->lag_id; 5549 else 5550 rif_subport->system_port = params->system_port; 5551 } 5552 5553 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable) 5554 { 5555 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5556 struct mlxsw_sp_rif_subport *rif_subport; 5557 char ritr_pl[MLXSW_REG_RITR_LEN]; 5558 5559 rif_subport = mlxsw_sp_rif_subport_rif(rif); 5560 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF, 5561 rif->rif_index, rif->vr_id, rif->dev->mtu); 5562 mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); 5563 mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag, 5564 rif_subport->lag ? rif_subport->lag_id : 5565 rif_subport->system_port, 5566 rif_subport->vid); 5567 5568 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 5569 } 5570 5571 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif) 5572 { 5573 int err; 5574 5575 err = mlxsw_sp_rif_subport_op(rif, true); 5576 if (err) 5577 return err; 5578 5579 err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5580 mlxsw_sp_fid_index(rif->fid), true); 5581 if (err) 5582 goto err_rif_fdb_op; 5583 5584 mlxsw_sp_fid_rif_set(rif->fid, rif); 5585 return 0; 5586 5587 err_rif_fdb_op: 5588 mlxsw_sp_rif_subport_op(rif, false); 5589 return err; 5590 } 5591 5592 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif) 5593 { 5594 struct mlxsw_sp_fid *fid = rif->fid; 5595 5596 mlxsw_sp_fid_rif_set(fid, NULL); 5597 mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5598 mlxsw_sp_fid_index(fid), false); 5599 mlxsw_sp_rif_subport_op(rif, false); 5600 } 5601 5602 static struct mlxsw_sp_fid * 5603 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif) 5604 { 5605 return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index); 5606 } 5607 5608 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = { 5609 .type = MLXSW_SP_RIF_TYPE_SUBPORT, 5610 .rif_size = sizeof(struct mlxsw_sp_rif_subport), 5611 .setup = mlxsw_sp_rif_subport_setup, 5612 .configure = mlxsw_sp_rif_subport_configure, 5613 .deconfigure = mlxsw_sp_rif_subport_deconfigure, 5614 .fid_get = mlxsw_sp_rif_subport_fid_get, 5615 }; 5616 5617 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif, 5618 enum mlxsw_reg_ritr_if_type type, 5619 u16 vid_fid, bool enable) 5620 { 5621 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5622 char ritr_pl[MLXSW_REG_RITR_LEN]; 5623 5624 mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id, 5625 rif->dev->mtu); 5626 mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr); 5627 mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid); 5628 5629 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 5630 } 5631 5632 static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp) 5633 { 5634 return mlxsw_core_max_ports(mlxsw_sp->core) + 1; 5635 } 5636 5637 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif) 5638 { 5639 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5640 u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); 5641 int err; 5642 5643 err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, true); 5644 if (err) 5645 return err; 5646 5647 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5648 mlxsw_sp_router_port(mlxsw_sp), true); 5649 if (err) 5650 goto err_fid_mc_flood_set; 5651 5652 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5653 mlxsw_sp_router_port(mlxsw_sp), true); 5654 if (err) 5655 goto err_fid_bc_flood_set; 5656 5657 err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5658 mlxsw_sp_fid_index(rif->fid), true); 5659 if (err) 5660 goto err_rif_fdb_op; 5661 5662 mlxsw_sp_fid_rif_set(rif->fid, rif); 5663 return 0; 5664 5665 err_rif_fdb_op: 5666 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5667 mlxsw_sp_router_port(mlxsw_sp), false); 5668 err_fid_bc_flood_set: 5669 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5670 mlxsw_sp_router_port(mlxsw_sp), false); 5671 err_fid_mc_flood_set: 5672 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false); 5673 return err; 5674 } 5675 5676 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif) 5677 { 5678 u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); 5679 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5680 struct mlxsw_sp_fid *fid = rif->fid; 5681 5682 mlxsw_sp_fid_rif_set(fid, NULL); 5683 mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5684 mlxsw_sp_fid_index(fid), false); 5685 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5686 mlxsw_sp_router_port(mlxsw_sp), false); 5687 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5688 mlxsw_sp_router_port(mlxsw_sp), false); 5689 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false); 5690 } 5691 5692 static struct mlxsw_sp_fid * 5693 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif) 5694 { 5695 u16 vid = is_vlan_dev(rif->dev) ? vlan_dev_vlan_id(rif->dev) : 1; 5696 5697 return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid); 5698 } 5699 5700 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = { 5701 .type = MLXSW_SP_RIF_TYPE_VLAN, 5702 .rif_size = sizeof(struct mlxsw_sp_rif), 5703 .configure = mlxsw_sp_rif_vlan_configure, 5704 .deconfigure = mlxsw_sp_rif_vlan_deconfigure, 5705 .fid_get = mlxsw_sp_rif_vlan_fid_get, 5706 }; 5707 5708 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif) 5709 { 5710 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5711 u16 fid_index = mlxsw_sp_fid_index(rif->fid); 5712 int err; 5713 5714 err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, 5715 true); 5716 if (err) 5717 return err; 5718 5719 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5720 mlxsw_sp_router_port(mlxsw_sp), true); 5721 if (err) 5722 goto err_fid_mc_flood_set; 5723 5724 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5725 mlxsw_sp_router_port(mlxsw_sp), true); 5726 if (err) 5727 goto err_fid_bc_flood_set; 5728 5729 err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5730 mlxsw_sp_fid_index(rif->fid), true); 5731 if (err) 5732 goto err_rif_fdb_op; 5733 5734 mlxsw_sp_fid_rif_set(rif->fid, rif); 5735 return 0; 5736 5737 err_rif_fdb_op: 5738 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5739 mlxsw_sp_router_port(mlxsw_sp), false); 5740 err_fid_bc_flood_set: 5741 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5742 mlxsw_sp_router_port(mlxsw_sp), false); 5743 err_fid_mc_flood_set: 5744 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false); 5745 return err; 5746 } 5747 5748 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif) 5749 { 5750 u16 fid_index = mlxsw_sp_fid_index(rif->fid); 5751 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5752 struct mlxsw_sp_fid *fid = rif->fid; 5753 5754 mlxsw_sp_fid_rif_set(fid, NULL); 5755 mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, 5756 mlxsw_sp_fid_index(fid), false); 5757 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, 5758 mlxsw_sp_router_port(mlxsw_sp), false); 5759 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, 5760 mlxsw_sp_router_port(mlxsw_sp), false); 5761 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false); 5762 } 5763 5764 static struct mlxsw_sp_fid * 5765 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif) 5766 { 5767 return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex); 5768 } 5769 5770 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = { 5771 .type = MLXSW_SP_RIF_TYPE_FID, 5772 .rif_size = sizeof(struct mlxsw_sp_rif), 5773 .configure = mlxsw_sp_rif_fid_configure, 5774 .deconfigure = mlxsw_sp_rif_fid_deconfigure, 5775 .fid_get = mlxsw_sp_rif_fid_fid_get, 5776 }; 5777 5778 static struct mlxsw_sp_rif_ipip_lb * 5779 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif) 5780 { 5781 return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common); 5782 } 5783 5784 static void 5785 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif, 5786 const struct mlxsw_sp_rif_params *params) 5787 { 5788 struct mlxsw_sp_rif_params_ipip_lb *params_lb; 5789 struct mlxsw_sp_rif_ipip_lb *rif_lb; 5790 5791 params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb, 5792 common); 5793 rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif); 5794 rif_lb->lb_config = params_lb->lb_config; 5795 } 5796 5797 static int 5798 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, 5799 struct mlxsw_sp_vr *ul_vr, bool enable) 5800 { 5801 struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config; 5802 struct mlxsw_sp_rif *rif = &lb_rif->common; 5803 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5804 char ritr_pl[MLXSW_REG_RITR_LEN]; 5805 u32 saddr4; 5806 5807 switch (lb_cf.ul_protocol) { 5808 case MLXSW_SP_L3_PROTO_IPV4: 5809 saddr4 = be32_to_cpu(lb_cf.saddr.addr4); 5810 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, 5811 rif->rif_index, rif->vr_id, rif->dev->mtu); 5812 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt, 5813 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET, 5814 ul_vr->id, saddr4, lb_cf.okey); 5815 break; 5816 5817 case MLXSW_SP_L3_PROTO_IPV6: 5818 return -EAFNOSUPPORT; 5819 } 5820 5821 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); 5822 } 5823 5824 static int 5825 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) 5826 { 5827 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); 5828 u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); 5829 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5830 struct mlxsw_sp_vr *ul_vr; 5831 int err; 5832 5833 ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id); 5834 if (IS_ERR(ul_vr)) 5835 return PTR_ERR(ul_vr); 5836 5837 err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true); 5838 if (err) 5839 goto err_loopback_op; 5840 5841 lb_rif->ul_vr_id = ul_vr->id; 5842 ++ul_vr->rif_count; 5843 return 0; 5844 5845 err_loopback_op: 5846 mlxsw_sp_vr_put(ul_vr); 5847 return err; 5848 } 5849 5850 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) 5851 { 5852 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); 5853 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; 5854 struct mlxsw_sp_vr *ul_vr; 5855 5856 ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id]; 5857 mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false); 5858 5859 --ul_vr->rif_count; 5860 mlxsw_sp_vr_put(ul_vr); 5861 } 5862 5863 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = { 5864 .type = MLXSW_SP_RIF_TYPE_IPIP_LB, 5865 .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb), 5866 .setup = mlxsw_sp_rif_ipip_lb_setup, 5867 .configure = mlxsw_sp_rif_ipip_lb_configure, 5868 .deconfigure = mlxsw_sp_rif_ipip_lb_deconfigure, 5869 }; 5870 5871 static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = { 5872 [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops, 5873 [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_ops, 5874 [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops, 5875 [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp_rif_ipip_lb_ops, 5876 }; 5877 5878 static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) 5879 { 5880 u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); 5881 5882 mlxsw_sp->router->rifs = kcalloc(max_rifs, 5883 sizeof(struct mlxsw_sp_rif *), 5884 GFP_KERNEL); 5885 if (!mlxsw_sp->router->rifs) 5886 return -ENOMEM; 5887 5888 mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr; 5889 5890 return 0; 5891 } 5892 5893 static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp) 5894 { 5895 int i; 5896 5897 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) 5898 WARN_ON_ONCE(mlxsw_sp->router->rifs[i]); 5899 5900 kfree(mlxsw_sp->router->rifs); 5901 } 5902 5903 static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp) 5904 { 5905 mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr; 5906 INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list); 5907 return 0; 5908 } 5909 5910 static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp) 5911 { 5912 WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list)); 5913 } 5914 5915 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb) 5916 { 5917 struct mlxsw_sp_router *router; 5918 5919 /* Flush pending FIB notifications and then flush the device's 5920 * table before requesting another dump. The FIB notification 5921 * block is unregistered, so no need to take RTNL. 5922 */ 5923 mlxsw_core_flush_owq(); 5924 router = container_of(nb, struct mlxsw_sp_router, fib_nb); 5925 mlxsw_sp_router_fib_flush(router->mlxsw_sp); 5926 } 5927 5928 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) 5929 { 5930 char rgcr_pl[MLXSW_REG_RGCR_LEN]; 5931 u64 max_rifs; 5932 int err; 5933 5934 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS)) 5935 return -EIO; 5936 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); 5937 5938 mlxsw_reg_rgcr_pack(rgcr_pl, true, true); 5939 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs); 5940 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); 5941 if (err) 5942 return err; 5943 return 0; 5944 } 5945 5946 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) 5947 { 5948 char rgcr_pl[MLXSW_REG_RGCR_LEN]; 5949 5950 mlxsw_reg_rgcr_pack(rgcr_pl, false, false); 5951 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl); 5952 } 5953 5954 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp) 5955 { 5956 struct mlxsw_sp_router *router; 5957 int err; 5958 5959 router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL); 5960 if (!router) 5961 return -ENOMEM; 5962 mlxsw_sp->router = router; 5963 router->mlxsw_sp = mlxsw_sp; 5964 5965 INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list); 5966 err = __mlxsw_sp_router_init(mlxsw_sp); 5967 if (err) 5968 goto err_router_init; 5969 5970 err = mlxsw_sp_rifs_init(mlxsw_sp); 5971 if (err) 5972 goto err_rifs_init; 5973 5974 err = mlxsw_sp_ipips_init(mlxsw_sp); 5975 if (err) 5976 goto err_ipips_init; 5977 5978 err = rhashtable_init(&mlxsw_sp->router->nexthop_ht, 5979 &mlxsw_sp_nexthop_ht_params); 5980 if (err) 5981 goto err_nexthop_ht_init; 5982 5983 err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht, 5984 &mlxsw_sp_nexthop_group_ht_params); 5985 if (err) 5986 goto err_nexthop_group_ht_init; 5987 5988 err = mlxsw_sp_lpm_init(mlxsw_sp); 5989 if (err) 5990 goto err_lpm_init; 5991 5992 err = mlxsw_sp_vrs_init(mlxsw_sp); 5993 if (err) 5994 goto err_vrs_init; 5995 5996 err = mlxsw_sp_neigh_init(mlxsw_sp); 5997 if (err) 5998 goto err_neigh_init; 5999 6000 mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event; 6001 err = register_fib_notifier(&mlxsw_sp->router->fib_nb, 6002 mlxsw_sp_router_fib_dump_flush); 6003 if (err) 6004 goto err_register_fib_notifier; 6005 6006 return 0; 6007 6008 err_register_fib_notifier: 6009 mlxsw_sp_neigh_fini(mlxsw_sp); 6010 err_neigh_init: 6011 mlxsw_sp_vrs_fini(mlxsw_sp); 6012 err_vrs_init: 6013 mlxsw_sp_lpm_fini(mlxsw_sp); 6014 err_lpm_init: 6015 rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht); 6016 err_nexthop_group_ht_init: 6017 rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); 6018 err_nexthop_ht_init: 6019 mlxsw_sp_ipips_fini(mlxsw_sp); 6020 err_ipips_init: 6021 mlxsw_sp_rifs_fini(mlxsw_sp); 6022 err_rifs_init: 6023 __mlxsw_sp_router_fini(mlxsw_sp); 6024 err_router_init: 6025 kfree(mlxsw_sp->router); 6026 return err; 6027 } 6028 6029 void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) 6030 { 6031 unregister_fib_notifier(&mlxsw_sp->router->fib_nb); 6032 mlxsw_sp_neigh_fini(mlxsw_sp); 6033 mlxsw_sp_vrs_fini(mlxsw_sp); 6034 mlxsw_sp_lpm_fini(mlxsw_sp); 6035 rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht); 6036 rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); 6037 mlxsw_sp_ipips_fini(mlxsw_sp); 6038 mlxsw_sp_rifs_fini(mlxsw_sp); 6039 __mlxsw_sp_router_fini(mlxsw_sp); 6040 kfree(mlxsw_sp->router); 6041 } 6042