Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfp: flower: tunnel neigh support bond offload

Support hardware offload when tunnel neigh out port is bond.
These feature work with the nfp firmware. If the firmware
supports the NFP_FL_FEATS_TUNNEL_NEIGH_LAG feature, nfp driver
write the bond information to the firmware neighbor table or
do nothing for bond. when neighbor MAC changes, nfp driver
need to update the neighbor information too.

Signed-off-by: Yanguo Li <yanguo.li@corigine.com>
Reviewed-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yanguo Li and committed by
David S. Miller
abc21095 04d63e62

+115 -22
+42 -12
drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
··· 154 154 return NULL; 155 155 } 156 156 157 - int nfp_flower_lag_populate_pre_action(struct nfp_app *app, 158 - struct net_device *master, 159 - struct nfp_fl_pre_lag *pre_act, 160 - struct netlink_ext_ack *extack) 157 + static int nfp_fl_lag_get_group_info(struct nfp_app *app, 158 + struct net_device *netdev, 159 + __be16 *group_id, 160 + u8 *batch_ver, 161 + u8 *group_inst) 161 162 { 162 163 struct nfp_flower_priv *priv = app->priv; 163 164 struct nfp_fl_lag_group *group = NULL; ··· 166 165 167 166 mutex_lock(&priv->nfp_lag.lock); 168 167 group = nfp_fl_lag_find_group_for_master_with_lag(&priv->nfp_lag, 169 - master); 168 + netdev); 170 169 if (!group) { 171 170 mutex_unlock(&priv->nfp_lag.lock); 171 + return -ENOENT; 172 + } 173 + 174 + if (group_id) 175 + *group_id = cpu_to_be16(group->group_id); 176 + 177 + if (batch_ver) { 178 + temp_vers = cpu_to_be32(priv->nfp_lag.batch_ver << 179 + NFP_FL_PRE_LAG_VER_OFF); 180 + memcpy(batch_ver, &temp_vers, 3); 181 + } 182 + 183 + if (group_inst) 184 + *group_inst = group->group_inst; 185 + 186 + mutex_unlock(&priv->nfp_lag.lock); 187 + 188 + return 0; 189 + } 190 + 191 + int nfp_flower_lag_populate_pre_action(struct nfp_app *app, 192 + struct net_device *master, 193 + struct nfp_fl_pre_lag *pre_act, 194 + struct netlink_ext_ack *extack) 195 + { 196 + if (nfp_fl_lag_get_group_info(app, master, &pre_act->group_id, 197 + pre_act->lag_version, 198 + &pre_act->instance)) { 172 199 NL_SET_ERR_MSG_MOD(extack, "invalid entry: group does not exist for LAG action"); 173 200 return -ENOENT; 174 201 } 175 202 176 - pre_act->group_id = cpu_to_be16(group->group_id); 177 - temp_vers = cpu_to_be32(priv->nfp_lag.batch_ver << 178 - NFP_FL_PRE_LAG_VER_OFF); 179 - memcpy(pre_act->lag_version, &temp_vers, 3); 180 - pre_act->instance = group->group_inst; 181 - mutex_unlock(&priv->nfp_lag.lock); 182 - 183 203 return 0; 204 + } 205 + 206 + void nfp_flower_lag_get_info_from_netdev(struct nfp_app *app, 207 + struct net_device *netdev, 208 + struct nfp_tun_neigh_lag *lag) 209 + { 210 + nfp_fl_lag_get_group_info(app, netdev, NULL, 211 + lag->lag_version, &lag->lag_instance); 184 212 } 185 213 186 214 int nfp_flower_lag_get_output_id(struct nfp_app *app, struct net_device *master)
+9
drivers/net/ethernet/netronome/nfp/flower/main.c
··· 76 76 u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app, 77 77 struct net_device *netdev) 78 78 { 79 + struct nfp_flower_priv *priv = app->priv; 79 80 int ext_port; 81 + int gid; 80 82 81 83 if (nfp_netdev_is_nfp_repr(netdev)) { 82 84 return nfp_repr_get_port_id(netdev); ··· 88 86 return 0; 89 87 90 88 return nfp_flower_internal_port_get_port_id(ext_port); 89 + } else if (netif_is_lag_master(netdev) && 90 + priv->flower_ext_feats & NFP_FL_FEATS_TUNNEL_NEIGH_LAG) { 91 + gid = nfp_flower_lag_get_output_id(app, netdev); 92 + if (gid < 0) 93 + return 0; 94 + 95 + return (NFP_FL_LAG_OUT | gid); 91 96 } 92 97 93 98 return 0;
+20 -1
drivers/net/ethernet/netronome/nfp/flower/main.h
··· 52 52 #define NFP_FL_FEATS_QOS_PPS BIT(9) 53 53 #define NFP_FL_FEATS_QOS_METER BIT(10) 54 54 #define NFP_FL_FEATS_DECAP_V2 BIT(11) 55 + #define NFP_FL_FEATS_TUNNEL_NEIGH_LAG BIT(12) 55 56 #define NFP_FL_FEATS_HOST_ACK BIT(31) 56 57 57 58 #define NFP_FL_ENABLE_FLOW_MERGE BIT(0) ··· 70 69 NFP_FL_FEATS_VLAN_QINQ | \ 71 70 NFP_FL_FEATS_QOS_PPS | \ 72 71 NFP_FL_FEATS_QOS_METER | \ 73 - NFP_FL_FEATS_DECAP_V2) 72 + NFP_FL_FEATS_DECAP_V2 | \ 73 + NFP_FL_FEATS_TUNNEL_NEIGH_LAG) 74 74 75 75 struct nfp_fl_mask_id { 76 76 struct circ_buf mask_id_free_list; ··· 106 104 }; 107 105 108 106 /** 107 + * struct nfp_tun_neigh_lag - lag info 108 + * @lag_version: lag version 109 + * @lag_instance: lag instance 110 + */ 111 + struct nfp_tun_neigh_lag { 112 + u8 lag_version[3]; 113 + u8 lag_instance; 114 + }; 115 + 116 + /** 109 117 * struct nfp_tun_neigh - basic neighbour data 110 118 * @dst_addr: Destination MAC address 111 119 * @src_addr: Source MAC address ··· 145 133 * @src_ipv4: Source IPv4 address 146 134 * @common: Neighbour/route common info 147 135 * @ext: Neighbour/route extended info 136 + * @lag: lag port info 148 137 */ 149 138 struct nfp_tun_neigh_v4 { 150 139 __be32 dst_ipv4; 151 140 __be32 src_ipv4; 152 141 struct nfp_tun_neigh common; 153 142 struct nfp_tun_neigh_ext ext; 143 + struct nfp_tun_neigh_lag lag; 154 144 }; 155 145 156 146 /** ··· 161 147 * @src_ipv6: Source IPv6 address 162 148 * @common: Neighbour/route common info 163 149 * @ext: Neighbour/route extended info 150 + * @lag: lag port info 164 151 */ 165 152 struct nfp_tun_neigh_v6 { 166 153 struct in6_addr dst_ipv6; 167 154 struct in6_addr src_ipv6; 168 155 struct nfp_tun_neigh common; 169 156 struct nfp_tun_neigh_ext ext; 157 + struct nfp_tun_neigh_lag lag; 170 158 }; 171 159 172 160 /** ··· 663 647 struct netlink_ext_ack *extack); 664 648 int nfp_flower_lag_get_output_id(struct nfp_app *app, 665 649 struct net_device *master); 650 + void nfp_flower_lag_get_info_from_netdev(struct nfp_app *app, 651 + struct net_device *netdev, 652 + struct nfp_tun_neigh_lag *lag); 666 653 void nfp_flower_qos_init(struct nfp_app *app); 667 654 void nfp_flower_qos_cleanup(struct nfp_app *app); 668 655 int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev,
+44 -9
drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
··· 290 290 mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6)) 291 291 plen -= sizeof(struct nfp_tun_neigh_ext); 292 292 293 + if (!(priv->flower_ext_feats & NFP_FL_FEATS_TUNNEL_NEIGH_LAG) && 294 + (mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH || 295 + mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6)) 296 + plen -= sizeof(struct nfp_tun_neigh_lag); 297 + 293 298 skb = nfp_flower_cmsg_alloc(app, plen, mtype, flag); 294 299 if (!skb) 295 300 return -ENOMEM; ··· 473 468 neigh_table_params); 474 469 if (!nn_entry && !neigh_invalid) { 475 470 struct nfp_tun_neigh_ext *ext; 471 + struct nfp_tun_neigh_lag *lag; 476 472 struct nfp_tun_neigh *common; 477 473 478 474 nn_entry = kzalloc(sizeof(*nn_entry) + neigh_size, ··· 494 488 payload->dst_ipv6 = flowi6->daddr; 495 489 common = &payload->common; 496 490 ext = &payload->ext; 491 + lag = &payload->lag; 497 492 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6; 498 493 } else { 499 494 struct flowi4 *flowi4 = (struct flowi4 *)flow; ··· 505 498 payload->dst_ipv4 = flowi4->daddr; 506 499 common = &payload->common; 507 500 ext = &payload->ext; 501 + lag = &payload->lag; 508 502 mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 509 503 } 510 504 ext->host_ctx = cpu_to_be32(U32_MAX); ··· 513 505 ext->vlan_tci = cpu_to_be16(U16_MAX); 514 506 ether_addr_copy(common->src_addr, netdev->dev_addr); 515 507 neigh_ha_snapshot(common->dst_addr, neigh, netdev); 508 + 509 + if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT) 510 + nfp_flower_lag_get_info_from_netdev(app, netdev, lag); 516 511 common->port_id = cpu_to_be32(port_id); 517 512 518 513 if (rhashtable_insert_fast(&priv->neigh_table, ··· 558 547 if (nn_entry->flow) 559 548 list_del(&nn_entry->list_head); 560 549 kfree(nn_entry); 561 - } else if (nn_entry && !neigh_invalid && override) { 562 - mtype = is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 : 563 - NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 564 - nfp_tun_link_predt_entries(app, nn_entry); 565 - nfp_flower_xmit_tun_conf(app, mtype, neigh_size, 566 - nn_entry->payload, 567 - GFP_ATOMIC); 550 + } else if (nn_entry && !neigh_invalid) { 551 + struct nfp_tun_neigh *common; 552 + u8 dst_addr[ETH_ALEN]; 553 + bool is_mac_change; 554 + 555 + if (is_ipv6) { 556 + struct nfp_tun_neigh_v6 *payload; 557 + 558 + payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload; 559 + common = &payload->common; 560 + mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6; 561 + } else { 562 + struct nfp_tun_neigh_v4 *payload; 563 + 564 + payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload; 565 + common = &payload->common; 566 + mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH; 567 + } 568 + 569 + ether_addr_copy(dst_addr, common->dst_addr); 570 + neigh_ha_snapshot(common->dst_addr, neigh, netdev); 571 + is_mac_change = !ether_addr_equal(dst_addr, common->dst_addr); 572 + if (override || is_mac_change) { 573 + if (is_mac_change && nn_entry->flow) { 574 + list_del(&nn_entry->list_head); 575 + nn_entry->flow = NULL; 576 + } 577 + nfp_tun_link_predt_entries(app, nn_entry); 578 + nfp_flower_xmit_tun_conf(app, mtype, neigh_size, 579 + nn_entry->payload, 580 + GFP_ATOMIC); 581 + } 568 582 } 569 583 570 584 spin_unlock_bh(&priv->predt_lock); ··· 629 593 app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb); 630 594 app = app_priv->app; 631 595 632 - if (!nfp_netdev_is_nfp_repr(n->dev) && 633 - !nfp_flower_internal_port_can_offload(app, n->dev)) 596 + if (!nfp_flower_get_port_id_from_netdev(app, n->dev)) 634 597 return NOTIFY_DONE; 635 598 636 599 #if IS_ENABLED(CONFIG_INET)