* [PATCH 7/10] ipvs: Remove all remaining references to rt->rt_{src,dst} @ 2011-05-10 5:31 David Miller 2011-05-10 22:46 ` Julian Anastasov 0 siblings, 1 reply; 3+ messages in thread From: David Miller @ 2011-05-10 5:31 UTC (permalink / raw) To: netdev These values are always obtainable via the ip_vs_conn flow key. Signed-off-by: David S. Miller <davem@davemloft.net> --- net/netfilter/ipvs/ip_vs_core.c | 2 +- net/netfilter/ipvs/ip_vs_xmit.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 07accf6..fa8c1fd 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1384,7 +1384,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) skb_rtable(skb)->rt_flags & RTCF_LOCAL) { IP_VS_DBG(1, "%s(): " "local delivery to %pI4 but in FORWARD\n", - __func__, &skb_rtable(skb)->rt_dst); + __func__, &cp->fl.u.ip4.daddr); verdict = NF_DROP; } diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 2a300fe..99e7644 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -510,6 +510,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct rtable *rt; /* Route to the other host */ int mtu; struct iphdr *iph = ip_hdr(skb); + struct flowi4 *fl4; int local; EnterFunction(10); @@ -549,8 +550,10 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, } #endif + fl4 = &cp->fl.u.ip4; + /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(fl4->daddr) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " "stopping DNAT to loopback address"); @@ -767,6 +770,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, __be16 df = old_iph->frag_off; struct iphdr *iph; /* Our new IP header */ unsigned int max_headroom; /* The extra header space needed */ + struct flowi4 *fl4; int mtu; int ret; @@ -833,6 +837,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, skb_dst_drop(skb); skb_dst_set(skb, &rt->dst); + fl4 = &cp->fl.u.ip4; + /* * Push down and install the IPIP header. */ @@ -842,8 +848,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, iph->frag_off = df; iph->protocol = IPPROTO_IPIP; iph->tos = tos; - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = fl4->daddr; + iph->saddr = fl4->saddr; iph->ttl = old_iph->ttl; ip_select_ident(iph, &rt->dst, NULL); @@ -1127,6 +1133,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, int offset) { struct rtable *rt; /* Route to the other host */ + struct flowi4 *fl4; int mtu; int rc; int local; @@ -1176,8 +1183,10 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, } #endif + fl4 = &cp->fl.u.ip4; + /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(fl4->daddr) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG(1, "%s(): " "stopping DNAT to loopback %pI4\n", -- 1.7.5.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 7/10] ipvs: Remove all remaining references to rt->rt_{src,dst} 2011-05-10 5:31 [PATCH 7/10] ipvs: Remove all remaining references to rt->rt_{src,dst} David Miller @ 2011-05-10 22:46 ` Julian Anastasov 2011-05-13 5:35 ` Hans Schillstrom 0 siblings, 1 reply; 3+ messages in thread From: Julian Anastasov @ 2011-05-10 22:46 UTC (permalink / raw) To: David Miller; +Cc: netdev Remove all remaining references to rt->rt_{src,dst} by using dest->dst_saddr to cache saddr (used for TUN mode). For ICMP in FORWARD hook just restrict the rt_mode for NAT to disable LOCALNODE. All other modes do not allow IP_VS_RT_MODE_RDR, so we should be safe with the ICMP forwarding. Using cp->daddr as replacement for rt_dst is safe for all modes except BYPASS, even when cp->dest is NULL because it is cp->daddr that is used to assign cp->dest for sync-ed connections. Signed-off-by: Julian Anastasov <ja@ssi.bg> --- I'm proposing this patch as replacement for original patches 6 and 7, it can be number 7 again. The idea is to avoid storing flowi in cp. diff -urp net-next-2.6-7ef73bc/linux/include/net/ip_vs.h linux/include/net/ip_vs.h --- net-next-2.6-7ef73bc/linux/include/net/ip_vs.h 2011-05-09 07:24:07.000000000 +0300 +++ linux/include/net/ip_vs.h 2011-05-11 00:46:02.510271856 +0300 @@ -665,9 +665,7 @@ struct ip_vs_dest { struct dst_entry *dst_cache; /* destination cache entry */ u32 dst_rtos; /* RT_TOS(tos) for dst */ u32 dst_cookie; -#ifdef CONFIG_IP_VS_IPV6 - struct in6_addr dst_saddr; -#endif + union nf_inet_addr dst_saddr; /* for virtual service */ struct ip_vs_service *svc; /* service it belongs to */ @@ -1236,7 +1234,8 @@ extern int ip_vs_tunnel_xmit extern int ip_vs_dr_xmit (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); extern int ip_vs_icmp_xmit -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, int offset); +(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, + int offset, unsigned int hooknum); extern void ip_vs_dst_reset(struct ip_vs_dest *dest); #ifdef CONFIG_IP_VS_IPV6 @@ -1250,7 +1249,7 @@ extern int ip_vs_dr_xmit_v6 (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); extern int ip_vs_icmp_xmit_v6 (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, - int offset); + int offset, unsigned int hooknum); #endif #ifdef CONFIG_SYSCTL diff -urp net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_core.c linux/net/netfilter/ipvs/ip_vs_core.c --- net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_core.c 2011-05-09 07:24:07.000000000 +0300 +++ linux/net/netfilter/ipvs/ip_vs_core.c 2011-05-11 01:07:29.429270382 +0300 @@ -1378,15 +1378,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int * ip_vs_in_stats(cp, skb); if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) offset += 2 * sizeof(__u16); - verdict = ip_vs_icmp_xmit(skb, cp, pp, offset); - /* LOCALNODE from FORWARD hook is not supported */ - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && - skb_rtable(skb)->rt_flags & RTCF_LOCAL) { - IP_VS_DBG(1, "%s(): " - "local delivery to %pI4 but in FORWARD\n", - __func__, &skb_rtable(skb)->rt_dst); - verdict = NF_DROP; - } + verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum); out: __ip_vs_conn_put(cp); @@ -1408,7 +1400,6 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, in struct ip_vs_protocol *pp; struct ip_vs_proto_data *pd; unsigned int offset, verdict; - struct rt6_info *rt; *related = 1; @@ -1470,23 +1461,12 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, in if (!cp) return NF_ACCEPT; - verdict = NF_DROP; - /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || IPPROTO_SCTP == cih->nexthdr) offset += 2 * sizeof(__u16); - verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); - /* LOCALNODE from FORWARD hook is not supported */ - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && - (rt = (struct rt6_info *) skb_dst(skb)) && - rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) { - IP_VS_DBG(1, "%s(): " - "local delivery to %pI6 but in FORWARD\n", - __func__, &rt->rt6i_dst); - verdict = NF_DROP; - } + verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum); __ip_vs_conn_put(cp); diff -urp net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_xmit.c linux/net/netfilter/ipvs/ip_vs_xmit.c --- net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_xmit.c 2011-05-10 23:52:06.000000000 +0300 +++ linux/net/netfilter/ipvs/ip_vs_xmit.c 2011-05-11 01:08:21.837272458 +0300 @@ -87,7 +87,7 @@ __ip_vs_dst_check(struct ip_vs_dest *des /* Get route to destination or remote server */ static struct rtable * __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, - __be32 daddr, u32 rtos, int rt_mode) + __be32 daddr, u32 rtos, int rt_mode, __be32 *ret_saddr) { struct net *net = dev_net(skb_dst(skb)->dev); struct rtable *rt; /* Route to the other host */ @@ -98,7 +98,12 @@ __ip_vs_get_out_rt(struct sk_buff *skb, spin_lock(&dest->dst_lock); if (!(rt = (struct rtable *) __ip_vs_dst_check(dest, rtos))) { - rt = ip_route_output(net, dest->addr.ip, 0, rtos, 0); + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = dest->addr.ip; + fl4.flowi4_tos = rtos; + rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { spin_unlock(&dest->dst_lock); IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", @@ -106,19 +111,30 @@ __ip_vs_get_out_rt(struct sk_buff *skb, return NULL; } __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); - IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n", - &dest->addr.ip, + dest->dst_saddr.ip = fl4.saddr; + IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " + "rtos=%X\n", + &dest->addr.ip, &dest->dst_saddr.ip, atomic_read(&rt->dst.__refcnt), rtos); } daddr = dest->addr.ip; + if (ret_saddr) + *ret_saddr = dest->dst_saddr.ip; spin_unlock(&dest->dst_lock); } else { - rt = ip_route_output(net, daddr, 0, rtos, 0); + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; + fl4.flowi4_tos = rtos; + rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) { IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr); return NULL; } + if (ret_saddr) + *ret_saddr = fl4.saddr; } local = rt->rt_flags & RTCF_LOCAL; @@ -249,7 +265,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *sk u32 cookie; dst = __ip_vs_route_output_v6(net, &dest->addr.in6, - &dest->dst_saddr, + &dest->dst_saddr.in6, do_xfrm); if (!dst) { spin_unlock(&dest->dst_lock); @@ -259,11 +275,11 @@ __ip_vs_get_out_rt_v6(struct sk_buff *sk cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; __ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie); IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n", - &dest->addr.in6, &dest->dst_saddr, + &dest->addr.in6, &dest->dst_saddr.in6, atomic_read(&rt->dst.__refcnt)); } if (ret_saddr) - ipv6_addr_copy(ret_saddr, &dest->dst_saddr); + ipv6_addr_copy(ret_saddr, &dest->dst_saddr.in6); spin_unlock(&dest->dst_lock); } else { dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm); @@ -386,7 +402,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, s EnterFunction(10); if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos), - IP_VS_RT_MODE_NON_LOCAL))) + IP_VS_RT_MODE_NON_LOCAL, NULL))) goto tx_error_icmp; /* MTU checking */ @@ -518,7 +534,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, stru RT_TOS(iph->tos), IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR))) + IP_VS_RT_MODE_RDR, NULL))) goto tx_error_icmp; local = rt->rt_flags & RTCF_LOCAL; /* @@ -540,7 +556,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, stru #endif /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(cp->daddr.ip) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " "stopping DNAT to loopback address"); @@ -751,6 +767,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s struct ip_vs_protocol *pp) { struct rtable *rt; /* Route to the other host */ + __be32 saddr; /* Source for tunnel */ struct net_device *tdev; /* Device to other host */ struct iphdr *old_iph = ip_hdr(skb); u8 tos = old_iph->tos; @@ -764,7 +781,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(tos), IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL))) + IP_VS_RT_MODE_NON_LOCAL, + &saddr))) goto tx_error_icmp; if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); @@ -832,8 +850,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s iph->frag_off = df; iph->protocol = IPPROTO_IPIP; iph->tos = tos; - iph->daddr = rt->rt_dst; - iph->saddr = rt->rt_src; + iph->daddr = cp->daddr.ip; + iph->saddr = saddr; iph->ttl = old_iph->ttl; ip_select_ident(iph, &rt->dst, NULL); @@ -996,7 +1014,7 @@ 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))) + IP_VS_RT_MODE_NON_LOCAL, NULL))) goto tx_error_icmp; if (rt->rt_flags & RTCF_LOCAL) { ip_rt_put(rt); @@ -1114,12 +1132,13 @@ tx_error: */ int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset) + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) { struct rtable *rt; /* Route to the other host */ int mtu; int rc; int local; + int rt_mode; EnterFunction(10); @@ -1140,11 +1159,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str * mangle and send the packet here (only for VS/NAT) */ + /* LOCALNODE from FORWARD hook is not supported */ + rt_mode = (hooknum != NF_INET_FORWARD) ? + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, RT_TOS(ip_hdr(skb)->tos), - IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR))) + rt_mode, NULL))) goto tx_error_icmp; local = rt->rt_flags & RTCF_LOCAL; @@ -1167,7 +1188,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str #endif /* From world but DNAT to loopback address? */ - if (local && ipv4_is_loopback(rt->rt_dst) && + if (local && ipv4_is_loopback(cp->daddr.ip) && rt_is_input_route(skb_rtable(skb))) { IP_VS_DBG(1, "%s(): " "stopping DNAT to loopback %pI4\n", @@ -1232,12 +1253,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str #ifdef CONFIG_IP_VS_IPV6 int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, int offset) + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) { struct rt6_info *rt; /* Route to the other host */ int mtu; int rc; int local; + int rt_mode; EnterFunction(10); @@ -1258,10 +1280,12 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, * mangle and send the packet here (only for VS/NAT) */ + /* LOCALNODE from FORWARD hook is not supported */ + rt_mode = (hooknum != NF_INET_FORWARD) ? + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, - 0, (IP_VS_RT_MODE_LOCAL | - IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR)))) + 0, rt_mode))) goto tx_error_icmp; local = __ip_vs_is_local_route6(rt); ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 7/10] ipvs: Remove all remaining references to rt->rt_{src,dst} 2011-05-10 22:46 ` Julian Anastasov @ 2011-05-13 5:35 ` Hans Schillstrom 0 siblings, 0 replies; 3+ messages in thread From: Hans Schillstrom @ 2011-05-13 5:35 UTC (permalink / raw) To: Julian Anastasov; +Cc: David Miller, netdev@vger.kernel.org On Wednesday 11 May 2011 00:46:05 Julian Anastasov wrote: > > Remove all remaining references to rt->rt_{src,dst} > by using dest->dst_saddr to cache saddr (used for TUN mode). > For ICMP in FORWARD hook just restrict the rt_mode for NAT > to disable LOCALNODE. All other modes do not allow > IP_VS_RT_MODE_RDR, so we should be safe with the ICMP > forwarding. Using cp->daddr as replacement for rt_dst > is safe for all modes except BYPASS, even when cp->dest is > NULL because it is cp->daddr that is used to assign cp->dest > for sync-ed connections. > No problems found after two days of testing. > Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com> > --- > > I'm proposing this patch as replacement for > original patches 6 and 7, it can be number 7 again. > The idea is to avoid storing flowi in cp. > > diff -urp net-next-2.6-7ef73bc/linux/include/net/ip_vs.h linux/include/net/ip_vs.h > --- net-next-2.6-7ef73bc/linux/include/net/ip_vs.h 2011-05-09 07:24:07.000000000 +0300 > +++ linux/include/net/ip_vs.h 2011-05-11 00:46:02.510271856 +0300 > @@ -665,9 +665,7 @@ struct ip_vs_dest { > struct dst_entry *dst_cache; /* destination cache entry */ > u32 dst_rtos; /* RT_TOS(tos) for dst */ > u32 dst_cookie; > -#ifdef CONFIG_IP_VS_IPV6 > - struct in6_addr dst_saddr; > -#endif > + union nf_inet_addr dst_saddr; > > /* for virtual service */ > struct ip_vs_service *svc; /* service it belongs to */ > @@ -1236,7 +1234,8 @@ extern int ip_vs_tunnel_xmit > extern int ip_vs_dr_xmit > (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); > extern int ip_vs_icmp_xmit > -(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, int offset); > +(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, > + int offset, unsigned int hooknum); > extern void ip_vs_dst_reset(struct ip_vs_dest *dest); > > #ifdef CONFIG_IP_VS_IPV6 > @@ -1250,7 +1249,7 @@ extern int ip_vs_dr_xmit_v6 > (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp); > extern int ip_vs_icmp_xmit_v6 > (struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, > - int offset); > + int offset, unsigned int hooknum); > #endif > > #ifdef CONFIG_SYSCTL > diff -urp net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_core.c linux/net/netfilter/ipvs/ip_vs_core.c > --- net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_core.c 2011-05-09 07:24:07.000000000 +0300 > +++ linux/net/netfilter/ipvs/ip_vs_core.c 2011-05-11 01:07:29.429270382 +0300 > @@ -1378,15 +1378,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int * > ip_vs_in_stats(cp, skb); > if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) > offset += 2 * sizeof(__u16); > - verdict = ip_vs_icmp_xmit(skb, cp, pp, offset); > - /* LOCALNODE from FORWARD hook is not supported */ > - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && > - skb_rtable(skb)->rt_flags & RTCF_LOCAL) { > - IP_VS_DBG(1, "%s(): " > - "local delivery to %pI4 but in FORWARD\n", > - __func__, &skb_rtable(skb)->rt_dst); > - verdict = NF_DROP; > - } > + verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum); > > out: > __ip_vs_conn_put(cp); > @@ -1408,7 +1400,6 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, in > struct ip_vs_protocol *pp; > struct ip_vs_proto_data *pd; > unsigned int offset, verdict; > - struct rt6_info *rt; > > *related = 1; > > @@ -1470,23 +1461,12 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, in > if (!cp) > return NF_ACCEPT; > > - verdict = NF_DROP; > - > /* do the statistics and put it back */ > ip_vs_in_stats(cp, skb); > if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || > IPPROTO_SCTP == cih->nexthdr) > offset += 2 * sizeof(__u16); > - verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); > - /* LOCALNODE from FORWARD hook is not supported */ > - if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && > - (rt = (struct rt6_info *) skb_dst(skb)) && > - rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) { > - IP_VS_DBG(1, "%s(): " > - "local delivery to %pI6 but in FORWARD\n", > - __func__, &rt->rt6i_dst); > - verdict = NF_DROP; > - } > + verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum); > > __ip_vs_conn_put(cp); > > diff -urp net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_xmit.c linux/net/netfilter/ipvs/ip_vs_xmit.c > --- net-next-2.6-7ef73bc/linux/net/netfilter/ipvs/ip_vs_xmit.c 2011-05-10 23:52:06.000000000 +0300 > +++ linux/net/netfilter/ipvs/ip_vs_xmit.c 2011-05-11 01:08:21.837272458 +0300 > @@ -87,7 +87,7 @@ __ip_vs_dst_check(struct ip_vs_dest *des > /* Get route to destination or remote server */ > static struct rtable * > __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, > - __be32 daddr, u32 rtos, int rt_mode) > + __be32 daddr, u32 rtos, int rt_mode, __be32 *ret_saddr) > { > struct net *net = dev_net(skb_dst(skb)->dev); > struct rtable *rt; /* Route to the other host */ > @@ -98,7 +98,12 @@ __ip_vs_get_out_rt(struct sk_buff *skb, > spin_lock(&dest->dst_lock); > if (!(rt = (struct rtable *) > __ip_vs_dst_check(dest, rtos))) { > - rt = ip_route_output(net, dest->addr.ip, 0, rtos, 0); > + struct flowi4 fl4; > + > + memset(&fl4, 0, sizeof(fl4)); > + fl4.daddr = dest->addr.ip; > + fl4.flowi4_tos = rtos; > + rt = ip_route_output_key(net, &fl4); > if (IS_ERR(rt)) { > spin_unlock(&dest->dst_lock); > IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", > @@ -106,19 +111,30 @@ __ip_vs_get_out_rt(struct sk_buff *skb, > return NULL; > } > __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); > - IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n", > - &dest->addr.ip, > + dest->dst_saddr.ip = fl4.saddr; > + IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " > + "rtos=%X\n", > + &dest->addr.ip, &dest->dst_saddr.ip, > atomic_read(&rt->dst.__refcnt), rtos); > } > daddr = dest->addr.ip; > + if (ret_saddr) > + *ret_saddr = dest->dst_saddr.ip; > spin_unlock(&dest->dst_lock); > } else { > - rt = ip_route_output(net, daddr, 0, rtos, 0); > + struct flowi4 fl4; > + > + memset(&fl4, 0, sizeof(fl4)); > + fl4.daddr = daddr; > + fl4.flowi4_tos = rtos; > + rt = ip_route_output_key(net, &fl4); > if (IS_ERR(rt)) { > IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", > &daddr); > return NULL; > } > + if (ret_saddr) > + *ret_saddr = fl4.saddr; > } > > local = rt->rt_flags & RTCF_LOCAL; > @@ -249,7 +265,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *sk > u32 cookie; > > dst = __ip_vs_route_output_v6(net, &dest->addr.in6, > - &dest->dst_saddr, > + &dest->dst_saddr.in6, > do_xfrm); > if (!dst) { > spin_unlock(&dest->dst_lock); > @@ -259,11 +275,11 @@ __ip_vs_get_out_rt_v6(struct sk_buff *sk > cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; > __ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie); > IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n", > - &dest->addr.in6, &dest->dst_saddr, > + &dest->addr.in6, &dest->dst_saddr.in6, > atomic_read(&rt->dst.__refcnt)); > } > if (ret_saddr) > - ipv6_addr_copy(ret_saddr, &dest->dst_saddr); > + ipv6_addr_copy(ret_saddr, &dest->dst_saddr.in6); > spin_unlock(&dest->dst_lock); > } else { > dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm); > @@ -386,7 +402,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, s > EnterFunction(10); > > if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos), > - IP_VS_RT_MODE_NON_LOCAL))) > + IP_VS_RT_MODE_NON_LOCAL, NULL))) > goto tx_error_icmp; > > /* MTU checking */ > @@ -518,7 +534,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, stru > RT_TOS(iph->tos), > IP_VS_RT_MODE_LOCAL | > IP_VS_RT_MODE_NON_LOCAL | > - IP_VS_RT_MODE_RDR))) > + IP_VS_RT_MODE_RDR, NULL))) > goto tx_error_icmp; > local = rt->rt_flags & RTCF_LOCAL; > /* > @@ -540,7 +556,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, stru > #endif > > /* From world but DNAT to loopback address? */ > - if (local && ipv4_is_loopback(rt->rt_dst) && > + if (local && ipv4_is_loopback(cp->daddr.ip) && > rt_is_input_route(skb_rtable(skb))) { > IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " > "stopping DNAT to loopback address"); > @@ -751,6 +767,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s > struct ip_vs_protocol *pp) > { > struct rtable *rt; /* Route to the other host */ > + __be32 saddr; /* Source for tunnel */ > struct net_device *tdev; /* Device to other host */ > struct iphdr *old_iph = ip_hdr(skb); > u8 tos = old_iph->tos; > @@ -764,7 +781,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s > > if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, > RT_TOS(tos), IP_VS_RT_MODE_LOCAL | > - IP_VS_RT_MODE_NON_LOCAL))) > + IP_VS_RT_MODE_NON_LOCAL, > + &saddr))) > goto tx_error_icmp; > if (rt->rt_flags & RTCF_LOCAL) { > ip_rt_put(rt); > @@ -832,8 +850,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, s > iph->frag_off = df; > iph->protocol = IPPROTO_IPIP; > iph->tos = tos; > - iph->daddr = rt->rt_dst; > - iph->saddr = rt->rt_src; > + iph->daddr = cp->daddr.ip; > + iph->saddr = saddr; > iph->ttl = old_iph->ttl; > ip_select_ident(iph, &rt->dst, NULL); > > @@ -996,7 +1014,7 @@ 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))) > + IP_VS_RT_MODE_NON_LOCAL, NULL))) > goto tx_error_icmp; > if (rt->rt_flags & RTCF_LOCAL) { > ip_rt_put(rt); > @@ -1114,12 +1132,13 @@ tx_error: > */ > int > ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, > - struct ip_vs_protocol *pp, int offset) > + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) > { > struct rtable *rt; /* Route to the other host */ > int mtu; > int rc; > int local; > + int rt_mode; > > EnterFunction(10); > > @@ -1140,11 +1159,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str > * mangle and send the packet here (only for VS/NAT) > */ > > + /* LOCALNODE from FORWARD hook is not supported */ > + rt_mode = (hooknum != NF_INET_FORWARD) ? > + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | > + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; > if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, > RT_TOS(ip_hdr(skb)->tos), > - IP_VS_RT_MODE_LOCAL | > - IP_VS_RT_MODE_NON_LOCAL | > - IP_VS_RT_MODE_RDR))) > + rt_mode, NULL))) > goto tx_error_icmp; > local = rt->rt_flags & RTCF_LOCAL; > > @@ -1167,7 +1188,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str > #endif > > /* From world but DNAT to loopback address? */ > - if (local && ipv4_is_loopback(rt->rt_dst) && > + if (local && ipv4_is_loopback(cp->daddr.ip) && > rt_is_input_route(skb_rtable(skb))) { > IP_VS_DBG(1, "%s(): " > "stopping DNAT to loopback %pI4\n", > @@ -1232,12 +1253,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, str > #ifdef CONFIG_IP_VS_IPV6 > int > ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, > - struct ip_vs_protocol *pp, int offset) > + struct ip_vs_protocol *pp, int offset, unsigned int hooknum) > { > struct rt6_info *rt; /* Route to the other host */ > int mtu; > int rc; > int local; > + int rt_mode; > > EnterFunction(10); > > @@ -1258,10 +1280,12 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, > * mangle and send the packet here (only for VS/NAT) > */ > > + /* LOCALNODE from FORWARD hook is not supported */ > + rt_mode = (hooknum != NF_INET_FORWARD) ? > + IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | > + IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; > if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, > - 0, (IP_VS_RT_MODE_LOCAL | > - IP_VS_RT_MODE_NON_LOCAL | > - IP_VS_RT_MODE_RDR)))) > + 0, rt_mode))) > goto tx_error_icmp; > > local = __ip_vs_is_local_route6(rt); > -- > To unsubscribe from this list: send the line "unsubscribe netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- Regards Hans Schillstrom <hans.schillstrom@ericsson.com> ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-05-13 5:42 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-05-10 5:31 [PATCH 7/10] ipvs: Remove all remaining references to rt->rt_{src,dst} David Miller 2011-05-10 22:46 ` Julian Anastasov 2011-05-13 5:35 ` Hans Schillstrom
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).