|
@@ -345,7 +345,7 @@ nfp_flower_calculate_key_layers(struct nfp_app *app,
|
|
|
}
|
|
|
|
|
|
static struct nfp_fl_payload *
|
|
|
-nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
|
|
|
+nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer, bool egress)
|
|
|
{
|
|
|
struct nfp_fl_payload *flow_pay;
|
|
|
|
|
@@ -371,6 +371,8 @@ nfp_flower_allocate_new(struct nfp_fl_key_ls *key_layer)
|
|
|
flow_pay->meta.flags = 0;
|
|
|
spin_lock_init(&flow_pay->lock);
|
|
|
|
|
|
+ flow_pay->ingress_offload = !egress;
|
|
|
+
|
|
|
return flow_pay;
|
|
|
|
|
|
err_free_mask:
|
|
@@ -402,8 +404,20 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
struct nfp_flower_priv *priv = app->priv;
|
|
|
struct nfp_fl_payload *flow_pay;
|
|
|
struct nfp_fl_key_ls *key_layer;
|
|
|
+ struct net_device *ingr_dev;
|
|
|
int err;
|
|
|
|
|
|
+ ingr_dev = egress ? NULL : netdev;
|
|
|
+ flow_pay = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
|
|
|
+ NFP_FL_STATS_CTX_DONT_CARE);
|
|
|
+ if (flow_pay) {
|
|
|
+ /* Ignore as duplicate if it has been added by different cb. */
|
|
|
+ if (flow_pay->ingress_offload && egress)
|
|
|
+ return 0;
|
|
|
+ else
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
key_layer = kmalloc(sizeof(*key_layer), GFP_KERNEL);
|
|
|
if (!key_layer)
|
|
|
return -ENOMEM;
|
|
@@ -413,12 +427,14 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
if (err)
|
|
|
goto err_free_key_ls;
|
|
|
|
|
|
- flow_pay = nfp_flower_allocate_new(key_layer);
|
|
|
+ flow_pay = nfp_flower_allocate_new(key_layer, egress);
|
|
|
if (!flow_pay) {
|
|
|
err = -ENOMEM;
|
|
|
goto err_free_key_ls;
|
|
|
}
|
|
|
|
|
|
+ flow_pay->ingress_dev = egress ? NULL : netdev;
|
|
|
+
|
|
|
err = nfp_flower_compile_flow_match(flow, key_layer, netdev, flow_pay,
|
|
|
tun_type);
|
|
|
if (err)
|
|
@@ -428,7 +444,8 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
if (err)
|
|
|
goto err_destroy_flow;
|
|
|
|
|
|
- err = nfp_compile_flow_metadata(app, flow, flow_pay);
|
|
|
+ err = nfp_compile_flow_metadata(app, flow, flow_pay,
|
|
|
+ flow_pay->ingress_dev);
|
|
|
if (err)
|
|
|
goto err_destroy_flow;
|
|
|
|
|
@@ -462,6 +479,7 @@ err_free_key_ls:
|
|
|
* @app: Pointer to the APP handle
|
|
|
* @netdev: netdev structure.
|
|
|
* @flow: TC flower classifier offload structure
|
|
|
+ * @egress: Netdev is the egress dev.
|
|
|
*
|
|
|
* Removes a flow from the repeated hash structure and clears the
|
|
|
* action payload.
|
|
@@ -470,15 +488,18 @@ err_free_key_ls:
|
|
|
*/
|
|
|
static int
|
|
|
nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
- struct tc_cls_flower_offload *flow)
|
|
|
+ struct tc_cls_flower_offload *flow, bool egress)
|
|
|
{
|
|
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
|
|
struct nfp_fl_payload *nfp_flow;
|
|
|
+ struct net_device *ingr_dev;
|
|
|
int err;
|
|
|
|
|
|
- nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
|
|
|
+ ingr_dev = egress ? NULL : netdev;
|
|
|
+ nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
|
|
|
+ NFP_FL_STATS_CTX_DONT_CARE);
|
|
|
if (!nfp_flow)
|
|
|
- return -ENOENT;
|
|
|
+ return egress ? 0 : -ENOENT;
|
|
|
|
|
|
err = nfp_modify_flow_metadata(app, nfp_flow);
|
|
|
if (err)
|
|
@@ -505,7 +526,9 @@ err_free_flow:
|
|
|
/**
|
|
|
* nfp_flower_get_stats() - Populates flow stats obtained from hardware.
|
|
|
* @app: Pointer to the APP handle
|
|
|
+ * @netdev: Netdev structure.
|
|
|
* @flow: TC flower classifier offload structure
|
|
|
+ * @egress: Netdev is the egress dev.
|
|
|
*
|
|
|
* Populates a flow statistics structure which which corresponds to a
|
|
|
* specific flow.
|
|
@@ -513,14 +536,21 @@ err_free_flow:
|
|
|
* Return: negative value on error, 0 if stats populated successfully.
|
|
|
*/
|
|
|
static int
|
|
|
-nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
|
|
|
+nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev,
|
|
|
+ struct tc_cls_flower_offload *flow, bool egress)
|
|
|
{
|
|
|
struct nfp_fl_payload *nfp_flow;
|
|
|
+ struct net_device *ingr_dev;
|
|
|
|
|
|
- nfp_flow = nfp_flower_search_fl_table(app, flow->cookie);
|
|
|
+ ingr_dev = egress ? NULL : netdev;
|
|
|
+ nfp_flow = nfp_flower_search_fl_table(app, flow->cookie, ingr_dev,
|
|
|
+ NFP_FL_STATS_CTX_DONT_CARE);
|
|
|
if (!nfp_flow)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ if (nfp_flow->ingress_offload && egress)
|
|
|
+ return 0;
|
|
|
+
|
|
|
spin_lock_bh(&nfp_flow->lock);
|
|
|
tcf_exts_stats_update(flow->exts, nfp_flow->stats.bytes,
|
|
|
nfp_flow->stats.pkts, nfp_flow->stats.used);
|
|
@@ -543,9 +573,9 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
case TC_CLSFLOWER_REPLACE:
|
|
|
return nfp_flower_add_offload(app, netdev, flower, egress);
|
|
|
case TC_CLSFLOWER_DESTROY:
|
|
|
- return nfp_flower_del_offload(app, netdev, flower);
|
|
|
+ return nfp_flower_del_offload(app, netdev, flower, egress);
|
|
|
case TC_CLSFLOWER_STATS:
|
|
|
- return nfp_flower_get_stats(app, flower);
|
|
|
+ return nfp_flower_get_stats(app, netdev, flower, egress);
|
|
|
}
|
|
|
|
|
|
return -EOPNOTSUPP;
|