* [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).