Skip to content

Commit 4577139

Browse files
borkmanndavem330
authored andcommitted
net: use jump label patching for ingress qdisc in __netif_receive_skb_core
Even if we make use of classifier and actions from the egress path, we're going into handle_ing() executing additional code on a per-packet cost for ingress qdisc, just to realize that nothing is attached on ingress. Instead, this can just be blinded out as a no-op entirely with the use of a static key. On input fast-path, we already make use of static keys in various places, e.g. skb time stamping, in RPS, etc. It makes sense to not waste time when we're assured that no ingress qdisc is attached anywhere. Enabling/disabling of that code path is being done via two helpers, namely net_{inc,dec}_ingress_queue(), that are being invoked under RTNL mutex when a ingress qdisc is being either initialized or destructed. Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent dfc96c1 commit 4577139

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

include/linux/rtnetlink.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,20 @@ static inline struct netdev_queue *dev_ingress_queue(struct net_device *dev)
7777
return rtnl_dereference(dev->ingress_queue);
7878
}
7979

80-
extern struct netdev_queue *dev_ingress_queue_create(struct net_device *dev);
80+
struct netdev_queue *dev_ingress_queue_create(struct net_device *dev);
81+
82+
#ifdef CONFIG_NET_CLS_ACT
83+
void net_inc_ingress_queue(void);
84+
void net_dec_ingress_queue(void);
85+
#else
86+
static inline void net_inc_ingress_queue(void)
87+
{
88+
}
89+
90+
static inline void net_dec_ingress_queue(void)
91+
{
92+
}
93+
#endif
8194

8295
extern void rtnetlink_init(void);
8396
extern void __rtnl_unlock(void);

net/core/dev.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,22 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
16301630
}
16311631
EXPORT_SYMBOL(call_netdevice_notifiers);
16321632

1633+
#ifdef CONFIG_NET_CLS_ACT
1634+
static struct static_key ingress_needed __read_mostly;
1635+
1636+
void net_inc_ingress_queue(void)
1637+
{
1638+
static_key_slow_inc(&ingress_needed);
1639+
}
1640+
EXPORT_SYMBOL_GPL(net_inc_ingress_queue);
1641+
1642+
void net_dec_ingress_queue(void)
1643+
{
1644+
static_key_slow_dec(&ingress_needed);
1645+
}
1646+
EXPORT_SYMBOL_GPL(net_dec_ingress_queue);
1647+
#endif
1648+
16331649
static struct static_key netstamp_needed __read_mostly;
16341650
#ifdef HAVE_JUMP_LABEL
16351651
/* We are not allowed to call static_key_slow_dec() from irq context
@@ -3547,7 +3563,7 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb,
35473563
struct netdev_queue *rxq = rcu_dereference(skb->dev->ingress_queue);
35483564

35493565
if (!rxq || rcu_access_pointer(rxq->qdisc) == &noop_qdisc)
3550-
goto out;
3566+
return skb;
35513567

35523568
if (*pt_prev) {
35533569
*ret = deliver_skb(skb, *pt_prev, orig_dev);
@@ -3561,8 +3577,6 @@ static inline struct sk_buff *handle_ing(struct sk_buff *skb,
35613577
return NULL;
35623578
}
35633579

3564-
out:
3565-
skb->tc_verd = 0;
35663580
return skb;
35673581
}
35683582
#endif
@@ -3698,12 +3712,15 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
36983712

36993713
skip_taps:
37003714
#ifdef CONFIG_NET_CLS_ACT
3701-
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
3702-
if (!skb)
3703-
goto unlock;
3715+
if (static_key_false(&ingress_needed)) {
3716+
skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
3717+
if (!skb)
3718+
goto unlock;
3719+
}
3720+
3721+
skb->tc_verd = 0;
37043722
ncls:
37053723
#endif
3706-
37073724
if (pfmemalloc && !skb_pfmemalloc_protocol(skb))
37083725
goto drop;
37093726

net/sched/sch_ingress.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,19 @@ static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch)
8888

8989
/* ------------------------------------------------------------- */
9090

91+
static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
92+
{
93+
net_inc_ingress_queue();
94+
95+
return 0;
96+
}
97+
9198
static void ingress_destroy(struct Qdisc *sch)
9299
{
93100
struct ingress_qdisc_data *p = qdisc_priv(sch);
94101

95102
tcf_destroy_chain(&p->filter_list);
103+
net_dec_ingress_queue();
96104
}
97105

98106
static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
@@ -124,6 +132,7 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
124132
.id = "ingress",
125133
.priv_size = sizeof(struct ingress_qdisc_data),
126134
.enqueue = ingress_enqueue,
135+
.init = ingress_init,
127136
.destroy = ingress_destroy,
128137
.dump = ingress_dump,
129138
.owner = THIS_MODULE,

0 commit comments

Comments
 (0)