Skip to content

Commit 4b5026a

Browse files
committed
Merge branch 'net-sched-reflect-hw-offload-in-classifiers'
Or Gerlitz says: ==================== net/sched: Reflect HW offload status in classifiers Currently there is no way of querying whether a filter is offloaded to HW or not when using "both" policy (where none of skip_sw or skip_hw flags are set by user-space). Added two new flags, "in hw" and "not in hw" such that user space can determine if a filter is actually offloaded to hw. The "in hw" UAPI semantics was chosen so it's similar to the "skip hw" flag logic. If none of these two flags are set, this signals running over older kernel. As an example, add one vlan push + fwd rule, one matchall rule and one u32 rule without any flags, and another vlan + fwd skip_sw rule, such that the different TC classifier attempt to offload all of them -- all over mlx5 SRIOV VF rep: flower skip_sw indev eth2_0 src_mac e4:11:22:33:44:50 dst_mac e4:1d:2d:a5:f3:9d action vlan push id 52 action mirred egress redirect dev eth2 flower indev eth2_0 src_mac e4:11:22:33:44:50 dst_mac e4:11:22:33:44:51 action vlan push id 53 action mirred egress redirect dev eth2 u32 ht 800: flowid 800:1 match ip src 192.168.1.0/24 action drop Since that VF rep doesn't offload matchall/u32 and can currently offload only one vlan push rule we expect three of the rules not to be offloaded: filter protocol ip pref 99 u32 filter protocol ip pref 99 u32 fh 800: ht divisor 1 filter protocol ip pref 99 u32 fh 800::1 order 1 key ht 800 bkt 0 flowid 800:1 not in_hw match c0a80100/ffffff00 at 12 action order 1: gact action drop random type none pass val 0 index 8 ref 1 bind 1 filter protocol all pref 49150 matchall filter protocol all pref 49150 matchall handle 0x1 not in_hw action order 1: mirred (Egress Mirror to device veth1) pipe index 27 ref 1 bind 1 filter protocol ip pref 49151 flower filter protocol ip pref 49151 flower handle 0x1 indev eth2_0 dst_mac e4:11:22:33:44:51 src_mac e4:11:22:33:44:50 eth_type ipv4 not in_hw action order 1: vlan push id 53 protocol 802.1Q priority 0 pipe index 20 ref 1 bind 1 action order 2: mirred (Egress Redirect to device eth2) stolen index 26 ref 1 bind 1 filter protocol ip pref 49152 flower filter protocol ip pref 49152 flower handle 0x1 indev eth2_0 dst_mac e4:1d:2d:a5:f3:9d src_mac e4:11:22:33:44:50 eth_type ipv4 skip_sw in_hw action order 1: vlan push id 52 protocol 802.1Q priority 0 pipe index 19 ref 1 bind 1 action order 2: mirred (Egress Redirect to device eth2) stolen index 25 ref 1 bind 1 v3 --> v4 changes: - removed extra parenthesis (Dave) v2 --> v3 changes: - fixed the matchall dump flags patch to do proper checks (Jakub) - added the same proper checks to flower where they were missing - that flower patch was added as #1 and hence all the other patches are offed-by-one v1 --> v2 changes: - applied feedback from Jakub and Dave -- where none of the skip flags were set, the suggested approach didn't allow user space to distringuish between old kernel to a case when offloading to HW worked fine. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents ad8e963 + 5cecb6c commit 4b5026a

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

include/net/pkt_cls.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,11 @@ static inline bool tc_flags_valid(u32 flags)
481481
return true;
482482
}
483483

484+
static inline bool tc_in_hw(u32 flags)
485+
{
486+
return (flags & TCA_CLS_FLAGS_IN_HW) ? true : false;
487+
}
488+
484489
enum tc_fl_command {
485490
TC_CLSFLOWER_REPLACE,
486491
TC_CLSFLOWER_DESTROY,

include/uapi/linux/pkt_cls.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,10 @@ enum {
103103
#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
104104

105105
/* tca flags definitions */
106-
#define TCA_CLS_FLAGS_SKIP_HW (1 << 0)
107-
#define TCA_CLS_FLAGS_SKIP_SW (1 << 1)
106+
#define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */
107+
#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */
108+
#define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */
109+
#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
108110

109111
/* U32 filters */
110112

net/sched/cls_bpf.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
148148
struct net_device *dev = tp->q->dev_queue->dev;
149149
struct tc_cls_bpf_offload bpf_offload = {};
150150
struct tc_to_netdev offload;
151+
int err;
151152

152153
offload.type = TC_SETUP_CLSBPF;
153154
offload.cls_bpf = &bpf_offload;
@@ -159,8 +160,13 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
159160
bpf_offload.exts_integrated = prog->exts_integrated;
160161
bpf_offload.gen_flags = prog->gen_flags;
161162

162-
return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
163-
tp->protocol, &offload);
163+
err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
164+
tp->protocol, &offload);
165+
166+
if (!err && (cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE))
167+
prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
168+
169+
return err;
164170
}
165171

