|
@@ -93,6 +93,7 @@ struct fq_sched_data {
|
|
|
u32 flow_refill_delay;
|
|
|
u32 flow_max_rate; /* optional max rate per flow */
|
|
|
u32 flow_plimit; /* max packets per flow */
|
|
|
+ u32 orphan_mask; /* mask for orphaned skb */
|
|
|
struct rb_root *fq_root;
|
|
|
u8 rate_enable;
|
|
|
u8 fq_trees_log;
|
|
@@ -223,11 +224,20 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
|
|
|
if (unlikely((skb->priority & TC_PRIO_MAX) == TC_PRIO_CONTROL))
|
|
|
return &q->internal;
|
|
|
|
|
|
- if (unlikely(!sk)) {
|
|
|
+ /* SYNACK messages are attached to a listener socket.
|
|
|
+ * 1) They are not part of a 'flow' yet
|
|
|
+ * 2) We do not want to rate limit them (eg SYNFLOOD attack),
|
|
|
+ * especially if the listener set SO_MAX_PACING_RATE
|
|
|
+ * 3) We pretend they are orphaned
|
|
|
+ */
|
|
|
+ if (!sk || sk->sk_state == TCP_LISTEN) {
|
|
|
+ unsigned long hash = skb_get_hash(skb) & q->orphan_mask;
|
|
|
+
|
|
|
/* By forcing low order bit to 1, we make sure to not
|
|
|
* collide with a local flow (socket pointers are word aligned)
|
|
|
*/
|
|
|
- sk = (struct sock *)(skb_get_hash(skb) | 1L);
|
|
|
+ sk = (struct sock *)((hash << 1) | 1UL);
|
|
|
+ skb_orphan(skb);
|
|
|
}
|
|
|
|
|
|
root = &q->fq_root[hash_32((u32)(long)sk, q->fq_trees_log)];
|
|
@@ -704,6 +714,9 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
|
|
|
q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
|
|
|
}
|
|
|
|
|
|
+ if (tb[TCA_FQ_ORPHAN_MASK])
|
|
|
+ q->orphan_mask = nla_get_u32(tb[TCA_FQ_ORPHAN_MASK]);
|
|
|
+
|
|
|
if (!err) {
|
|
|
sch_tree_unlock(sch);
|
|
|
err = fq_resize(sch, fq_log);
|
|
@@ -749,6 +762,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt)
|
|
|
q->delayed = RB_ROOT;
|
|
|
q->fq_root = NULL;
|
|
|
q->fq_trees_log = ilog2(1024);
|
|
|
+ q->orphan_mask = 1024 - 1;
|
|
|
qdisc_watchdog_init(&q->watchdog, sch);
|
|
|
|
|
|
if (opt)
|
|
@@ -778,6 +792,7 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
|
nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
|
|
|
nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY,
|
|
|
jiffies_to_usecs(q->flow_refill_delay)) ||
|
|
|
+ nla_put_u32(skb, TCA_FQ_ORPHAN_MASK, q->orphan_mask) ||
|
|
|
nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
|
|
|
goto nla_put_failure;
|
|
|
|