diff options
author | David S. Miller <davem@davemloft.net> | 2013-10-21 18:39:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-21 18:39:36 -0400 |
commit | 3a70417c1d8fb11b38e5a8ae7a268ac581e8c95c (patch) | |
tree | 5839a5ca70c8228fa40fdc610243491e35a065b1 /net/ipv6/route.c | |
parent | 4440c6f7d5f3df81077d87dee52b2f8120610967 (diff) | |
parent | 56e42441ed54b092d6c7411138ce60d049e7c731 (diff) |
Merge branch 'rt6i_gateway'
Julian Anastasov says:
====================
ipv6: use rt6i_gateway as nexthop
The following patchset makes sure that rt6i_gateway
contains valid nexthop information in all cases, so that
we can use different nexthop for sending.
The first patch is a simple fix that makes IPVS, TEE,
RAW(hdrincl) and RTF_DYNAMIC(without RTF_GATEWAY) work as
before 3.9. There is a single corner case not solved by
this patch: RAW(hdrincl) or TEE using local address for
nexthop, a silly feature, I guess. In this case we
see zeroes in rt6i_gateway because we get route that is not
cloned. This is solved only with patch 2.
The second patch is an optimization that makes sure
all resulting routes have rt6i_gateway filled, so that we
can avoid the complex ipv6_addr_any() call added to rt6_nexthop()
by patch 1. And it sets rt6i_gateway for local routes, a case
not handled by patch 1.
The third patch uses the new rt6_nexthop() function to fix
the matching of gateways in the same way as commit bbb5823cf742a7
("netfilter: nf_conntrack: fix rt_gateway checks for H.323 helper")
fixes nf_conntrack_h323_main.c for IPv4. Currently, it depends on
the new definition of rt6_nexthop() in patch 2. Actually, if
patch 2 is applied, patch 3 becomes a cosmetic change.
I see the following two alternatives for applying these
patches:
1. Linger patch 2 in net-next to avoid surprises in the upcoming
release. In this case patch 3 can be reworked not to depend on
the new rt6_nexthop() definition in patch 2. I guess this is a
better option, so that patch 2 can be reviewed and tested for
longer time.
2. Include all 3 patches in net tree - more risky because this
is my first attempt to change IPv6.
Here is the situation as handled by patch 2:
In IPv6 the resolved routes are always host routes (/128
with DST_HOST), mostly cloned ones. We allow routes in FIB
to contain rt6i_gateway with zeroes (eg. for local subnets) but
on cloning we can fill the rt6i_gateway field in result.
This works even without this patchset.
There is a single special case where dst is provided as
skb_dst directly without a routing call: icmp6_dst_alloc(). It is a
private dst allocated just for the particular ICMP packet. Patch 2
fills rt6i_gateway in this case, needed for the new rt6_nexthop()
simplification.
The last case is addrconf_dst_alloc(), it can put in
FIB local/anycast routes when addresses are added. Patch 2
needs to fill rt6i_gateway in this case because such routes
are returned without cloning.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c979dd96d82a..c1ee3813e1ae 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -851,7 +851,6 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, | |||
851 | if (ort->rt6i_dst.plen != 128 && | 851 | if (ort->rt6i_dst.plen != 128 && |
852 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) | 852 | ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) |
853 | rt->rt6i_flags |= RTF_ANYCAST; | 853 | rt->rt6i_flags |= RTF_ANYCAST; |
854 | rt->rt6i_gateway = *daddr; | ||
855 | } | 854 | } |
856 | 855 | ||
857 | rt->rt6i_flags |= RTF_CACHE; | 856 | rt->rt6i_flags |= RTF_CACHE; |
@@ -1338,6 +1337,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1338 | rt->dst.flags |= DST_HOST; | 1337 | rt->dst.flags |= DST_HOST; |
1339 | rt->dst.output = ip6_output; | 1338 | rt->dst.output = ip6_output; |
1340 | atomic_set(&rt->dst.__refcnt, 1); | 1339 | atomic_set(&rt->dst.__refcnt, 1); |
1340 | rt->rt6i_gateway = fl6->daddr; | ||
1341 | rt->rt6i_dst.addr = fl6->daddr; | 1341 | rt->rt6i_dst.addr = fl6->daddr; |
1342 | rt->rt6i_dst.plen = 128; | 1342 | rt->rt6i_dst.plen = 128; |
1343 | rt->rt6i_idev = idev; | 1343 | rt->rt6i_idev = idev; |
@@ -1873,7 +1873,10 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, | |||
1873 | in6_dev_hold(rt->rt6i_idev); | 1873 | in6_dev_hold(rt->rt6i_idev); |
1874 | rt->dst.lastuse = jiffies; | 1874 | rt->dst.lastuse = jiffies; |
1875 | 1875 | ||
1876 | rt->rt6i_gateway = ort->rt6i_gateway; | 1876 | if (ort->rt6i_flags & RTF_GATEWAY) |
1877 | rt->rt6i_gateway = ort->rt6i_gateway; | ||
1878 | else | ||
1879 | rt->rt6i_gateway = *dest; | ||
1877 | rt->rt6i_flags = ort->rt6i_flags; | 1880 | rt->rt6i_flags = ort->rt6i_flags; |
1878 | if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == | 1881 | if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == |
1879 | (RTF_DEFAULT | RTF_ADDRCONF)) | 1882 | (RTF_DEFAULT | RTF_ADDRCONF)) |
@@ -2160,6 +2163,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2160 | else | 2163 | else |
2161 | rt->rt6i_flags |= RTF_LOCAL; | 2164 | rt->rt6i_flags |= RTF_LOCAL; |
2162 | 2165 | ||
2166 | rt->rt6i_gateway = *addr; | ||
2163 | rt->rt6i_dst.addr = *addr; | 2167 | rt->rt6i_dst.addr = *addr; |
2164 | rt->rt6i_dst.plen = 128; | 2168 | rt->rt6i_dst.plen = 128; |
2165 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); | 2169 | rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL); |