Skip to content

Commit

Permalink
sfc: neighbour lookup for TC encap action offload
Browse files Browse the repository at this point in the history
For each neighbour we're interested in, create a struct efx_neigh_binder
 object which has a list of all the encap_actions using it.  When we
 receive a neighbouring update (through the netevent notifier), find the
 corresponding efx_neigh_binder and update all its users.
Since the actual generation of encap headers is still only a stub, the
 resulting rules still get left on fallback actions.

Signed-off-by: Edward Cree <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
Reviewed-by: Pieter Jansen van Vuuren <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
Edward Cree authored and kuba-moo committed Jun 10, 2023
1 parent f136315 commit 7e5e7d8
Show file tree
Hide file tree
Showing 8 changed files with 569 additions and 6 deletions.
34 changes: 34 additions & 0 deletions drivers/net/ethernet/sfc/ef100_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "rx_common.h"
#include "ef100_sriov.h"
#include "tc_bindings.h"
#include "tc_encap_actions.h"
#include "efx_devlink.h"

static void ef100_update_name(struct efx_nic *efx)
Expand Down Expand Up @@ -300,14 +301,38 @@ int ef100_netdev_event(struct notifier_block *this,
{
struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier);
struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
struct ef100_nic_data *nic_data = efx->nic_data;
int err;

if (efx->net_dev == net_dev &&
(event == NETDEV_CHANGENAME || event == NETDEV_REGISTER))
ef100_update_name(efx);

if (!nic_data->grp_mae)
return NOTIFY_DONE;
err = efx_tc_netdev_event(efx, event, net_dev);
if (err & NOTIFY_STOP_MASK)
return err;

return NOTIFY_DONE;
}

static int ef100_netevent_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct efx_nic *efx = container_of(this, struct efx_nic, netevent_notifier);
struct ef100_nic_data *nic_data = efx->nic_data;
int err;

if (!nic_data->grp_mae)
return NOTIFY_DONE;
err = efx_tc_netevent_event(efx, event, ptr);
if (err & NOTIFY_STOP_MASK)
return err;

return NOTIFY_DONE;
};

static int ef100_register_netdev(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
Expand Down Expand Up @@ -367,6 +392,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data)
rtnl_unlock();

unregister_netdevice_notifier(&efx->netdev_notifier);
unregister_netevent_notifier(&efx->netevent_notifier);
#if defined(CONFIG_SFC_SRIOV)
if (!efx->type->is_vf)
efx_ef100_pci_sriov_disable(efx, true);
Expand Down Expand Up @@ -487,6 +513,14 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data)
goto fail;
}

efx->netevent_notifier.notifier_call = ef100_netevent_event;
rc = register_netevent_notifier(&efx->netevent_notifier);
if (rc) {
netif_err(efx, probe, efx->net_dev,
"Failed to register netevent notifier, rc=%d\n", rc);
goto fail;
}

efx_probe_devlink_unlock(efx);
return rc;
fail:
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/sfc/net_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/mtd/mtd.h>
#include <net/busy_poll.h>
#include <net/xdp.h>
#include <net/netevent.h>

