mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
[IPV6]: ROUTE: Add support for Router Preference (RFC4191).
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8238dd0698
commit
ebacaaa0fd
6 changed files with 49 additions and 7 deletions
|
@ -40,14 +40,16 @@ struct icmp6hdr {
|
||||||
struct icmpv6_nd_ra {
|
struct icmpv6_nd_ra {
|
||||||
__u8 hop_limit;
|
__u8 hop_limit;
|
||||||
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||||
__u8 reserved:6,
|
__u8 reserved:4,
|
||||||
|
router_pref:2,
|
||||||
other:1,
|
other:1,
|
||||||
managed:1;
|
managed:1;
|
||||||
|
|
||||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||||
__u8 managed:1,
|
__u8 managed:1,
|
||||||
other:1,
|
other:1,
|
||||||
reserved:6;
|
router_pref:2,
|
||||||
|
reserved:4;
|
||||||
#else
|
#else
|
||||||
#error "Please fix <asm/byteorder.h>"
|
#error "Please fix <asm/byteorder.h>"
|
||||||
#endif
|
#endif
|
||||||
|
@ -70,8 +72,13 @@ struct icmp6hdr {
|
||||||
#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
|
#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
|
||||||
#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
|
#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
|
||||||
#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
|
#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
|
||||||
|
#define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ICMPV6_ROUTER_PREF_LOW 0x3
|
||||||
|
#define ICMPV6_ROUTER_PREF_MEDIUM 0x0
|
||||||
|
#define ICMPV6_ROUTER_PREF_HIGH 0x1
|
||||||
|
#define ICMPV6_ROUTER_PREF_INVALID 0x2
|
||||||
|
|
||||||
#define ICMPV6_DEST_UNREACH 1
|
#define ICMPV6_DEST_UNREACH 1
|
||||||
#define ICMPV6_PKT_TOOBIG 2
|
#define ICMPV6_PKT_TOOBIG 2
|
||||||
|
|
|
@ -27,8 +27,16 @@
|
||||||
#define RTF_FLOW 0x02000000 /* flow significant route */
|
#define RTF_FLOW 0x02000000 /* flow significant route */
|
||||||
#define RTF_POLICY 0x04000000 /* policy route */
|
#define RTF_POLICY 0x04000000 /* policy route */
|
||||||
|
|
||||||
|
#define RTF_PREF(pref) ((pref) << 27)
|
||||||
|
#define RTF_PREF_MASK 0x18000000
|
||||||
|
|
||||||
#define RTF_LOCAL 0x80000000
|
#define RTF_LOCAL 0x80000000
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
#define IPV6_EXTRACT_PREF(flag) (((flag) & RTF_PREF_MASK) >> 27)
|
||||||
|
#define IPV6_DECODE_PREF(pref) ((pref) ^ 2) /* 1:low,2:med,3:high */
|
||||||
|
#endif
|
||||||
|
|
||||||
struct in6_rtmsg {
|
struct in6_rtmsg {
|
||||||
struct in6_addr rtmsg_dst;
|
struct in6_addr rtmsg_dst;
|
||||||
struct in6_addr rtmsg_src;
|
struct in6_addr rtmsg_src;
|
||||||
|
|
|
@ -87,7 +87,8 @@ extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
|
||||||
extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr,
|
extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
|
extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
|
||||||
struct net_device *dev);
|
struct net_device *dev,
|
||||||
|
unsigned int pref);
|
||||||
|
|
||||||
extern void rt6_purge_dflt_routers(void);
|
extern void rt6_purge_dflt_routers(void);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,17 @@ config IPV6_PRIVACY
|
||||||
|
|
||||||
See <file:Documentation/networking/ip-sysctl.txt> for details.
|
See <file:Documentation/networking/ip-sysctl.txt> for details.
|
||||||
|
|
||||||
|
config IPV6_ROUTER_PREF
|
||||||
|
bool "IPv6: Router Preference (RFC 4191) support"
|
||||||
|
depends on IPV6
|
||||||
|
---help---
|
||||||
|
Router Preference is an optional extension to the Router
|
||||||
|
Advertisement message to improve the ability of hosts
|
||||||
|
to pick more appropriate router, especially when the hosts
|
||||||
|
is placed in a multi-homed network.
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
config INET6_AH
|
config INET6_AH
|
||||||
tristate "IPv6: AH transformation"
|
tristate "IPv6: AH transformation"
|
||||||
depends on IPV6
|
depends on IPV6
|
||||||
|
|
|
@ -1023,6 +1023,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
||||||
int lifetime;
|
int lifetime;
|
||||||
struct ndisc_options ndopts;
|
struct ndisc_options ndopts;
|
||||||
int optlen;
|
int optlen;
|
||||||
|
unsigned int pref = 0;
|
||||||
|
|
||||||
__u8 * opt = (__u8 *)(ra_msg + 1);
|
__u8 * opt = (__u8 *)(ra_msg + 1);
|
||||||
|
|
||||||
|
@ -1086,6 +1087,13 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
||||||
|
|
||||||
lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
|
lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IPV6_ROUTER_PREF
|
||||||
|
pref = ra_msg->icmph.icmp6_router_pref;
|
||||||
|
/* 10b is handled as if it were 00b (medium) */
|
||||||
|
if (pref == ICMPV6_ROUTER_PREF_INVALID)
|
||||||
|
pref = ICMPV6_ROUTER_PREF_MEDIUM;
|
||||||
|
#endif
|
||||||
|
|
||||||
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
|
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
|
||||||
|
|
||||||
if (rt)
|
if (rt)
|
||||||
|
@ -1101,7 +1109,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
||||||
ND_PRINTK3(KERN_DEBUG
|
ND_PRINTK3(KERN_DEBUG
|
||||||
"ICMPv6 RA: adding default router.\n");
|
"ICMPv6 RA: adding default router.\n");
|
||||||
|
|
||||||
rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
|
rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref);
|
||||||
if (rt == NULL) {
|
if (rt == NULL) {
|
||||||
ND_PRINTK0(KERN_ERR
|
ND_PRINTK0(KERN_ERR
|
||||||
"ICMPv6 RA: %s() failed to add default route.\n",
|
"ICMPv6 RA: %s() failed to add default route.\n",
|
||||||
|
@ -1120,6 +1128,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
neigh->flags |= NTF_ROUTER;
|
neigh->flags |= NTF_ROUTER;
|
||||||
|
} else if (rt) {
|
||||||
|
rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rt)
|
if (rt)
|
||||||
|
|
|
@ -251,8 +251,11 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
|
||||||
int m = rt6_check_dev(rt, oif);
|
int m = rt6_check_dev(rt, oif);
|
||||||
if (!m && (strict & RT6_SELECT_F_IFACE))
|
if (!m && (strict & RT6_SELECT_F_IFACE))
|
||||||
return -1;
|
return -1;
|
||||||
|
#ifdef CONFIG_IPV6_ROUTER_PREF
|
||||||
|
m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
|
||||||
|
#endif
|
||||||
if (rt6_check_neigh(rt))
|
if (rt6_check_neigh(rt))
|
||||||
m |= 4;
|
m |= 16;
|
||||||
else if (strict & RT6_SELECT_F_REACHABLE)
|
else if (strict & RT6_SELECT_F_REACHABLE)
|
||||||
return -1;
|
return -1;
|
||||||
return m;
|
return m;
|
||||||
|
@ -1256,7 +1259,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
|
struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
|
||||||
struct net_device *dev)
|
struct net_device *dev,
|
||||||
|
unsigned int pref)
|
||||||
{
|
{
|
||||||
struct in6_rtmsg rtmsg;
|
struct in6_rtmsg rtmsg;
|
||||||
|
|
||||||
|
@ -1264,7 +1268,8 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
|
||||||
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
|
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
|
||||||
ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
|
ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
|
||||||
rtmsg.rtmsg_metric = 1024;
|
rtmsg.rtmsg_metric = 1024;
|
||||||
rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES;
|
rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES |
|
||||||
|
RTF_PREF(pref);
|
||||||
|
|
||||||
rtmsg.rtmsg_ifindex = dev->ifindex;
|
rtmsg.rtmsg_ifindex = dev->ifindex;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue