Merge branch 'use-tc_cls_can_offload_and_chain0-throughout-the-drivers'

Jakub Kicinski says:

====================
use tc_cls_can_offload_and_chain0() throughout the drivers

This set makes all drivers use a new tc_cls_can_offload_and_chain0()
helper which will set extack in case TC hw offload flag is disabled.

I chose to keep the new helper which also looks at the chain but
renamed it more appropriately.  The rationale being that most drivers
don't accept chains other than 0 and since we have to pass extack
to the helper we can as well pass the entire struct tc_cls_common_offload
and perform the most common checks.

This code makes the assumption that type_data in the callback can
be interpreted as struct tc_cls_common_offload, i.e. the real offload
structure has common part as the first member.  This allows us to
make the check once for all classifier types if driver supports
more than one.

v1:
 - drop the type validation in nfp and netdevsim.
v2:
 - reorder checks in patch 1;
 - split other changes from patch 1;
 - add the i40e patch in;
 - add one more test case - for chain 0 extack.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-01-25 21:23:09 -05:00
commit b89d06ce58
14 changed files with 72 additions and 47 deletions

View File

@ -7778,7 +7778,8 @@ static int bnxt_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
{
struct bnxt *bp = cb_priv;
if (!bnxt_tc_flower_enabled(bp) || !tc_can_offload(bp->dev))
if (!bnxt_tc_flower_enabled(bp) ||
!tc_cls_can_offload_and_chain0(bp->dev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -1474,9 +1474,6 @@ int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
{
int rc = 0;
if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
rc = bnxt_tc_add_flow(bp, src_fid, cls_flower);

View File

@ -124,7 +124,8 @@ static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
struct bnxt *bp = vf_rep->bp;
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
if (!bnxt_tc_flower_enabled(vf_rep->bp) || !tc_can_offload(bp->dev))
if (!bnxt_tc_flower_enabled(vf_rep->bp) ||
!tc_cls_can_offload_and_chain0(bp->dev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -2928,9 +2928,6 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
static int cxgb_setup_tc_flower(struct net_device *dev,
struct tc_cls_flower_offload *cls_flower)
{
if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return cxgb4_tc_flower_replace(dev, cls_flower);
@ -2946,9 +2943,6 @@ static int cxgb_setup_tc_flower(struct net_device *dev,
static int cxgb_setup_tc_cls_u32(struct net_device *dev,
struct tc_cls_u32_offload *cls_u32)
{
if (cls_u32->common.chain_index)
return -EOPNOTSUPP;
switch (cls_u32->command) {
case TC_CLSU32_NEW_KNODE:
case TC_CLSU32_REPLACE_KNODE:
@ -2974,7 +2968,7 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return -EINVAL;
}
if (!tc_can_offload(dev))
if (!tc_cls_can_offload_and_chain0(dev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -7437,11 +7437,6 @@ static int i40e_setup_tc_cls_flower(struct i40e_netdev_priv *np,
{
struct i40e_vsi *vsi = np->vsi;
if (!tc_can_offload(vsi->netdev))
return -EOPNOTSUPP;
if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return i40e_configure_clsflower(vsi, cls_flower);
@ -7459,6 +7454,9 @@ static int i40e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
{
struct i40e_netdev_priv *np = cb_priv;
if (!tc_cls_can_offload_and_chain0(np->vsi->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {
case TC_SETUP_CLSFLOWER:
return i40e_setup_tc_cls_flower(np, type_data);

View File

@ -9303,9 +9303,6 @@ free_jump:
static int ixgbe_setup_tc_cls_u32(struct ixgbe_adapter *adapter,
struct tc_cls_u32_offload *cls_u32)
{
if (cls_u32->common.chain_index)
return -EOPNOTSUPP;
switch (cls_u32->command) {
case TC_CLSU32_NEW_KNODE:
case TC_CLSU32_REPLACE_KNODE:
@ -9327,7 +9324,7 @@ static int ixgbe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
{
struct ixgbe_adapter *adapter = cb_priv;
if (!tc_can_offload(adapter->netdev))
if (!tc_cls_can_offload_and_chain0(adapter->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -2944,9 +2944,6 @@ out:
static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *cls_flower)
{
if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return mlx5e_configure_flower(priv, cls_flower);
@ -2964,7 +2961,7 @@ int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
{
struct mlx5e_priv *priv = cb_priv;
if (!tc_can_offload(priv->netdev))
if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -719,9 +719,6 @@ static int
mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *cls_flower)
{
if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
case TC_CLSFLOWER_REPLACE:
return mlx5e_configure_flower(priv, cls_flower);
@ -739,7 +736,7 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
{
struct mlx5e_priv *priv = cb_priv;
if (!tc_can_offload(priv->netdev))
if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -1738,9 +1738,6 @@ static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
struct tc_cls_matchall_offload *f,
bool ingress)
{
if (f->common.chain_index)
return -EOPNOTSUPP;
switch (f->command) {
case TC_CLSMATCHALL_REPLACE:
return mlxsw_sp_port_add_cls_matchall(mlxsw_sp_port, f,
@ -1780,7 +1777,8 @@ static int mlxsw_sp_setup_tc_block_cb_matchall(enum tc_setup_type type,
switch (type) {
case TC_SETUP_CLSMATCHALL:
if (!tc_can_offload(mlxsw_sp_port->dev))
if (!tc_cls_can_offload_and_chain0(mlxsw_sp_port->dev,
type_data))
return -EOPNOTSUPP;
return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data,

View File

@ -130,7 +130,7 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
"only offload of BPF classifiers supported");
return -EOPNOTSUPP;
}
if (!tc_can_offload_extack(nn->dp.netdev, cls_bpf->common.extack))
if (!tc_cls_can_offload_and_chain0(nn->dp.netdev, &cls_bpf->common))
return -EOPNOTSUPP;
if (!nfp_net_ebpf_capable(nn)) {
NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
@ -142,8 +142,6 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
"only ETH_P_ALL supported as filter protocol");
return -EOPNOTSUPP;
}
if (cls_bpf->common.chain_index)
return -EOPNOTSUPP;
/* Only support TC direct action */
if (!cls_bpf->exts_integrated ||

View File

@ -483,8 +483,7 @@ static int
nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flower, bool egress)
{
if (!eth_proto_is_802_3(flower->common.protocol) ||
flower->common.chain_index)
if (!eth_proto_is_802_3(flower->common.protocol))
return -EOPNOTSUPP;
switch (flower->command) {
@ -504,7 +503,7 @@ int nfp_flower_setup_tc_egress_cb(enum tc_setup_type type, void *type_data,
{
struct nfp_repr *repr = cb_priv;
if (!tc_can_offload(repr->netdev))
if (!tc_cls_can_offload_and_chain0(repr->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {
@ -521,7 +520,7 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
{
struct nfp_repr *repr = cb_priv;
if (!tc_can_offload(repr->netdev))
if (!tc_cls_can_offload_and_chain0(repr->netdev, type_data))
return -EOPNOTSUPP;
switch (type) {

View File

@ -135,7 +135,7 @@ int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type,
return -EOPNOTSUPP;
}
if (!tc_can_offload_extack(ns->netdev, cls_bpf->common.extack))
if (!tc_cls_can_offload_and_chain0(ns->netdev, &cls_bpf->common))
return -EOPNOTSUPP;
if (cls_bpf->common.protocol != htons(ETH_P_ALL)) {
@ -144,9 +144,6 @@ int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type,
return -EOPNOTSUPP;
}
if (cls_bpf->common.chain_index)
return -EOPNOTSUPP;
if (!ns->bpf_tc_accept) {
NSIM_EA(cls_bpf->common.extack,
"netdevsim configured to reject BPF TC offload");

View File

@ -656,6 +656,20 @@ static inline bool tc_can_offload_extack(const struct net_device *dev,
return can;
}
static inline bool
tc_cls_can_offload_and_chain0(const struct net_device *dev,
struct tc_cls_common_offload *common)
{
if (!tc_can_offload_extack(dev, common->extack))
return false;
if (common->chain_index) {
NL_SET_ERR_MSG(common->extack,
"Driver supports only offload of chain 0");
return false;
}
return true;
}
static inline bool tc_skip_hw(u32 flags)
{
return (flags & TCA_CLS_FLAGS_SKIP_HW) ? true : false;

View File

@ -430,13 +430,15 @@ class NetdevSim:
return filters
def cls_filter_op(self, op, qdisc="ingress", prio=None, handle=None,
cls="", params="",
chain=None, cls="", params="",
fail=True, include_stderr=False):
spec = ""
if prio is not None:
spec += " prio %d" % (prio)
if handle:
spec += " handle %s" % (handle)
if chain is not None:
spec += " chain %d" % (chain)
return tc("filter {op} dev {dev} {qdisc} {spec} {cls} {params}"\
.format(op=op, dev=self['ifname'], qdisc=qdisc, spec=spec,
@ -444,7 +446,7 @@ class NetdevSim:
fail=fail, include_stderr=include_stderr)
def cls_bpf_add_filter(self, bpf, op="add", prio=None, handle=None,
da=False, verbose=False,
chain=None, da=False, verbose=False,
skip_sw=False, skip_hw=False,
fail=True, include_stderr=False):
cls = "bpf " + bpf
@ -460,7 +462,7 @@ class NetdevSim:
params += " skip_hw"
return self.cls_filter_op(op=op, prio=prio, handle=handle, cls=cls,
params=params,
chain=chain, params=params,
fail=fail, include_stderr=include_stderr)
def set_ethtool_tc_offloads(self, enable, fail=True):
@ -543,6 +545,10 @@ def check_extack(output, reference, args):
def check_extack_nsim(output, reference, args):
check_extack(output, "Error: netdevsim: " + reference, args)
def check_no_extack(res, needle):
fail((res[1] + res[2]).count(needle) or (res[1] + res[2]).count("Warning:"),
"Found '%s' in command output, leaky extack?" % (needle))
def check_verifier_log(output, reference):
lines = output.split("\n")
for l in reversed(lines):
@ -550,6 +556,18 @@ def check_verifier_log(output, reference):
return
fail(True, "Missing or incorrect message from netdevsim in verifier log")
def test_spurios_extack(sim, obj, skip_hw, needle):
res = sim.cls_bpf_add_filter(obj, prio=1, handle=1, skip_hw=skip_hw,
include_stderr=True)
check_no_extack(res, needle)
res = sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1,
skip_hw=skip_hw, include_stderr=True)
check_no_extack(res, needle)
res = sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf",
include_stderr=True)
check_no_extack(res, needle)
# Parse command line
parser = argparse.ArgumentParser()
parser.add_argument("--log", help="output verbose log to given file")
@ -663,6 +681,14 @@ try:
args)
sim.wait_for_flush()
start_test("Test non-0 chain offload...")
ret, _, err = sim.cls_bpf_add_filter(obj, chain=1, prio=1, handle=1,
skip_sw=True,
fail=False, include_stderr=True)
fail(ret == 0, "Offloaded a filter to chain other than 0")
check_extack(err, "Error: Driver supports only offload of chain 0.", args)
sim.tc_flush_filters()
start_test("Test TC replace...")
sim.cls_bpf_add_filter(obj, prio=1, handle=1)
sim.cls_bpf_add_filter(obj, op="replace", prio=1, handle=1)
@ -687,6 +713,17 @@ try:
(j))
sim.cls_filter_op(op="delete", prio=1, handle=1, cls="bpf")
start_test("Test spurious extack from the driver...")
test_spurios_extack(sim, obj, False, "netdevsim")
test_spurios_extack(sim, obj, True, "netdevsim")
sim.set_ethtool_tc_offloads(False)
test_spurios_extack(sim, obj, False, "TC offload is disabled")
test_spurios_extack(sim, obj, True, "TC offload is disabled")
sim.set_ethtool_tc_offloads(True)
sim.tc_flush_filters()
start_test("Test TC offloads work...")