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