Skip to content

Commit e578d9c

Browse files
Florian Westphaldavem330
Florian Westphal
authored andcommitted
net: sched: use counter to break reclassify loops
Seems all we want here is to avoid endless 'goto reclassify' loop. tc_classify_compat even resets this counter when something other than TC_ACT_RECLASSIFY is returned, so this skb-counter doesn't break hypothetical loops induced by something other than perpetual TC_ACT_RECLASSIFY return values. skb_act_clone is now identical to skb_clone, so just use that. Tested with following (bogus) filter: tc filter add dev eth0 parent ffff: \ protocol ip u32 match u32 0 0 police rate 10Kbit burst \ 64000 mtu 1500 action reclassify Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b04096f commit e578d9c

File tree

5 files changed

+5
-30
lines changed

5 files changed

+5
-30
lines changed

Documentation/networking/tc-actions-env-rules.txt

-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ For example if your action queues a packet to be processed later,
88
or intentionally branches by redirecting a packet, then you need to
99
clone the packet.
1010

11-
There are certain fields in the skb tc_verd that need to be reset so we
12-
avoid loops, etc. A few are generic enough that skb_act_clone()
13-
resets them for you, so invoke skb_act_clone() rather than skb_clone().
14-
1511
2) If you munge any packet thou shalt call pskb_expand_head in the case
1612
someone else is referencing the skb. After that you "own" the skb.
1713

include/net/sch_generic.h

-15
Original file line numberDiff line numberDiff line change
@@ -739,21 +739,6 @@ static inline u32 qdisc_l2t(struct qdisc_rate_table* rtab, unsigned int pktlen)
739739
return rtab->data[slot];
740740
}
741741

742-
#ifdef CONFIG_NET_CLS_ACT
743-
static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,
744-
int action)
745-
{
746-
struct sk_buff *n;
747-
748-
n = skb_clone(skb, gfp_mask);
749-
750-
if (n) {
751-
n->tc_verd = SET_TC_VERD(n->tc_verd, 0);
752-
}
753-
return n;
754-
}
755-
#endif
756-
757742
struct psched_ratecfg {
758743
u64 rate_bytes_ps; /* bytes per second */
759744
u32 mult;

include/uapi/linux/pkt_cls.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ bits 9,10,11: redirect counter - redirect TTL. Loop avoidance
4444
#define TC_OK2MUNGE _TC_MAKEMASK1(1)
4545
#define SET_TC_OK2MUNGE(v) ( TC_OK2MUNGE | (v & ~TC_OK2MUNGE))
4646
#define CLR_TC_OK2MUNGE(v) ( v & ~TC_OK2MUNGE)
47-
#endif
4847

4948
#define S_TC_VERD _TC_MAKE32(2)
5049
#define M_TC_VERD _TC_MAKEMASK(4,S_TC_VERD)
5150
#define G_TC_VERD(x) _TC_GETVALUE(x,S_TC_VERD,M_TC_VERD)
5251
#define V_TC_VERD(x) _TC_MAKEVALUE(x,S_TC_VERD)
5352
#define SET_TC_VERD(v,n) ((V_TC_VERD(n)) | (v & ~M_TC_VERD))
53+
#endif
5454

5555
#define S_TC_FROM _TC_MAKE32(6)
5656
#define M_TC_FROM _TC_MAKEMASK(2,S_TC_FROM)

net/sched/act_mirred.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
151151
}
152152

153153
at = G_TC_AT(skb->tc_verd);
154-
skb2 = skb_act_clone(skb, GFP_ATOMIC, m->tcf_action);
154+
skb2 = skb_clone(skb, GFP_ATOMIC);
155155
if (skb2 == NULL)
156156
goto out;
157157

net/sched/sch_api.c

+3-9
Original file line numberDiff line numberDiff line change
@@ -1816,13 +1816,8 @@ int tc_classify_compat(struct sk_buff *skb, const struct tcf_proto *tp,
18161816
continue;
18171817
err = tp->classify(skb, tp, res);
18181818

1819-
if (err >= 0) {
1820-
#ifdef CONFIG_NET_CLS_ACT
1821-
if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
1822-
skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
1823-
#endif
1819+
if (err >= 0)
18241820
return err;
1825-
}
18261821
}
18271822
return -1;
18281823
}
@@ -1834,23 +1829,22 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
18341829
int err = 0;
18351830
#ifdef CONFIG_NET_CLS_ACT
18361831
const struct tcf_proto *otp = tp;
1832+
int limit = 0;
18371833
reclassify:
18381834
#endif
18391835

18401836
err = tc_classify_compat(skb, tp, res);
18411837
#ifdef CONFIG_NET_CLS_ACT
18421838
if (err == TC_ACT_RECLASSIFY) {
1843-
u32 verd = G_TC_VERD(skb->tc_verd);
18441839
tp = otp;
18451840

1846-
if (verd++ >= MAX_REC_LOOP) {
1841+
if (unlikely(limit++ >= MAX_REC_LOOP)) {
18471842
net_notice_ratelimited("%s: packet reclassify loop rule prio %u protocol %02x\n",
18481843
tp->q->ops->id,
18491844
tp->prio & 0xffff,
18501845
ntohs(tp->protocol));
18511846
return TC_ACT_SHOT;
18521847
}
1853-
skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
18541848
goto reclassify;
18551849
}
18561850
#endif

0 commit comments

Comments
 (0)