Skip to content

Commit 4d12ba4

Browse files
jahurleydavem330
authored andcommitted
nfp: flower: allow offloading of matches on 'internal' ports
Recent FW modifications allow the offloading of non repr ports. These ports exist internally on the NFP. So if a rule outputs to an 'internal' port, then the packet will recirculate back into the system but will now have this internal port as it's incoming port. These ports are indicated by a specific type field combined with an 8 bit port id. Add private app data to assign additional port ids for use in offloads. Provide functions to lookup or create new ids when a rule attempts to match on an internal netdev - the only internal netdevs currently supported are of type openvswitch. Have a netdev notifier to release port ids on netdev unregister. OvS offloads rules that match on internal ports as TC egress filters. Ensure that such rules are accepted by the driver. Signed-off-by: John Hurley <[email protected]> Signed-off-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2f2622f commit 4d12ba4

File tree

5 files changed

+153
-9
lines changed

5 files changed

+153
-9
lines changed

drivers/net/ethernet/netronome/nfp/flower/cmsg.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,13 @@ enum nfp_flower_cmsg_port_vnic_type {
474474
#define NFP_FLOWER_CMSG_PORT_PCIE_Q GENMASK(5, 0)
475475
#define NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM GENMASK(7, 0)
476476

477+
static inline u32 nfp_flower_internal_port_get_port_id(u8 internal_port)
478+
{
479+
return FIELD_PREP(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM, internal_port) |
480+
FIELD_PREP(NFP_FLOWER_CMSG_PORT_TYPE,
481+
NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT);
482+
}
483+
477484
static inline u32 nfp_flower_cmsg_phys_port(u8 phys_port)
478485
{
479486
return FIELD_PREP(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM, phys_port) |

drivers/net/ethernet/netronome/nfp/flower/main.c

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
#define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
2424

25+
#define NFP_MIN_INT_PORT_ID 1
26+
#define NFP_MAX_INT_PORT_ID 256
27+
2528
static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
2629
{
2730
return "FLOWER";
@@ -32,6 +35,100 @@ static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
3235
return DEVLINK_ESWITCH_MODE_SWITCHDEV;
3336
}
3437

38+
static int
39+
nfp_flower_lookup_internal_port_id(struct nfp_flower_priv *priv,
40+
struct net_device *netdev)
41+
{
42+
struct net_device *entry;
43+
int i, id = 0;
44+
45+
rcu_read_lock();
46+
idr_for_each_entry(&priv->internal_ports.port_ids, entry, i)
47+
if (entry == netdev) {
48+
id = i;
49+
break;
50+
}
51+
rcu_read_unlock();
52+
53+
return id;
54+
}
55+
56+
static int
57+
nfp_flower_get_internal_port_id(struct nfp_app *app, struct net_device *netdev)
58+
{
59+
struct nfp_flower_priv *priv = app->priv;
60+
int id;
61+
62+
id = nfp_flower_lookup_internal_port_id(priv, netdev);
63+
if (id > 0)
64+
return id;
65+
66+
idr_preload(GFP_ATOMIC);
67+
spin_lock_bh(&priv->internal_ports.lock);
68+
id = idr_alloc(&priv->internal_ports.port_ids, netdev,
69+
NFP_MIN_INT_PORT_ID, NFP_MAX_INT_PORT_ID, GFP_ATOMIC);
70+
spin_unlock_bh(&priv->internal_ports.lock);
71+
idr_preload_end();
72+
73+
return id;
74+
}
75+
76+
u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app,
77+
struct net_device *netdev)
78+
{
79+
int ext_port;
80+
81+
if (nfp_netdev_is_nfp_repr(netdev)) {
82+
return nfp_repr_get_port_id(netdev);
83+
} else if (nfp_flower_internal_port_can_offload(app, netdev)) {
84+
ext_port = nfp_flower_get_internal_port_id(app, netdev);
85+
if (ext_port < 0)
86+
return 0;
87+
88+
return nfp_flower_internal_port_get_port_id(ext_port);
89+
}
90+
91+
return 0;
92+
}
93+
94+
static void
95+
nfp_flower_free_internal_port_id(struct nfp_app *app, struct net_device *netdev)
96+
{
97+
struct nfp_flower_priv *priv = app->priv;
98+
int id;
99+
100+
id = nfp_flower_lookup_internal_port_id(priv, netdev);
101+
if (!id)
102+
return;
103+
104+
spin_lock_bh(&priv->internal_ports.lock);
105+
idr_remove(&priv->internal_ports.port_ids, id);
106+
spin_unlock_bh(&priv->internal_ports.lock);
107+
}
108+
109+
static int
110+
nfp_flower_internal_port_event_handler(struct nfp_app *app,
111+
struct net_device *netdev,
112+
unsigned long event)
113+
{
114+
if (event == NETDEV_UNREGISTER &&
115+
nfp_flower_internal_port_can_offload(app, netdev))
116+
nfp_flower_free_internal_port_id(app, netdev);
117+
118+
return NOTIFY_OK;
119+
}
120+
121+
static void nfp_flower_internal_port_init(struct nfp_flower_priv *priv)
122+
{
123+
spin_lock_init(&priv->internal_ports.lock);
124+
idr_init(&priv->internal_ports.port_ids);
125+
}
126+
127+
static void nfp_flower_internal_port_cleanup(struct nfp_flower_priv *priv)
128+
{
129+
idr_destroy(&priv->internal_ports.port_ids);
130+
}
131+
35132
static struct nfp_flower_non_repr_priv *
36133
nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev)
37134
{
@@ -645,12 +742,14 @@ static int nfp_flower_init(struct nfp_app *app)
645742
/* Tell the firmware that the driver supports flow merging. */
646743
err = nfp_rtsym_write_le(app->pf->rtbl,
647744
"_abi_flower_merge_hint_enable", 1);
648-
if (!err)
745+
if (!err) {
649746
app_priv->flower_ext_feats |= NFP_FL_FEATS_FLOW_MERGE;
650-
else if (err == -ENOENT)
747+
nfp_flower_internal_port_init(app_priv);
748+
} else if (err == -ENOENT) {
651749
nfp_warn(app->cpp, "Flow merge not supported by FW.\n");
652-
else
750+
} else {
653751
goto err_lag_clean;
752+
}
654753
} else {
655754
nfp_warn(app->cpp, "Flow mod/merge not supported by FW.\n");
656755
}
@@ -681,6 +780,9 @@ static void nfp_flower_clean(struct nfp_app *app)
681780
if (app_priv->flower_ext_feats & NFP_FL_FEATS_LAG)
682781
nfp_flower_lag_cleanup(&app_priv->nfp_lag);
683782