#include "enum.h"
#include "bitfield.h"
Expand Down Expand Up @@ -996,6 +997,7 @@ struct efx_mae;
* @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their
* xdp_rxq_info structures?
* @netdev_notifier: Netdevice notifier.
* @netevent_notifier: Netevent notifier (for neighbour updates).
* @tc: state for TC offload (EF100).
* @devlink: reference to devlink structure owned by this device
* @dl_port: devlink port associated with the PF
Expand Down Expand Up @@ -1183,6 +1185,7 @@ struct efx_nic {
bool xdp_rxq_info_failed;

struct notifier_block netdev_notifier;
struct notifier_block netevent_notifier;
struct efx_tc_state *tc;

struct devlink *devlink;
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ethernet/sfc/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev)
* May return NULL for the PF (us), or an error pointer for a device that
* isn't supported as a TC offload endpoint
*/
static struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
struct net_device *dev)
struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
struct net_device *dev)
{
struct efx_rep *efv;

Expand Down Expand Up @@ -71,7 +71,7 @@ static s64 efx_tc_flower_internal_mport(struct efx_nic *efx, struct efx_rep *efv
}

/* Convert a driver-internal vport ID into an external device (wire or VF) */
static s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv)
{
u32 mport;

Expand Down Expand Up @@ -112,8 +112,10 @@ static void efx_tc_free_action_set(struct efx_nic *efx,
}
if (act->count)
efx_tc_flower_put_counter_index(efx, act->count);
if (act->encap_md)
if (act->encap_md) {
list_del(&act->encap_user);
efx_tc_flower_release_encap_md(efx, act->encap_md);
}
kfree(act);
}

Expand Down Expand Up @@ -1115,6 +1117,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
goto release;
}
act->encap_md = encap;
list_add_tail(&act->encap_user, &encap->users);
act->dest_mport = encap->dest_mport;
act->deliver = 1;
rc = efx_mae_alloc_action_set(efx, act);
Expand All @@ -1123,6 +1126,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx,
goto release;
}
list_add_tail(&act->list, &rule->acts.list);
act->user = &rule->acts;
act = NULL;
if (fa->id == FLOW_ACTION_REDIRECT)
break; /* end of the line */
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/ethernet/sfc/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ struct efx_tc_action_set {
__be16 vlan_proto[2]; /* Ethertypes for vlan_push */
struct efx_tc_counter_index *count;
struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */
struct list_head encap_user; /* entry on encap_md->users list */
struct efx_tc_action_set_list *user; /* Only populated if encap_md */
u32 dest_mport;
u32 fw_id; /* index of this entry in firmware actions table */
struct list_head list;
Expand Down Expand Up @@ -151,6 +153,7 @@ enum efx_tc_rule_prios {
* @encap_ht: Hashtable of TC encap actions
* @encap_match_ht: Hashtable of TC encap matches
* @match_action_ht: Hashtable of TC match-action rules
* @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder)
* @reps_mport_id: MAE port allocated for representor RX
* @reps_filter_uc: VNIC filter for representor unicast RX (promisc)
* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti)
Expand Down Expand Up @@ -181,6 +184,7 @@ struct efx_tc_state {
struct rhashtable encap_ht;
struct rhashtable encap_match_ht;
struct rhashtable match_action_ht;
struct rhashtable neigh_ht;
u32 reps_mport_id, reps_mport_vport_id;
s32 reps_filter_uc, reps_filter_mc;
bool flush_counters;
Expand All @@ -201,6 +205,9 @@ struct efx_tc_state {
struct efx_rep;

enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev);
struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
struct net_device *dev);
s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv);
int efx_tc_configure_default_rule_rep(struct efx_rep *efv);
void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
struct efx_tc_flow_rule *rule);
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/ethernet/sfc/tc_bindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "tc_bindings.h"
#include "tc.h"
#include "tc_encap_actions.h"

struct efx_tc_block_binding {
struct list_head list;
Expand Down Expand Up @@ -226,3 +227,15 @@ int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type,

return -EOPNOTSUPP;
}

int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
struct net_device *net_dev)
{
if (efx->type->is_vf)
return NOTIFY_DONE;

if (event == NETDEV_UNREGISTER)
efx_tc_unregister_egdev(efx, net_dev);

return NOTIFY_OK;
}
2 changes: 2 additions & 0 deletions drivers/net/ethernet/sfc/tc_bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch,
void *cb_priv, enum tc_setup_type type,
void *type_data, void *data,
void (*cleanup)(struct flow_block_cb *block_cb));
int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event,
struct net_device *net_dev);
#endif /* EFX_TC_BINDINGS_H */
Loading

0 comments on commit 7e5e7d8

Please sign in to comment.