Commit 7e5e7d80 authored by Edward Cree's avatar Edward Cree Committed by Jakub Kicinski
Browse files

sfc: neighbour lookup for TC encap action offload



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: default avatarEdward Cree <ecree.xilinx@gmail.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Reviewed-by: default avatarPieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f1363154
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -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)
@@ -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;
@@ -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);
@@ -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:
+3 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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
@@ -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;
+8 −4
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ 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 efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx,
					 struct net_device *dev)
{
	struct efx_rep *efv;
@@ -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;

@@ -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);
}

@@ -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);
@@ -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 */
+7 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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;
@@ -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);
+13 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
}
Loading