783+
if (app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE)
784+
nfp_flower_internal_port_cleanup(app_priv);
785+
684786
nfp_flower_metadata_cleanup(app);
685787
vfree(app->priv);
686788
app->priv = NULL;
@@ -779,6 +881,10 @@ nfp_flower_netdev_event(struct nfp_app *app, struct net_device *netdev,
779881
if (ret & NOTIFY_STOP_MASK)
780882
return ret;
781883

884+
ret = nfp_flower_internal_port_event_handler(app, netdev, event);
885+
if (ret & NOTIFY_STOP_MASK)
886+
return ret;
887+
782888
return nfp_tunnel_mac_event_handler(app, netdev, event, ptr);
783889
}
784890

drivers/net/ethernet/netronome/nfp/flower/main.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,16 @@ struct nfp_fl_lag {
116116
struct sk_buff_head retrans_skbs;
117117
};
118118

119+
/**
120+
* struct nfp_fl_internal_ports - Flower APP priv data for additional ports
121+
* @port_ids: Assignment of ids to any additional ports
122+
* @lock: Lock for extra ports list
123+
*/
124+
struct nfp_fl_internal_ports {
125+
struct idr port_ids;
126+
spinlock_t lock;
127+
};
128+
119129
/**
120130
* struct nfp_flower_priv - Flower APP per-vNIC priv data
121131
* @app: Back pointer to app
@@ -145,6 +155,7 @@ struct nfp_fl_lag {
145155
* @non_repr_priv: List of offloaded non-repr ports and their priv data
146156
* @active_mem_unit: Current active memory unit for flower rules
147157
* @total_mem_units: Total number of available memory units for flower rules
158+
* @internal_ports: Internal port ids used in offloaded rules
148159
*/
149160
struct nfp_flower_priv {
150161
struct nfp_app *app;
@@ -171,6 +182,7 @@ struct nfp_flower_priv {
171182
struct list_head non_repr_priv;
172183
unsigned int active_mem_unit;
173184
unsigned int total_mem_units;
185+
struct nfp_fl_internal_ports internal_ports;
174186
};
175187

176188
/**
@@ -249,6 +261,22 @@ struct nfp_fl_stats_frame {
249261
__be64 stats_cookie;
250262
};
251263

264+
static inline bool
265+
nfp_flower_internal_port_can_offload(struct nfp_app *app,
266+
struct net_device *netdev)
267+
{
268+
struct nfp_flower_priv *app_priv = app->priv;
269+
270+
if (!(app_priv->flower_ext_feats & NFP_FL_FEATS_FLOW_MERGE))
271+
return false;
272+
if (!netdev->rtnl_link_ops)
273+
return false;
274+
if (!strcmp(netdev->rtnl_link_ops->kind, "openvswitch"))
275+
return true;
276+
277+
return false;
278+
}
279+
252280
int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
253281
unsigned int host_ctx_split);
254282
void nfp_flower_metadata_cleanup(struct nfp_app *app);
@@ -313,4 +341,6 @@ void
313341
__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv);
314342
void
315343
nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev);
344+
u32 nfp_flower_get_port_id_from_netdev(struct nfp_app *app,
345+
struct net_device *netdev);
316346
#endif

drivers/net/ethernet/netronome/nfp/flower/match.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,13 +326,12 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
326326
struct nfp_fl_payload *nfp_flow,
327327
enum nfp_flower_tun_type tun_type)
328328
{
329-
u32 cmsg_port = 0;
329+
u32 port_id;
330330
int err;
331331
u8 *ext;
332332
u8 *msk;
333333

334-
if (nfp_netdev_is_nfp_repr(netdev))
335-
cmsg_port = nfp_repr_get_port_id(netdev);
334+
port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
336335

337336
memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
338337
memset(nfp_flow->mask_data, 0, key_ls->key_size);
@@ -358,13 +357,13 @@ int nfp_flower_compile_flow_match(struct nfp_app *app,
358357

359358
/* Populate Exact Port data. */
360359
err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
361-
cmsg_port, false, tun_type);
360+
port_id, false, tun_type);
362361
if (err)
363362
return err;
364363

365364
/* Populate Mask Port Data. */
366365
err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
367-
cmsg_port, true, tun_type);
366+
port_id, true, tun_type);
368367
if (err)
369368
return err;
370369

drivers/net/ethernet/netronome/nfp/flower/offload.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,9 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
682682
struct nfp_flower_priv *priv = app->priv;
683683
int err;
684684

685-
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
685+
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
686+
!(f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
687+
nfp_flower_internal_port_can_offload(app, netdev)))
686688
return -EOPNOTSUPP;
687689

688690
switch (f->command) {

0 commit comments

Comments
 (0)