Skip to content

Commit e37f3b1

Browse files
Edward Creekuba-moo
authored andcommitted
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: Edward Cree <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 77eb407 commit e37f3b1

File tree

7 files changed

+158
-3
lines changed

7 files changed

+158
-3
lines changed

drivers/net/ethernet/sfc/ef100_nic.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "ef100_tx.h"
2525
#include "ef100_sriov.h"
2626
#include "ef100_netdev.h"
27+
#include "tc.h"
2728
#include "mae.h"
2829
#include "rx_common.h"
2930

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

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

397409
static void ef100_filter_table_down(struct efx_nic *efx)
398410
{
411+
#ifdef CONFIG_SFC_SRIOV
412+
efx_tc_remove_rep_filters(efx);
413+
#endif
399414
down_write(&efx->filter_sem);
400415
efx_mcdi_filter_del_vlan(efx, 0);
401416
efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);

drivers/net/ethernet/sfc/filter.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,15 @@ enum efx_filter_priority {
8888
* the automatic filter in its place.
8989
* @EFX_FILTER_FLAG_RX: Filter is for RX
9090
* @EFX_FILTER_FLAG_TX: Filter is for TX
91+
* @EFX_FILTER_FLAG_VPORT_ID: Virtual port ID for adapter switching.
9192
*/
9293
enum efx_filter_flags {
9394
EFX_FILTER_FLAG_RX_RSS = 0x01,
9495
EFX_FILTER_FLAG_RX_SCATTER = 0x02,
9596
EFX_FILTER_FLAG_RX_OVER_AUTO = 0x04,
9697
EFX_FILTER_FLAG_RX = 0x08,
9798
EFX_FILTER_FLAG_TX = 0x10,
99+
EFX_FILTER_FLAG_VPORT_ID = 0x20,
98100
};
99101

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

301+
/**
302+
* efx_filter_set_vport_id - override virtual port id relating to filter
303+
* @spec: Specification to initialise
304+
* @vport_id: firmware ID of the virtual port
305+
*/
306+
static inline void efx_filter_set_vport_id(struct efx_filter_spec *spec,
307+
u32 vport_id)
308+
{
309+
spec->flags |= EFX_FILTER_FLAG_VPORT_ID;
310+
spec->vport_id = vport_id;
311+
}
312+
295313
static inline void efx_filter_set_encap_type(struct efx_filter_spec *spec,
296314
enum efx_encap_type encap_type)
297315
{

drivers/net/ethernet/sfc/mae.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,43 @@
1313
#include "mcdi.h"
1414
#include "mcdi_pcol_mae.h"
1515

16+
int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label)
17+
{
18+
MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
19+
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN);
20+
size_t outlen;
21+
int rc;
22+
23+
if (WARN_ON_ONCE(!id))
24+
return -EINVAL;
25+
if (WARN_ON_ONCE(!label))
26+
return -EINVAL;
27+
28+
MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_TYPE,
29+
MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_MPORT_TYPE_ALIAS);
30+
MCDI_SET_DWORD(inbuf, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
31+
MAE_MPORT_SELECTOR_ASSIGNED);
32+
rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_ALLOC, inbuf, sizeof(inbuf),
33+
outbuf, sizeof(outbuf), &outlen);
34+
if (rc)
35+
return rc;
36+
if (outlen < sizeof(outbuf))
37+
return -EIO;
38+
*id = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_MPORT_ID);
39+
*label = MCDI_DWORD(outbuf, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
40+
return 0;
41+
}
42+
43+
int efx_mae_free_mport(struct efx_nic *efx, u32 id)
44+
{
45+
MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MPORT_FREE_IN_LEN);
46+
47+
BUILD_BUG_ON(MC_CMD_MAE_MPORT_FREE_OUT_LEN);
48+
MCDI_SET_DWORD(inbuf, MAE_MPORT_FREE_IN_MPORT_ID, id);
49+
return efx_mcdi_rpc(efx, MC_CMD_MAE_MPORT_FREE, inbuf, sizeof(inbuf),
50+
NULL, 0, NULL);
51+
}
52+
1653
void efx_mae_mport_wire(struct efx_nic *efx, u32 *out)
1754
{
1855
efx_dword_t mport;

drivers/net/ethernet/sfc/mae.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "tc.h"
1818
#include "mcdi_pcol.h" /* needed for various MC_CMD_MAE_*_NULL defines */
1919

20+
int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label);
21+
int efx_mae_free_mport(struct efx_nic *efx, u32 id);
22+
2023
void efx_mae_mport_wire(struct efx_nic *efx, u32 *out);
2124
void efx_mae_mport_uplink(struct efx_nic *efx, u32 *out);
2225
void efx_mae_mport_vf(struct efx_nic *efx, u32 vf_id, u32 *out);

