| From 8d6957fe79380bad40501151d2a87336cbd122a2 Mon Sep 17 00:00:00 2001 |
| From: Julian Anastasov <ja@ssi.bg> |
| Date: Mon, 8 Oct 2012 11:41:20 +0000 |
| Subject: ipvs: fix ARP resolving for direct routing mode |
| |
| |
| From: Julian Anastasov <ja@ssi.bg> |
| |
| [ Upstream commit ad4d3ef8b7eb527cca478dc08c02c10936e64115 ] |
| |
| After the change "Make neigh lookups directly in output packet path" |
| (commit a263b30936) IPVS can not reach the real server for DR mode |
| because we resolve the destination address from IP header, not from |
| route neighbour. Use the new FLOWI_FLAG_KNOWN_NH flag to request |
| output routes with known nexthop, so that it has preference |
| on resolving. |
| |
| Signed-off-by: Julian Anastasov <ja@ssi.bg> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/netfilter/ipvs/ip_vs_xmit.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/net/netfilter/ipvs/ip_vs_xmit.c |
| +++ b/net/netfilter/ipvs/ip_vs_xmit.c |
| @@ -49,6 +49,7 @@ enum { |
| IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to |
| * local |
| */ |
| + IP_VS_RT_MODE_KNOWN_NH = 16,/* Route via remote addr */ |
| }; |
| |
| /* |
| @@ -103,6 +104,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, |
| memset(&fl4, 0, sizeof(fl4)); |
| fl4.daddr = dest->addr.ip; |
| fl4.flowi4_tos = rtos; |
| + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? |
| + FLOWI_FLAG_KNOWN_NH : 0; |
| rt = ip_route_output_key(net, &fl4); |
| if (IS_ERR(rt)) { |
| spin_unlock(&dest->dst_lock); |
| @@ -127,6 +130,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, |
| memset(&fl4, 0, sizeof(fl4)); |
| fl4.daddr = daddr; |
| fl4.flowi4_tos = rtos; |
| + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? |
| + FLOWI_FLAG_KNOWN_NH : 0; |
| rt = ip_route_output_key(net, &fl4); |
| if (IS_ERR(rt)) { |
| IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", |
| @@ -1014,7 +1019,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struc |
| if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
| RT_TOS(iph->tos), |
| IP_VS_RT_MODE_LOCAL | |
| - IP_VS_RT_MODE_NON_LOCAL, NULL))) |
| + IP_VS_RT_MODE_NON_LOCAL | |
| + IP_VS_RT_MODE_KNOWN_NH, NULL))) |
| goto tx_error_icmp; |
| if (rt->rt_flags & RTCF_LOCAL) { |
| ip_rt_put(rt); |