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