Commit ee78378f authored by Alex Gartrell's avatar Alex Gartrell Committed by Simon Horman

ipvs: Make ip_vs_schedule aware of inverse iph'es

This is necessary to schedule icmp later.
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 802c41ad
...@@ -245,20 +245,30 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -245,20 +245,30 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) }; const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
union nf_inet_addr snet; /* source network of the client, union nf_inet_addr snet; /* source network of the client,
after masking */ after masking */
const union nf_inet_addr *src_addr, *dst_addr;
if (likely(!ip_vs_iph_inverse(iph))) {
src_addr = &iph->saddr;
dst_addr = &iph->daddr;
} else {
src_addr = &iph->daddr;
dst_addr = &iph->saddr;
}
/* Mask saddr with the netmask to adjust template granularity */ /* Mask saddr with the netmask to adjust template granularity */
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6) if (svc->af == AF_INET6)
ipv6_addr_prefix(&snet.in6, &iph->saddr.in6, ipv6_addr_prefix(&snet.in6, &src_addr->in6,
(__force __u32) svc->netmask); (__force __u32) svc->netmask);
else else
#endif #endif
snet.ip = iph->saddr.ip & svc->netmask; snet.ip = src_addr->ip & svc->netmask;
IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u " IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
"mnet %s\n", "mnet %s\n",
IP_VS_DBG_ADDR(svc->af, &iph->saddr), ntohs(src_port), IP_VS_DBG_ADDR(svc->af, src_addr), ntohs(src_port),
IP_VS_DBG_ADDR(svc->af, &iph->daddr), ntohs(dst_port), IP_VS_DBG_ADDR(svc->af, dst_addr), ntohs(dst_port),
IP_VS_DBG_ADDR(svc->af, &snet)); IP_VS_DBG_ADDR(svc->af, &snet));
/* /*
...@@ -276,7 +286,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -276,7 +286,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/ */
{ {
int protocol = iph->protocol; int protocol = iph->protocol;
const union nf_inet_addr *vaddr = &iph->daddr; const union nf_inet_addr *vaddr = dst_addr;
__be16 vport = 0; __be16 vport = 0;
if (dst_port == svc->port) { if (dst_port == svc->port) {
...@@ -366,8 +376,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc, ...@@ -366,8 +376,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
/* /*
* Create a new connection according to the template * Create a new connection according to the template
*/ */
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr, ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, src_addr,
src_port, &iph->daddr, dst_port, &param); src_port, dst_addr, dst_port, &param);
cp = ip_vs_conn_new(&param, dest->af, &dest->addr, dport, flags, dest, cp = ip_vs_conn_new(&param, dest->af, &dest->addr, dport, flags, dest,
skb->mark); skb->mark);
...@@ -418,7 +428,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -418,7 +428,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_conn *cp = NULL; struct ip_vs_conn *cp = NULL;
struct ip_vs_scheduler *sched; struct ip_vs_scheduler *sched;
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
__be16 _ports[2], *pptr; __be16 _ports[2], *pptr, cport, vport;
const void *caddr, *vaddr;
unsigned int flags; unsigned int flags;
*ignored = 1; *ignored = 1;
...@@ -429,13 +440,25 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -429,13 +440,25 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
if (pptr == NULL) if (pptr == NULL)
return NULL; return NULL;
if (likely(!ip_vs_iph_inverse(iph))) {
cport = pptr[0];
caddr = &iph->saddr;
vport = pptr[1];
vaddr = &iph->daddr;
} else {
cport = pptr[1];
caddr = &iph->daddr;
vport = pptr[0];
vaddr = &iph->saddr;
}
/* /*
* FTPDATA needs this check when using local real server. * FTPDATA needs this check when using local real server.
* Never schedule Active FTPDATA connections from real server. * Never schedule Active FTPDATA connections from real server.
* For LVS-NAT they must be already created. For other methods * For LVS-NAT they must be already created. For other methods
* with persistence the connection is created on SYN+ACK. * with persistence the connection is created on SYN+ACK.
*/ */
if (pptr[0] == FTPDATA) { if (cport == FTPDATA) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off, IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off,
"Not scheduling FTPDATA"); "Not scheduling FTPDATA");
return NULL; return NULL;
...@@ -462,7 +485,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -462,7 +485,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
* Persistent service * Persistent service
*/ */
if (svc->flags & IP_VS_SVC_F_PERSISTENT) if (svc->flags & IP_VS_SVC_F_PERSISTENT)
return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored, return ip_vs_sched_persist(svc, skb, cport, vport, ignored,
iph); iph);
*ignored = 0; *ignored = 0;
...@@ -470,7 +493,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -470,7 +493,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
/* /*
* Non-persistent service * Non-persistent service
*/ */
if (!svc->fwmark && pptr[1] != svc->port) { if (!svc->fwmark && vport != svc->port) {
if (!svc->port) if (!svc->port)
pr_err("Schedule: port zero only supported " pr_err("Schedule: port zero only supported "
"in persistent services, " "in persistent services, "
...@@ -502,10 +525,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -502,10 +525,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_conn_param p; struct ip_vs_conn_param p;
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
&iph->saddr, pptr[0], &iph->daddr, caddr, cport, vaddr, vport, &p);
pptr[1], &p);
cp = ip_vs_conn_new(&p, dest->af, &dest->addr, cp = ip_vs_conn_new(&p, dest->af, &dest->addr,
dest->port ? dest->port : pptr[1], dest->port ? dest->port : vport,
flags, dest, skb->mark); flags, dest, skb->mark);
if (!cp) { if (!cp) {
*ignored = -1; *ignored = -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment