Skip to content

Commit

Permalink
nfp: flower: tunnel neigh support bond offload
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yanguo Li authored and David S. Miller committed Oct 24, 2022
1 parent 04d63e6 commit abc2109
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 21 deletions.
52 changes: 41 additions & 11 deletions drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,34 +154,64 @@ nfp_fl_lag_find_group_for_master_with_lag(struct nfp_fl_lag *lag,
return NULL;
}

int nfp_flower_lag_populate_pre_action(struct nfp_app *app,
struct net_device *master,
struct nfp_fl_pre_lag *pre_act,
struct netlink_ext_ack *extack)
static int nfp_fl_lag_get_group_info(struct nfp_app *app,
struct net_device *netdev,
__be16 *group_id,
u8 *batch_ver,
u8 *group_inst)
{
struct nfp_flower_priv *priv = app->priv;
struct nfp_fl_lag_group *group = NULL;
__be32 temp_vers;

mutex_lock(&priv->nfp_lag.lock);
group = nfp_fl_lag_find_group_for_master_with_lag(&priv->nfp_lag,
master);
netdev);
if (!group) {
mutex_unlock(&priv->nfp_lag.lock);
NL_SET_ERR_MSG_MOD(extack, "invalid entry: group does not exist for LAG action");
return -ENOENT;
}

pre_act->group_id = cpu_to_be16(group->group_id);
temp_vers = cpu_to_be32(priv->nfp_lag.batch_ver <<
NFP_FL_PRE_LAG_VER_OFF);
memcpy(pre_act->lag_version, &temp_vers, 3);
pre_act->instance = group->group_inst;
if (group_id)
*group_id = cpu_to_be16(group->group_id);

if (batch_ver) {
temp_vers = cpu_to_be32(priv->nfp_lag.batch_ver <<
NFP_FL_PRE_LAG_VER_OFF);
memcpy(batch_ver, &temp_vers, 3);
}

if (group_inst)
*group_inst = group->group_inst;

mutex_unlock(&priv->nfp_lag.lock);

return 0;
}

int nfp_flower_lag_populate_pre_action(struct nfp_app *app,
struct net_device *master,
struct nfp_fl_pre_lag *pre_act,
struct netlink_ext_ack *extack)
{
if (nfp_fl_lag_get_group_info(app, master, &pre_act->group_id,
pre_act->lag_version,
&pre_act->instance)) {
NL_SET_ERR_MSG_MOD(extack, "invalid entry: group does not exist for LAG action");
return -ENOENT;
}

return 0;
}

void nfp_flower_lag_get_info_from_netdev(struct nfp_app *app,
struct net_device *netdev,
struct nfp_tun_neigh_lag *lag)
{
nfp_fl_lag_get_group_info(app, netdev, NULL,
lag->lag_version, &lag->lag_instance);
}

int nfp_flower_lag_get_output_id(struct nfp_app *app, struct net_device *master)
{
struct nfp_flower_priv *priv = app->priv;
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/netronome/nfp/flower/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ nfp_flower_get_internal_port_id(struct nfp_app *app, struct net_device *netdev)
u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app,
struct net_device *netdev)
{
struct nfp_flower_priv *priv = app->priv;
int ext_port;
int gid;

if (nfp_netdev_is_nfp_repr(netdev)) {
return nfp_repr_get_port_id(netdev);
Expand All @@ -86,6 +88,13 @@ u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app,
return 0;

return nfp_flower_internal_port_get_port_id(ext_port);
} else if (netif_is_lag_master(netdev) &&
priv->flower_ext_feats & NFP_FL_FEATS_TUNNEL_NEIGH_LAG) {
gid = nfp_flower_lag_get_output_id(app, netdev);
if (gid < 0)
return 0;

return (NFP_FL_LAG_OUT | gid);
}

return 0;
Expand Down
21 changes: 20 additions & 1 deletion drivers/net/ethernet/netronome/nfp/flower/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct nfp_app;
#define NFP_FL_FEATS_QOS_PPS BIT(9)
#define NFP_FL_FEATS_QOS_METER BIT(10)
#define NFP_FL_FEATS_DECAP_V2 BIT(11)
#define NFP_FL_FEATS_TUNNEL_NEIGH_LAG BIT(12)
#define NFP_FL_FEATS_HOST_ACK BIT(31)

#define NFP_FL_ENABLE_FLOW_MERGE BIT(0)
Expand All @@ -69,7 +70,8 @@ struct nfp_app;
NFP_FL_FEATS_VLAN_QINQ | \
NFP_FL_FEATS_QOS_PPS | \
NFP_FL_FEATS_QOS_METER | \
NFP_FL_FEATS_DECAP_V2)
NFP_FL_FEATS_DECAP_V2 | \
NFP_FL_FEATS_TUNNEL_NEIGH_LAG)

