Skip to content

Commit

Permalink
net: sched: cls_u32: call block callbacks for offload
Browse files Browse the repository at this point in the history
Use the newly introduced callbacks infrastructure and call block
callbacks alongside with the existing per-netdev ndo_setup_tc.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Oct 21, 2017
1 parent 7746041 commit 245dc51
Showing 1 changed file with 52 additions and 20 deletions.
72 changes: 52 additions & 20 deletions net/sched/cls_u32.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,68 +465,85 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};

if (!tc_should_offload(dev, 0))
return;

tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_DELETE_HNODE;
cls_u32.hnode.divisor = h->divisor;
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;

dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
if (tc_can_offload(dev))
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}

static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
u32 flags)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
bool skip_sw = tc_skip_sw(flags);
bool offloaded = false;
int err;

if (!tc_should_offload(dev, flags))
return tc_skip_sw(flags) ? -EINVAL : 0;

tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_NEW_HNODE;
cls_u32.hnode.divisor = h->divisor;
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;

err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
if (tc_skip_sw(flags))
if (tc_can_offload(dev)) {
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
&cls_u32);
if (err) {
if (skip_sw)
return err;
} else {
offloaded = true;
}
}

err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
if (err < 0) {
u32_clear_hw_hnode(tp, h);
return err;
} else if (err > 0) {
offloaded = true;
}

if (skip_sw && !offloaded)
return -EINVAL;

return 0;
}

static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};

if (!tc_should_offload(dev, 0))
return;

tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_DELETE_KNODE;
cls_u32.knode.handle = handle;

dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
if (tc_can_offload(dev))
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}

static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
u32 flags)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
bool skip_sw = tc_skip_sw(flags);
int err;

if (!tc_should_offload(dev, flags))
return tc_skip_sw(flags) ? -EINVAL : 0;

tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_REPLACE_KNODE;
cls_u32.knode.handle = n->handle;
Expand All @@ -543,13 +560,28 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
if (n->ht_down)
cls_u32.knode.link_handle = n->ht_down->handle;

err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);

if (!err)
n->flags |= TCA_CLS_FLAGS_IN_HW;
if (tc_can_offload(dev)) {
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
&cls_u32);
if (err) {
if (skip_sw)
return err;
} else {
n->flags |= TCA_CLS_FLAGS_IN_HW;
}
}

if (tc_skip_sw(flags))
err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
if (err < 0) {
u32_remove_hw_knode(tp, n->handle);
return err;
} else if (err > 0) {
n->flags |= TCA_CLS_FLAGS_IN_HW;
}

if (skip_sw && !(n->flags && TCA_CLS_FLAGS_IN_HW))
return -EINVAL;

return 0;
}
Expand Down

0 comments on commit 245dc51

Please sign in to comment.