ipv4/ipv6: Prepare for new route gateway semantics.
In the future the ipv4/ipv6 route gateway will take on two types of values: 1) INADDR_ANY/IN6ADDR_ANY, for local network routes, and in this case the neighbour must be obtained using the destination address in ipv4/ipv6 header as the lookup key. 2) Everything else, the actual nexthop route address. So if the gateway is not inaddr-any we use it, otherwise we must use the packet's destination address. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
09e9b813d3
Коммит
39232973b7
|
@ -1117,10 +1117,15 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, const vo
|
||||||
static const __be32 inaddr_any = 0;
|
static const __be32 inaddr_any = 0;
|
||||||
struct net_device *dev = dst->dev;
|
struct net_device *dev = dst->dev;
|
||||||
const __be32 *pkey = daddr;
|
const __be32 *pkey = daddr;
|
||||||
|
const struct rtable *rt;
|
||||||
struct neighbour *n;
|
struct neighbour *n;
|
||||||
|
|
||||||
|
rt = (const struct rtable *) dst;
|
||||||
|
|
||||||
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
|
if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
|
||||||
pkey = &inaddr_any;
|
pkey = &inaddr_any;
|
||||||
|
else if (rt->rt_gateway)
|
||||||
|
pkey = (const __be32 *) &rt->rt_gateway;
|
||||||
|
|
||||||
n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey);
|
n = __ipv4_neigh_lookup(&arp_tbl, dev, *(__force u32 *)pkey);
|
||||||
if (n)
|
if (n)
|
||||||
|
|
|
@ -121,9 +121,23 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline const void *choose_neigh_daddr(struct rt6_info *rt, const void *daddr)
|
||||||
|
{
|
||||||
|
struct in6_addr *p = &rt->rt6i_gateway;
|
||||||
|
|
||||||
|
if (p->s6_addr32[0] | p->s6_addr32[1] |
|
||||||
|
p->s6_addr32[2] | p->s6_addr32[3])
|
||||||
|
return (const void *) p;
|
||||||
|
return daddr;
|
||||||
|
}
|
||||||
|
|
||||||
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
|
static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
|
||||||
{
|
{
|
||||||
struct neighbour *n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
|
struct rt6_info *rt = (struct rt6_info *) dst;
|
||||||
|
struct neighbour *n;
|
||||||
|
|
||||||
|
daddr = choose_neigh_daddr(rt, daddr);
|
||||||
|
n = __ipv6_neigh_lookup(&nd_tbl, dst->dev, daddr);
|
||||||
if (n)
|
if (n)
|
||||||
return n;
|
return n;
|
||||||
return neigh_create(&nd_tbl, daddr, dst->dev);
|
return neigh_create(&nd_tbl, daddr, dst->dev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче