Commit db43b30c authored by Vishal Kulkarni's avatar Vishal Kulkarni Committed by David S. Miller
Browse files

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: default avatarRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: default avatarVishal Kulkarni <vishal@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c8729cac
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -1573,6 +1573,22 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
	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,
		     u32 *rules)
{
@@ -1636,6 +1652,48 @@ static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
	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. */
static int cxgb4_ntuple_set_filter(struct net_device *netdev,
				   struct ethtool_rxnfc *cmd)
@@ -1702,6 +1760,9 @@ static int set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
	case ETHTOOL_SRXCLSRLINS:
		ret = cxgb4_ntuple_set_filter(dev, cmd);
		break;
	case ETHTOOL_SRXCLSRLDEL:
		ret = cxgb4_ntuple_del_filter(dev, cmd);
		break;
	default:
		break;
	}
+21 −9
Original line number Diff line number Diff line
@@ -797,23 +797,38 @@ free_entry:
	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,
			    struct flow_cls_offload *cls)
{
	struct adapter *adap = netdev2adap(dev);
	struct ch_tc_flower_entry *ch_flower;
	u32 tc_prio;
	bool hash;
	int ret;

	ch_flower = ch_flower_lookup(adap, cls->cookie);
	if (!ch_flower)
		return -ENOENT;

	hash = ch_flower->fs.hash;
	tc_prio = ch_flower->fs.tc_prio;

	ret = cxgb4_del_filter(dev, ch_flower->filter_id, &ch_flower->fs);
	ret = cxgb4_flow_rule_destroy(dev, ch_flower->fs.tc_prio,
				      &ch_flower->fs, ch_flower->filter_id);
	if (ret)
		goto err;

@@ -825,9 +840,6 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
	}
	kfree_rcu(ch_flower, rcu);

	if (hash)
		cxgb4_tc_flower_hash_prio_del(adap, tc_prio);

err:
	return ret;
}
+2 −0
Original line number Diff line number Diff line
@@ -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,
			    u32 tc_prio, struct netlink_ext_ack *extack,
			    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);
void cxgb4_cleanup_tc_flower(struct adapter *adap);