Skip to content

Commit

Permalink
Merge branch 'tc-sw-only'
Browse files Browse the repository at this point in the history
John Fastabend says:

====================
tc software only

This adds a software only flag to tc but incorporates a bunch of comments
from the original attempt at this.

First instead of having the offload decision logic be embedded in cls_u32
I lifted into cls_pkt.h so it can be used anywhere and named the flag
TCA_CLS_FLAGS_SKIP_HW (Thanks Jiri ;)

In order to do this I put the flag defines in pkt_cls.h as well. However
it was suggested that perhaps these flags could be lifted into the
upper layer of TCA_ as well but I'm afraid this can not be done with
existing tc design as far as I can tell. The problem is the filters are
packed and unpacked in the classifier specific code and pushing the flags
through the high level doesn't seem easily doable. And we already have
this design where classifiers handle generic options such as actions and
policers. So I think adding one more thing here is OK as 'tc', et. al.
already know how to handle this type of thing.
====================

Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 1, 2016
2 parents d2e42a1 + 9e8ce79 commit bd070e2
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
3 changes: 0 additions & 3 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8400,9 +8400,6 @@ int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,

if (TC_H_MAJ(handle) == TC_H_MAJ(TC_H_INGRESS) &&
tc->type == TC_SETUP_CLSU32) {
if (!(dev->features & NETIF_F_HW_TC))
return -EINVAL;

switch (tc->cls_u32->command) {
case TC_CLSU32_NEW_KNODE:
case TC_CLSU32_REPLACE_KNODE:
Expand Down
17 changes: 17 additions & 0 deletions include/net/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,21 @@ struct tc_cls_u32_offload {
};
};

/* tca flags definitions */
#define TCA_CLS_FLAGS_SKIP_HW 1

static inline bool tc_should_offload(struct net_device *dev, u32 flags)
{
if (!(dev->features & NETIF_F_HW_TC))
return false;

if (flags & TCA_CLS_FLAGS_SKIP_HW)
return false;

if (!dev->netdev_ops->ndo_setup_tc)
return false;

return true;
}

#endif
1 change: 1 addition & 0 deletions include/uapi/linux/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ enum {
TCA_U32_INDEV,
TCA_U32_PCNT,
TCA_U32_MARK,
TCA_U32_FLAGS,
__TCA_U32_MAX
};

Expand Down
37 changes: 27 additions & 10 deletions net/sched/cls_u32.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct tc_u_knode {
#ifdef CONFIG_CLS_U32_PERF
struct tc_u32_pcnt __percpu *pf;
#endif
u32 flags;
#ifdef CONFIG_CLS_U32_MARK
u32 val;
u32 mask;
Expand Down Expand Up @@ -434,15 +435,17 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
offload.type = TC_SETUP_CLSU32;
offload.cls_u32 = &u32_offload;

if (dev->netdev_ops->ndo_setup_tc) {
if (tc_should_offload(dev, 0)) {
offload.cls_u32->command = TC_CLSU32_DELETE_KNODE;
offload.cls_u32->knode.handle = handle;
dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
tp->protocol, &offload);
}
}

static void u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
static void 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 tc_cls_u32_offload u32_offload = {0};
Expand All @@ -451,7 +454,7 @@ static void u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
offload.type = TC_SETUP_CLSU32;
offload.cls_u32 = &u32_offload;

if (dev->netdev_ops->ndo_setup_tc) {
if (tc_should_offload(dev, flags)) {
offload.cls_u32->command = TC_CLSU32_NEW_HNODE;
offload.cls_u32->hnode.divisor = h->divisor;
offload.cls_u32->hnode.handle = h->handle;
Expand All @@ -471,7 +474,7 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
offload.type = TC_SETUP_CLSU32;
offload.cls_u32 = &u32_offload;

if (dev->netdev_ops->ndo_setup_tc) {
if (tc_should_offload(dev, 0)) {
offload.cls_u32->command = TC_CLSU32_DELETE_HNODE;
offload.cls_u32->hnode.divisor = h->divisor;
offload.cls_u32->hnode.handle = h->handle;
Expand All @@ -482,7 +485,9 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
}
}

static void u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n)
static void 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 tc_cls_u32_offload u32_offload = {0};
Expand All @@ -491,7 +496,7 @@ static void u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n)
offload.type = TC_SETUP_CLSU32;
offload.cls_u32 = &u32_offload;

if (dev->netdev_ops->ndo_setup_tc) {
if (tc_should_offload(dev, flags)) {
offload.cls_u32->command = TC_CLSU32_REPLACE_KNODE;
offload.cls_u32->knode.handle = n->handle;
offload.cls_u32->knode.fshift = n->fshift;
Expand Down Expand Up @@ -679,6 +684,7 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
[TCA_U32_SEL] = { .len = sizeof(struct tc_u32_sel) },
[TCA_U32_INDEV] = { .type = NLA_STRING, .len = IFNAMSIZ },
[TCA_U32_MARK] = { .len = sizeof(struct tc_u32_mark) },
[TCA_U32_FLAGS] = { .type = NLA_U32 },
};

static int u32_set_parms(struct net *net, struct tcf_proto *tp,
Expand Down Expand Up @@ -786,6 +792,7 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
#endif
new->fshift = n->fshift;
new->res = n->res;
new->flags = n->flags;
RCU_INIT_POINTER(new->ht_down, n->ht_down);

/* bump reference count as long as we hold pointer to structure */
Expand Down Expand Up @@ -825,7 +832,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
struct tc_u32_sel *s;
struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_U32_MAX + 1];
u32 htid;
u32 htid, flags = 0;
int err;
#ifdef CONFIG_CLS_U32_PERF
size_t size;
Expand All @@ -838,13 +845,19 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
if (err < 0)
return err;

if (tb[TCA_U32_FLAGS])
flags = nla_get_u32(tb[TCA_U32_FLAGS]);

n = (struct tc_u_knode *)*arg;
if (n) {
struct tc_u_knode *new;

if (TC_U32_KEY(n->handle) == 0)
return -EINVAL;

if (n->flags != flags)
return -EINVAL;

new = u32_init_knode(tp, n);
if (!new)
return -ENOMEM;
Expand All @@ -861,7 +874,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
u32_replace_knode(tp, tp_c, new);
tcf_unbind_filter(tp, &n->res);
call_rcu(&n->rcu, u32_delete_key_rcu);
u32_replace_hw_knode(tp, new);
u32_replace_hw_knode(tp, new, flags);
return 0;
}

Expand Down Expand Up @@ -889,7 +902,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
rcu_assign_pointer(tp_c->hlist, ht);
*arg = (unsigned long)ht;

u32_replace_hw_hnode(tp, ht);
u32_replace_hw_hnode(tp, ht, flags);
return 0;
}

Expand Down Expand Up @@ -940,6 +953,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
RCU_INIT_POINTER(n->ht_up, ht);
n->handle = handle;
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
n->flags = flags;
tcf_exts_init(&n->exts, TCA_U32_ACT, TCA_U32_POLICE);
n->tp = tp;

Expand Down Expand Up @@ -972,7 +986,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,

RCU_INIT_POINTER(n->next, pins);
rcu_assign_pointer(*ins, n);
u32_replace_hw_knode(tp, n);
u32_replace_hw_knode(tp, n, flags);
*arg = (unsigned long)n;
return 0;
}
Expand Down Expand Up @@ -1077,6 +1091,9 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
nla_put_u32(skb, TCA_U32_LINK, ht_down->handle))
goto nla_put_failure;

if (n->flags && nla_put_u32(skb, TCA_U32_FLAGS, n->flags))
goto nla_put_failure;

#ifdef CONFIG_CLS_U32_MARK
if ((n->val || n->mask)) {
struct tc_u32_mark mark = {.val = n->val,
Expand Down

0 comments on commit bd070e2

Please sign in to comment.