drivers/net/ethernet/sfc/mcdi_filters.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,10 @@ static void efx_mcdi_filter_push_prep(struct efx_nic *efx,
221221
efx_mcdi_filter_push_prep_set_match_fields(efx, spec, inbuf);
222222
}
223223

224-
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, efx->vport_id);
224+
if (flags & EFX_FILTER_FLAG_VPORT_ID)
225+
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, spec->vport_id);
226+
else
227+
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_PORT_ID, efx->vport_id);
225228
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_RX_DEST,
226229
spec->dmaq_id == EFX_FILTER_RX_DMAQ_ID_DROP ?
227230
MC_CMD_FILTER_OP_IN_RX_DEST_DROP :
@@ -488,6 +491,7 @@ static s32 efx_mcdi_filter_insert_locked(struct efx_nic *efx,
488491
saved_spec->flags |= spec->flags;
489492
saved_spec->rss_context = spec->rss_context;
490493
saved_spec->dmaq_id = spec->dmaq_id;
494+
saved_spec->vport_id = spec->vport_id;
491495
}
492496
} else if (!replacing) {
493497
kfree(saved_spec);

drivers/net/ethernet/sfc/tc.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "tc.h"
1313
#include "mae.h"
1414
#include "ef100_rep.h"
15+
#include "efx.h"
1516

1617
static void efx_tc_free_action_set(struct efx_nic *efx,
1718
struct efx_tc_action_set *act, bool in_hw)
@@ -122,7 +123,7 @@ int efx_tc_configure_default_rule_rep(struct efx_rep *efv)
122123
u32 ing_port, eg_port;
123124

124125
efx_mae_mport_mport(efx, efv->mport, &ing_port);
125-
efx_mae_mport_uplink(efx, &eg_port);
126+
efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port);
126127
return efx_tc_configure_default_rule(efx, ing_port, eg_port, rule);
127128
}
128129

@@ -134,21 +135,87 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
134135
rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
135136
}
136137

