aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2006-03-20 20:04:53 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-20 20:04:53 -0500
commitebacaaa0fdf4402cdf4c8e569f54af36b6f0aa2d (patch)
tree5d1cc0c6d94b5226507434bb86e6e2a69fdd4204 /net/ipv6
parent8238dd0698b480e432acd955c45f9f907b8d27de (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/ipv6')
-rw-r--r--net/ipv6/Kconfig11
-rw-r--r--net/ipv6/ndisc.c12
-rw-r--r--net/ipv6/route.c11
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
41config 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
41config INET6_AH 52config 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
1258struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, 1261struct 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