diff options
-rw-r--r-- | include/uapi/linux/pkt_sched.h | 2 | ||||
-rw-r--r-- | net/sched/sch_fq.c | 19 |
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 | ||