138+
static int efx_tc_configure_rep_mport(struct efx_nic *efx)
139+
{
140+
u32 rep_mport_label;
141+
int rc;
142+
143+
rc = efx_mae_allocate_mport(efx, &efx->tc->reps_mport_id, &rep_mport_label);
144+
if (rc)
145+
return rc;
146+
pci_dbg(efx->pci_dev, "created rep mport 0x%08x (0x%04x)\n",
147+
efx->tc->reps_mport_id, rep_mport_label);
148+
/* Use mport *selector* as vport ID */
149+
efx_mae_mport_mport(efx, efx->tc->reps_mport_id,
150+
&efx->tc->reps_mport_vport_id);
151+
return 0;
152+
}
153+
154+
static void efx_tc_deconfigure_rep_mport(struct efx_nic *efx)
155+
{
156+
efx_mae_free_mport(efx, efx->tc->reps_mport_id);
157+
efx->tc->reps_mport_id = MAE_MPORT_SELECTOR_NULL;
158+
}
159+
160+
int efx_tc_insert_rep_filters(struct efx_nic *efx)
161+
{
162+
struct efx_filter_spec promisc, allmulti;
163+
int rc;
164+
165+
if (efx->type->is_vf)
166+
return 0;
167+
if (!efx->tc)
168+
return 0;
169+
efx_filter_init_rx(&promisc, EFX_FILTER_PRI_REQUIRED, 0, 0);
170+
efx_filter_set_uc_def(&promisc);
171+
efx_filter_set_vport_id(&promisc, efx->tc->reps_mport_vport_id);
172+
rc = efx_filter_insert_filter(efx, &promisc, false);
173+
if (rc < 0)
174+
return rc;
175+
efx->tc->reps_filter_uc = rc;
176+
efx_filter_init_rx(&allmulti, EFX_FILTER_PRI_REQUIRED, 0, 0);
177+
efx_filter_set_mc_def(&allmulti);
178+
efx_filter_set_vport_id(&allmulti, efx->tc->reps_mport_vport_id);
179+
rc = efx_filter_insert_filter(efx, &allmulti, false);
180+
if (rc < 0)
181+
return rc;
182+
efx->tc->reps_filter_mc = rc;
183+
return 0;
184+
}
185+
186+
void efx_tc_remove_rep_filters(struct efx_nic *efx)
187+
{
188+
if (efx->type->is_vf)
189+
return;
190+
if (!efx->tc)
191+
return;
192+
if (efx->tc->reps_filter_mc >= 0)
193+
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx->tc->reps_filter_mc);
194+
efx->tc->reps_filter_mc = -1;
195+
if (efx->tc->reps_filter_uc >= 0)
196+
efx_filter_remove_id_safe(efx, EFX_FILTER_PRI_REQUIRED, efx->tc->reps_filter_uc);
197+
efx->tc->reps_filter_uc = -1;
198+
}
199+
137200
int efx_init_tc(struct efx_nic *efx)
138201
{
139202
int rc;
140203

141204
rc = efx_tc_configure_default_rule_pf(efx);
142205
if (rc)
143206
return rc;
144-
return efx_tc_configure_default_rule_wire(efx);
207+
rc = efx_tc_configure_default_rule_wire(efx);
208+
if (rc)
209+
return rc;
210+
return efx_tc_configure_rep_mport(efx);
145211
}
146212

147213
void efx_fini_tc(struct efx_nic *efx)
148214
{
149215
/* We can get called even if efx_init_struct_tc() failed */
150216
if (!efx->tc)
151217
return;
218+
efx_tc_deconfigure_rep_mport(efx);
152219
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
153220
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
154221
}
@@ -162,6 +229,8 @@ int efx_init_struct_tc(struct efx_nic *efx)
162229
if (!efx->tc)
163230
return -ENOMEM;
164231

232+
efx->tc->reps_filter_uc = -1;
233+
efx->tc->reps_filter_mc = -1;
165234
INIT_LIST_HEAD(&efx->tc->dflt.pf.acts.list);
166235
efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
167236
INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list);

drivers/net/ethernet/sfc/tc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,18 @@ enum efx_tc_rule_prios {
4949
/**
5050
* struct efx_tc_state - control plane data for TC offload
5151
*
52+
* @reps_mport_id: MAE port allocated for representor RX
53+
* @reps_filter_uc: VNIC filter for representor unicast RX (promisc)
54+
* @reps_filter_mc: VNIC filter for representor multicast RX (allmulti)
55+
* @reps_mport_vport_id: vport_id for representor RX filters
5256
* @dflt: Match-action rules for default switching; at priority
5357
* %EFX_TC_PRIO_DFLT. Named by *ingress* port
5458
* @dflt.pf: rule for traffic ingressing from PF (egresses to wire)
5559
* @dflt.wire: rule for traffic ingressing from wire (egresses to PF)
5660
*/
5761
struct efx_tc_state {
62+
u32 reps_mport_id, reps_mport_vport_id;
63+
s32 reps_filter_uc, reps_filter_mc;
5864
struct {
5965
struct efx_tc_flow_rule pf;
6066
struct efx_tc_flow_rule wire;
@@ -67,6 +73,9 @@ int efx_tc_configure_default_rule_rep(struct efx_rep *efv);
6773
void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
6874
struct efx_tc_flow_rule *rule);
6975

76+
int efx_tc_insert_rep_filters(struct efx_nic *efx);
77+
void efx_tc_remove_rep_filters(struct efx_nic *efx);
78+
7079
int efx_init_tc(struct efx_nic *efx);
7180
void efx_fini_tc(struct efx_nic *efx);
7281

0 commit comments

Comments
 (0)