diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-03-20 20:04:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:04:53 -0500 |
commit | ebacaaa0fdf4402cdf4c8e569f54af36b6f0aa2d (patch) | |
tree | 5d1cc0c6d94b5226507434bb86e6e2a69fdd4204 /net | |
parent | 8238dd0698b480e432acd955c45f9f907b8d27de (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/Kconfig | 11 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 12 | ||||
-rw-r--r-- | net/ipv6/route.c | 11 |
3 files changed, 30 insertions, 4 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index f925f206d8ff..c456ead8a4a3 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -38,6 +38,17 @@ config IPV6_PRIVACY | |||
38 | 38 | ||
39 | See <file:Documentation/networking/ip-sysctl.txt> for details. | 39 | See <file:Documentation/networking/ip-sysctl.txt> for details. |
40 | 40 | ||
41 | config IPV6_ROUTER_PREF | ||
42 | bool "IPv6: Router Preference (RFC 4191) support" | ||
43 | depends on IPV6 | ||
44 | ---help--- | ||
45 | Router Preference is an optional extension to the Router | ||
46 | Advertisement message to improve the ability of hosts | ||
47 | to pick more appropriate router, especially when the hosts | ||
48 | is placed in a multi-homed network. | ||
49 | |||
50 | If unsure, say N. | ||
51 | |||
41 | config INET6_AH | 52 | config INET6_AH |
42 | tristate "IPv6: AH transformation" | 53 | tristate "IPv6: AH transformation" |
43 | depends on IPV6 | 54 | depends on IPV6 |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3b56be85234e..966ab6b3022e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1023,6 +1023,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1023 | int lifetime; | 1023 | int lifetime; |
1024 | struct ndisc_options ndopts; | 1024 | struct ndisc_options ndopts; |
1025 | int optlen; | 1025 | int optlen; |
1026 | unsigned int pref = 0; | ||
1026 | 1027 | ||
1027 | __u8 * opt = (__u8 *)(ra_msg + 1); | 1028 | __u8 * opt = (__u8 *)(ra_msg + 1); |
1028 | 1029 | ||
@@ -1086,6 +1087,13 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1086 | 1087 | ||
1087 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); | 1088 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); |
1088 | 1089 | ||
1090 | #ifdef CONFIG_IPV6_ROUTER_PREF | ||
1091 | pref = ra_msg->icmph.icmp6_router_pref; | ||
1092 | /* 10b is handled as if it were 00b (medium) */ | ||
1093 | if (pref == ICMPV6_ROUTER_PREF_INVALID) | ||
1094 | pref = ICMPV6_ROUTER_PREF_MEDIUM; | ||
1095 | #endif | ||
1096 | |||
1089 | rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); | 1097 | rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); |
1090 | 1098 | ||
1091 | if (rt) | 1099 | if (rt) |
@@ -1101,7 +1109,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1101 | ND_PRINTK3(KERN_DEBUG | 1109 | ND_PRINTK3(KERN_DEBUG |
1102 | "ICMPv6 RA: adding default router.\n"); | 1110 | "ICMPv6 RA: adding default router.\n"); |
1103 | 1111 | ||
1104 | rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); | 1112 | rt = rt6_add_dflt_router(&skb->nh.ipv6h->saddr, skb->dev, pref); |
1105 | if (rt == NULL) { | 1113 | if (rt == NULL) { |
1106 | ND_PRINTK0(KERN_ERR | 1114 | ND_PRINTK0(KERN_ERR |
1107 | "ICMPv6 RA: %s() failed to add default route.\n", | 1115 | "ICMPv6 RA: %s() failed to add default route.\n", |
@@ -1120,6 +1128,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1120 | return; | 1128 | return; |
1121 | } | 1129 | } |
1122 | neigh->flags |= NTF_ROUTER; | 1130 | neigh->flags |= NTF_ROUTER; |
1131 | } else if (rt) { | ||
1132 | rt->rt6i_flags |= (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); | ||
1123 | } | 1133 | } |
1124 | 1134 | ||
1125 | if (rt) | 1135 | if (rt) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6a068e7f81f1..a7030fed1a18 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -251,8 +251,11 @@ static int rt6_score_route(struct rt6_info *rt, int oif, | |||
251 | int m = rt6_check_dev(rt, oif); | 251 | int m = rt6_check_dev(rt, oif); |
252 | if (!m && (strict & RT6_SELECT_F_IFACE)) | 252 | if (!m && (strict & RT6_SELECT_F_IFACE)) |
253 | return -1; | 253 | return -1; |
254 | #ifdef CONFIG_IPV6_ROUTER_PREF | ||
255 | m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; | ||
256 | #endif | ||
254 | if (rt6_check_neigh(rt)) | 257 | if (rt6_check_neigh(rt)) |
255 | m |= 4; | 258 | m |= 16; |
256 | else if (strict & RT6_SELECT_F_REACHABLE) | 259 | else if (strict & RT6_SELECT_F_REACHABLE) |
257 | return -1; | 260 | return -1; |
258 | return m; | 261 | return m; |
@@ -1256,7 +1259,8 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1256 | } | 1259 | } |
1257 | 1260 | ||
1258 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | 1261 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, |
1259 | struct net_device *dev) | 1262 | struct net_device *dev, |
1263 | unsigned int pref) | ||
1260 | { | 1264 | { |
1261 | struct in6_rtmsg rtmsg; | 1265 | struct in6_rtmsg rtmsg; |
1262 | 1266 | ||
@@ -1264,7 +1268,8 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1264 | rtmsg.rtmsg_type = RTMSG_NEWROUTE; | 1268 | rtmsg.rtmsg_type = RTMSG_NEWROUTE; |
1265 | ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); | 1269 | ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); |
1266 | rtmsg.rtmsg_metric = 1024; | 1270 | rtmsg.rtmsg_metric = 1024; |
1267 | rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES; | 1271 | rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES | |
1272 | RTF_PREF(pref); | ||
1268 | 1273 | ||
1269 | rtmsg.rtmsg_ifindex = dev->ifindex; | 1274 | rtmsg.rtmsg_ifindex = dev->ifindex; |
1270 | 1275 | ||