aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-11-08 05:45:04 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-08 16:41:31 -0500
commit9ecd04bc04af7df98b3a93c571e31b6ef6a90681 (patch)
tree3850ea9ffad64f46cfa20ac7b9a2c8e0f4b56517 /net/sched
parent8d8bdfe8034399357df58b5f3e4da638a9e9a257 (diff)
sch_choke: use skb_header_pointer()
Remove the assumption that skb_get_rxhash() makes IP header and ports linear, and use skb_header_pointer() instead in choke_match_flow() This permits __skb_get_rxhash() to use skb_header_pointer() eventually. 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_choke.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 3422b25df9e4..061bcb744bbd 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -152,15 +152,14 @@ static bool choke_match_flow(struct sk_buff *skb1,
152{ 152{
153 int off1, off2, poff; 153 int off1, off2, poff;
154 const u32 *ports1, *ports2; 154 const u32 *ports1, *ports2;
155 u32 _ports1, _ports2;
155 u8 ip_proto; 156 u8 ip_proto;
156 __u32 hash1; 157 __u32 hash1;
157 158
158 if (skb1->protocol != skb2->protocol) 159 if (skb1->protocol != skb2->protocol)
159 return false; 160 return false;
160 161
161 /* Use hash value as quick check 162 /* Use rxhash value as quick check */
162 * Assumes that __skb_get_rxhash makes IP header and ports linear
163 */
164 hash1 = skb_get_rxhash(skb1); 163 hash1 = skb_get_rxhash(skb1);
165 if (!hash1 || hash1 != skb_get_rxhash(skb2)) 164 if (!hash1 || hash1 != skb_get_rxhash(skb2))
166 return false; 165 return false;
@@ -172,10 +171,12 @@ static bool choke_match_flow(struct sk_buff *skb1,
172 switch (skb1->protocol) { 171 switch (skb1->protocol) {
173 case __constant_htons(ETH_P_IP): { 172 case __constant_htons(ETH_P_IP): {
174 const struct iphdr *ip1, *ip2; 173 const struct iphdr *ip1, *ip2;
174 struct iphdr _ip1, _ip2;
175 175
176 ip1 = (const struct iphdr *) (skb1->data + off1); 176 ip1 = skb_header_pointer(skb1, off1, sizeof(_ip1), &_ip1);
177 ip2 = (const struct iphdr *) (skb2->data + off2); 177 ip2 = skb_header_pointer(skb2, off2, sizeof(_ip2), &_ip2);
178 178 if (!ip1 || !ip2)
179 return false;
179 ip_proto = ip1->protocol; 180 ip_proto = ip1->protocol;
180 if (ip_proto != ip2->protocol || 181 if (ip_proto != ip2->protocol ||
181 ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr) 182 ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr)
@@ -190,9 +191,12 @@ static bool choke_match_flow(struct sk_buff *skb1,
190 191
191 case __constant_htons(ETH_P_IPV6): { 192 case __constant_htons(ETH_P_IPV6): {
192 const struct ipv6hdr *ip1, *ip2; 193 const struct ipv6hdr *ip1, *ip2;
194 struct ipv6hdr _ip1, _ip2;
193 195
194 ip1 = (const struct ipv6hdr *) (skb1->data + off1); 196 ip1 = skb_header_pointer(skb1, off1, sizeof(_ip1), &_ip1);
195 ip2 = (const struct ipv6hdr *) (skb2->data + off2); 197 ip2 = skb_header_pointer(skb2, off2, sizeof(_ip2), &_ip2);
198 if (!ip1 || !ip2)
199 return false;
196 200
197 ip_proto = ip1->nexthdr; 201 ip_proto = ip1->nexthdr;
198 if (ip_proto != ip2->nexthdr || 202 if (ip_proto != ip2->nexthdr ||
@@ -214,8 +218,11 @@ static bool choke_match_flow(struct sk_buff *skb1,
214 off1 += poff; 218 off1 += poff;
215 off2 += poff; 219 off2 += poff;
216 220
217 ports1 = (__force u32 *)(skb1->data + off1); 221 ports1 = skb_header_pointer(skb1, off1, sizeof(_ports1), &_ports1);
218 ports2 = (__force u32 *)(skb2->data + off2); 222 ports2 = skb_header_pointer(skb2, off2, sizeof(_ports2), &_ports2);
223 if (!ports1 || !ports2)
224 return false;
225
219 return *ports1 == *ports2; 226 return *ports1 == *ports2;
220} 227}
221 228