diff options
author | Julius Volz <juliusv@google.com> | 2008-09-02 09:55:44 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2008-09-04 21:17:08 -0400 |
commit | 38cdcc9a039b92a9972dca3c954fb3d8b3ef13bf (patch) | |
tree | 8294d515a5863cc767e9dcd3d7a0efb056b2dca8 | |
parent | 28364a59f3dfe7fed3560ec7aff9b7aeb02824fb (diff) |
IPVS: Add IPv6 support to xmit() support functions
Add IPv6 support to IP_VS_XMIT() and to the xmit routing cache, introducing
a new function __ip_vs_get_out_rt_v6().
Signed-off-by: Julius Volz <juliusv@google.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r-- | net/ipv4/ipvs/ip_vs_xmit.c | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 88199c9f2d31..fd8342ec7e15 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <net/udp.h> | 20 | #include <net/udp.h> |
21 | #include <net/icmp.h> /* for icmp_send */ | 21 | #include <net/icmp.h> /* for icmp_send */ |
22 | #include <net/route.h> /* for ip_route_output */ | 22 | #include <net/route.h> /* for ip_route_output */ |
23 | #include <net/ipv6.h> | ||
24 | #include <net/ip6_route.h> | ||
25 | #include <linux/icmpv6.h> | ||
23 | #include <linux/netfilter.h> | 26 | #include <linux/netfilter.h> |
24 | #include <linux/netfilter_ipv4.h> | 27 | #include <linux/netfilter_ipv4.h> |
25 | 28 | ||
@@ -47,7 +50,8 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie) | |||
47 | 50 | ||
48 | if (!dst) | 51 | if (!dst) |
49 | return NULL; | 52 | return NULL; |
50 | if ((dst->obsolete || rtos != dest->dst_rtos) && | 53 | if ((dst->obsolete |
54 | || (dest->af == AF_INET && rtos != dest->dst_rtos)) && | ||
51 | dst->ops->check(dst, cookie) == NULL) { | 55 | dst->ops->check(dst, cookie) == NULL) { |
52 | dest->dst_cache = NULL; | 56 | dest->dst_cache = NULL; |
53 | dst_release(dst); | 57 | dst_release(dst); |
@@ -109,6 +113,70 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) | |||
109 | return rt; | 113 | return rt; |
110 | } | 114 | } |
111 | 115 | ||
116 | #ifdef CONFIG_IP_VS_IPV6 | ||
117 | static struct rt6_info * | ||
118 | __ip_vs_get_out_rt_v6(struct ip_vs_conn *cp) | ||
119 | { | ||
120 | struct rt6_info *rt; /* Route to the other host */ | ||
121 | struct ip_vs_dest *dest = cp->dest; | ||
122 | |||
123 | if (dest) { | ||
124 | spin_lock(&dest->dst_lock); | ||
125 | rt = (struct rt6_info *)__ip_vs_dst_check(dest, 0, 0); | ||
126 | if (!rt) { | ||
127 | struct flowi fl = { | ||
128 | .oif = 0, | ||
129 | .nl_u = { | ||
130 | .ip6_u = { | ||
131 | .daddr = dest->addr.in6, | ||
132 | .saddr = { | ||
133 | .s6_addr32 = | ||
134 | { 0, 0, 0, 0 }, | ||
135 | }, | ||
136 | }, | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | rt = (struct rt6_info *)ip6_route_output(&init_net, | ||
141 | NULL, &fl); | ||
142 | if (!rt) { | ||
143 | spin_unlock(&dest->dst_lock); | ||
144 | IP_VS_DBG_RL("ip6_route_output error, " | ||
145 | "dest: " NIP6_FMT "\n", | ||
146 | NIP6(dest->addr.in6)); | ||
147 | return NULL; | ||
148 | } | ||
149 | __ip_vs_dst_set(dest, 0, dst_clone(&rt->u.dst)); | ||
150 | IP_VS_DBG(10, "new dst " NIP6_FMT ", refcnt=%d\n", | ||
151 | NIP6(dest->addr.in6), | ||
152 | atomic_read(&rt->u.dst.__refcnt)); | ||
153 | } | ||
154 | spin_unlock(&dest->dst_lock); | ||
155 | } else { | ||
156 | struct flowi fl = { | ||
157 | .oif = 0, | ||
158 | .nl_u = { | ||
159 | .ip6_u = { | ||
160 | .daddr = cp->daddr.in6, | ||
161 | .saddr = { | ||
162 | .s6_addr32 = { 0, 0, 0, 0 }, | ||
163 | }, | ||
164 | }, | ||
165 | }, | ||
166 | }; | ||
167 | |||
168 | rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl); | ||
169 | if (!rt) { | ||
170 | IP_VS_DBG_RL("ip6_route_output error, dest: " | ||
171 | NIP6_FMT "\n", NIP6(cp->daddr.in6)); | ||
172 | return NULL; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | return rt; | ||
177 | } | ||
178 | #endif | ||
179 | |||
112 | 180 | ||
113 | /* | 181 | /* |
114 | * Release dest->dst_cache before a dest is removed | 182 | * Release dest->dst_cache before a dest is removed |
@@ -123,11 +191,11 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) | |||
123 | dst_release(old_dst); | 191 | dst_release(old_dst); |
124 | } | 192 | } |
125 | 193 | ||
126 | #define IP_VS_XMIT(skb, rt) \ | 194 | #define IP_VS_XMIT(pf, skb, rt) \ |
127 | do { \ | 195 | do { \ |
128 | (skb)->ipvs_property = 1; \ | 196 | (skb)->ipvs_property = 1; \ |
129 | skb_forward_csum(skb); \ | 197 | skb_forward_csum(skb); \ |
130 | NF_HOOK(PF_INET, NF_INET_LOCAL_OUT, (skb), NULL, \ | 198 | NF_HOOK(pf, NF_INET_LOCAL_OUT, (skb), NULL, \ |
131 | (rt)->u.dst.dev, dst_output); \ | 199 | (rt)->u.dst.dev, dst_output); \ |
132 | } while (0) | 200 | } while (0) |
133 | 201 | ||
@@ -200,7 +268,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
200 | /* Another hack: avoid icmp_send in ip_fragment */ | 268 | /* Another hack: avoid icmp_send in ip_fragment */ |
201 | skb->local_df = 1; | 269 | skb->local_df = 1; |
202 | 270 | ||
203 | IP_VS_XMIT(skb, rt); | 271 | IP_VS_XMIT(PF_INET, skb, rt); |
204 | 272 | ||
205 | LeaveFunction(10); | 273 | LeaveFunction(10); |
206 | return NF_STOLEN; | 274 | return NF_STOLEN; |
@@ -276,7 +344,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
276 | /* Another hack: avoid icmp_send in ip_fragment */ | 344 | /* Another hack: avoid icmp_send in ip_fragment */ |
277 | skb->local_df = 1; | 345 | skb->local_df = 1; |
278 | 346 | ||
279 | IP_VS_XMIT(skb, rt); | 347 | IP_VS_XMIT(PF_INET, skb, rt); |
280 | 348 | ||
281 | LeaveFunction(10); | 349 | LeaveFunction(10); |
282 | return NF_STOLEN; | 350 | return NF_STOLEN; |
@@ -467,7 +535,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
467 | /* Another hack: avoid icmp_send in ip_fragment */ | 535 | /* Another hack: avoid icmp_send in ip_fragment */ |
468 | skb->local_df = 1; | 536 | skb->local_df = 1; |
469 | 537 | ||
470 | IP_VS_XMIT(skb, rt); | 538 | IP_VS_XMIT(PF_INET, skb, rt); |
471 | 539 | ||
472 | LeaveFunction(10); | 540 | LeaveFunction(10); |
473 | return NF_STOLEN; | 541 | return NF_STOLEN; |
@@ -540,7 +608,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
540 | /* Another hack: avoid icmp_send in ip_fragment */ | 608 | /* Another hack: avoid icmp_send in ip_fragment */ |
541 | skb->local_df = 1; | 609 | skb->local_df = 1; |
542 | 610 | ||
543 | IP_VS_XMIT(skb, rt); | 611 | IP_VS_XMIT(PF_INET, skb, rt); |
544 | 612 | ||
545 | rc = NF_STOLEN; | 613 | rc = NF_STOLEN; |
546 | goto out; | 614 | goto out; |