Skip to content

Commit 5b33f48

Browse files
amirvdavem330
authored andcommitted
net/flower: Introduce hardware offload support
This patch is based on a patch made by John Fastabend. It adds support for offloading cls_flower. when NETIF_F_HW_TC is on: flags = 0 => Rule will be processed twice - by hardware, and if still relevant, by software. flags = SKIP_HW => Rull will be processed by software only If hardware fail/not capabale to apply the rule, operation will NOT fail. Filter will be processed by SW only. Acked-by: Jiri Pirko <[email protected]> Suggested-by: John Fastabend <[email protected]> Signed-off-by: Amir Vadai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 10f7903 commit 5b33f48

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

include/linux/netdevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
786786
enum {
787787
TC_SETUP_MQPRIO,
788788
TC_SETUP_CLSU32,
789+
TC_SETUP_CLSFLOWER,
789790
};
790791

791792
struct tc_cls_u32_offload;
@@ -795,6 +796,7 @@ struct tc_to_netdev {
795796
union {
796797
u8 tc;
797798
struct tc_cls_u32_offload *cls_u32;
799+
struct tc_cls_flower_offload *cls_flower;
798800
};
799801
};
800802

include/net/pkt_cls.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,18 @@ static inline bool tc_should_offload(struct net_device *dev, u32 flags)
409409
return true;
410410
}
411411

412+
enum tc_fl_command {
413+
TC_CLSFLOWER_REPLACE,
414+
TC_CLSFLOWER_DESTROY,
415+
};
416+
417+
struct tc_cls_flower_offload {
418+
enum tc_fl_command command;
419+
u64 cookie;
420+
struct flow_dissector *dissector;
421+
struct fl_flow_key *mask;
422+
struct fl_flow_key *key;
423+
struct tcf_exts *exts;
424+
};
425+
412426
#endif

include/uapi/linux/pkt_cls.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ enum {
417417
TCA_FLOWER_KEY_TCP_DST, /* be16 */
418418
TCA_FLOWER_KEY_UDP_SRC, /* be16 */
419419
TCA_FLOWER_KEY_UDP_DST, /* be16 */
420+
421+
TCA_FLOWER_FLAGS,
420422
__TCA_FLOWER_MAX,
421423
};
422424

net/sched/cls_flower.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,51 @@ static void fl_destroy_filter(struct rcu_head *head)
165165
kfree(f);
166166
}
167167

168+
static void fl_hw_destroy_filter(struct tcf_proto *tp, u64 cookie)
169+
{
170+
struct net_device *dev = tp->q->dev_queue->dev;
171+
struct tc_cls_flower_offload offload = {0};
172+
struct tc_to_netdev tc;
173+
174+
if (!tc_should_offload(dev, 0))
175+
return;
176+
177+
offload.command = TC_CLSFLOWER_DESTROY;
178+
offload.cookie = cookie;
179+
180+
tc.type = TC_SETUP_CLSFLOWER;
181+
tc.cls_flower = &offload;
182+
183+
dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
184+
}
185+
186+
static void fl_hw_replace_filter(struct tcf_proto *tp,
187+
struct flow_dissector *dissector,
188+
struct fl_flow_key *mask,
189+
struct fl_flow_key *key,
190+
struct tcf_exts *actions,
191+
u64 cookie, u32 flags)
192+
{
193+
struct net_device *dev = tp->q->dev_queue->dev;
194+
struct tc_cls_flower_offload offload = {0};
195+
struct tc_to_netdev tc;
196+
197+
if (!tc_should_offload(dev, flags))
198+
return;
199+
200+
offload.command = TC_CLSFLOWER_REPLACE;
201+
offload.cookie = cookie;
202+
offload.dissector = dissector;
203+
offload.mask = mask;
204+
offload.key = key;
205+
offload.exts = actions;
206+
207+
tc.type = TC_SETUP_CLSFLOWER;
208+
tc.cls_flower = &offload;
209+
210+
dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
211+
}
212+
168213
static bool fl_destroy(struct tcf_proto *tp, bool force)
169214
{
170215
struct cls_fl_head *head = rtnl_dereference(tp->root);
@@ -174,6 +219,7 @@ static bool fl_destroy(struct tcf_proto *tp, bool force)
174219
return false;
175220

176221
list_for_each_entry_safe(f, next, &head->filters, list) {
222+
fl_hw_destroy_filter(tp, (u64)f);
177223
list_del_rcu(&f->list);
178224
call_rcu(&f->rcu, fl_destroy_filter);
179225
}
@@ -459,6 +505,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
459505
struct cls_fl_filter *fnew;
460506
struct nlattr *tb[TCA_FLOWER_MAX + 1];
461507
struct fl_flow_mask mask = {};
508+
u32 flags = 0;
462509
int err;
463510

464511
if (!tca[TCA_OPTIONS])
@@ -486,6 +533,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
486533
}
487534
fnew->handle = handle;
488535

536+
if (tb[TCA_FLOWER_FLAGS])
537+
flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
538+
489539
err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr);
490540
if (err)
491541
goto errout;
@@ -498,9 +548,20 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
498548
head->ht_params);
499549
if (err)
500550
goto errout;
501-
if (fold)
551+
552+
fl_hw_replace_filter(tp,
553+
&head->dissector,
554+
&mask.key,
555+
&fnew->key,
556+
&fnew->exts,
557+
(u64)fnew,
558+
flags);
559+
560+
if (fold) {
502561
rhashtable_remove_fast(&head->ht, &fold->ht_node,
503562
head->ht_params);
563+
fl_hw_destroy_filter(tp, (u64)fold);
564+
}
504565

505566
*arg = (unsigned long) fnew;
506567

@@ -527,6 +588,7 @@ static int fl_delete(struct tcf_proto *tp, unsigned long arg)
527588
rhashtable_remove_fast(&head->ht, &f->ht_node,
528589
head->ht_params);
529590
list_del_rcu(&f->list);
591+
fl_hw_destroy_filter(tp, (u64)f);
530592
tcf_unbind_filter(tp, &f->res);
531593
call_rcu(&f->rcu, fl_destroy_filter);
532594
return 0;

0 commit comments

Comments
 (0)