|
@@ -364,13 +364,16 @@ err_unreach:
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
#ifdef CONFIG_IP_VS_IPV6
|
|
static struct dst_entry *
|
|
static struct dst_entry *
|
|
__ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
|
|
__ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
|
|
- struct in6_addr *ret_saddr, int do_xfrm)
|
|
|
|
|
|
+ struct in6_addr *ret_saddr, int do_xfrm, int rt_mode)
|
|
{
|
|
{
|
|
struct dst_entry *dst;
|
|
struct dst_entry *dst;
|
|
struct flowi6 fl6 = {
|
|
struct flowi6 fl6 = {
|
|
.daddr = *daddr,
|
|
.daddr = *daddr,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ if (rt_mode & IP_VS_RT_MODE_KNOWN_NH)
|
|
|
|
+ fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
|
|
|
|
+
|
|
dst = ip6_route_output(net, NULL, &fl6);
|
|
dst = ip6_route_output(net, NULL, &fl6);
|
|
if (dst->error)
|
|
if (dst->error)
|
|
goto out_err;
|
|
goto out_err;
|
|
@@ -427,7 +430,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
|
|
}
|
|
}
|
|
dst = __ip_vs_route_output_v6(net, &dest->addr.in6,
|
|
dst = __ip_vs_route_output_v6(net, &dest->addr.in6,
|
|
&dest_dst->dst_saddr.in6,
|
|
&dest_dst->dst_saddr.in6,
|
|
- do_xfrm);
|
|
|
|
|
|
+ do_xfrm, rt_mode);
|
|
if (!dst) {
|
|
if (!dst) {
|
|
__ip_vs_dst_set(dest, NULL, NULL, 0);
|
|
__ip_vs_dst_set(dest, NULL, NULL, 0);
|
|
spin_unlock_bh(&dest->dst_lock);
|
|
spin_unlock_bh(&dest->dst_lock);
|
|
@@ -446,7 +449,8 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
|
|
*ret_saddr = dest_dst->dst_saddr.in6;
|
|
*ret_saddr = dest_dst->dst_saddr.in6;
|
|
} else {
|
|
} else {
|
|
noref = 0;
|
|
noref = 0;
|
|
- dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm);
|
|
|
|
|
|
+ dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm,
|
|
|
|
+ rt_mode);
|
|
if (!dst)
|
|
if (!dst)
|
|
goto err_unreach;
|
|
goto err_unreach;
|
|
rt = (struct rt6_info *) dst;
|
|
rt = (struct rt6_info *) dst;
|
|
@@ -1164,7 +1168,8 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|
local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
|
|
local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
|
|
NULL, ipvsh, 0,
|
|
NULL, ipvsh, 0,
|
|
IP_VS_RT_MODE_LOCAL |
|
|
IP_VS_RT_MODE_LOCAL |
|
|
- IP_VS_RT_MODE_NON_LOCAL);
|
|
|
|
|
|
+ IP_VS_RT_MODE_NON_LOCAL |
|
|
|
|
+ IP_VS_RT_MODE_KNOWN_NH);
|
|
if (local < 0)
|
|
if (local < 0)
|
|
goto tx_error;
|
|
goto tx_error;
|
|
if (local) {
|
|
if (local) {
|