tunnel_conf.c (39429B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4#include <linux/etherdevice.h> 5#include <linux/inetdevice.h> 6#include <net/netevent.h> 7#include <linux/idr.h> 8#include <net/dst_metadata.h> 9#include <net/arp.h> 10 11#include "cmsg.h" 12#include "main.h" 13#include "../nfp_net_repr.h" 14#include "../nfp_net.h" 15 16#define NFP_FL_MAX_ROUTES 32 17 18#define NFP_TUN_PRE_TUN_RULE_LIMIT 32 19#define NFP_TUN_PRE_TUN_RULE_DEL BIT(0) 20#define NFP_TUN_PRE_TUN_IDX_BIT BIT(3) 21#define NFP_TUN_PRE_TUN_IPV6_BIT BIT(7) 22 23/** 24 * struct nfp_tun_pre_tun_rule - rule matched before decap 25 * @flags: options for the rule offset 26 * @port_idx: index of destination MAC address for the rule 27 * @vlan_tci: VLAN info associated with MAC 28 * @host_ctx_id: stats context of rule to update 29 */ 30struct nfp_tun_pre_tun_rule { 31 __be32 flags; 32 __be16 port_idx; 33 __be16 vlan_tci; 34 __be32 host_ctx_id; 35}; 36 37/** 38 * struct nfp_tun_active_tuns - periodic message of active tunnels 39 * @seq: sequence number of the message 40 * @count: number of tunnels report in message 41 * @flags: options part of the request 42 * @tun_info.ipv4: dest IPv4 address of active route 43 * @tun_info.egress_port: port the encapsulated packet egressed 44 * @tun_info.extra: reserved for future use 45 * @tun_info: tunnels that have sent traffic in reported period 46 */ 47struct nfp_tun_active_tuns { 48 __be32 seq; 49 __be32 count; 50 __be32 flags; 51 struct route_ip_info { 52 __be32 ipv4; 53 __be32 egress_port; 54 __be32 extra[2]; 55 } tun_info[]; 56}; 57 58/** 59 * struct nfp_tun_active_tuns_v6 - periodic message of active IPv6 tunnels 60 * @seq: sequence number of the message 61 * @count: number of tunnels report in message 62 * @flags: options part of the request 63 * @tun_info.ipv6: dest IPv6 address of active route 64 * @tun_info.egress_port: port the encapsulated packet egressed 65 * @tun_info.extra: reserved for future use 66 * @tun_info: tunnels that have sent traffic in reported period 67 */ 68struct nfp_tun_active_tuns_v6 { 69 __be32 seq; 70 __be32 count; 71 __be32 flags; 72 struct route_ip_info_v6 { 73 struct in6_addr ipv6; 74 __be32 egress_port; 75 __be32 extra[2]; 76 } tun_info[]; 77}; 78 79/** 80 * struct nfp_tun_req_route_ipv4 - NFP requests a route/neighbour lookup 81 * @ingress_port: ingress port of packet that signalled request 82 * @ipv4_addr: destination ipv4 address for route 83 * @reserved: reserved for future use 84 */ 85struct nfp_tun_req_route_ipv4 { 86 __be32 ingress_port; 87 __be32 ipv4_addr; 88 __be32 reserved[2]; 89}; 90 91/** 92 * struct nfp_tun_req_route_ipv6 - NFP requests an IPv6 route/neighbour lookup 93 * @ingress_port: ingress port of packet that signalled request 94 * @ipv6_addr: destination ipv6 address for route 95 */ 96struct nfp_tun_req_route_ipv6 { 97 __be32 ingress_port; 98 struct in6_addr ipv6_addr; 99}; 100 101/** 102 * struct nfp_offloaded_route - routes that are offloaded to the NFP 103 * @list: list pointer 104 * @ip_add: destination of route - can be IPv4 or IPv6 105 */ 106struct nfp_offloaded_route { 107 struct list_head list; 108 u8 ip_add[]; 109}; 110 111#define NFP_FL_IPV4_ADDRS_MAX 32 112 113/** 114 * struct nfp_tun_ipv4_addr - set the IP address list on the NFP 115 * @count: number of IPs populated in the array 116 * @ipv4_addr: array of IPV4_ADDRS_MAX 32 bit IPv4 addresses 117 */ 118struct nfp_tun_ipv4_addr { 119 __be32 count; 120 __be32 ipv4_addr[NFP_FL_IPV4_ADDRS_MAX]; 121}; 122 123/** 124 * struct nfp_ipv4_addr_entry - cached IPv4 addresses 125 * @ipv4_addr: IP address 126 * @ref_count: number of rules currently using this IP 127 * @list: list pointer 128 */ 129struct nfp_ipv4_addr_entry { 130 __be32 ipv4_addr; 131 int ref_count; 132 struct list_head list; 133}; 134 135#define NFP_FL_IPV6_ADDRS_MAX 4 136 137/** 138 * struct nfp_tun_ipv6_addr - set the IP address list on the NFP 139 * @count: number of IPs populated in the array 140 * @ipv6_addr: array of IPV6_ADDRS_MAX 128 bit IPv6 addresses 141 */ 142struct nfp_tun_ipv6_addr { 143 __be32 count; 144 struct in6_addr ipv6_addr[NFP_FL_IPV6_ADDRS_MAX]; 145}; 146 147#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG 0x2 148 149/** 150 * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP 151 * @flags: MAC address offload options 152 * @count: number of MAC addresses in the message (should be 1) 153 * @index: index of MAC address in the lookup table 154 * @addr: interface MAC address 155 */ 156struct nfp_tun_mac_addr_offload { 157 __be16 flags; 158 __be16 count; 159 __be16 index; 160 u8 addr[ETH_ALEN]; 161}; 162 163enum nfp_flower_mac_offload_cmd { 164 NFP_TUNNEL_MAC_OFFLOAD_ADD = 0, 165 NFP_TUNNEL_MAC_OFFLOAD_DEL = 1, 166 NFP_TUNNEL_MAC_OFFLOAD_MOD = 2, 167}; 168 169#define NFP_MAX_MAC_INDEX 0xff 170 171/** 172 * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC 173 * @ht_node: Hashtable entry 174 * @addr: Offloaded MAC address 175 * @index: Offloaded index for given MAC address 176 * @ref_count: Number of devs using this MAC address 177 * @repr_list: List of reprs sharing this MAC address 178 * @bridge_count: Number of bridge/internal devs with MAC 179 */ 180struct nfp_tun_offloaded_mac { 181 struct rhash_head ht_node; 182 u8 addr[ETH_ALEN]; 183 u16 index; 184 int ref_count; 185 struct list_head repr_list; 186 int bridge_count; 187}; 188 189static const struct rhashtable_params offloaded_macs_params = { 190 .key_offset = offsetof(struct nfp_tun_offloaded_mac, addr), 191 .head_offset = offsetof(struct nfp_tun_offloaded_mac, ht_node), 192 .key_len = ETH_ALEN, 193 .automatic_shrinking = true, 194}; 195 196void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb) 197{ 198 struct nfp_tun_active_tuns *payload; 199 struct net_device *netdev; 200 int count, i, pay_len; 201 struct neighbour *n; 202 __be32 ipv4_addr; 203 u32 port; 204 205 payload = nfp_flower_cmsg_get_data(skb); 206 count = be32_to_cpu(payload->count); 207 if (count > NFP_FL_MAX_ROUTES) { 208 nfp_flower_cmsg_warn(app, "Tunnel keep-alive request exceeds max routes.\n"); 209 return; 210 } 211 212 pay_len = nfp_flower_cmsg_get_data_len(skb); 213 if (pay_len != struct_size(payload, tun_info, count)) { 214 nfp_flower_cmsg_warn(app, "Corruption in tunnel keep-alive message.\n"); 215 return; 216 } 217 218 rcu_read_lock(); 219 for (i = 0; i < count; i++) { 220 ipv4_addr = payload->tun_info[i].ipv4; 221 port = be32_to_cpu(payload->tun_info[i].egress_port); 222 netdev = nfp_app_dev_get(app, port, NULL); 223 if (!netdev) 224 continue; 225 226 n = neigh_lookup(&arp_tbl, &ipv4_addr, netdev); 227 if (!n) 228 continue; 229 230 /* Update the used timestamp of neighbour */ 231 neigh_event_send(n, NULL); 232 neigh_release(n); 233 } 234 rcu_read_unlock(); 235} 236 237void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb) 238{ 239#if IS_ENABLED(CONFIG_IPV6) 240 struct nfp_tun_active_tuns_v6 *payload; 241 struct net_device *netdev; 242 int count, i, pay_len; 243 struct neighbour *n; 244 void *ipv6_add; 245 u32 port; 246 247 payload = nfp_flower_cmsg_get_data(skb); 248 count = be32_to_cpu(payload->count); 249 if (count > NFP_FL_IPV6_ADDRS_MAX) { 250 nfp_flower_cmsg_warn(app, "IPv6 tunnel keep-alive request exceeds max routes.\n"); 251 return; 252 } 253 254 pay_len = nfp_flower_cmsg_get_data_len(skb); 255 if (pay_len != struct_size(payload, tun_info, count)) { 256 nfp_flower_cmsg_warn(app, "Corruption in tunnel keep-alive message.\n"); 257 return; 258 } 259 260 rcu_read_lock(); 261 for (i = 0; i < count; i++) { 262 ipv6_add = &payload->tun_info[i].ipv6; 263 port = be32_to_cpu(payload->tun_info[i].egress_port); 264 netdev = nfp_app_dev_get(app, port, NULL); 265 if (!netdev) 266 continue; 267 268 n = neigh_lookup(&nd_tbl, ipv6_add, netdev); 269 if (!n) 270 continue; 271 272 /* Update the used timestamp of neighbour */ 273 neigh_event_send(n, NULL); 274 neigh_release(n); 275 } 276 rcu_read_unlock(); 277#endif 278} 279 280static int 281nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata, 282 gfp_t flag) 283{ 284 struct nfp_flower_priv *priv = app->priv; 285 struct sk_buff *skb; 286 unsigned char *msg; 287 288 if (!(priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2) && 289 (mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH || 290 mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6)) 291 plen -= sizeof(struct nfp_tun_neigh_ext); 292 293 skb = nfp_flower_cmsg_alloc(app, plen, mtype, flag); 294 if (!skb) 295 return -ENOMEM; 296 297 msg = nfp_flower_cmsg_get_data(skb); 298 memcpy(msg, pdata, nfp_flower_cmsg_get_data_len(skb)); 299 300 nfp_ctrl_tx(app->ctrl, skb); 301 return 0; 302} 303 304static void 305nfp_tun_mutual_link(struct nfp_predt_entry *predt, 306 struct nfp_neigh_entry *neigh) 307{ 308 struct nfp_fl_payload *flow_pay = predt->flow_pay; 309 struct nfp_tun_neigh_ext *ext; 310 struct nfp_tun_neigh *common; 311 312 if (flow_pay->pre_tun_rule.is_ipv6 != neigh->is_ipv6) 313 return; 314 315 /* In the case of bonding it is possible that there might already 316 * be a flow linked (as the MAC address gets shared). If a flow 317 * is already linked just return. 318 */ 319 if (neigh->flow) 320 return; 321 322 common = neigh->is_ipv6 ? 323 &((struct nfp_tun_neigh_v6 *)neigh->payload)->common : 324 &((struct nfp_tun_neigh_v4 *)neigh->payload)->common; 325 ext = neigh->is_ipv6 ? 326 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext : 327 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext; 328 329 if (memcmp(flow_pay->pre_tun_rule.loc_mac, 330 common->src_addr, ETH_ALEN) || 331 memcmp(flow_pay->pre_tun_rule.rem_mac, 332 common->dst_addr, ETH_ALEN)) 333 return; 334 335 list_add(&neigh->list_head, &predt->nn_list); 336 neigh->flow = predt; 337 ext->host_ctx = flow_pay->meta.host_ctx_id; 338 ext->vlan_tci = flow_pay->pre_tun_rule.vlan_tci; 339 ext->vlan_tpid = flow_pay->pre_tun_rule.vlan_tpid; 340} 341 342static void 343nfp_tun_link_predt_entries(struct nfp_app *app, 344 struct nfp_neigh_entry *nn_entry) 345{ 346 struct nfp_flower_priv *priv = app->priv; 347 struct nfp_predt_entry *predt, *tmp; 348 349 list_for_each_entry_safe(predt, tmp, &priv->predt_list, list_head) { 350 nfp_tun_mutual_link(predt, nn_entry); 351 } 352} 353 354void nfp_tun_link_and_update_nn_entries(struct nfp_app *app, 355 struct nfp_predt_entry *predt) 356{ 357 struct nfp_flower_priv *priv = app->priv; 358 struct nfp_neigh_entry *nn_entry; 359 struct rhashtable_iter iter; 360 size_t neigh_size; 361 u8 type; 362 363 rhashtable_walk_enter(&priv->neigh_table, &iter); 364 rhashtable_walk_start(&iter); 365 while ((nn_entry = rhashtable_walk_next(&iter)) != NULL) { 366 if (IS_ERR(nn_entry)) 367 continue; 368 nfp_tun_mutual_link(predt, nn_entry); 369 neigh_size = nn_entry->is_ipv6 ? 370 sizeof(struct nfp_tun_neigh_v6) : 371 sizeof(struct nfp_tun_neigh_v4); 372 type = nn_entry->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 : 373 NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 374 nfp_flower_xmit_tun_conf(app, type, neigh_size, 375 nn_entry->payload, 376 GFP_ATOMIC); 377 } 378 rhashtable_walk_stop(&iter); 379 rhashtable_walk_exit(&iter); 380} 381 382static void nfp_tun_cleanup_nn_entries(struct nfp_app *app) 383{ 384 struct nfp_flower_priv *priv = app->priv; 385 struct nfp_neigh_entry *neigh; 386 struct nfp_tun_neigh_ext *ext; 387 struct rhashtable_iter iter; 388 size_t neigh_size; 389 u8 type; 390 391 rhashtable_walk_enter(&priv->neigh_table, &iter); 392 rhashtable_walk_start(&iter); 393 while ((neigh = rhashtable_walk_next(&iter)) != NULL) { 394 if (IS_ERR(neigh)) 395 continue; 396 ext = neigh->is_ipv6 ? 397 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext : 398 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext; 399 ext->host_ctx = cpu_to_be32(U32_MAX); 400 ext->vlan_tpid = cpu_to_be16(U16_MAX); 401 ext->vlan_tci = cpu_to_be16(U16_MAX); 402 403 neigh_size = neigh->is_ipv6 ? 404 sizeof(struct nfp_tun_neigh_v6) : 405 sizeof(struct nfp_tun_neigh_v4); 406 type = neigh->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 : 407 NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 408 nfp_flower_xmit_tun_conf(app, type, neigh_size, neigh->payload, 409 GFP_ATOMIC); 410 411 rhashtable_remove_fast(&priv->neigh_table, &neigh->ht_node, 412 neigh_table_params); 413 if (neigh->flow) 414 list_del(&neigh->list_head); 415 kfree(neigh); 416 } 417 rhashtable_walk_stop(&iter); 418 rhashtable_walk_exit(&iter); 419} 420 421void nfp_tun_unlink_and_update_nn_entries(struct nfp_app *app, 422 struct nfp_predt_entry *predt) 423{ 424 struct nfp_neigh_entry *neigh, *tmp; 425 struct nfp_tun_neigh_ext *ext; 426 size_t neigh_size; 427 u8 type; 428 429 list_for_each_entry_safe(neigh, tmp, &predt->nn_list, list_head) { 430 ext = neigh->is_ipv6 ? 431 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext : 432 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext; 433 neigh->flow = NULL; 434 ext->host_ctx = cpu_to_be32(U32_MAX); 435 ext->vlan_tpid = cpu_to_be16(U16_MAX); 436 ext->vlan_tci = cpu_to_be16(U16_MAX); 437 list_del(&neigh->list_head); 438 neigh_size = neigh->is_ipv6 ? 439 sizeof(struct nfp_tun_neigh_v6) : 440 sizeof(struct nfp_tun_neigh_v4); 441 type = neigh->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 : 442 NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 443 nfp_flower_xmit_tun_conf(app, type, neigh_size, neigh->payload, 444 GFP_ATOMIC); 445 } 446} 447 448static void 449nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app, 450 void *flow, struct neighbour *neigh, bool is_ipv6) 451{ 452 bool neigh_invalid = !(neigh->nud_state & NUD_VALID) || neigh->dead; 453 size_t neigh_size = is_ipv6 ? sizeof(struct nfp_tun_neigh_v6) : 454 sizeof(struct nfp_tun_neigh_v4); 455 unsigned long cookie = (unsigned long)neigh; 456 struct nfp_flower_priv *priv = app->priv; 457 struct nfp_neigh_entry *nn_entry; 458 u32 port_id; 459 u8 mtype; 460 461 port_id = nfp_flower_get_port_id_from_netdev(app, netdev); 462 if (!port_id) 463 return; 464 465 spin_lock_bh(&priv->predt_lock); 466 nn_entry = rhashtable_lookup_fast(&priv->neigh_table, &cookie, 467 neigh_table_params); 468 if (!nn_entry && !neigh_invalid) { 469 struct nfp_tun_neigh_ext *ext; 470 struct nfp_tun_neigh *common; 471 472 nn_entry = kzalloc(sizeof(*nn_entry) + neigh_size, 473 GFP_ATOMIC); 474 if (!nn_entry) 475 goto err; 476 477 nn_entry->payload = (char *)&nn_entry[1]; 478 nn_entry->neigh_cookie = cookie; 479 nn_entry->is_ipv6 = is_ipv6; 480 nn_entry->flow = NULL; 481 if (is_ipv6) { 482 struct flowi6 *flowi6 = (struct flowi6 *)flow; 483 struct nfp_tun_neigh_v6 *payload; 484 485 payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload; 486 payload->src_ipv6 = flowi6->saddr; 487 payload->dst_ipv6 = flowi6->daddr; 488 common = &payload->common; 489 ext = &payload->ext; 490 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6; 491 } else { 492 struct flowi4 *flowi4 = (struct flowi4 *)flow; 493 struct nfp_tun_neigh_v4 *payload; 494 495 payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload; 496 payload->src_ipv4 = flowi4->saddr; 497 payload->dst_ipv4 = flowi4->daddr; 498 common = &payload->common; 499 ext = &payload->ext; 500 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 501 } 502 ext->host_ctx = cpu_to_be32(U32_MAX); 503 ext->vlan_tpid = cpu_to_be16(U16_MAX); 504 ext->vlan_tci = cpu_to_be16(U16_MAX); 505 ether_addr_copy(common->src_addr, netdev->dev_addr); 506 neigh_ha_snapshot(common->dst_addr, neigh, netdev); 507 common->port_id = cpu_to_be32(port_id); 508 509 if (rhashtable_insert_fast(&priv->neigh_table, 510 &nn_entry->ht_node, 511 neigh_table_params)) 512 goto err; 513 514 nfp_tun_link_predt_entries(app, nn_entry); 515 nfp_flower_xmit_tun_conf(app, mtype, neigh_size, 516 nn_entry->payload, 517 GFP_ATOMIC); 518 } else if (nn_entry && neigh_invalid) { 519 if (is_ipv6) { 520 struct flowi6 *flowi6 = (struct flowi6 *)flow; 521 struct nfp_tun_neigh_v6 *payload; 522 523 payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload; 524 memset(payload, 0, sizeof(struct nfp_tun_neigh_v6)); 525 payload->dst_ipv6 = flowi6->daddr; 526 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6; 527 } else { 528 struct flowi4 *flowi4 = (struct flowi4 *)flow; 529 struct nfp_tun_neigh_v4 *payload; 530 531 payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload; 532 memset(payload, 0, sizeof(struct nfp_tun_neigh_v4)); 533 payload->dst_ipv4 = flowi4->daddr; 534 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 535 } 536 /* Trigger ARP to verify invalid neighbour state. */ 537 neigh_event_send(neigh, NULL); 538 rhashtable_remove_fast(&priv->neigh_table, 539 &nn_entry->ht_node, 540 neigh_table_params); 541 542 nfp_flower_xmit_tun_conf(app, mtype, neigh_size, 543 nn_entry->payload, 544 GFP_ATOMIC); 545 546 if (nn_entry->flow) 547 list_del(&nn_entry->list_head); 548 kfree(nn_entry); 549 } 550 551 spin_unlock_bh(&priv->predt_lock); 552 return; 553 554err: 555 kfree(nn_entry); 556 spin_unlock_bh(&priv->predt_lock); 557 nfp_flower_cmsg_warn(app, "Neighbour configuration failed.\n"); 558} 559 560static int 561nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event, 562 void *ptr) 563{ 564 struct nfp_flower_priv *app_priv; 565 struct netevent_redirect *redir; 566 struct neighbour *n; 567 struct nfp_app *app; 568 bool neigh_invalid; 569 int err; 570 571 switch (event) { 572 case NETEVENT_REDIRECT: 573 redir = (struct netevent_redirect *)ptr; 574 n = redir->neigh; 575 break; 576 case NETEVENT_NEIGH_UPDATE: 577 n = (struct neighbour *)ptr; 578 break; 579 default: 580 return NOTIFY_DONE; 581 } 582 583 neigh_invalid = !(n->nud_state & NUD_VALID) || n->dead; 584 585 app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb); 586 app = app_priv->app; 587 588 if (!nfp_netdev_is_nfp_repr(n->dev) && 589 !nfp_flower_internal_port_can_offload(app, n->dev)) 590 return NOTIFY_DONE; 591 592#if IS_ENABLED(CONFIG_INET) 593 if (n->tbl->family == AF_INET6) { 594#if IS_ENABLED(CONFIG_IPV6) 595 struct flowi6 flow6 = {}; 596 597 flow6.daddr = *(struct in6_addr *)n->primary_key; 598 if (!neigh_invalid) { 599 struct dst_entry *dst; 600 /* Use ipv6_dst_lookup_flow to populate flow6->saddr 601 * and other fields. This information is only needed 602 * for new entries, lookup can be skipped when an entry 603 * gets invalidated - as only the daddr is needed for 604 * deleting. 605 */ 606 dst = ip6_dst_lookup_flow(dev_net(n->dev), NULL, 607 &flow6, NULL); 608 if (IS_ERR(dst)) 609 return NOTIFY_DONE; 610 611 dst_release(dst); 612 } 613 nfp_tun_write_neigh(n->dev, app, &flow6, n, true); 614#else 615 return NOTIFY_DONE; 616#endif /* CONFIG_IPV6 */ 617 } else { 618 struct flowi4 flow4 = {}; 619 620 flow4.daddr = *(__be32 *)n->primary_key; 621 if (!neigh_invalid) { 622 struct rtable *rt; 623 /* Use ip_route_output_key to populate flow4->saddr and 624 * other fields. This information is only needed for 625 * new entries, lookup can be skipped when an entry 626 * gets invalidated - as only the daddr is needed for 627 * deleting. 628 */ 629 rt = ip_route_output_key(dev_net(n->dev), &flow4); 630 err = PTR_ERR_OR_ZERO(rt); 631 if (err) 632 return NOTIFY_DONE; 633 634 ip_rt_put(rt); 635 } 636 nfp_tun_write_neigh(n->dev, app, &flow4, n, false); 637 } 638#else 639 return NOTIFY_DONE; 640#endif /* CONFIG_INET */ 641 642 return NOTIFY_OK; 643} 644 645void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb) 646{ 647 struct nfp_tun_req_route_ipv4 *payload; 648 struct net_device *netdev; 649 struct flowi4 flow = {}; 650 struct neighbour *n; 651 struct rtable *rt; 652 int err; 653 654 payload = nfp_flower_cmsg_get_data(skb); 655 656 rcu_read_lock(); 657 netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL); 658 if (!netdev) 659 goto fail_rcu_unlock; 660 661 flow.daddr = payload->ipv4_addr; 662 flow.flowi4_proto = IPPROTO_UDP; 663 664#if IS_ENABLED(CONFIG_INET) 665 /* Do a route lookup on same namespace as ingress port. */ 666 rt = ip_route_output_key(dev_net(netdev), &flow); 667 err = PTR_ERR_OR_ZERO(rt); 668 if (err) 669 goto fail_rcu_unlock; 670#else 671 goto fail_rcu_unlock; 672#endif 673 674 /* Get the neighbour entry for the lookup */ 675 n = dst_neigh_lookup(&rt->dst, &flow.daddr); 676 ip_rt_put(rt); 677 if (!n) 678 goto fail_rcu_unlock; 679 nfp_tun_write_neigh(n->dev, app, &flow, n, false); 680 neigh_release(n); 681 rcu_read_unlock(); 682 return; 683 684fail_rcu_unlock: 685 rcu_read_unlock(); 686 nfp_flower_cmsg_warn(app, "Requested route not found.\n"); 687} 688 689void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb) 690{ 691 struct nfp_tun_req_route_ipv6 *payload; 692 struct net_device *netdev; 693 struct flowi6 flow = {}; 694 struct dst_entry *dst; 695 struct neighbour *n; 696 697 payload = nfp_flower_cmsg_get_data(skb); 698 699 rcu_read_lock(); 700 netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL); 701 if (!netdev) 702 goto fail_rcu_unlock; 703 704 flow.daddr = payload->ipv6_addr; 705 flow.flowi6_proto = IPPROTO_UDP; 706 707#if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6) 708 dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow, 709 NULL); 710 if (IS_ERR(dst)) 711 goto fail_rcu_unlock; 712#else 713 goto fail_rcu_unlock; 714#endif 715 716 n = dst_neigh_lookup(dst, &flow.daddr); 717 dst_release(dst); 718 if (!n) 719 goto fail_rcu_unlock; 720 721 nfp_tun_write_neigh(n->dev, app, &flow, n, true); 722 neigh_release(n); 723 rcu_read_unlock(); 724 return; 725 726fail_rcu_unlock: 727 rcu_read_unlock(); 728 nfp_flower_cmsg_warn(app, "Requested IPv6 route not found.\n"); 729} 730 731static void nfp_tun_write_ipv4_list(struct nfp_app *app) 732{ 733 struct nfp_flower_priv *priv = app->priv; 734 struct nfp_ipv4_addr_entry *entry; 735 struct nfp_tun_ipv4_addr payload; 736 struct list_head *ptr, *storage; 737 int count; 738 739 memset(&payload, 0, sizeof(struct nfp_tun_ipv4_addr)); 740 mutex_lock(&priv->tun.ipv4_off_lock); 741 count = 0; 742 list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { 743 if (count >= NFP_FL_IPV4_ADDRS_MAX) { 744 mutex_unlock(&priv->tun.ipv4_off_lock); 745 nfp_flower_cmsg_warn(app, "IPv4 offload exceeds limit.\n"); 746 return; 747 } 748 entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); 749 payload.ipv4_addr[count++] = entry->ipv4_addr; 750 } 751 payload.count = cpu_to_be32(count); 752 mutex_unlock(&priv->tun.ipv4_off_lock); 753 754 nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS, 755 sizeof(struct nfp_tun_ipv4_addr), 756 &payload, GFP_KERNEL); 757} 758 759void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4) 760{ 761 struct nfp_flower_priv *priv = app->priv; 762 struct nfp_ipv4_addr_entry *entry; 763 struct list_head *ptr, *storage; 764 765 mutex_lock(&priv->tun.ipv4_off_lock); 766 list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { 767 entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); 768 if (entry->ipv4_addr == ipv4) { 769 entry->ref_count++; 770 mutex_unlock(&priv->tun.ipv4_off_lock); 771 return; 772 } 773 } 774 775 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 776 if (!entry) { 777 mutex_unlock(&priv->tun.ipv4_off_lock); 778 nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n"); 779 return; 780 } 781 entry->ipv4_addr = ipv4; 782 entry->ref_count = 1; 783 list_add_tail(&entry->list, &priv->tun.ipv4_off_list); 784 mutex_unlock(&priv->tun.ipv4_off_lock); 785 786 nfp_tun_write_ipv4_list(app); 787} 788 789void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4) 790{ 791 struct nfp_flower_priv *priv = app->priv; 792 struct nfp_ipv4_addr_entry *entry; 793 struct list_head *ptr, *storage; 794 795 mutex_lock(&priv->tun.ipv4_off_lock); 796 list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { 797 entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); 798 if (entry->ipv4_addr == ipv4) { 799 entry->ref_count--; 800 if (!entry->ref_count) { 801 list_del(&entry->list); 802 kfree(entry); 803 } 804 break; 805 } 806 } 807 mutex_unlock(&priv->tun.ipv4_off_lock); 808 809 nfp_tun_write_ipv4_list(app); 810} 811 812static void nfp_tun_write_ipv6_list(struct nfp_app *app) 813{ 814 struct nfp_flower_priv *priv = app->priv; 815 struct nfp_ipv6_addr_entry *entry; 816 struct nfp_tun_ipv6_addr payload; 817 int count = 0; 818 819 memset(&payload, 0, sizeof(struct nfp_tun_ipv6_addr)); 820 mutex_lock(&priv->tun.ipv6_off_lock); 821 list_for_each_entry(entry, &priv->tun.ipv6_off_list, list) { 822 if (count >= NFP_FL_IPV6_ADDRS_MAX) { 823 nfp_flower_cmsg_warn(app, "Too many IPv6 tunnel endpoint addresses, some cannot be offloaded.\n"); 824 break; 825 } 826 payload.ipv6_addr[count++] = entry->ipv6_addr; 827 } 828 mutex_unlock(&priv->tun.ipv6_off_lock); 829 payload.count = cpu_to_be32(count); 830 831 nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6, 832 sizeof(struct nfp_tun_ipv6_addr), 833 &payload, GFP_KERNEL); 834} 835 836struct nfp_ipv6_addr_entry * 837nfp_tunnel_add_ipv6_off(struct nfp_app *app, struct in6_addr *ipv6) 838{ 839 struct nfp_flower_priv *priv = app->priv; 840 struct nfp_ipv6_addr_entry *entry; 841 842 mutex_lock(&priv->tun.ipv6_off_lock); 843 list_for_each_entry(entry, &priv->tun.ipv6_off_list, list) 844 if (!memcmp(&entry->ipv6_addr, ipv6, sizeof(*ipv6))) { 845 entry->ref_count++; 846 mutex_unlock(&priv->tun.ipv6_off_lock); 847 return entry; 848 } 849 850 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 851 if (!entry) { 852 mutex_unlock(&priv->tun.ipv6_off_lock); 853 nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n"); 854 return NULL; 855 } 856 entry->ipv6_addr = *ipv6; 857 entry->ref_count = 1; 858 list_add_tail(&entry->list, &priv->tun.ipv6_off_list); 859 mutex_unlock(&priv->tun.ipv6_off_lock); 860 861 nfp_tun_write_ipv6_list(app); 862 863 return entry; 864} 865 866void 867nfp_tunnel_put_ipv6_off(struct nfp_app *app, struct nfp_ipv6_addr_entry *entry) 868{ 869 struct nfp_flower_priv *priv = app->priv; 870 bool freed = false; 871 872 mutex_lock(&priv->tun.ipv6_off_lock); 873 if (!--entry->ref_count) { 874 list_del(&entry->list); 875 kfree(entry); 876 freed = true; 877 } 878 mutex_unlock(&priv->tun.ipv6_off_lock); 879 880 if (freed) 881 nfp_tun_write_ipv6_list(app); 882} 883 884static int 885__nfp_tunnel_offload_mac(struct nfp_app *app, const u8 *mac, u16 idx, bool del) 886{ 887 struct nfp_tun_mac_addr_offload payload; 888 889 memset(&payload, 0, sizeof(payload)); 890 891 if (del) 892 payload.flags = cpu_to_be16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG); 893 894 /* FW supports multiple MACs per cmsg but restrict to single. */ 895 payload.count = cpu_to_be16(1); 896 payload.index = cpu_to_be16(idx); 897 ether_addr_copy(payload.addr, mac); 898 899 return nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC, 900 sizeof(struct nfp_tun_mac_addr_offload), 901 &payload, GFP_KERNEL); 902} 903 904static bool nfp_tunnel_port_is_phy_repr(int port) 905{ 906 if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == 907 NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) 908 return true; 909 910 return false; 911} 912 913static u16 nfp_tunnel_get_mac_idx_from_phy_port_id(int port) 914{ 915 return port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; 916} 917 918static u16 nfp_tunnel_get_global_mac_idx_from_ida(int id) 919{ 920 return id << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; 921} 922 923static int nfp_tunnel_get_ida_from_global_mac_idx(u16 nfp_mac_idx) 924{ 925 return nfp_mac_idx >> 8; 926} 927 928static bool nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx) 929{ 930 return (nfp_mac_idx & 0xff) == NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; 931} 932 933static struct nfp_tun_offloaded_mac * 934nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, const u8 *mac) 935{ 936 struct nfp_flower_priv *priv = app->priv; 937 938 return rhashtable_lookup_fast(&priv->tun.offloaded_macs, mac, 939 offloaded_macs_params); 940} 941 942static void 943nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac *entry, 944 struct net_device *netdev, bool mod) 945{ 946 if (nfp_netdev_is_nfp_repr(netdev)) { 947 struct nfp_flower_repr_priv *repr_priv; 948 struct nfp_repr *repr; 949 950 repr = netdev_priv(netdev); 951 repr_priv = repr->app_priv; 952 953 /* If modifing MAC, remove repr from old list first. */ 954 if (mod) 955 list_del(&repr_priv->mac_list); 956 957 list_add_tail(&repr_priv->mac_list, &entry->repr_list); 958 } else if (nfp_flower_is_supported_bridge(netdev)) { 959 entry->bridge_count++; 960 } 961 962 entry->ref_count++; 963} 964 965static int 966nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, 967 int port, bool mod) 968{ 969 struct nfp_flower_priv *priv = app->priv; 970 struct nfp_tun_offloaded_mac *entry; 971 int ida_idx = -1, err; 972 u16 nfp_mac_idx = 0; 973 974 entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); 975 if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { 976 if (entry->bridge_count || 977 !nfp_flower_is_supported_bridge(netdev)) { 978 nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, 979 netdev, mod); 980 return 0; 981 } 982 983 /* MAC is global but matches need to go to pre_tun table. */ 984 nfp_mac_idx = entry->index | NFP_TUN_PRE_TUN_IDX_BIT; 985 } 986 987 if (!nfp_mac_idx) { 988 /* Assign a global index if non-repr or MAC is now shared. */ 989 if (entry || !port) { 990 ida_idx = ida_alloc_max(&priv->tun.mac_off_ids, 991 NFP_MAX_MAC_INDEX, GFP_KERNEL); 992 if (ida_idx < 0) 993 return ida_idx; 994 995 nfp_mac_idx = 996 nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); 997 998 if (nfp_flower_is_supported_bridge(netdev)) 999 nfp_mac_idx |= NFP_TUN_PRE_TUN_IDX_BIT; 1000 1001 } else { 1002 nfp_mac_idx = 1003 nfp_tunnel_get_mac_idx_from_phy_port_id(port); 1004 } 1005 } 1006 1007 if (!entry) { 1008 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1009 if (!entry) { 1010 err = -ENOMEM; 1011 goto err_free_ida; 1012 } 1013 1014 ether_addr_copy(entry->addr, netdev->dev_addr); 1015 INIT_LIST_HEAD(&entry->repr_list); 1016 1017 if (rhashtable_insert_fast(&priv->tun.offloaded_macs, 1018 &entry->ht_node, 1019 offloaded_macs_params)) { 1020 err = -ENOMEM; 1021 goto err_free_entry; 1022 } 1023 } 1024 1025 err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, 1026 nfp_mac_idx, false); 1027 if (err) { 1028 /* If not shared then free. */ 1029 if (!entry->ref_count) 1030 goto err_remove_hash; 1031 goto err_free_ida; 1032 } 1033 1034 entry->index = nfp_mac_idx; 1035 nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod); 1036 1037 return 0; 1038 1039err_remove_hash: 1040 rhashtable_remove_fast(&priv->tun.offloaded_macs, &entry->ht_node, 1041 offloaded_macs_params); 1042err_free_entry: 1043 kfree(entry); 1044err_free_ida: 1045 if (ida_idx != -1) 1046 ida_free(&priv->tun.mac_off_ids, ida_idx); 1047 1048 return err; 1049} 1050 1051static int 1052nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, 1053 const u8 *mac, bool mod) 1054{ 1055 struct nfp_flower_priv *priv = app->priv; 1056 struct nfp_flower_repr_priv *repr_priv; 1057 struct nfp_tun_offloaded_mac *entry; 1058 struct nfp_repr *repr; 1059 u16 nfp_mac_idx; 1060 int ida_idx; 1061 1062 entry = nfp_tunnel_lookup_offloaded_macs(app, mac); 1063 if (!entry) 1064 return 0; 1065 1066 entry->ref_count--; 1067 /* If del is part of a mod then mac_list is still in use elsewheree. */ 1068 if (nfp_netdev_is_nfp_repr(netdev) && !mod) { 1069 repr = netdev_priv(netdev); 1070 repr_priv = repr->app_priv; 1071 list_del(&repr_priv->mac_list); 1072 } 1073 1074 if (nfp_flower_is_supported_bridge(netdev)) { 1075 entry->bridge_count--; 1076 1077 if (!entry->bridge_count && entry->ref_count) { 1078 nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; 1079 if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, 1080 false)) { 1081 nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n", 1082 netdev_name(netdev)); 1083 return 0; 1084 } 1085 1086 entry->index = nfp_mac_idx; 1087 return 0; 1088 } 1089 } 1090 1091 /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ 1092 if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { 1093 int port, err; 1094 1095 repr_priv = list_first_entry(&entry->repr_list, 1096 struct nfp_flower_repr_priv, 1097 mac_list); 1098 repr = repr_priv->nfp_repr; 1099 port = nfp_repr_get_port_id(repr->netdev); 1100 nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port); 1101 err = __nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, false); 1102 if (err) { 1103 nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n", 1104 netdev_name(netdev)); 1105 return 0; 1106 } 1107 1108 ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); 1109 ida_free(&priv->tun.mac_off_ids, ida_idx); 1110 entry->index = nfp_mac_idx; 1111 return 0; 1112 } 1113 1114 if (entry->ref_count) 1115 return 0; 1116 1117 WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, 1118 &entry->ht_node, 1119 offloaded_macs_params)); 1120 1121 if (nfp_flower_is_supported_bridge(netdev)) 1122 nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT; 1123 else 1124 nfp_mac_idx = entry->index; 1125 1126 /* If MAC has global ID then extract and free the ida entry. */ 1127 if (nfp_tunnel_is_mac_idx_global(nfp_mac_idx)) { 1128 ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); 1129 ida_free(&priv->tun.mac_off_ids, ida_idx); 1130 } 1131 1132 kfree(entry); 1133 1134 return __nfp_tunnel_offload_mac(app, mac, 0, true); 1135} 1136 1137static int 1138nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, 1139 enum nfp_flower_mac_offload_cmd cmd) 1140{ 1141 struct nfp_flower_non_repr_priv *nr_priv = NULL; 1142 bool non_repr = false, *mac_offloaded; 1143 u8 *off_mac = NULL; 1144 int err, port = 0; 1145 1146 if (nfp_netdev_is_nfp_repr(netdev)) { 1147 struct nfp_flower_repr_priv *repr_priv; 1148 struct nfp_repr *repr; 1149 1150 repr = netdev_priv(netdev); 1151 if (repr->app != app) 1152 return 0; 1153 1154 repr_priv = repr->app_priv; 1155 if (repr_priv->on_bridge) 1156 return 0; 1157 1158 mac_offloaded = &repr_priv->mac_offloaded; 1159 off_mac = &repr_priv->offloaded_mac_addr[0]; 1160 port = nfp_repr_get_port_id(netdev); 1161 if (!nfp_tunnel_port_is_phy_repr(port)) 1162 return 0; 1163 } else if (nfp_fl_is_netdev_to_offload(netdev)) { 1164 nr_priv = nfp_flower_non_repr_priv_get(app, netdev); 1165 if (!nr_priv) 1166 return -ENOMEM; 1167 1168 mac_offloaded = &nr_priv->mac_offloaded; 1169 off_mac = &nr_priv->offloaded_mac_addr[0]; 1170 non_repr = true; 1171 } else { 1172 return 0; 1173 } 1174 1175 if (!is_valid_ether_addr(netdev->dev_addr)) { 1176 err = -EINVAL; 1177 goto err_put_non_repr_priv; 1178 } 1179 1180 if (cmd == NFP_TUNNEL_MAC_OFFLOAD_MOD && !*mac_offloaded) 1181 cmd = NFP_TUNNEL_MAC_OFFLOAD_ADD; 1182 1183 switch (cmd) { 1184 case NFP_TUNNEL_MAC_OFFLOAD_ADD: 1185 err = nfp_tunnel_add_shared_mac(app, netdev, port, false); 1186 if (err) 1187 goto err_put_non_repr_priv; 1188 1189 if (non_repr) 1190 __nfp_flower_non_repr_priv_get(nr_priv); 1191 1192 *mac_offloaded = true; 1193 ether_addr_copy(off_mac, netdev->dev_addr); 1194 break; 1195 case NFP_TUNNEL_MAC_OFFLOAD_DEL: 1196 /* Only attempt delete if add was successful. */ 1197 if (!*mac_offloaded) 1198 break; 1199 1200 if (non_repr) 1201 __nfp_flower_non_repr_priv_put(nr_priv); 1202 1203 *mac_offloaded = false; 1204 1205 err = nfp_tunnel_del_shared_mac(app, netdev, netdev->dev_addr, 1206 false); 1207 if (err) 1208 goto err_put_non_repr_priv; 1209 1210 break; 1211 case NFP_TUNNEL_MAC_OFFLOAD_MOD: 1212 /* Ignore if changing to the same address. */ 1213 if (ether_addr_equal(netdev->dev_addr, off_mac)) 1214 break; 1215 1216 err = nfp_tunnel_add_shared_mac(app, netdev, port, true); 1217 if (err) 1218 goto err_put_non_repr_priv; 1219 1220 /* Delete the previous MAC address. */ 1221 err = nfp_tunnel_del_shared_mac(app, netdev, off_mac, true); 1222 if (err) 1223 nfp_flower_cmsg_warn(app, "Failed to remove offload of replaced MAC addr on %s.\n", 1224 netdev_name(netdev)); 1225 1226 ether_addr_copy(off_mac, netdev->dev_addr); 1227 break; 1228 default: 1229 err = -EINVAL; 1230 goto err_put_non_repr_priv; 1231 } 1232 1233 if (non_repr) 1234 __nfp_flower_non_repr_priv_put(nr_priv); 1235 1236 return 0; 1237 1238err_put_non_repr_priv: 1239 if (non_repr) 1240 __nfp_flower_non_repr_priv_put(nr_priv); 1241 1242 return err; 1243} 1244 1245int nfp_tunnel_mac_event_handler(struct nfp_app *app, 1246 struct net_device *netdev, 1247 unsigned long event, void *ptr) 1248{ 1249 int err; 1250 1251 if (event == NETDEV_DOWN) { 1252 err = nfp_tunnel_offload_mac(app, netdev, 1253 NFP_TUNNEL_MAC_OFFLOAD_DEL); 1254 if (err) 1255 nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n", 1256 netdev_name(netdev)); 1257 } else if (event == NETDEV_UP) { 1258 err = nfp_tunnel_offload_mac(app, netdev, 1259 NFP_TUNNEL_MAC_OFFLOAD_ADD); 1260 if (err) 1261 nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", 1262 netdev_name(netdev)); 1263 } else if (event == NETDEV_CHANGEADDR) { 1264 /* Only offload addr change if netdev is already up. */ 1265 if (!(netdev->flags & IFF_UP)) 1266 return NOTIFY_OK; 1267 1268 err = nfp_tunnel_offload_mac(app, netdev, 1269 NFP_TUNNEL_MAC_OFFLOAD_MOD); 1270 if (err) 1271 nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n", 1272 netdev_name(netdev)); 1273 } else if (event == NETDEV_CHANGEUPPER) { 1274 /* If a repr is attached to a bridge then tunnel packets 1275 * entering the physical port are directed through the bridge 1276 * datapath and cannot be directly detunneled. Therefore, 1277 * associated offloaded MACs and indexes should not be used 1278 * by fw for detunneling. 1279 */ 1280 struct netdev_notifier_changeupper_info *info = ptr; 1281 struct net_device *upper = info->upper_dev; 1282 struct nfp_flower_repr_priv *repr_priv; 1283 struct nfp_repr *repr; 1284 1285 if (!nfp_netdev_is_nfp_repr(netdev) || 1286 !nfp_flower_is_supported_bridge(upper)) 1287 return NOTIFY_OK; 1288 1289 repr = netdev_priv(netdev); 1290 if (repr->app != app) 1291 return NOTIFY_OK; 1292 1293 repr_priv = repr->app_priv; 1294 1295 if (info->linking) { 1296 if (nfp_tunnel_offload_mac(app, netdev, 1297 NFP_TUNNEL_MAC_OFFLOAD_DEL)) 1298 nfp_flower_cmsg_warn(app, "Failed to delete offloaded MAC on %s.\n", 1299 netdev_name(netdev)); 1300 repr_priv->on_bridge = true; 1301 } else { 1302 repr_priv->on_bridge = false; 1303 1304 if (!(netdev->flags & IFF_UP)) 1305 return NOTIFY_OK; 1306 1307 if (nfp_tunnel_offload_mac(app, netdev, 1308 NFP_TUNNEL_MAC_OFFLOAD_ADD)) 1309 nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", 1310 netdev_name(netdev)); 1311 } 1312 } 1313 return NOTIFY_OK; 1314} 1315 1316int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app, 1317 struct nfp_fl_payload *flow) 1318{ 1319 struct nfp_flower_priv *app_priv = app->priv; 1320 struct nfp_tun_offloaded_mac *mac_entry; 1321 struct nfp_flower_meta_tci *key_meta; 1322 struct nfp_tun_pre_tun_rule payload; 1323 struct net_device *internal_dev; 1324 int err; 1325 1326 if (app_priv->pre_tun_rule_cnt == NFP_TUN_PRE_TUN_RULE_LIMIT) 1327 return -ENOSPC; 1328 1329 memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); 1330 1331 internal_dev = flow->pre_tun_rule.dev; 1332 payload.vlan_tci = flow->pre_tun_rule.vlan_tci; 1333 payload.host_ctx_id = flow->meta.host_ctx_id; 1334 1335 /* Lookup MAC index for the pre-tunnel rule egress device. 1336 * Note that because the device is always an internal port, it will 1337 * have a constant global index so does not need to be tracked. 1338 */ 1339 mac_entry = nfp_tunnel_lookup_offloaded_macs(app, 1340 internal_dev->dev_addr); 1341 if (!mac_entry) 1342 return -ENOENT; 1343 1344 /* Set/clear IPV6 bit. cpu_to_be16() swap will lead to MSB being 1345 * set/clear for port_idx. 1346 */ 1347 key_meta = (struct nfp_flower_meta_tci *)flow->unmasked_data; 1348 if (key_meta->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV6) 1349 mac_entry->index |= NFP_TUN_PRE_TUN_IPV6_BIT; 1350 else 1351 mac_entry->index &= ~NFP_TUN_PRE_TUN_IPV6_BIT; 1352 1353 payload.port_idx = cpu_to_be16(mac_entry->index); 1354 1355 /* Copy mac id and vlan to flow - dev may not exist at delete time. */ 1356 flow->pre_tun_rule.vlan_tci = payload.vlan_tci; 1357 flow->pre_tun_rule.port_idx = payload.port_idx; 1358 1359 err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, 1360 sizeof(struct nfp_tun_pre_tun_rule), 1361 (unsigned char *)&payload, GFP_KERNEL); 1362 if (err) 1363 return err; 1364 1365 app_priv->pre_tun_rule_cnt++; 1366 1367 return 0; 1368} 1369 1370int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app, 1371 struct nfp_fl_payload *flow) 1372{ 1373 struct nfp_flower_priv *app_priv = app->priv; 1374 struct nfp_tun_pre_tun_rule payload; 1375 u32 tmp_flags = 0; 1376 int err; 1377 1378 memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule)); 1379 1380 tmp_flags |= NFP_TUN_PRE_TUN_RULE_DEL; 1381 payload.flags = cpu_to_be32(tmp_flags); 1382 payload.vlan_tci = flow->pre_tun_rule.vlan_tci; 1383 payload.port_idx = flow->pre_tun_rule.port_idx; 1384 1385 err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, 1386 sizeof(struct nfp_tun_pre_tun_rule), 1387 (unsigned char *)&payload, GFP_KERNEL); 1388 if (err) 1389 return err; 1390 1391 app_priv->pre_tun_rule_cnt--; 1392 1393 return 0; 1394} 1395 1396int nfp_tunnel_config_start(struct nfp_app *app) 1397{ 1398 struct nfp_flower_priv *priv = app->priv; 1399 int err; 1400 1401 /* Initialise rhash for MAC offload tracking. */ 1402 err = rhashtable_init(&priv->tun.offloaded_macs, 1403 &offloaded_macs_params); 1404 if (err) 1405 return err; 1406 1407 ida_init(&priv->tun.mac_off_ids); 1408 1409 /* Initialise priv data for IPv4/v6 offloading. */ 1410 mutex_init(&priv->tun.ipv4_off_lock); 1411 INIT_LIST_HEAD(&priv->tun.ipv4_off_list); 1412 mutex_init(&priv->tun.ipv6_off_lock); 1413 INIT_LIST_HEAD(&priv->tun.ipv6_off_list); 1414 1415 /* Initialise priv data for neighbour offloading. */ 1416 priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler; 1417 1418 err = register_netevent_notifier(&priv->tun.neigh_nb); 1419 if (err) { 1420 rhashtable_free_and_destroy(&priv->tun.offloaded_macs, 1421 nfp_check_rhashtable_empty, NULL); 1422 return err; 1423 } 1424 1425 return 0; 1426} 1427 1428void nfp_tunnel_config_stop(struct nfp_app *app) 1429{ 1430 struct nfp_flower_priv *priv = app->priv; 1431 struct nfp_ipv4_addr_entry *ip_entry; 1432 struct list_head *ptr, *storage; 1433 1434 unregister_netevent_notifier(&priv->tun.neigh_nb); 1435 1436 ida_destroy(&priv->tun.mac_off_ids); 1437 1438 /* Free any memory that may be occupied by ipv4 list. */ 1439 list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { 1440 ip_entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); 1441 list_del(&ip_entry->list); 1442 kfree(ip_entry); 1443 } 1444 1445 mutex_destroy(&priv->tun.ipv6_off_lock); 1446 1447 /* Destroy rhash. Entries should be cleaned on netdev notifier unreg. */ 1448 rhashtable_free_and_destroy(&priv->tun.offloaded_macs, 1449 nfp_check_rhashtable_empty, NULL); 1450 1451 nfp_tun_cleanup_nn_entries(app); 1452}