aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/pkt_sched.h2
-rw-r--r--net/sched/sch_fq.c19
2 files changed, 19 insertions, 2 deletions
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index d62316baae94..534b84710745 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -774,6 +774,8 @@ enum {
774 774
775 TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */ 775 TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */
776 776
777 TCA_FQ_ORPHAN_MASK, /* mask applied to orphaned skb hashes */
778
777 __TCA_FQ_MAX 779 __TCA_FQ_MAX
778}; 780};
779 781
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 69a3dbf55c60..a00c43043001 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -93,6 +93,7 @@ struct fq_sched_data {
93 u32 flow_refill_delay; 93 u32 flow_refill_delay;
94 u32 flow_max_rate; /* optional max rate per flow */ 94 u32 flow_max_rate; /* optional max rate per flow */
95 u32 flow_plimit; /* max packets per flow */ 95 u32 flow_plimit; /* max packets per flow */
96 u32 orphan_mask; /* mask for orphaned skb */
96 struct rb_root *fq_root; 97 struct rb_root *fq_root;
97 u8 rate_enable; 98 u8 rate_enable;
98 u8 fq_trees_log; 99 u8 fq_trees_log;
@@ -223,11 +224,20 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
223 if (unlikely((skb->priority & TC_PRIO_MAX) == TC_PRIO_CONTROL)) 224 if (unlikely((skb->priority & TC_PRIO_MAX) == TC_PRIO_CONTROL))
224 return &q->internal; 225 return &q->internal;
225 226
226 if (unlikely(!sk)) { 227 /* SYNACK messages are attached to a listener socket.
228 * 1) They are not part of a 'flow' yet
229 * 2) We do not want to rate limit them (eg SYNFLOOD attack),
230 * especially if the listener set SO_MAX_PACING_RATE
231 * 3) We pretend they are orphaned
232 */
233 if (!sk || sk->sk_state == TCP_LISTEN) {
234 unsigned long hash = skb_get_hash(skb) & q->orphan_mask;
235
227 /* By forcing low order bit to 1, we make sure to not 236 /* By forcing low order bit to 1, we make sure to not
228 * collide with a local flow (socket pointers are word aligned) 237 * collide with a local flow (socket pointers are word aligned)
229 */ 238 */
230 sk = (struct sock *)(skb_get_hash(skb) | 1L); 239 sk = (struct sock *)((hash << 1) | 1UL);
240 skb_orphan(skb);
231 } 241 }
232 242
233 root = &q->fq_root[hash_32((u32)(long)sk, q->fq_trees_log)]; 243 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)
704 q->flow_refill_delay = usecs_to_jiffies(usecs_delay); 714 q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
705 } 715 }
706 716
717 if (tb[TCA_FQ_ORPHAN_MASK])
718 q->orphan_mask = nla_get_u32(tb[TCA_FQ_ORPHAN_MASK]);
719
707 if (!err) { 720 if (!err) {
708 sch_tree_unlock(sch); 721 sch_tree_unlock(sch);
709 err = fq_resize(sch, fq_log); 722 err = fq_resize(sch, fq_log);
@@ -749,6 +762,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt)
749 q->delayed = RB_ROOT; 762 q->delayed = RB_ROOT;
750 q->fq_root = NULL; 763 q->fq_root = NULL;
751 q->fq_trees_log = ilog2(1024); 764 q->fq_trees_log = ilog2(1024);
765 q->orphan_mask = 1024 - 1;
752 qdisc_watchdog_init(&q->watchdog, sch); 766 qdisc_watchdog_init(&q->watchdog, sch);
753 767
754 if (opt) 768 if (opt)
@@ -778,6 +792,7 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
778 nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) || 792 nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
779 nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY, 793 nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY,
780 jiffies_to_usecs(q->flow_refill_delay)) || 794 jiffies_to_usecs(q->flow_refill_delay)) ||
795 nla_put_u32(skb, TCA_FQ_ORPHAN_MASK, q->orphan_mask) ||
781 nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) 796 nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
782 goto nla_put_failure; 797 goto nla_put_failure;
783 798