Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1471f35e authored by Alex Gartrell's avatar Alex Gartrell Committed by Simon Horman
Browse files

ipvs: sh: support scheduling icmp/inverse packets consistently



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

Signed-off-by: default avatarAlex Gartrell <agartrell@fb.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 3481894f
Loading
Loading
Loading
Loading
+21 −24
Original line number Diff line number Diff line
@@ -280,35 +280,29 @@ static int ip_vs_sh_dest_changed(struct ip_vs_service *svc,
static inline __be16
ip_vs_sh_get_port(const struct sk_buff *skb, struct ip_vs_iphdr *iph)
{
	__be16 port;
	struct tcphdr _tcph, *th;
	struct udphdr _udph, *uh;
	sctp_sctphdr_t _sctph, *sh;
	__be16 _ports[2], *ports;

	/* At this point we know that we have a valid packet of some kind.
	 * Because ICMP packets are only guaranteed to have the first 8
	 * bytes, let's just grab the ports.  Fortunately they're in the
	 * same position for all three of the protocols we care about.
	 */
	switch (iph->protocol) {
	case IPPROTO_TCP:
		th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
		if (unlikely(th == NULL))
			return 0;
		port = th->source;
		break;
	case IPPROTO_UDP:
		uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
		if (unlikely(uh == NULL))
			return 0;
		port = uh->source;
		break;
	case IPPROTO_SCTP:
		sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
		if (unlikely(sh == NULL))
		ports = skb_header_pointer(skb, iph->len, sizeof(_ports),
					   &_ports);
		if (unlikely(!ports))
			return 0;
		port = sh->source;
		break;

		if (likely(!ip_vs_iph_inverse(iph)))
			return ports[0];
		else
			return ports[1];
	default:
		port = 0;
		return 0;
	}

	return port;
}


@@ -322,6 +316,9 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
	struct ip_vs_dest *dest;
	struct ip_vs_sh_state *s;
	__be16 port = 0;
	const union nf_inet_addr *hash_addr;

	hash_addr = ip_vs_iph_inverse(iph) ? &iph->daddr : &iph->saddr;

	IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");

@@ -331,9 +328,9 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
	s = (struct ip_vs_sh_state *) svc->sched_data;

	if (svc->flags & IP_VS_SVC_F_SCHED_SH_FALLBACK)
		dest = ip_vs_sh_get_fallback(svc, s, &iph->saddr, port);
		dest = ip_vs_sh_get_fallback(svc, s, hash_addr, port);
	else
		dest = ip_vs_sh_get(svc, s, &iph->saddr, port);
		dest = ip_vs_sh_get(svc, s, hash_addr, port);

	if (!dest) {
		ip_vs_scheduler_err(svc, "no destination available");
@@ -341,7 +338,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
	}

	IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
		      IP_VS_DBG_ADDR(svc->af, &iph->saddr),
		      IP_VS_DBG_ADDR(svc->af, hash_addr),
		      IP_VS_DBG_ADDR(dest->af, &dest->addr),
		      ntohs(dest->port));