Commit 1471f35efa86407fc180ca6d55363c684d166ef6

Authored by Alex Gartrell
Committed by Simon Horman
1 parent 3481894fcb

ipvs: sh: support scheduling icmp/inverse packets consistently

"source_hash" the dest fields if it's an inverse packet.

Signed-off-by: Alex Gartrell <agartrell@fb.com>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Simon Horman <horms@verge.net.au>

Showing 1 changed file with 21 additions and 24 deletions Side-by-side Diff

net/netfilter/ipvs/ip_vs_sh.c
... ... @@ -280,35 +280,29 @@
280 280 static inline __be16
281 281 ip_vs_sh_get_port(const struct sk_buff *skb, struct ip_vs_iphdr *iph)
282 282 {
283   - __be16 port;
284   - struct tcphdr _tcph, *th;
285   - struct udphdr _udph, *uh;
286   - sctp_sctphdr_t _sctph, *sh;
  283 + __be16 _ports[2], *ports;
287 284  
  285 + /* At this point we know that we have a valid packet of some kind.
  286 + * Because ICMP packets are only guaranteed to have the first 8
  287 + * bytes, let's just grab the ports. Fortunately they're in the
  288 + * same position for all three of the protocols we care about.
  289 + */
288 290 switch (iph->protocol) {
289 291 case IPPROTO_TCP:
290   - th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
291   - if (unlikely(th == NULL))
292   - return 0;
293   - port = th->source;
294   - break;
295 292 case IPPROTO_UDP:
296   - uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
297   - if (unlikely(uh == NULL))
298   - return 0;
299   - port = uh->source;
300   - break;
301 293 case IPPROTO_SCTP:
302   - sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
303   - if (unlikely(sh == NULL))
  294 + ports = skb_header_pointer(skb, iph->len, sizeof(_ports),
  295 + &_ports);
  296 + if (unlikely(!ports))
304 297 return 0;
305   - port = sh->source;
306   - break;
  298 +
  299 + if (likely(!ip_vs_iph_inverse(iph)))
  300 + return ports[0];
  301 + else
  302 + return ports[1];
307 303 default:
308   - port = 0;
  304 + return 0;
309 305 }
310   -
311   - return port;
312 306 }
313 307  
314 308  
315 309  
... ... @@ -322,7 +316,10 @@
322 316 struct ip_vs_dest *dest;
323 317 struct ip_vs_sh_state *s;
324 318 __be16 port = 0;
  319 + const union nf_inet_addr *hash_addr;
325 320  
  321 + hash_addr = ip_vs_iph_inverse(iph) ? &iph->daddr : &iph->saddr;
  322 +
326 323 IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
327 324  
328 325 if (svc->flags & IP_VS_SVC_F_SCHED_SH_PORT)
329 326  
... ... @@ -331,9 +328,9 @@
331 328 s = (struct ip_vs_sh_state *) svc->sched_data;
332 329  
333 330 if (svc->flags & IP_VS_SVC_F_SCHED_SH_FALLBACK)
334   - dest = ip_vs_sh_get_fallback(svc, s, &iph->saddr, port);
  331 + dest = ip_vs_sh_get_fallback(svc, s, hash_addr, port);
335 332 else
336   - dest = ip_vs_sh_get(svc, s, &iph->saddr, port);
  333 + dest = ip_vs_sh_get(svc, s, hash_addr, port);
337 334  
338 335 if (!dest) {
339 336 ip_vs_scheduler_err(svc, "no destination available");
... ... @@ -341,7 +338,7 @@
341 338 }
342 339  
343 340 IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
344   - IP_VS_DBG_ADDR(svc->af, &iph->saddr),
  341 + IP_VS_DBG_ADDR(svc->af, hash_addr),
345 342 IP_VS_DBG_ADDR(dest->af, &dest->addr),
346 343 ntohs(dest->port));
347 344