166172
static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
@@ -511,6 +517,9 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
511517
return ret;
512518
}
513519

520+
if (!tc_in_hw(prog->gen_flags))
521+
prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW;
522+
514523
if (oldprog) {
515524
list_replace_rcu(&oldprog->link, &prog->link);
516525
tcf_unbind_filter(tp, &oldprog->res);

net/sched/cls_flower.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
273273

274274
err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
275275
tc);
276+
if (!err)
277+
f->flags |= TCA_CLS_FLAGS_IN_HW;
276278

277279
if (tc_skip_sw(f->flags))
278280
return err;
@@ -912,6 +914,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
912914
goto errout;
913915
}
914916

917+
if (!tc_in_hw(fnew->flags))
918+
fnew->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
919+
915920
if (fold) {
916921
if (!tc_skip_sw(fold->flags))
917922
rhashtable_remove_fast(&head->ht, &fold->ht_node,
@@ -1229,7 +1234,8 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
12291234
if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags))
12301235
goto nla_put_failure;
12311236

1232-
nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags);
1237+
if (f->flags && nla_put_u32(skb, TCA_FLOWER_FLAGS, f->flags))
1238+
goto nla_put_failure;
12331239

12341240
if (tcf_exts_dump(skb, &f->exts))
12351241
goto nla_put_failure;

net/sched/cls_matchall.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,20 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
5656
struct net_device *dev = tp->q->dev_queue->dev;
5757
struct tc_to_netdev offload;
5858
struct tc_cls_matchall_offload mall_offload = {0};
59+
int err;
5960

6061
offload.type = TC_SETUP_MATCHALL;
6162
offload.cls_mall = &mall_offload;
6263
offload.cls_mall->command = TC_CLSMATCHALL_REPLACE;
6364
offload.cls_mall->exts = &head->exts;
6465
offload.cls_mall->cookie = cookie;
6566

66-
return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
67-
&offload);
67+
err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
68+
&offload);
69+
if (!err)
70+
head->flags |= TCA_CLS_FLAGS_IN_HW;
71+
72+
return err;
6873
}
6974

7075
static void mall_destroy_hw_filter(struct tcf_proto *tp,
@@ -194,6 +199,9 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
194199
}
195200
}
196201

202+
if (!tc_in_hw(new->flags))
203+
new->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
204+
197205
*arg = (unsigned long) head;
198206
rcu_assign_pointer(tp->root, new);
199207
if (head)
@@ -244,6 +252,9 @@ static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
244252
nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid))
245253
goto nla_put_failure;
246254

255+
if (head->flags && nla_put_u32(skb, TCA_MATCHALL_FLAGS, head->flags))
256+
goto nla_put_failure;
257+
247258
if (tcf_exts_dump(skb, &head->exts))
248259
goto nla_put_failure;
249260

net/sched/cls_u32.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,10 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
523523

524524
err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
525525
tp->protocol, &offload);
526+
527+
if (!err)
528+
n->flags |= TCA_CLS_FLAGS_IN_HW;
529+
526530
if (tc_skip_sw(flags))
527531
return err;
528532

@@ -895,6 +899,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
895899
return err;
896900
}
897901

902+
if (!tc_in_hw(new->flags))
903+
new->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
904+
898905
u32_replace_knode(tp, tp_c, new);
899906
tcf_unbind_filter(tp, &n->res);
900907
call_rcu(&n->rcu, u32_delete_key_rcu);
@@ -1014,6 +1021,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
10141021
if (err)
10151022
goto errhw;
10161023

1024+
if (!tc_in_hw(n->flags))
1025+
n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
1026+
10171027
ins = &ht->ht[TC_U32_HASH(handle)];
10181028
for (pins = rtnl_dereference(*ins); pins;
10191029
ins = &pins->next, pins = rtnl_dereference(*ins))

0 commit comments

Comments
 (0)