aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-11-28 22:40:45 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-29 13:17:03 -0500
commit11fca931d35a34d01ce209eb8d51ff667c9f5e7c (patch)
tree540b10f69a7a6c5249674cc1c67f231443fb6c47 /net/sched
parentf07d960df33c5aef8f513efce0fd201f962f94a1 (diff)
sch_sfq: use skb_flow_dissect()
Instead of using a custom flow dissector, use skb_flow_dissect() and benefit from tunnelling support. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/sch_sfq.c65
1 files changed, 10 insertions, 55 deletions
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 4f5510e2bd6f..30cda707e400 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -17,14 +17,13 @@
17#include <linux/in.h> 17#include <linux/in.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/ipv6.h>
21#include <linux/skbuff.h> 20#include <linux/skbuff.h>
22#include <linux/jhash.h> 21#include <linux/jhash.h>
23#include <linux/slab.h> 22#include <linux/slab.h>
24#include <linux/vmalloc.h> 23#include <linux/vmalloc.h>
25#include <net/ip.h>
26#include <net/netlink.h> 24#include <net/netlink.h>
27#include <net/pkt_sched.h> 25#include <net/pkt_sched.h>
26#include <net/flow_keys.h>
28 27
29 28
30/* Stochastic Fairness Queuing algorithm. 29/* Stochastic Fairness Queuing algorithm.
@@ -137,61 +136,17 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index
137 return &q->dep[val - SFQ_SLOTS]; 136 return &q->dep[val - SFQ_SLOTS];
138} 137}
139 138
140static unsigned int sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1) 139static unsigned int sfq_hash(const struct sfq_sched_data *q,
140 const struct sk_buff *skb)
141{ 141{
142 return jhash_2words(h, h1, q->perturbation) & (q->divisor - 1); 142 struct flow_keys keys;
143} 143 unsigned int hash;
144
145static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
146{
147 u32 h, h2;
148
149 switch (skb->protocol) {
150 case htons(ETH_P_IP):
151 {
152 const struct iphdr *iph;
153 int poff;
154
155 if (!pskb_network_may_pull(skb, sizeof(*iph)))
156 goto err;
157 iph = ip_hdr(skb);
158 h = (__force u32)iph->daddr;
159 h2 = (__force u32)iph->saddr ^ iph->protocol;
160 if (ip_is_fragment(iph))
161 break;
162 poff = proto_ports_offset(iph->protocol);
163 if (poff >= 0 &&
164 pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) {
165 iph = ip_hdr(skb);
166 h2 ^= *(u32 *)((void *)iph + iph->ihl * 4 + poff);
167 }
168 break;
169 }
170 case htons(ETH_P_IPV6):
171 {
172 const struct ipv6hdr *iph;
173 int poff;
174
175 if (!pskb_network_may_pull(skb, sizeof(*iph)))
176 goto err;
177 iph = ipv6_hdr(skb);
178 h = (__force u32)iph->daddr.s6_addr32[3];
179 h2 = (__force u32)iph->saddr.s6_addr32[3] ^ iph->nexthdr;
180 poff = proto_ports_offset(iph->nexthdr);
181 if (poff >= 0 &&
182 pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) {
183 iph = ipv6_hdr(skb);
184 h2 ^= *(u32 *)((void *)iph + sizeof(*iph) + poff);
185 }
186 break;
187 }
188 default:
189err:
190 h = (unsigned long)skb_dst(skb) ^ (__force u32)skb->protocol;
191 h2 = (unsigned long)skb->sk;
192 }
193 144
194 return sfq_fold_hash(q, h, h2); 145 skb_flow_dissect(skb, &keys);
146 hash = jhash_3words((__force u32)keys.dst,
147 (__force u32)keys.src ^ keys.ip_proto,
148 (__force u32)keys.ports, q->perturbation);
149 return hash & (q->divisor - 1);
195} 150}
196 151
197static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, 152static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,