|
@@ -131,7 +131,8 @@ static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f)
|
|
|
|
|
|
static int
|
|
|
nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
|
|
|
- struct tc_cls_flower_offload *flow)
|
|
|
+ struct tc_cls_flower_offload *flow,
|
|
|
+ bool egress)
|
|
|
{
|
|
|
struct flow_dissector_key_basic *mask_basic = NULL;
|
|
|
struct flow_dissector_key_basic *key_basic = NULL;
|
|
@@ -167,6 +168,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
|
|
|
skb_flow_dissector_target(flow->dissector,
|
|
|
FLOW_DISSECTOR_KEY_ENC_CONTROL,
|
|
|
flow->key);
|
|
|
+ if (!egress)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
if (mask_enc_ctl->addr_type != 0xffff ||
|
|
|
enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS)
|
|
|
return -EOPNOTSUPP;
|
|
@@ -194,6 +198,9 @@ nfp_flower_calculate_key_layers(struct nfp_fl_key_ls *ret_key_ls,
|
|
|
|
|
|
key_layer |= NFP_FLOWER_LAYER_VXLAN;
|
|
|
key_size += sizeof(struct nfp_flower_vxlan);
|
|
|
+ } else if (egress) {
|
|
|
+ /* Reject non tunnel matches offloaded to egress repr. */
|
|
|
+ return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
|
@@ -315,7 +322,7 @@ err_free_flow:
|
|
|
*/
|
|
|
static int
|
|
|
nfp_flower_add_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_flower_priv *priv = app->priv;
|
|
|
struct nfp_fl_payload *flow_pay;
|
|
@@ -326,7 +333,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
if (!key_layer)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- err = nfp_flower_calculate_key_layers(key_layer, flow);
|
|
|
+ err = nfp_flower_calculate_key_layers(key_layer, flow, egress);
|
|
|
if (err)
|
|
|
goto err_free_key_ls;
|
|
|
|
|
@@ -447,7 +454,7 @@ nfp_flower_get_stats(struct nfp_app *app, struct tc_cls_flower_offload *flow)
|
|
|
|
|
|
static int
|
|
|
nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
- struct tc_cls_flower_offload *flower)
|
|
|
+ struct tc_cls_flower_offload *flower, bool egress)
|
|
|
{
|
|
|
if (!eth_proto_is_802_3(flower->common.protocol) ||
|
|
|
flower->common.chain_index)
|
|
@@ -455,7 +462,7 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
|
|
|
switch (flower->command) {
|
|
|
case TC_CLSFLOWER_REPLACE:
|
|
|
- return nfp_flower_add_offload(app, netdev, flower);
|
|
|
+ return nfp_flower_add_offload(app, netdev, flower, egress);
|
|
|
case TC_CLSFLOWER_DESTROY:
|
|
|
return nfp_flower_del_offload(app, netdev, flower);
|
|
|
case TC_CLSFLOWER_STATS:
|
|
@@ -465,6 +472,23 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
+int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
|
|
|
+ void *cb_priv)
|
|
|
+{
|
|
|
+ struct nfp_repr *repr = cb_priv;
|
|
|
+
|
|
|
+ if (!tc_can_offload(repr->netdev))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case TC_SETUP_CLSFLOWER:
|
|
|
+ return nfp_flower_repr_offload(repr->app, repr->netdev,
|
|
|
+ type_data, true);
|
|
|
+ default:
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
|
|
|
void *type_data, void *cb_priv)
|
|
|
{
|
|
@@ -476,7 +500,7 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
|
|
|
switch (type) {
|
|
|
case TC_SETUP_CLSFLOWER:
|
|
|
return nfp_flower_repr_offload(repr->app, repr->netdev,
|
|
|
- type_data);
|
|
|
+ type_data, false);
|
|
|
default:
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|