struct nfp_fl_mask_id {
struct circ_buf mask_id_free_list;
Expand Down Expand Up @@ -103,6 +105,16 @@ struct nfp_fl_tunnel_offloads {
struct notifier_block neigh_nb;
};

/**
* struct nfp_tun_neigh_lag - lag info
* @lag_version: lag version
* @lag_instance: lag instance
*/
struct nfp_tun_neigh_lag {
u8 lag_version[3];
u8 lag_instance;
};

/**
* struct nfp_tun_neigh - basic neighbour data
* @dst_addr: Destination MAC address
Expand Down Expand Up @@ -133,12 +145,14 @@ struct nfp_tun_neigh_ext {
* @src_ipv4: Source IPv4 address
* @common: Neighbour/route common info
* @ext: Neighbour/route extended info
* @lag: lag port info
*/
struct nfp_tun_neigh_v4 {
__be32 dst_ipv4;
__be32 src_ipv4;
struct nfp_tun_neigh common;
struct nfp_tun_neigh_ext ext;
struct nfp_tun_neigh_lag lag;
};

/**
Expand All @@ -147,12 +161,14 @@ struct nfp_tun_neigh_v4 {
* @src_ipv6: Source IPv6 address
* @common: Neighbour/route common info
* @ext: Neighbour/route extended info
* @lag: lag port info
*/
struct nfp_tun_neigh_v6 {
struct in6_addr dst_ipv6;
struct in6_addr src_ipv6;
struct nfp_tun_neigh common;
struct nfp_tun_neigh_ext ext;
struct nfp_tun_neigh_lag lag;
};

/**
Expand Down Expand Up @@ -647,6 +663,9 @@ int nfp_flower_lag_populate_pre_action(struct nfp_app *app,
struct netlink_ext_ack *extack);
int nfp_flower_lag_get_output_id(struct nfp_app *app,
struct net_device *master);
void nfp_flower_lag_get_info_from_netdev(struct nfp_app *app,
struct net_device *netdev,
struct nfp_tun_neigh_lag *lag);
void nfp_flower_qos_init(struct nfp_app *app);
void nfp_flower_qos_cleanup(struct nfp_app *app);
int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev,
Expand Down
53 changes: 44 additions & 9 deletions drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata,
mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6))
plen -= sizeof(struct nfp_tun_neigh_ext);

if (!(priv->flower_ext_feats & NFP_FL_FEATS_TUNNEL_NEIGH_LAG) &&
(mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH ||
mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6))
plen -= sizeof(struct nfp_tun_neigh_lag);

skb = nfp_flower_cmsg_alloc(app, plen, mtype, flag);
if (!skb)
return -ENOMEM;
Expand Down Expand Up @@ -468,6 +473,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
neigh_table_params);
if (!nn_entry && !neigh_invalid) {
struct nfp_tun_neigh_ext *ext;
struct nfp_tun_neigh_lag *lag;
struct nfp_tun_neigh *common;

nn_entry = kzalloc(sizeof(*nn_entry) + neigh_size,
Expand All @@ -488,6 +494,7 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
payload->dst_ipv6 = flowi6->daddr;
common = &payload->common;
ext = &payload->ext;
lag = &payload->lag;
mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6;
} else {
struct flowi4 *flowi4 = (struct flowi4 *)flow;
Expand All @@ -498,13 +505,17 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
payload->dst_ipv4 = flowi4->daddr;
common = &payload->common;
ext = &payload->ext;
lag = &payload->lag;
mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
}
ext->host_ctx = cpu_to_be32(U32_MAX);
ext->vlan_tpid = cpu_to_be16(U16_MAX);
ext->vlan_tci = cpu_to_be16(U16_MAX);
ether_addr_copy(common->src_addr, netdev->dev_addr);
neigh_ha_snapshot(common->dst_addr, neigh, netdev);

if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT)
nfp_flower_lag_get_info_from_netdev(app, netdev, lag);
common->port_id = cpu_to_be32(port_id);

if (rhashtable_insert_fast(&priv->neigh_table,
Expand Down Expand Up @@ -547,13 +558,38 @@ nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
if (nn_entry->flow)
list_del(&nn_entry->list_head);
kfree(nn_entry);
} else if (nn_entry && !neigh_invalid && override) {
mtype = is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 :
NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
nfp_tun_link_predt_entries(app, nn_entry);
nfp_flower_xmit_tun_conf(app, mtype, neigh_size,
nn_entry->payload,
GFP_ATOMIC);
} else if (nn_entry && !neigh_invalid) {
struct nfp_tun_neigh *common;
u8 dst_addr[ETH_ALEN];
bool is_mac_change;

if (is_ipv6) {
struct nfp_tun_neigh_v6 *payload;

payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload;
common = &payload->common;
mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6;
} else {
struct nfp_tun_neigh_v4 *payload;

payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload;
common = &payload->common;
mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
}

ether_addr_copy(dst_addr, common->dst_addr);
neigh_ha_snapshot(common->dst_addr, neigh, netdev);
is_mac_change = !ether_addr_equal(dst_addr, common->dst_addr);
if (override || is_mac_change) {
if (is_mac_change && nn_entry->flow) {
list_del(&nn_entry->list_head);
nn_entry->flow = NULL;
}
nfp_tun_link_predt_entries(app, nn_entry);
nfp_flower_xmit_tun_conf(app, mtype, neigh_size,
nn_entry->payload,
GFP_ATOMIC);
}
}

spin_unlock_bh(&priv->predt_lock);
Expand Down Expand Up @@ -593,8 +629,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
app = app_priv->app;

if (!nfp_netdev_is_nfp_repr(n->dev) &&
!nfp_flower_internal_port_can_offload(app, n->dev))
if (!nfp_flower_get_port_id_from_netdev(app, n->dev))
return NOTIFY_DONE;

#if IS_ENABLED(CONFIG_INET)
Expand Down

0 comments on commit abc2109

Please sign in to comment.