FILE
tc_tun_encap.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2021 Mellanox Technologies. */ 3 4#include <net/fib_notifier.h> 5#include <net/nexthop.h> 6#include <net/ip_tunnels.h> 7#include "tc_tun_encap.h" 8#include "fs_core.h" 9#include "en_tc.h" 10#include "tc_tun.h" 11#include "rep/tc.h" 12#include "diag/en_tc_tracepoint.h" 13 14enum { 15 MLX5E_ROUTE_ENTRY_VALID = BIT(0), 16}; 17 18static int mlx5e_set_int_port_tunnel(struct mlx5e_priv *priv, 19 struct mlx5_flow_attr *attr, 20 struct mlx5e_encap_entry *e, 21 int out_index) 22{ 23 struct net_device *route_dev; 24 int err = 0; 25 26 route_dev = dev_get_by_index(dev_net(e->out_dev), e->route_dev_ifindex); 27 28 if (!route_dev || !netif_is_ovs_master(route_dev)) 29 goto out; 30 31 if (priv->mdev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_DMFS && 32 mlx5e_eswitch_uplink_rep(attr->parse_attr->filter_dev) && 33 (attr->esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) { 34 mlx5_core_warn(priv->mdev, 35 "Matching on external port with encap + fwd to table actions is not allowed for firmware steering\n"); 36 err = -EINVAL; 37 goto out; 38 } 39 40 err = mlx5e_set_fwd_to_int_port_actions(priv, attr, e->route_dev_ifindex, 41 MLX5E_TC_INT_PORT_EGRESS, 42 &attr->action, out_index); 43 44out: 45 dev_put(route_dev); 46 47 return err; 48} 49 50struct mlx5e_route_key { 51 int ip_version; 52 union { 53 __be32 v4; 54 struct in6_addr v6; 55 } endpoint_ip; 56}; 57 58struct mlx5e_route_entry { 59 struct mlx5e_route_key key; 60 struct list_head encap_entries; 61 struct list_head decap_flows; 62 u32 flags; 63 struct hlist_node hlist; 64 refcount_t refcnt; 65 int tunnel_dev_index; 66 struct rcu_head rcu; 67}; 68 69struct mlx5e_tc_tun_encap { 70 struct mlx5e_priv *priv; 71 struct notifier_block fib_nb; 72 spinlock_t route_lock; /* protects route_tbl */ 73 unsigned long route_tbl_last_update; 74 DECLARE_HASHTABLE(route_tbl, 8); 75}; 76 77static bool mlx5e_route_entry_valid(struct mlx5e_route_entry *r) 78{ 79 return r->flags & MLX5E_ROUTE_ENTRY_VALID; 80} 81 82int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow, 83 struct mlx5_flow_spec *spec) 84{ 85 struct mlx5_esw_flow_attr *esw_attr = flow->attr->esw_attr; 86 struct mlx5_rx_tun_attr *tun_attr; 87 void *daddr, *saddr; 88 u8 ip_version; 89 90 tun_attr = kvzalloc(sizeof(*tun_attr), GFP_KERNEL); 91 if (!tun_attr) 92 return -ENOMEM; 93 94 esw_attr->rx_tun_attr = tun_attr; 95 ip_version = mlx5e_tc_get_ip_version(spec, true); 96 97 if (ip_version == 4) { 98 daddr = MLX5_ADDR_OF(fte_match_param, spec->match_value, 99 outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4); 100 saddr = MLX5_ADDR_OF(fte_match_param, spec->match_value, 101 outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4); 102 tun_attr->dst_ip.v4 = *(__be32 *)daddr; 103 tun_attr->src_ip.v4 = *(__be32 *)saddr; 104 if (!tun_attr->dst_ip.v4 || !tun_attr->src_ip.v4) 105 return 0; 106 } 107#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6) 108 else if (ip_version == 6) { 109 int ipv6_size = MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6); 110 111 daddr = MLX5_ADDR_OF(fte_match_param, spec->match_value, 112 outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6); 113 saddr = MLX5_ADDR_OF(fte_match_param, spec->match_value, 114 outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6); 115 memcpy(&tun_attr->dst_ip.v6, daddr, ipv6_size); 116 memcpy(&tun_attr->src_ip.v6, saddr, ipv6_size); 117 if (ipv6_addr_any(&tun_attr->dst_ip.v6) || 118 ipv6_addr_any(&tun_attr->src_ip.v6)) 119 return 0; 120 } 121#endif 122 /* Only set the flag if both src and dst ip addresses exist. They are 123 * required to establish routing. 124 */ 125 flow_flag_set(flow, TUN_RX); 126 flow->attr->tun_ip_version = ip_version; 127 return 0; 128} 129 130static bool mlx5e_tc_flow_all_encaps_valid(struct mlx5_esw_flow_attr *esw_attr) 131{ 132 bool all_flow_encaps_valid = true; 133 int i; 134 135 /* Flow can be associated with multiple encap entries. 136 * Before offloading the flow verify that all of them have 137 * a valid neighbour. 138 */ 139 for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { 140 if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP)) 141 continue; 142 if (!(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP_VALID)) { 143 all_flow_encaps_valid = false; 144 break; 145 } 146 } 147 148 return all_flow_encaps_valid; 149} 150 151void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, 152 struct mlx5e_encap_entry *e, 153 struct list_head *flow_list) 154{ 155 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 156 struct mlx5_pkt_reformat_params reformat_params; 157 struct mlx5_esw_flow_attr *esw_attr; 158 struct mlx5_flow_handle *rule; 159 struct mlx5_flow_attr *attr; 160 struct mlx5_flow_spec *spec; 161 struct mlx5e_tc_flow *flow; 162 int err; 163 164 if (e->flags & MLX5_ENCAP_ENTRY_NO_ROUTE) 165 return; 166 167 memset(&reformat_params, 0, sizeof(reformat_params)); 168 reformat_params.type = e->reformat_type; 169 reformat_params.size = e->encap_size; 170 reformat_params.data = e->encap_header; 171 e->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, 172 &reformat_params, 173 MLX5_FLOW_NAMESPACE_FDB); 174 if (IS_ERR(e->pkt_reformat)) { 175 mlx5_core_warn(priv->mdev, "Failed to offload cached encapsulation header, %pe\n", 176 e->pkt_reformat); 177 return; 178 } 179 e->flags |= MLX5_ENCAP_ENTRY_VALID; 180 mlx5e_rep_queue_neigh_stats_work(priv); 181 182 list_for_each_entry(flow, flow_list, tmp_list) { 183 if (!mlx5e_is_offloaded_flow(flow) || !flow_flag_test(flow, SLOW)) 184 continue; 185 186 spec = &flow->attr->parse_attr->spec; 187 188 attr = mlx5e_tc_get_encap_attr(flow); 189 esw_attr = attr->esw_attr; 190 esw_attr->dests[flow->tmp_entry_index].pkt_reformat = e->pkt_reformat; 191 esw_attr->dests[flow->tmp_entry_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; 192 193 /* Do not offload flows with unresolved neighbors */ 194 if (!mlx5e_tc_flow_all_encaps_valid(esw_attr)) 195 continue; 196 197 err = mlx5e_tc_offload_flow_post_acts(flow); 198 if (err) { 199 mlx5_core_warn(priv->mdev, "Failed to update flow post acts, %d\n", 200 err); 201 continue; 202 } 203 204 /* update from slow path rule to encap rule */ 205 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, flow->attr); 206 if (IS_ERR(rule)) { 207 mlx5e_tc_unoffload_flow_post_acts(flow); 208 err = PTR_ERR(rule); 209 mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n", 210 err); 211 continue; 212 } 213 214 mlx5e_tc_unoffload_from_slow_path(esw, flow); 215 flow->rule[0] = rule; 216 /* was unset when slow path rule removed */ 217 flow_flag_set(flow, OFFLOADED); 218 } 219} 220 221void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, 222 struct mlx5e_encap_entry *e, 223 struct list_head *flow_list) 224{ 225 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 226 struct mlx5_esw_flow_attr *esw_attr; 227 struct mlx5_flow_handle *rule; 228 struct mlx5_flow_attr *attr; 229 struct mlx5_flow_spec *spec; 230 struct mlx5e_tc_flow *flow; 231 int err; 232 233 list_for_each_entry(flow, flow_list, tmp_list) { 234 if (!mlx5e_is_offloaded_flow(flow)) 235 continue; 236 237 attr = mlx5e_tc_get_encap_attr(flow); 238 esw_attr = attr->esw_attr; 239 /* mark the flow's encap dest as non-valid */ 240 esw_attr->dests[flow->tmp_entry_index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; 241 esw_attr->dests[flow->tmp_entry_index].pkt_reformat = NULL; 242 243 /* Clear pkt_reformat before checking slow path flag. Because 244 * in next iteration, the same flow is already set slow path 245 * flag, but still need to clear the pkt_reformat. 246 */ 247 if (flow_flag_test(flow, SLOW)) 248 continue; 249 250 /* update from encap rule to slow path rule */ 251 spec = &flow->attr->parse_attr->spec; 252 rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec); 253 254 if (IS_ERR(rule)) { 255 err = PTR_ERR(rule); 256 mlx5_core_warn(priv->mdev, "Failed to update slow path (encap) flow, %d\n", 257 err); 258 continue; 259 } 260 261 mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); 262 mlx5e_tc_unoffload_flow_post_acts(flow); 263 flow->rule[0] = rule; 264 /* was unset when fast path rule removed */ 265 flow_flag_set(flow, OFFLOADED); 266 } 267 268 /* we know that the encap is valid */ 269 e->flags &= ~MLX5_ENCAP_ENTRY_VALID; 270 mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat); 271 e->pkt_reformat = NULL; 272} 273 274static void mlx5e_take_tmp_flow(struct mlx5e_tc_flow *flow, 275 struct list_head *flow_list, 276 int index) 277{ 278 if (IS_ERR(mlx5e_flow_get(flow))) { 279 /* Flow is being deleted concurrently. Wait for it to be 280 * unoffloaded from hardware, otherwise deleting encap will 281 * fail. 282 */ 283 wait_for_completion(&flow->del_hw_done); 284 return; 285 } 286 wait_for_completion(&flow->init_done); 287 288 flow->tmp_entry_index = index; 289 list_add(&flow->tmp_list, flow_list); 290} 291 292/* Takes reference to all flows attached to encap and adds the flows to 293 * flow_list using 'tmp_list' list_head in mlx5e_tc_flow. 294 */ 295void mlx5e_take_all_encap_flows(struct mlx5e_encap_entry *e, struct list_head *flow_list) 296{ 297 struct encap_flow_item *efi; 298 struct mlx5e_tc_flow *flow; 299 300 list_for_each_entry(efi, &e->flows, list) { 301 flow = container_of(efi, struct mlx5e_tc_flow, encaps[efi->index]); 302 mlx5e_take_tmp_flow(flow, flow_list, efi->index); 303 } 304} 305 306/* Takes reference to all flows attached to route and adds the flows to 307 * flow_list using 'tmp_list' list_head in mlx5e_tc_flow. 308 */ 309static void mlx5e_take_all_route_decap_flows(struct mlx5e_route_entry *r, 310 struct list_head *flow_list) 311{ 312 struct mlx5e_tc_flow *flow; 313 314 list_for_each_entry(flow, &r->decap_flows, decap_routes) 315 mlx5e_take_tmp_flow(flow, flow_list, 0); 316} 317 318typedef bool (match_cb)(struct mlx5e_encap_entry *); 319 320static struct mlx5e_encap_entry * 321mlx5e_get_next_matching_encap(struct mlx5e_neigh_hash_entry *nhe, 322 struct mlx5e_encap_entry *e, 323 match_cb match) 324{ 325 struct mlx5e_encap_entry *next = NULL; 326 327retry: 328 rcu_read_lock(); 329 330 /* find encap with non-zero reference counter value */ 331 for (next = e ? 332 list_next_or_null_rcu(&nhe->encap_list, 333 &e->encap_list, 334 struct mlx5e_encap_entry, 335 encap_list) : 336 list_first_or_null_rcu(&nhe->encap_list, 337 struct mlx5e_encap_entry, 338 encap_list); 339 next; 340 next = list_next_or_null_rcu(&nhe->encap_list, 341 &next->encap_list, 342 struct mlx5e_encap_entry, 343 encap_list)) 344 if (mlx5e_encap_take(next)) 345 break; 346 347 rcu_read_unlock(); 348 349 /* release starting encap */ 350 if (e) 351 mlx5e_encap_put(netdev_priv(e->out_dev), e); 352 if (!next) 353 return next; 354 355 /* wait for encap to be fully initialized */ 356 wait_for_completion(&next->res_ready); 357 /* continue searching if encap entry is not in valid state after completion */ 358 if (!match(next)) { 359 e = next; 360 goto retry; 361 } 362 363 return next; 364} 365 366static bool mlx5e_encap_valid(struct mlx5e_encap_entry *e) 367{ 368 return e->flags & MLX5_ENCAP_ENTRY_VALID; 369} 370 371static struct mlx5e_encap_entry * 372mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe, 373 struct mlx5e_encap_entry *e) 374{ 375 return mlx5e_get_next_matching_encap(nhe, e, mlx5e_encap_valid); 376} 377 378static bool mlx5e_encap_initialized(struct mlx5e_encap_entry *e) 379{ 380 return e->compl_result >= 0; 381} 382 383struct mlx5e_encap_entry * 384mlx5e_get_next_init_encap(struct mlx5e_neigh_hash_entry *nhe, 385 struct mlx5e_encap_entry *e) 386{ 387 return mlx5e_get_next_matching_encap(nhe, e, mlx5e_encap_initialized); 388} 389 390void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe) 391{ 392 struct mlx5e_neigh *m_neigh = &nhe->m_neigh; 393 struct mlx5e_encap_entry *e = NULL; 394 struct mlx5e_tc_flow *flow; 395 struct mlx5_fc *counter; 396 struct neigh_table *tbl; 397 bool neigh_used = false; 398 struct neighbour *n; 399 u64 lastuse; 400 401 if (m_neigh->family == AF_INET) 402 tbl = &arp_tbl; 403#if IS_ENABLED(CONFIG_IPV6) 404 else if (m_neigh->family == AF_INET6) 405 tbl = ipv6_stub->nd_tbl; 406#endif 407 else 408 return; 409 410 /* mlx5e_get_next_valid_encap() releases previous encap before returning 411 * next one. 412 */ 413 while ((e = mlx5e_get_next_valid_encap(nhe, e)) != NULL) { 414 struct mlx5e_priv *priv = netdev_priv(e->out_dev); 415 struct encap_flow_item *efi, *tmp; 416 struct mlx5_eswitch *esw; 417 LIST_HEAD(flow_list); 418 419 esw = priv->mdev->priv.eswitch; 420 mutex_lock(&esw->offloads.encap_tbl_lock); 421 list_for_each_entry_safe(efi, tmp, &e->flows, list) { 422 flow = container_of(efi, struct mlx5e_tc_flow, 423 encaps[efi->index]); 424 if (IS_ERR(mlx5e_flow_get(flow))) 425 continue; 426 list_add(&flow->tmp_list, &flow_list); 427 428 if (mlx5e_is_offloaded_flow(flow)) { 429 counter = mlx5e_tc_get_counter(flow); 430 lastuse = mlx5_fc_query_lastuse(counter); 431 if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) { 432 neigh_used = true; 433 break; 434 } 435 } 436 } 437 mutex_unlock(&esw->offloads.encap_tbl_lock); 438 439 mlx5e_put_flow_list(priv, &flow_list); 440 if (neigh_used) { 441 /* release current encap before breaking the loop */ 442 mlx5e_encap_put(priv, e); 443 break; 444 } 445 } 446 447 trace_mlx5e_tc_update_neigh_used_value(nhe, neigh_used); 448 449 if (neigh_used) { 450 nhe->reported_lastuse = jiffies; 451 452 /* find the relevant neigh according to the cached device and 453 * dst ip pair 454 */ 455 n = neigh_lookup(tbl, &m_neigh->dst_ip, READ_ONCE(nhe->neigh_dev)); 456 if (!n) 457 return; 458 459 neigh_event_send(n, NULL); 460 neigh_release(n); 461 } 462} 463 464static void mlx5e_encap_dealloc(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) 465{ 466 WARN_ON(!list_empty(&e->flows)); 467 468 if (e->compl_result > 0) { 469 mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); 470 471 if (e->flags & MLX5_ENCAP_ENTRY_VALID) 472 mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat); 473 } 474 475 kfree(e->tun_info); 476 kfree(e->encap_header); 477 kfree_rcu(e, rcu); 478} 479 480static void mlx5e_decap_dealloc(struct mlx5e_priv *priv, 481 struct mlx5e_decap_entry *d) 482{ 483 WARN_ON(!list_empty(&d->flows)); 484 485 if (!d->compl_result) 486 mlx5_packet_reformat_dealloc(priv->mdev, d->pkt_reformat); 487 488 kfree_rcu(d, rcu); 489} 490 491void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) 492{ 493 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 494 495 if (!refcount_dec_and_mutex_lock(&e->refcnt, &esw->offloads.encap_tbl_lock)) 496 return; 497 list_del(&e->route_list); 498 hash_del_rcu(&e->encap_hlist); 499 mutex_unlock(&esw->offloads.encap_tbl_lock); 500 501 mlx5e_encap_dealloc(priv, e); 502} 503 504static void mlx5e_encap_put_locked(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) 505{ 506 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 507 508 lockdep_assert_held(&esw->offloads.encap_tbl_lock); 509 510 if (!refcount_dec_and_test(&e->refcnt)) 511 return; 512 list_del(&e->route_list); 513 hash_del_rcu(&e->encap_hlist); 514 mlx5e_encap_dealloc(priv, e); 515} 516 517static void mlx5e_decap_put(struct mlx5e_priv *priv, struct mlx5e_decap_entry *d) 518{ 519 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 520 521 if (!refcount_dec_and_mutex_lock(&d->refcnt, &esw->offloads.decap_tbl_lock)) 522 return; 523 hash_del_rcu(&d->hlist); 524 mutex_unlock(&esw->offloads.decap_tbl_lock); 525 526 mlx5e_decap_dealloc(priv, d); 527} 528 529static void mlx5e_detach_encap_route(struct mlx5e_priv *priv, 530 struct mlx5e_tc_flow *flow, 531 int out_index); 532 533void mlx5e_detach_encap(struct mlx5e_priv *priv, 534 struct mlx5e_tc_flow *flow, 535 struct mlx5_flow_attr *attr, 536 int out_index) 537{ 538 struct mlx5e_encap_entry *e = flow->encaps[out_index].e; 539 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 540 541 if (!mlx5e_is_eswitch_flow(flow)) 542 return; 543 544 if (attr->esw_attr->dests[out_index].flags & 545 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE) 546 mlx5e_detach_encap_route(priv, flow, out_index); 547 548 /* flow wasn't fully initialized */ 549 if (!e) 550 return; 551 552 mutex_lock(&esw->offloads.encap_tbl_lock); 553 list_del(&flow->encaps[out_index].list); 554 flow->encaps[out_index].e = NULL; 555 if (!refcount_dec_and_test(&e->refcnt)) { 556 mutex_unlock(&esw->offloads.encap_tbl_lock); 557 return; 558 } 559 list_del(&e->route_list); 560 hash_del_rcu(&e->encap_hlist); 561 mutex_unlock(&esw->offloads.encap_tbl_lock); 562 563 mlx5e_encap_dealloc(priv, e); 564} 565 566void mlx5e_detach_decap(struct mlx5e_priv *priv, 567 struct mlx5e_tc_flow *flow) 568{ 569 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 570 struct mlx5e_decap_entry *d = flow->decap_reformat; 571 572 if (!d) 573 return; 574 575 mutex_lock(&esw->offloads.decap_tbl_lock); 576 list_del(&flow->l3_to_l2_reformat); 577 flow->decap_reformat = NULL; 578 579 if (!refcount_dec_and_test(&d->refcnt)) { 580 mutex_unlock(&esw->offloads.decap_tbl_lock); 581 return; 582 } 583 hash_del_rcu(&d->hlist); 584 mutex_unlock(&esw->offloads.decap_tbl_lock); 585 586 mlx5e_decap_dealloc(priv, d); 587} 588 589bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a, 590 struct mlx5e_encap_key *b) 591{ 592 return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) == 0 && 593 a->tc_tunnel->tunnel_type == b->tc_tunnel->tunnel_type; 594} 595 596bool mlx5e_tc_tun_encap_info_equal_options(struct mlx5e_encap_key *a, 597 struct mlx5e_encap_key *b, 598 u32 tun_type) 599{ 600 struct ip_tunnel_info *a_info; 601 struct ip_tunnel_info *b_info; 602 bool a_has_opts, b_has_opts; 603 604 if (!mlx5e_tc_tun_encap_info_equal_generic(a, b)) 605 return false; 606 607 a_has_opts = test_bit(tun_type, a->ip_tun_key->tun_flags); 608 b_has_opts = test_bit(tun_type, b->ip_tun_key->tun_flags); 609 610 /* keys are equal when both don't have any options attached */ 611 if (!a_has_opts && !b_has_opts) 612 return true; 613 614 if (a_has_opts != b_has_opts) 615 return false; 616 617 /* options stored in memory next to ip_tunnel_info struct */ 618 a_info = container_of(a->ip_tun_key, struct ip_tunnel_info, key); 619 b_info = container_of(b->ip_tun_key, struct ip_tunnel_info, key); 620 621 return a_info->options_len == b_info->options_len && 622 !memcmp(ip_tunnel_info_opts(a_info), 623 ip_tunnel_info_opts(b_info), 624 a_info->options_len); 625} 626 627static int cmp_decap_info(struct mlx5e_decap_key *a, 628 struct mlx5e_decap_key *b) 629{ 630 return memcmp(&a->key, &b->key, sizeof(b->key)); 631} 632 633static int hash_encap_info(struct mlx5e_encap_key *key) 634{ 635 return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key), 636 key->tc_tunnel->tunnel_type); 637} 638 639static int hash_decap_info(struct mlx5e_decap_key *key) 640{ 641 return jhash(&key->key, sizeof(key->key), 0); 642} 643 644bool mlx5e_encap_take(struct mlx5e_encap_entry *e) 645{ 646 return refcount_inc_not_zero(&e->refcnt); 647} 648 649static bool mlx5e_decap_take(struct mlx5e_decap_entry *e) 650{ 651 return refcount_inc_not_zero(&e->refcnt); 652} 653 654static struct mlx5e_encap_entry * 655mlx5e_encap_get(struct mlx5e_priv *priv, struct mlx5e_encap_key *key, 656 uintptr_t hash_key) 657{ 658 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 659 struct mlx5e_encap_key e_key; 660 struct mlx5e_encap_entry *e; 661 662 hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, 663 encap_hlist, hash_key) { 664 e_key.ip_tun_key = &e->tun_info->key; 665 e_key.tc_tunnel = e->tunnel; 666 if (e->tunnel->encap_info_equal(&e_key, key) && 667 mlx5e_encap_take(e)) 668 return e; 669 } 670 671 return NULL; 672} 673 674static struct mlx5e_decap_entry * 675mlx5e_decap_get(struct mlx5e_priv *priv, struct mlx5e_decap_key *key, 676 uintptr_t hash_key) 677{ 678 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 679 struct mlx5e_decap_key r_key; 680 struct mlx5e_decap_entry *e; 681 682 hash_for_each_possible_rcu(esw->offloads.decap_tbl, e, 683 hlist, hash_key) { 684 r_key = e->key; 685 if (!cmp_decap_info(&r_key, key) && 686 mlx5e_decap_take(e)) 687 return e; 688 } 689 return NULL; 690} 691 692struct ip_tunnel_info *mlx5e_dup_tun_info(const struct ip_tunnel_info *tun_info) 693{ 694 size_t tun_size = sizeof(*tun_info) + tun_info->options_len; 695 696 return kmemdup(tun_info, tun_size, GFP_KERNEL); 697} 698 699static bool is_duplicated_encap_entry(struct mlx5e_priv *priv, 700 struct mlx5e_tc_flow *flow, 701 int out_index, 702 struct mlx5e_encap_entry *e, 703 struct netlink_ext_ack *extack) 704{ 705 int i; 706 707 for (i = 0; i < out_index; i++) { 708 if (flow->encaps[i].e != e) 709 continue; 710 NL_SET_ERR_MSG_MOD(extack, "can't duplicate encap action"); 711 netdev_err(priv->netdev, "can't duplicate encap action\n"); 712 return true; 713 } 714 715 return false; 716} 717 718static int mlx5e_set_vf_tunnel(struct mlx5_eswitch *esw, 719 struct mlx5_flow_attr *attr, 720 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, 721 struct net_device *out_dev, 722 int route_dev_ifindex, 723 int out_index) 724{ 725 struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; 726 struct net_device *route_dev; 727 u16 vport_num; 728 int err = 0; 729 u32 data; 730 731 route_dev = dev_get_by_index(dev_net(out_dev), route_dev_ifindex); 732 733 if (!route_dev || route_dev->netdev_ops != &mlx5e_netdev_ops || 734 !mlx5e_tc_is_vf_tunnel(out_dev, route_dev)) 735 goto out; 736 737 err = mlx5e_tc_query_route_vport(out_dev, route_dev, &vport_num); 738 if (err) 739 goto out; 740 741 attr->dest_chain = 0; 742 attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 743 esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE; 744 data = mlx5_eswitch_get_vport_metadata_for_set(esw_attr->in_mdev->priv.eswitch, 745 vport_num); 746 err = mlx5e_tc_match_to_reg_set_and_get_id(esw->dev, mod_hdr_acts, 747 MLX5_FLOW_NAMESPACE_FDB, 748 VPORT_TO_REG, data); 749 if (err >= 0) { 750 esw_attr->dests[out_index].src_port_rewrite_act_id = err; 751 err = 0; 752 } 753 754out: 755 dev_put(route_dev); 756 return err; 757} 758 759static int mlx5e_update_vf_tunnel(struct mlx5_eswitch *esw, 760 struct mlx5_esw_flow_attr *attr, 761 struct mlx5e_tc_mod_hdr_acts *mod_hdr_acts, 762 struct net_device *out_dev, 763 int route_dev_ifindex, 764 int out_index) 765{ 766 int act_id = attr->dests[out_index].src_port_rewrite_act_id; 767 struct net_device *route_dev; 768 u16 vport_num; 769 int err = 0; 770 u32 data; 771 772 route_dev = dev_get_by_index(dev_net(out_dev), route_dev_ifindex); 773 774 if (!route_dev || route_dev->netdev_ops != &mlx5e_netdev_ops || 775 !mlx5e_tc_is_vf_tunnel(out_dev, route_dev)) { 776 err = -ENODEV; 777 goto out; 778 } 779 780 err = mlx5e_tc_query_route_vport(out_dev, route_dev, &vport_num); 781 if (err) 782 goto out; 783 784 data = mlx5_eswitch_get_vport_metadata_for_set(attr->in_mdev->priv.eswitch, 785 vport_num); 786 mlx5e_tc_match_to_reg_mod_hdr_change(esw->dev, mod_hdr_acts, VPORT_TO_REG, act_id, data); 787 788out: 789 dev_put(route_dev); 790 return err; 791} 792 793static unsigned int mlx5e_route_tbl_get_last_update(struct mlx5e_priv *priv) 794{ 795 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 796 struct mlx5_rep_uplink_priv *uplink_priv; 797 struct mlx5e_rep_priv *uplink_rpriv; 798 struct mlx5e_tc_tun_encap *encap; 799 unsigned int ret; 800 801 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 802 uplink_priv = &uplink_rpriv->uplink_priv; 803 encap = uplink_priv->encap; 804 805 spin_lock_bh(&encap->route_lock); 806 ret = encap->route_tbl_last_update; 807 spin_unlock_bh(&encap->route_lock); 808 return ret; 809} 810 811static int mlx5e_attach_encap_route(struct mlx5e_priv *priv, 812 struct mlx5e_tc_flow *flow, 813 struct mlx5_flow_attr *attr, 814 struct mlx5e_encap_entry *e, 815 bool new_encap_entry, 816 unsigned long tbl_time_before, 817 int out_index); 818 819int mlx5e_attach_encap(struct mlx5e_priv *priv, 820 struct mlx5e_tc_flow *flow, 821 struct mlx5_flow_attr *attr, 822 struct net_device *mirred_dev, 823 int out_index, 824 struct netlink_ext_ack *extack, 825 struct net_device **encap_dev) 826{ 827 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 828 struct mlx5e_tc_flow_parse_attr *parse_attr; 829 const struct ip_tunnel_info *tun_info; 830 const struct mlx5e_mpls_info *mpls_info; 831 unsigned long tbl_time_before = 0; 832 struct mlx5e_encap_entry *e; 833 struct mlx5e_encap_key key; 834 bool entry_created = false; 835 unsigned short family; 836 uintptr_t hash_key; 837 int err = 0; 838 839 lockdep_assert_held(&esw->offloads.encap_tbl_lock); 840 841 parse_attr = attr->parse_attr; 842 tun_info = parse_attr->tun_info[out_index]; 843 mpls_info = &parse_attr->mpls_info[out_index]; 844 family = ip_tunnel_info_af(tun_info); 845 key.ip_tun_key = &tun_info->key; 846 key.tc_tunnel = mlx5e_get_tc_tun(mirred_dev); 847 if (!key.tc_tunnel) { 848 NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel"); 849 return -EOPNOTSUPP; 850 } 851 852 hash_key = hash_encap_info(&key); 853 854 e = mlx5e_encap_get(priv, &key, hash_key); 855 856 /* must verify if encap is valid or not */ 857 if (e) { 858 /* Check that entry was not already attached to this flow */ 859 if (is_duplicated_encap_entry(priv, flow, out_index, e, extack)) { 860 err = -EOPNOTSUPP; 861 goto out_err; 862 } 863 864 goto attach_flow; 865 } 866 867 e = kzalloc(sizeof(*e), GFP_KERNEL); 868 if (!e) { 869 err = -ENOMEM; 870 goto out_err; 871 } 872 873 refcount_set(&e->refcnt, 1); 874 init_completion(&e->res_ready); 875 entry_created = true; 876 INIT_LIST_HEAD(&e->route_list); 877 878 tun_info = mlx5e_dup_tun_info(tun_info); 879 if (!tun_info) { 880 err = -ENOMEM; 881 goto out_err_init; 882 } 883 e->tun_info = tun_info; 884 memcpy(&e->mpls_info, mpls_info, sizeof(*mpls_info)); 885 err = mlx5e_tc_tun_init_encap_attr(mirred_dev, priv, e, extack); 886 if (err) 887 goto out_err_init; 888 889 INIT_LIST_HEAD(&e->flows); 890 hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); 891 tbl_time_before = mlx5e_route_tbl_get_last_update(priv); 892 893 if (family == AF_INET) 894 err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e); 895 else if (family == AF_INET6) 896 err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e); 897 898 complete_all(&e->res_ready); 899 if (err) { 900 e->compl_result = err; 901 goto out_err; 902 } 903 e->compl_result = 1; 904 905attach_flow: 906 err = mlx5e_attach_encap_route(priv, flow, attr, e, entry_created, 907 tbl_time_before, out_index); 908 if (err) 909 goto out_err; 910 911 err = mlx5e_set_int_port_tunnel(priv, attr, e, out_index); 912 if (err == -EOPNOTSUPP) { 913 /* If device doesn't support int port offload, 914 * redirect to uplink vport. 915 */ 916 mlx5_core_dbg(priv->mdev, "attaching int port as encap dev not supported, using uplink\n"); 917 err = 0; 918 } else if (err) { 919 goto out_err; 920 } 921 922 flow->encaps[out_index].e = e; 923 list_add(&flow->encaps[out_index].list, &e->flows); 924 flow->encaps[out_index].index = out_index; 925 *encap_dev = e->out_dev; 926 if (e->flags & MLX5_ENCAP_ENTRY_VALID) { 927 attr->esw_attr->dests[out_index].pkt_reformat = e->pkt_reformat; 928 attr->esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; 929 } else { 930 flow_flag_set(flow, SLOW); 931 } 932 933 return err; 934 935out_err: 936 if (e) 937 mlx5e_encap_put_locked(priv, e); 938 return err; 939 940out_err_init: 941 kfree(tun_info); 942 kfree(e); 943 return err; 944} 945 946int mlx5e_attach_decap(struct mlx5e_priv *priv, 947 struct mlx5e_tc_flow *flow, 948 struct netlink_ext_ack *extack) 949{ 950 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 951 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; 952 struct mlx5_pkt_reformat_params reformat_params; 953 struct mlx5e_decap_entry *d; 954 struct mlx5e_decap_key key; 955 uintptr_t hash_key; 956 int err = 0; 957 958 if (sizeof(attr->eth) > MLX5_CAP_ESW(priv->mdev, max_encap_header_size)) { 959 NL_SET_ERR_MSG_MOD(extack, 960 "encap header larger than max supported"); 961 return -EOPNOTSUPP; 962 } 963 964 key.key = attr->eth; 965 hash_key = hash_decap_info(&key); 966 mutex_lock(&esw->offloads.decap_tbl_lock); 967 d = mlx5e_decap_get(priv, &key, hash_key); 968 if (d) { 969 mutex_unlock(&esw->offloads.decap_tbl_lock); 970 wait_for_completion(&d->res_ready); 971 mutex_lock(&esw->offloads.decap_tbl_lock); 972 if (d->compl_result) { 973 err = -EREMOTEIO; 974 goto out_free; 975 } 976 goto found; 977 } 978 979 d = kzalloc(sizeof(*d), GFP_KERNEL); 980 if (!d) { 981 err = -ENOMEM; 982 goto out_err; 983 } 984 985 d->key = key; 986 refcount_set(&d->refcnt, 1); 987 init_completion(&d->res_ready); 988 INIT_LIST_HEAD(&d->flows); 989 hash_add_rcu(esw->offloads.decap_tbl, &d->hlist, hash_key); 990 mutex_unlock(&esw->offloads.decap_tbl_lock); 991 992 memset(&reformat_params, 0, sizeof(reformat_params)); 993 reformat_params.type = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; 994 reformat_params.size = sizeof(attr->eth); 995 reformat_params.data = &attr->eth; 996 d->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, 997 &reformat_params, 998 MLX5_FLOW_NAMESPACE_FDB); 999 if (IS_ERR(d->pkt_reformat)) { 1000 err = PTR_ERR(d->pkt_reformat); 1001 d->compl_result = err; 1002 } 1003 mutex_lock(&esw->offloads.decap_tbl_lock); 1004 complete_all(&d->res_ready); 1005 if (err) 1006 goto out_free; 1007 1008found: 1009 flow->decap_reformat = d; 1010 attr->decap_pkt_reformat = d->pkt_reformat; 1011 list_add(&flow->l3_to_l2_reformat, &d->flows); 1012 mutex_unlock(&esw->offloads.decap_tbl_lock); 1013 return 0; 1014 1015out_free: 1016 mutex_unlock(&esw->offloads.decap_tbl_lock); 1017 mlx5e_decap_put(priv, d); 1018 return err; 1019 1020out_err: 1021 mutex_unlock(&esw->offloads.decap_tbl_lock); 1022 return err; 1023} 1024 1025int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv, 1026 struct mlx5e_tc_flow *flow, 1027 struct mlx5_flow_attr *attr, 1028 struct netlink_ext_ack *extack, 1029 bool *vf_tun) 1030{ 1031 struct mlx5e_tc_flow_parse_attr *parse_attr; 1032 struct mlx5_esw_flow_attr *esw_attr; 1033 struct net_device *encap_dev = NULL; 1034 struct mlx5e_rep_priv *rpriv; 1035 struct mlx5e_priv *out_priv; 1036 struct mlx5_eswitch *esw; 1037 int out_index; 1038 int err = 0; 1039 1040 parse_attr = attr->parse_attr; 1041 esw_attr = attr->esw_attr; 1042 *vf_tun = false; 1043 1044 esw = priv->mdev->priv.eswitch; 1045 mutex_lock(&esw->offloads.encap_tbl_lock); 1046 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { 1047 struct net_device *out_dev; 1048 int mirred_ifindex; 1049 1050 if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) 1051 continue; 1052 1053 mirred_ifindex = parse_attr->mirred_ifindex[out_index]; 1054 out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); 1055 if (!out_dev) { 1056 NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found"); 1057 err = -ENODEV; 1058 goto out; 1059 } 1060 err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index, 1061 extack, &encap_dev); 1062 dev_put(out_dev); 1063 if (err) 1064 goto out; 1065 1066 if (esw_attr->dests[out_index].flags & 1067 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE && 1068 !esw_attr->dest_int_port) 1069 *vf_tun = true; 1070 1071 out_priv = netdev_priv(encap_dev); 1072 rpriv = out_priv->ppriv; 1073 esw_attr->dests[out_index].vport_valid = true; 1074 esw_attr->dests[out_index].vport = rpriv->rep->vport; 1075 esw_attr->dests[out_index].mdev = out_priv->mdev; 1076 } 1077 1078 if (*vf_tun && esw_attr->out_count > 1) { 1079 NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported"); 1080 err = -EOPNOTSUPP; 1081 goto out; 1082 } 1083 1084out: 1085 mutex_unlock(&esw->offloads.encap_tbl_lock); 1086 return err; 1087} 1088 1089void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv, 1090 struct mlx5e_tc_flow *flow, 1091 struct mlx5_flow_attr *attr) 1092{ 1093 struct mlx5_esw_flow_attr *esw_attr; 1094 int out_index; 1095 1096 if (!mlx5e_is_eswitch_flow(flow)) 1097 return; 1098 1099 esw_attr = attr->esw_attr; 1100 1101 for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { 1102 if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) 1103 continue; 1104 1105 mlx5e_detach_encap(flow->priv, flow, attr, out_index); 1106 kfree(attr->parse_attr->tun_info[out_index]); 1107 } 1108} 1109 1110static int cmp_route_info(struct mlx5e_route_key *a, 1111 struct mlx5e_route_key *b) 1112{ 1113 if (a->ip_version == 4 && b->ip_version == 4) 1114 return memcmp(&a->endpoint_ip.v4, &b->endpoint_ip.v4, 1115 sizeof(a->endpoint_ip.v4)); 1116 else if (a->ip_version == 6 && b->ip_version == 6) 1117 return memcmp(&a->endpoint_ip.v6, &b->endpoint_ip.v6, 1118 sizeof(a->endpoint_ip.v6)); 1119 return 1; 1120} 1121 1122static u32 hash_route_info(struct mlx5e_route_key *key) 1123{ 1124 if (key->ip_version == 4) 1125 return jhash(&key->endpoint_ip.v4, sizeof(key->endpoint_ip.v4), 0); 1126 return jhash(&key->endpoint_ip.v6, sizeof(key->endpoint_ip.v6), 0); 1127} 1128 1129static void mlx5e_route_dealloc(struct mlx5e_priv *priv, 1130 struct mlx5e_route_entry *r) 1131{ 1132 WARN_ON(!list_empty(&r->decap_flows)); 1133 WARN_ON(!list_empty(&r->encap_entries)); 1134 1135 kfree_rcu(r, rcu); 1136} 1137 1138static void mlx5e_route_put(struct mlx5e_priv *priv, struct mlx5e_route_entry *r) 1139{ 1140 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1141 1142 if (!refcount_dec_and_mutex_lock(&r->refcnt, &esw->offloads.encap_tbl_lock)) 1143 return; 1144 1145 hash_del_rcu(&r->hlist); 1146 mutex_unlock(&esw->offloads.encap_tbl_lock); 1147 1148 mlx5e_route_dealloc(priv, r); 1149} 1150 1151static void mlx5e_route_put_locked(struct mlx5e_priv *priv, struct mlx5e_route_entry *r) 1152{ 1153 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1154 1155 lockdep_assert_held(&esw->offloads.encap_tbl_lock); 1156 1157 if (!refcount_dec_and_test(&r->refcnt)) 1158 return; 1159 hash_del_rcu(&r->hlist); 1160 mlx5e_route_dealloc(priv, r); 1161} 1162 1163static struct mlx5e_route_entry * 1164mlx5e_route_get(struct mlx5e_tc_tun_encap *encap, struct mlx5e_route_key *key, 1165 u32 hash_key) 1166{ 1167 struct mlx5e_route_key r_key; 1168 struct mlx5e_route_entry *r; 1169 1170 hash_for_each_possible(encap->route_tbl, r, hlist, hash_key) { 1171 r_key = r->key; 1172 if (!cmp_route_info(&r_key, key) && 1173 refcount_inc_not_zero(&r->refcnt)) 1174 return r; 1175 } 1176 return NULL; 1177} 1178 1179static struct mlx5e_route_entry * 1180mlx5e_route_get_create(struct mlx5e_priv *priv, 1181 struct mlx5e_route_key *key, 1182 int tunnel_dev_index, 1183 unsigned long *route_tbl_change_time) 1184{ 1185 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1186 struct mlx5_rep_uplink_priv *uplink_priv; 1187 struct mlx5e_rep_priv *uplink_rpriv; 1188 struct mlx5e_tc_tun_encap *encap; 1189 struct mlx5e_route_entry *r; 1190 u32 hash_key; 1191 1192 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 1193 uplink_priv = &uplink_rpriv->uplink_priv; 1194 encap = uplink_priv->encap; 1195 1196 hash_key = hash_route_info(key); 1197 spin_lock_bh(&encap->route_lock); 1198 r = mlx5e_route_get(encap, key, hash_key); 1199 spin_unlock_bh(&encap->route_lock); 1200 if (r) { 1201 if (!mlx5e_route_entry_valid(r)) { 1202 mlx5e_route_put_locked(priv, r); 1203 return ERR_PTR(-EINVAL); 1204 } 1205 return r; 1206 } 1207 1208 r = kzalloc(sizeof(*r), GFP_KERNEL); 1209 if (!r) 1210 return ERR_PTR(-ENOMEM); 1211 1212 r->key = *key; 1213 r->flags |= MLX5E_ROUTE_ENTRY_VALID; 1214 r->tunnel_dev_index = tunnel_dev_index; 1215 refcount_set(&r->refcnt, 1); 1216 INIT_LIST_HEAD(&r->decap_flows); 1217 INIT_LIST_HEAD(&r->encap_entries); 1218 1219 spin_lock_bh(&encap->route_lock); 1220 *route_tbl_change_time = encap->route_tbl_last_update; 1221 hash_add(encap->route_tbl, &r->hlist, hash_key); 1222 spin_unlock_bh(&encap->route_lock); 1223 1224 return r; 1225} 1226 1227static struct mlx5e_route_entry * 1228mlx5e_route_lookup_for_update(struct mlx5e_tc_tun_encap *encap, struct mlx5e_route_key *key) 1229{ 1230 u32 hash_key = hash_route_info(key); 1231 struct mlx5e_route_entry *r; 1232 1233 spin_lock_bh(&encap->route_lock); 1234 encap->route_tbl_last_update = jiffies; 1235 r = mlx5e_route_get(encap, key, hash_key); 1236 spin_unlock_bh(&encap->route_lock); 1237 1238 return r; 1239} 1240 1241struct mlx5e_tc_fib_event_data { 1242 struct work_struct work; 1243 unsigned long event; 1244 struct mlx5e_route_entry *r; 1245 struct net_device *ul_dev; 1246}; 1247 1248static void mlx5e_tc_fib_event_work(struct work_struct *work); 1249static struct mlx5e_tc_fib_event_data * 1250mlx5e_tc_init_fib_work(unsigned long event, struct net_device *ul_dev, gfp_t flags) 1251{ 1252 struct mlx5e_tc_fib_event_data *fib_work; 1253 1254 fib_work = kzalloc(sizeof(*fib_work), flags); 1255 if (WARN_ON(!fib_work)) 1256 return NULL; 1257 1258 INIT_WORK(&fib_work->work, mlx5e_tc_fib_event_work); 1259 fib_work->event = event; 1260 fib_work->ul_dev = ul_dev; 1261 1262 return fib_work; 1263} 1264 1265static int 1266mlx5e_route_enqueue_update(struct mlx5e_priv *priv, 1267 struct mlx5e_route_entry *r, 1268 unsigned long event) 1269{ 1270 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1271 struct mlx5e_tc_fib_event_data *fib_work; 1272 struct mlx5e_rep_priv *uplink_rpriv; 1273 struct net_device *ul_dev; 1274 1275 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 1276 ul_dev = uplink_rpriv->netdev; 1277 1278 fib_work = mlx5e_tc_init_fib_work(event, ul_dev, GFP_KERNEL); 1279 if (!fib_work) 1280 return -ENOMEM; 1281 1282 dev_hold(ul_dev); 1283 refcount_inc(&r->refcnt); 1284 fib_work->r = r; 1285 queue_work(priv->wq, &fib_work->work); 1286 1287 return 0; 1288} 1289 1290int mlx5e_attach_decap_route(struct mlx5e_priv *priv, 1291 struct mlx5e_tc_flow *flow) 1292{ 1293 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1294 unsigned long tbl_time_before, tbl_time_after; 1295 struct mlx5e_tc_flow_parse_attr *parse_attr; 1296 struct mlx5_flow_attr *attr = flow->attr; 1297 struct mlx5_esw_flow_attr *esw_attr; 1298 struct mlx5e_route_entry *r; 1299 struct mlx5e_route_key key; 1300 int err = 0; 1301 1302 esw_attr = attr->esw_attr; 1303 parse_attr = attr->parse_attr; 1304 mutex_lock(&esw->offloads.encap_tbl_lock); 1305 if (!esw_attr->rx_tun_attr) 1306 goto out; 1307 1308 tbl_time_before = mlx5e_route_tbl_get_last_update(priv); 1309 tbl_time_after = tbl_time_before; 1310 err = mlx5e_tc_tun_route_lookup(priv, &parse_attr->spec, attr, parse_attr->filter_dev); 1311 if (err || !esw_attr->rx_tun_attr->decap_vport) 1312 goto out; 1313 1314 key.ip_version = attr->tun_ip_version; 1315 if (key.ip_version == 4) 1316 key.endpoint_ip.v4 = esw_attr->rx_tun_attr->dst_ip.v4; 1317 else 1318 key.endpoint_ip.v6 = esw_attr->rx_tun_attr->dst_ip.v6; 1319 1320 r = mlx5e_route_get_create(priv, &key, parse_attr->filter_dev->ifindex, 1321 &tbl_time_after); 1322 if (IS_ERR(r)) { 1323 err = PTR_ERR(r); 1324 goto out; 1325 } 1326 /* Routing changed concurrently. FIB event handler might have missed new 1327 * entry, schedule update. 1328 */ 1329 if (tbl_time_before != tbl_time_after) { 1330 err = mlx5e_route_enqueue_update(priv, r, FIB_EVENT_ENTRY_REPLACE); 1331 if (err) { 1332 mlx5e_route_put_locked(priv, r); 1333 goto out; 1334 } 1335 } 1336 1337 flow->decap_route = r; 1338 list_add(&flow->decap_routes, &r->decap_flows); 1339 mutex_unlock(&esw->offloads.encap_tbl_lock); 1340 return 0; 1341 1342out: 1343 mutex_unlock(&esw->offloads.encap_tbl_lock); 1344 return err; 1345} 1346 1347static int mlx5e_attach_encap_route(struct mlx5e_priv *priv, 1348 struct mlx5e_tc_flow *flow, 1349 struct mlx5_flow_attr *attr, 1350 struct mlx5e_encap_entry *e, 1351 bool new_encap_entry, 1352 unsigned long tbl_time_before, 1353 int out_index) 1354{ 1355 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1356 unsigned long tbl_time_after = tbl_time_before; 1357 struct mlx5e_tc_flow_parse_attr *parse_attr; 1358 const struct ip_tunnel_info *tun_info; 1359 struct mlx5_esw_flow_attr *esw_attr; 1360 struct mlx5e_route_entry *r; 1361 struct mlx5e_route_key key; 1362 unsigned short family; 1363 int err = 0; 1364 1365 esw_attr = attr->esw_attr; 1366 parse_attr = attr->parse_attr; 1367 tun_info = parse_attr->tun_info[out_index]; 1368 family = ip_tunnel_info_af(tun_info); 1369 1370 if (family == AF_INET) { 1371 key.endpoint_ip.v4 = tun_info->key.u.ipv4.src; 1372 key.ip_version = 4; 1373 } else if (family == AF_INET6) { 1374 key.endpoint_ip.v6 = tun_info->key.u.ipv6.src; 1375 key.ip_version = 6; 1376 } 1377 1378 err = mlx5e_set_vf_tunnel(esw, attr, &parse_attr->mod_hdr_acts, e->out_dev, 1379 e->route_dev_ifindex, out_index); 1380 if (err || !(esw_attr->dests[out_index].flags & 1381 MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)) 1382 return err; 1383 1384 r = mlx5e_route_get_create(priv, &key, parse_attr->mirred_ifindex[out_index], 1385 &tbl_time_after); 1386 if (IS_ERR(r)) 1387 return PTR_ERR(r); 1388 /* Routing changed concurrently. FIB event handler might have missed new 1389 * entry, schedule update. 1390 */ 1391 if (tbl_time_before != tbl_time_after) { 1392 err = mlx5e_route_enqueue_update(priv, r, FIB_EVENT_ENTRY_REPLACE); 1393 if (err) { 1394 mlx5e_route_put_locked(priv, r); 1395 return err; 1396 } 1397 } 1398 1399 flow->encap_routes[out_index].r = r; 1400 if (new_encap_entry) 1401 list_add(&e->route_list, &r->encap_entries); 1402 flow->encap_routes[out_index].index = out_index; 1403 return 0; 1404} 1405 1406void mlx5e_detach_decap_route(struct mlx5e_priv *priv, 1407 struct mlx5e_tc_flow *flow) 1408{ 1409 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1410 struct mlx5e_route_entry *r = flow->decap_route; 1411 1412 if (!r) 1413 return; 1414 1415 mutex_lock(&esw->offloads.encap_tbl_lock); 1416 list_del(&flow->decap_routes); 1417 flow->decap_route = NULL; 1418 1419 if (!refcount_dec_and_test(&r->refcnt)) { 1420 mutex_unlock(&esw->offloads.encap_tbl_lock); 1421 return; 1422 } 1423 hash_del_rcu(&r->hlist); 1424 mutex_unlock(&esw->offloads.encap_tbl_lock); 1425 1426 mlx5e_route_dealloc(priv, r); 1427} 1428 1429static void mlx5e_detach_encap_route(struct mlx5e_priv *priv, 1430 struct mlx5e_tc_flow *flow, 1431 int out_index) 1432{ 1433 struct mlx5e_route_entry *r = flow->encap_routes[out_index].r; 1434 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1435 struct mlx5e_encap_entry *e, *tmp; 1436 1437 if (!r) 1438 return; 1439 1440 mutex_lock(&esw->offloads.encap_tbl_lock); 1441 flow->encap_routes[out_index].r = NULL; 1442 1443 if (!refcount_dec_and_test(&r->refcnt)) { 1444 mutex_unlock(&esw->offloads.encap_tbl_lock); 1445 return; 1446 } 1447 list_for_each_entry_safe(e, tmp, &r->encap_entries, route_list) 1448 list_del_init(&e->route_list); 1449 hash_del_rcu(&r->hlist); 1450 mutex_unlock(&esw->offloads.encap_tbl_lock); 1451 1452 mlx5e_route_dealloc(priv, r); 1453} 1454 1455static void mlx5e_invalidate_encap(struct mlx5e_priv *priv, 1456 struct mlx5e_encap_entry *e, 1457 struct list_head *encap_flows) 1458{ 1459 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1460 struct mlx5e_tc_flow *flow; 1461 1462 list_for_each_entry(flow, encap_flows, tmp_list) { 1463 struct mlx5_esw_flow_attr *esw_attr; 1464 struct mlx5_flow_attr *attr; 1465 1466 if (!mlx5e_is_offloaded_flow(flow)) 1467 continue; 1468 1469 attr = mlx5e_tc_get_encap_attr(flow); 1470 esw_attr = attr->esw_attr; 1471 1472 if (flow_flag_test(flow, SLOW)) { 1473 mlx5e_tc_unoffload_from_slow_path(esw, flow); 1474 } else { 1475 mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); 1476 mlx5e_tc_unoffload_flow_post_acts(flow); 1477 } 1478 1479 mlx5e_tc_detach_mod_hdr(priv, flow, attr); 1480 attr->modify_hdr = NULL; 1481 1482 esw_attr->dests[flow->tmp_entry_index].flags &= 1483 ~MLX5_ESW_DEST_ENCAP_VALID; 1484 esw_attr->dests[flow->tmp_entry_index].pkt_reformat = NULL; 1485 } 1486 1487 e->flags |= MLX5_ENCAP_ENTRY_NO_ROUTE; 1488 if (e->flags & MLX5_ENCAP_ENTRY_VALID) { 1489 e->flags &= ~MLX5_ENCAP_ENTRY_VALID; 1490 mlx5_packet_reformat_dealloc(priv->mdev, e->pkt_reformat); 1491 e->pkt_reformat = NULL; 1492 } 1493} 1494 1495static void mlx5e_reoffload_encap(struct mlx5e_priv *priv, 1496 struct net_device *tunnel_dev, 1497 struct mlx5e_encap_entry *e, 1498 struct list_head *encap_flows) 1499{ 1500 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1501 struct mlx5e_tc_flow *flow; 1502 int err; 1503 1504 err = ip_tunnel_info_af(e->tun_info) == AF_INET ? 1505 mlx5e_tc_tun_update_header_ipv4(priv, tunnel_dev, e) : 1506 mlx5e_tc_tun_update_header_ipv6(priv, tunnel_dev, e); 1507 if (err) 1508 mlx5_core_warn(priv->mdev, "Failed to update encap header, %d", err); 1509 e->flags &= ~MLX5_ENCAP_ENTRY_NO_ROUTE; 1510 1511 list_for_each_entry(flow, encap_flows, tmp_list) { 1512 struct mlx5e_tc_flow_parse_attr *parse_attr; 1513 struct mlx5_esw_flow_attr *esw_attr; 1514 struct mlx5_flow_handle *rule; 1515 struct mlx5_flow_attr *attr; 1516 struct mlx5_flow_spec *spec; 1517 1518 if (flow_flag_test(flow, FAILED)) 1519 continue; 1520 1521 spec = &flow->attr->parse_attr->spec; 1522 1523 attr = mlx5e_tc_get_encap_attr(flow); 1524 esw_attr = attr->esw_attr; 1525 parse_attr = attr->parse_attr; 1526 1527 err = mlx5e_update_vf_tunnel(esw, esw_attr, &parse_attr->mod_hdr_acts, 1528 e->out_dev, e->route_dev_ifindex, 1529 flow->tmp_entry_index); 1530 if (err) { 1531 mlx5_core_warn(priv->mdev, "Failed to update VF tunnel err=%d", err); 1532 continue; 1533 } 1534 1535 err = mlx5e_tc_attach_mod_hdr(priv, flow, attr); 1536 if (err) { 1537 mlx5_core_warn(priv->mdev, "Failed to update flow mod_hdr err=%d", 1538 err); 1539 continue; 1540 } 1541 1542 if (e->flags & MLX5_ENCAP_ENTRY_VALID) { 1543 esw_attr->dests[flow->tmp_entry_index].pkt_reformat = e->pkt_reformat; 1544 esw_attr->dests[flow->tmp_entry_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; 1545 if (!mlx5e_tc_flow_all_encaps_valid(esw_attr)) 1546 goto offload_to_slow_path; 1547 1548 err = mlx5e_tc_offload_flow_post_acts(flow); 1549 if (err) { 1550 mlx5_core_warn(priv->mdev, "Failed to update flow post acts, %d\n", 1551 err); 1552 goto offload_to_slow_path; 1553 } 1554 1555 /* update from slow path rule to encap rule */ 1556 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, flow->attr); 1557 if (IS_ERR(rule)) { 1558 mlx5e_tc_unoffload_flow_post_acts(flow); 1559 err = PTR_ERR(rule); 1560 mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n", 1561 err); 1562 } else { 1563 flow->rule[0] = rule; 1564 } 1565 } else { 1566offload_to_slow_path: 1567 rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec); 1568 /* mark the flow's encap dest as non-valid */ 1569 esw_attr->dests[flow->tmp_entry_index].flags &= 1570 ~MLX5_ESW_DEST_ENCAP_VALID; 1571 1572 if (IS_ERR(rule)) { 1573 err = PTR_ERR(rule); 1574 mlx5_core_warn(priv->mdev, "Failed to update slow path (encap) flow, %d\n", 1575 err); 1576 } else { 1577 flow->rule[0] = rule; 1578 } 1579 } 1580 flow_flag_set(flow, OFFLOADED); 1581 } 1582} 1583 1584static int mlx5e_update_route_encaps(struct mlx5e_priv *priv, 1585 struct mlx5e_route_entry *r, 1586 struct list_head *flow_list, 1587 bool replace) 1588{ 1589 struct net_device *tunnel_dev; 1590 struct mlx5e_encap_entry *e; 1591 1592 tunnel_dev = __dev_get_by_index(dev_net(priv->netdev), r->tunnel_dev_index); 1593 if (!tunnel_dev) 1594 return -ENODEV; 1595 1596 list_for_each_entry(e, &r->encap_entries, route_list) { 1597 LIST_HEAD(encap_flows); 1598 1599 mlx5e_take_all_encap_flows(e, &encap_flows); 1600 if (list_empty(&encap_flows)) 1601 continue; 1602 1603 if (mlx5e_route_entry_valid(r)) 1604 mlx5e_invalidate_encap(priv, e, &encap_flows); 1605 1606 if (!replace) { 1607 list_splice(&encap_flows, flow_list); 1608 continue; 1609 } 1610 1611 mlx5e_reoffload_encap(priv, tunnel_dev, e, &encap_flows); 1612 list_splice(&encap_flows, flow_list); 1613 } 1614 1615 return 0; 1616} 1617 1618static void mlx5e_unoffload_flow_list(struct mlx5e_priv *priv, 1619 struct list_head *flow_list) 1620{ 1621 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1622 struct mlx5e_tc_flow *flow; 1623 1624 list_for_each_entry(flow, flow_list, tmp_list) 1625 if (mlx5e_is_offloaded_flow(flow)) 1626 mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); 1627} 1628 1629static void mlx5e_reoffload_decap(struct mlx5e_priv *priv, 1630 struct list_head *decap_flows) 1631{ 1632 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1633 struct mlx5e_tc_flow *flow; 1634 1635 list_for_each_entry(flow, decap_flows, tmp_list) { 1636 struct mlx5e_tc_flow_parse_attr *parse_attr; 1637 struct mlx5_flow_attr *attr = flow->attr; 1638 struct mlx5_flow_handle *rule; 1639 struct mlx5_flow_spec *spec; 1640 int err; 1641 1642 if (flow_flag_test(flow, FAILED)) 1643 continue; 1644 1645 parse_attr = attr->parse_attr; 1646 spec = &parse_attr->spec; 1647 err = mlx5e_tc_tun_route_lookup(priv, spec, attr, parse_attr->filter_dev); 1648 if (err) { 1649 mlx5_core_warn(priv->mdev, "Failed to lookup route for flow, %d\n", 1650 err); 1651 continue; 1652 } 1653 1654 rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, attr); 1655 if (IS_ERR(rule)) { 1656 err = PTR_ERR(rule); 1657 mlx5_core_warn(priv->mdev, "Failed to update cached decap flow, %d\n", 1658 err); 1659 } else { 1660 flow->rule[0] = rule; 1661 flow_flag_set(flow, OFFLOADED); 1662 } 1663 } 1664} 1665 1666static int mlx5e_update_route_decap_flows(struct mlx5e_priv *priv, 1667 struct mlx5e_route_entry *r, 1668 struct list_head *flow_list, 1669 bool replace) 1670{ 1671 struct net_device *tunnel_dev; 1672 LIST_HEAD(decap_flows); 1673 1674 tunnel_dev = __dev_get_by_index(dev_net(priv->netdev), r->tunnel_dev_index); 1675 if (!tunnel_dev) 1676 return -ENODEV; 1677 1678 mlx5e_take_all_route_decap_flows(r, &decap_flows); 1679 if (mlx5e_route_entry_valid(r)) 1680 mlx5e_unoffload_flow_list(priv, &decap_flows); 1681 if (replace) 1682 mlx5e_reoffload_decap(priv, &decap_flows); 1683 1684 list_splice(&decap_flows, flow_list); 1685 1686 return 0; 1687} 1688 1689static void mlx5e_tc_fib_event_work(struct work_struct *work) 1690{ 1691 struct mlx5e_tc_fib_event_data *event_data = 1692 container_of(work, struct mlx5e_tc_fib_event_data, work); 1693 struct net_device *ul_dev = event_data->ul_dev; 1694 struct mlx5e_priv *priv = netdev_priv(ul_dev); 1695 struct mlx5e_route_entry *r = event_data->r; 1696 struct mlx5_eswitch *esw; 1697 LIST_HEAD(flow_list); 1698 bool replace; 1699 int err; 1700 1701 /* sync with concurrent neigh updates */ 1702 rtnl_lock(); 1703 esw = priv->mdev->priv.eswitch; 1704 mutex_lock(&esw->offloads.encap_tbl_lock); 1705 replace = event_data->event == FIB_EVENT_ENTRY_REPLACE; 1706 1707 if (!mlx5e_route_entry_valid(r) && !replace) 1708 goto out; 1709 1710 err = mlx5e_update_route_encaps(priv, r, &flow_list, replace); 1711 if (err) 1712 mlx5_core_warn(priv->mdev, "Failed to update route encaps, %d\n", 1713 err); 1714 1715 err = mlx5e_update_route_decap_flows(priv, r, &flow_list, replace); 1716 if (err) 1717 mlx5_core_warn(priv->mdev, "Failed to update route decap flows, %d\n", 1718 err); 1719 1720 if (replace) 1721 r->flags |= MLX5E_ROUTE_ENTRY_VALID; 1722out: 1723 mutex_unlock(&esw->offloads.encap_tbl_lock); 1724 rtnl_unlock(); 1725 1726 mlx5e_put_flow_list(priv, &flow_list); 1727 mlx5e_route_put(priv, event_data->r); 1728 dev_put(event_data->ul_dev); 1729 kfree(event_data); 1730} 1731 1732static struct mlx5e_tc_fib_event_data * 1733mlx5e_init_fib_work_ipv4(struct mlx5e_priv *priv, 1734 struct net_device *ul_dev, 1735 struct mlx5e_tc_tun_encap *encap, 1736 unsigned long event, 1737 struct fib_notifier_info *info) 1738{ 1739 struct fib_entry_notifier_info *fen_info; 1740 struct mlx5e_tc_fib_event_data *fib_work; 1741 struct mlx5e_route_entry *r; 1742 struct mlx5e_route_key key; 1743 struct net_device *fib_dev; 1744 1745 fen_info = container_of(info, struct fib_entry_notifier_info, info); 1746 if (fen_info->fi->nh) 1747 return NULL; 1748 fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev; 1749 if (!fib_dev || fib_dev->netdev_ops != &mlx5e_netdev_ops || 1750 fen_info->dst_len != 32) 1751 return NULL; 1752 1753 fib_work = mlx5e_tc_init_fib_work(event, ul_dev, GFP_ATOMIC); 1754 if (!fib_work) 1755 return ERR_PTR(-ENOMEM); 1756 1757 key.endpoint_ip.v4 = htonl(fen_info->dst); 1758 key.ip_version = 4; 1759 1760 /* Can't fail after this point because releasing reference to r 1761 * requires obtaining sleeping mutex which we can't do in atomic 1762 * context. 1763 */ 1764 r = mlx5e_route_lookup_for_update(encap, &key); 1765 if (!r) 1766 goto out; 1767 fib_work->r = r; 1768 dev_hold(ul_dev); 1769 1770 return fib_work; 1771 1772out: 1773 kfree(fib_work); 1774 return NULL; 1775} 1776 1777static struct mlx5e_tc_fib_event_data * 1778mlx5e_init_fib_work_ipv6(struct mlx5e_priv *priv, 1779 struct net_device *ul_dev, 1780 struct mlx5e_tc_tun_encap *encap, 1781 unsigned long event, 1782 struct fib_notifier_info *info) 1783{ 1784 struct fib6_entry_notifier_info *fen_info; 1785 struct mlx5e_tc_fib_event_data *fib_work; 1786 struct mlx5e_route_entry *r; 1787 struct mlx5e_route_key key; 1788 struct net_device *fib_dev; 1789 1790 fen_info = container_of(info, struct fib6_entry_notifier_info, info); 1791 fib_dev = fib6_info_nh_dev(fen_info->rt); 1792 if (fib_dev->netdev_ops != &mlx5e_netdev_ops || 1793 fen_info->rt->fib6_dst.plen != 128) 1794 return NULL; 1795 1796 fib_work = mlx5e_tc_init_fib_work(event, ul_dev, GFP_ATOMIC); 1797 if (!fib_work) 1798 return ERR_PTR(-ENOMEM); 1799 1800 memcpy(&key.endpoint_ip.v6, &fen_info->rt->fib6_dst.addr, 1801 sizeof(fen_info->rt->fib6_dst.addr)); 1802 key.ip_version = 6; 1803 1804 /* Can't fail after this point because releasing reference to r 1805 * requires obtaining sleeping mutex which we can't do in atomic 1806 * context. 1807 */ 1808 r = mlx5e_route_lookup_for_update(encap, &key); 1809 if (!r) 1810 goto out; 1811 fib_work->r = r; 1812 dev_hold(ul_dev); 1813 1814 return fib_work; 1815 1816out: 1817 kfree(fib_work); 1818 return NULL; 1819} 1820 1821static int mlx5e_tc_tun_fib_event(struct notifier_block *nb, unsigned long event, void *ptr) 1822{ 1823 struct mlx5e_tc_fib_event_data *fib_work; 1824 struct fib_notifier_info *info = ptr; 1825 struct mlx5e_tc_tun_encap *encap; 1826 struct net_device *ul_dev; 1827 struct mlx5e_priv *priv; 1828 1829 encap = container_of(nb, struct mlx5e_tc_tun_encap, fib_nb); 1830 priv = encap->priv; 1831 ul_dev = priv->netdev; 1832 priv = netdev_priv(ul_dev); 1833 1834 switch (event) { 1835 case FIB_EVENT_ENTRY_REPLACE: 1836 case FIB_EVENT_ENTRY_DEL: 1837 if (info->family == AF_INET) 1838 fib_work = mlx5e_init_fib_work_ipv4(priv, ul_dev, encap, event, info); 1839 else if (info->family == AF_INET6) 1840 fib_work = mlx5e_init_fib_work_ipv6(priv, ul_dev, encap, event, info); 1841 else 1842 return NOTIFY_DONE; 1843 1844 if (!IS_ERR_OR_NULL(fib_work)) { 1845 queue_work(priv->wq, &fib_work->work); 1846 } else if (IS_ERR(fib_work)) { 1847 NL_SET_ERR_MSG_MOD(info->extack, "Failed to init fib work"); 1848 mlx5_core_warn(priv->mdev, "Failed to init fib work, %pe\n", 1849 fib_work); 1850 } 1851 1852 break; 1853 default: 1854 return NOTIFY_DONE; 1855 } 1856 1857 return NOTIFY_DONE; 1858} 1859 1860struct mlx5e_tc_tun_encap *mlx5e_tc_tun_init(struct mlx5e_priv *priv) 1861{ 1862 struct mlx5e_tc_tun_encap *encap; 1863 int err; 1864 1865 encap = kvzalloc(sizeof(*encap), GFP_KERNEL); 1866 if (!encap) 1867 return ERR_PTR(-ENOMEM); 1868 1869 encap->priv = priv; 1870 encap->fib_nb.notifier_call = mlx5e_tc_tun_fib_event; 1871 spin_lock_init(&encap->route_lock); 1872 hash_init(encap->route_tbl); 1873 err = register_fib_notifier(dev_net(priv->netdev), &encap->fib_nb, 1874 NULL, NULL); 1875 if (err) { 1876 kvfree(encap); 1877 return ERR_PTR(err); 1878 } 1879 1880 return encap; 1881} 1882 1883void mlx5e_tc_tun_cleanup(struct mlx5e_tc_tun_encap *encap) 1884{ 1885 if (!encap) 1886 return; 1887 1888 unregister_fib_notifier(dev_net(encap->priv->netdev), &encap->fib_nb); 1889 flush_workqueue(encap->priv->wq); /* flush fib event works */ 1890 kvfree(encap); 1891}
~/
Read-only file preview.