From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Julius R. Volz" Subject: [PATCH 14/26] IPVS: Extend xmit routing cache to support IPv6. Date: Wed, 11 Jun 2008 19:11:57 +0200 Message-ID: <1213204329-10973-15-git-send-email-juliusv@google.com> References: <1213204329-10973-1-git-send-email-juliusv@google.com> Cc: horms@verge.net.au, davem@davemloft.net, vbusam@google.com, "Julius R. Volz" To: lvs-devel@vger.kernel.org, netdev@vger.kernel.org Return-path: In-Reply-To: <1213204329-10973-1-git-send-email-juliusv@google.com> Sender: lvs-devel-owner@vger.kernel.org List-Id: netdev.vger.kernel.org Extend xmit destination routing cache to support lookup of IPv6 destinations. Signed-off-by: Julius R. Volz 1 files changed, 74 insertions(+), 0 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 6b6ce6b..94b8fcb 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -22,6 +22,9 @@ #include #include /* for icmp_send */ #include /* for ip_route_output */ +#include +#include +#include #include #include @@ -59,6 +62,25 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie) return dst; } +#ifdef CONFIG_IP_VS_IPV6 +static inline struct dst_entry * +__ip_vs_dst_check_v6(struct ip_vs_dest *dest, u32 cookie) +{ + struct dst_entry *dst = dest->dst_cache; + + if (!dst) + return NULL; + if ((dst->obsolete) && + dst->ops->check(dst, cookie) == NULL) { + dest->dst_cache = NULL; + dst_release(dst); + return NULL; + } + dst_hold(dst); + return dst; +} +#endif + static struct rtable * __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) { @@ -111,6 +133,58 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp, u32 rtos) return rt; } +#ifdef CONFIG_IP_VS_IPV6 +static struct rt6_info * +__ip_vs_get_out_rt_v6(struct ip_vs_conn *cp) +{ + struct rt6_info *rt; /* Route to the other host */ + struct ip_vs_dest *dest = cp->dest; + + if (dest) { + spin_lock(&dest->dst_lock); + if (!(rt = (struct rt6_info *) + __ip_vs_dst_check_v6(dest, 0))) { + struct flowi fl = { + .oif = 0, + .nl_u = { + .ip6_u = { + .daddr = dest->addr.v6, + .saddr = { .s6_addr32 = {0, 0, 0, 0} }, } }, + }; + + if (!(rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl))) { + spin_unlock(&dest->dst_lock); + IP_VS_DBG_RL("ip6_route_output error, " + "dest: " NIP6_FMT "\n", + NIP6(dest->addr.v6)); + return NULL; + } + __ip_vs_dst_set(dest, 0, dst_clone(&rt->u.dst)); + IP_VS_DBG(10, "new dst " NIP6_FMT ", refcnt=%d\n", + NIP6(dest->addr.v6), + atomic_read(&rt->u.dst.__refcnt)); + } + spin_unlock(&dest->dst_lock); + } else { + struct flowi fl = { + .oif = 0, + .nl_u = { + .ip6_u = { + .daddr = cp->daddr.v6, + .saddr = { .s6_addr32 = {0, 0, 0, 0}}, } }, + }; + + if (!(rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl))) { + IP_VS_DBG_RL("ip6_route_output error, dest: " + NIP6_FMT "\n", NIP6(cp->daddr.v6)); + return NULL; + } + } + + return rt; +} +#endif + /* * Release dest->dst_cache before a dest is removed -- 1.5.3.6