cxgb4: add ethtool n-tuple filter deletion

Add support to delete ethtool n-tuple filter. Fetch the appropriate
filter region (HPFILTER, HASH, NORMAL) in which the filter exists,
and delete it from the respective region, accordingly.

Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vishal Kulkarni 2020-06-19 19:51:37 +05:30 committed by David S. Miller
parent c8729cac2a
commit db43b30cd8
3 changed files with 84 additions and 9 deletions

View File

@ -1573,6 +1573,22 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
return -EPERM; return -EPERM;
} }
static struct filter_entry *cxgb4_get_filter_entry(struct adapter *adap,
u32 ftid)
{
struct tid_info *t = &adap->tids;
struct filter_entry *f;
if (ftid < t->nhpftids)
f = &adap->tids.hpftid_tab[ftid];
else if (ftid < t->nftids)
f = &adap->tids.ftid_tab[ftid - t->nhpftids];
else
f = lookup_tid(&adap->tids, ftid);
return f;
}
static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
u32 *rules) u32 *rules)
{ {
@ -1636,6 +1652,48 @@ static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static int cxgb4_ntuple_del_filter(struct net_device *dev,
struct ethtool_rxnfc *cmd)
{
struct cxgb4_ethtool_filter_info *filter_info;
struct adapter *adapter = netdev2adap(dev);
struct port_info *pi = netdev_priv(dev);
struct filter_entry *f;
u32 filter_id;
int ret;
if (!(adapter->flags & CXGB4_FULL_INIT_DONE))
return -EAGAIN; /* can still change nfilters */
if (!adapter->ethtool_filters)
return -EOPNOTSUPP;
if (cmd->fs.location >= adapter->ethtool_filters->nentries) {
dev_err(adapter->pdev_dev,
"Location must be < %u",
adapter->ethtool_filters->nentries);
return -ERANGE;
}
filter_info = &adapter->ethtool_filters->port[pi->port_id];
if (!test_bit(cmd->fs.location, filter_info->bmap))
return -ENOENT;
filter_id = filter_info->loc_array[cmd->fs.location];
f = cxgb4_get_filter_entry(adapter, filter_id);
ret = cxgb4_flow_rule_destroy(dev, f->fs.tc_prio, &f->fs, filter_id);
if (ret)
goto err;
clear_bit(cmd->fs.location, filter_info->bmap);
filter_info->in_use--;
err:
return ret;
}
/* Add Ethtool n-tuple filters. */ /* Add Ethtool n-tuple filters. */
static int cxgb4_ntuple_set_filter(struct net_device *netdev, static int cxgb4_ntuple_set_filter(struct net_device *netdev,
struct ethtool_rxnfc *cmd) struct ethtool_rxnfc *cmd)
@ -1702,6 +1760,9 @@ static int set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
case ETHTOOL_SRXCLSRLINS: case ETHTOOL_SRXCLSRLINS:
ret = cxgb4_ntuple_set_filter(dev, cmd); ret = cxgb4_ntuple_set_filter(dev, cmd);
break; break;
case ETHTOOL_SRXCLSRLDEL:
ret = cxgb4_ntuple_del_filter(dev, cmd);
break;
default: default:
break; break;
} }

View File

@ -797,23 +797,38 @@ free_entry:
return ret; return ret;
} }
int cxgb4_flow_rule_destroy(struct net_device *dev, u32 tc_prio,
struct ch_filter_specification *fs, int tid)
{
struct adapter *adap = netdev2adap(dev);
u8 hash;
int ret;
hash = fs->hash;
ret = cxgb4_del_filter(dev, tid, fs);
if (ret)
return ret;
if (hash)
cxgb4_tc_flower_hash_prio_del(adap, tc_prio);
return ret;
}
int cxgb4_tc_flower_destroy(struct net_device *dev, int cxgb4_tc_flower_destroy(struct net_device *dev,
struct flow_cls_offload *cls) struct flow_cls_offload *cls)
{ {
struct adapter *adap = netdev2adap(dev); struct adapter *adap = netdev2adap(dev);
struct ch_tc_flower_entry *ch_flower; struct ch_tc_flower_entry *ch_flower;
u32 tc_prio;
bool hash;
int ret; int ret;
ch_flower = ch_flower_lookup(adap, cls->cookie); ch_flower = ch_flower_lookup(adap, cls->cookie);
if (!ch_flower) if (!ch_flower)
return -ENOENT; return -ENOENT;
hash = ch_flower->fs.hash; ret = cxgb4_flow_rule_destroy(dev, ch_flower->fs.tc_prio,
tc_prio = ch_flower->fs.tc_prio; &ch_flower->fs, ch_flower->filter_id);
ret = cxgb4_del_filter(dev, ch_flower->filter_id, &ch_flower->fs);
if (ret) if (ret)
goto err; goto err;
@ -825,9 +840,6 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
} }
kfree_rcu(ch_flower, rcu); kfree_rcu(ch_flower, rcu);
if (hash)
cxgb4_tc_flower_hash_prio_del(adap, tc_prio);
err: err:
return ret; return ret;
} }

View File

@ -124,6 +124,8 @@ int cxgb4_tc_flower_stats(struct net_device *dev,
int cxgb4_flow_rule_replace(struct net_device *dev, struct flow_rule *rule, int cxgb4_flow_rule_replace(struct net_device *dev, struct flow_rule *rule,
u32 tc_prio, struct netlink_ext_ack *extack, u32 tc_prio, struct netlink_ext_ack *extack,
struct ch_filter_specification *fs, u32 *tid); struct ch_filter_specification *fs, u32 *tid);
int cxgb4_flow_rule_destroy(struct net_device *dev, u32 tc_prio,
struct ch_filter_specification *fs, int tid);
int cxgb4_init_tc_flower(struct adapter *adap); int cxgb4_init_tc_flower(struct adapter *adap);
void cxgb4_cleanup_tc_flower(struct adapter *adap); void cxgb4_cleanup_tc_flower(struct adapter *adap);