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

sfc: use a dynamic m-port for representor RX and set it promisc



Representors do not want to be subject to the PF's Ethernet address
 filters, since traffic from VFs will typically have a destination
 either elsewhere on the link segment or on an overlay network.
So, create a dynamic m-port with promiscuous and all-multicast
 filters, and set it as the egress port of representor default rules.
 Since the m-port is an alias of the calling PF's own m-port, traffic
 will still be delivered to the PF's RXQs, but it will be subject to
 the VNRX filter rules installed on the dynamic m-port (specified by
 the v-port ID field of the filter spec).

Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 77eb4074
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "ef100_tx.h"
#include "ef100_sriov.h"
#include "ef100_netdev.h"
#include "tc.h"
#include "mae.h"
#include "rx_common.h"

@@ -383,7 +384,18 @@ static int ef100_filter_table_up(struct efx_nic *efx)
	rc = efx_mcdi_filter_add_vlan(efx, 0);
	if (rc)
		goto fail_vlan0;
	/* Drop the lock: we've finished altering table existence, and
	 * filter insertion will need to take the lock for read.
	 */
	up_write(&efx->filter_sem);
#ifdef CONFIG_SFC_SRIOV
	rc = efx_tc_insert_rep_filters(efx);
	/* Rep filter failure is nonfatal */
	if (rc)
		netif_warn(efx, drv, efx->net_dev,
			   "Failed to insert representor filters, rc %d\n",
			   rc);
#endif
	return 0;

fail_vlan0:
@@ -396,6 +408,9 @@ static int ef100_filter_table_up(struct efx_nic *efx)

static void ef100_filter_table_down(struct efx_nic *efx)
{
#ifdef CONFIG_SFC_SRIOV
	efx_tc_remove_rep_filters(efx);
#endif
	down_write(&efx->filter_sem);
	efx_mcdi_filter_del_vlan(efx, 0);
	efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);
+18 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ enum efx_filter_priority {
 *	the automatic filter in its place.
 * @EFX_FILTER_FLAG_RX: Filter is for RX
 * @EFX_FILTER_FLAG_TX: Filter is for TX
 * @EFX_FILTER_FLAG_VPORT_ID: Virtual port ID for adapter switching.
 */
enum efx_filter_flags {
	EFX_FILTER_FLAG_RX_RSS = 0x01,
@@ -95,6 +96,7 @@ enum efx_filter_flags {
	EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04,
	EFX_FILTER_FLAG_RX = 0x08,
	EFX_FILTER_FLAG_TX = 0x10,
	EFX_FILTER_FLAG_VPORT_ID = 0x20,
};

/** enum efx_encap_type - types of encapsulation
@@ -127,6 +129,9 @@ enum efx_encap_type {
 *	MCFW context_id.
 * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for
 *	an RX drop filter
 * @vport_id: Virtual port ID associated with RX queue, for adapter switching,
 *	if %EFX_FILTER_FLAG_VPORT_ID is set.  This is an MCFW vport_id, or on
 *	EF100 an mport selector.
 * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set
 * @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set
 * @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or
@@ -156,6 +161,7 @@ struct efx_filter_spec {
	u32	priority:2;
	u32	flags:6;
	u32	dmaq_id:12;
	u32	vport_id;
	u32	rss_context;
	__be16	outer_vid __aligned(4); /* allow jhash2() of match values */
	__be16	inner_vid;
@@ -292,6 +298,18 @@ static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec)
	return 0;
}

/**
 * efx_filter_set_vport_id - override virtual port id relating to filter
 * @spec: Specification to initialise
 * @vport_id: firmware ID of the virtual port
 */
static inline void efx_filter_set_vport_id(struct efx_filter_spec *spec,
					   u32 vport_id)
{
	spec->flags |= EFX_FILTER_FLAG_VPORT_ID;
	spec->vport_id = vport_id;
}

static inline void efx_filter_set_encap_type(struct efx_filter_spec *spec,
					     enum efx_encap_type encap_type)
{
+37 −0
Original line number Diff line number Diff line
@@ -13,6 +13,43 @@
#include "mcdi.h"
#include "mcdi_pcol_mae.h"

int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN);
	size_t outlen;
	int rc;

	if (WARN_ON_ONCE(!id))
		return -EINVAL;
	if (WARN_ON_ONCE(!label))
		return -EINVAL;

	MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_TYPE,
		       MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS);
	MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
		       MAE_MPORT_SELECTOR_ASSIGNED);
	rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_ALLOC, inbuf, sizeof(inbuf),
			  outbuf, sizeof(outbuf), &outlen);
	if (rc)
		return rc;
	if (outlen < sizeof(outbuf))
		return -EIO;
	*id = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID);
	*label = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
	return 0;
}

int efx_mae_free_mport(struct efx_nic *efx, u32 id)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_FREE_IN_LEN);

	BUILD_BUG_ON(MC_CMD_MAE_MPORT_FREE_OUT_LEN);
	MCDI_SET_DWORD(inbuf, MAE_MPORT_FREE_IN_MPORT_ID, id);
	return efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_FREE, inbuf, sizeof(inbuf),
			    NULL, 0, NULL);
}

void efx_mae_mport_wire(struct efx_nic *efx, u32 *out)
{
	efx_dword_t mport;
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,9 @@
#include "tc.h"
#include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */

int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label);
int efx_mae_free_mport(struct efx_nic *efx, u32 id);

void efx_mae_mport_wire(struct efx_nic *efx, u32 *out);
void efx_mae_mport_uplink(struct efx_nic *efx, u32 *out);
void efx_mae_mport_vf(struct efx_nic *efx, u32 vf_id, u32 *out);
+5 −1
Original line number Diff line number Diff line
@@ -221,6 +221,9 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
		efx_mcdi_filter_push_prep_set_match_fields(efx, spec, inbuf);
	}

	if (flags & EFX_FILTER_FLAG_VPORT_ID)
		MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, spec->vport_id);
	else
		MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, efx->vport_id);
	MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST,
		       spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ?
@@ -488,6 +491,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
			saved_spec->flags |= spec->flags;
			saved_spec->rss_context = spec->rss_context;
			saved_spec->dmaq_id = spec->dmaq_id;
			saved_spec->vport_id = spec->vport_id;
		}
	} else if (!replacing) {
		kfree(saved_spec);
Loading