Index: kernel/linux22/net/ipv6/route.c
===================================================================
RCS file: /cvsroot/usagi/usagi/kernel/linux22/net/ipv6/route.c,v
retrieving revision 1.12
retrieving revision 1.14
diff -u -r1.12 -r1.14
--- kernel/linux22/net/ipv6/route.c 2001/08/19 18:37:42 1.12
+++ kernel/linux22/net/ipv6/route.c 2001/08/22 13:22:36 1.14
@@ -1,4 +1,4 @@
-/* $USAGI: route.c,v 1.12 2001/08/19 18:37:42 yoshfuji Exp $ */
+/* $USAGI: route.c,v 1.14 2001/08/22 13:22:36 yoshfuji Exp $ */
/*
* Linux INET6 implementation
@@ -15,6 +15,17 @@
* 2 of the License, or (at your option) any later version.
*/
+/* Changes:
+ *
+ * yoshfuji@USAGI
+ * reworked default router selection.
+ * - respect outgoing interface
+ * - select from (probably) reachable routers (i.e.
+ * routers in REACHABLE, STALE, DELAY or PROBE states).
+ * - always select the same router if it is (probably)
+ * reachable. otherwise, round-robin the list.
+ */
+
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -252,6 +263,7 @@
* SHOULD round robin
*/
if (rt6_dflt_pointer) {
+ int ok = 0;
for (sprt = rt6_dflt_pointer->u.next;
sprt; sprt = sprt->u.next) {
if (sprt->u.dst.error == 0) {
@@ -260,23 +272,53 @@
}
}
for (sprt = rt;
- !match && sprt && sprt != rt6_dflt_pointer;
- sprt = sprt->u.next) {
+ sprt; sprt = sprt->u.next) {
+ if (sprt == rt6_dflt_pointer) {
+ ok = 1;
+ break;
+ }
if (sprt->u.dst.error == 0) {
match = sprt;
break;
}
+ }
+ if (!ok) {
+ /* rt6_dflt_router is for others */
+ match = NULL;
+ }
+ }
+ }
+
+ if (match) {
+ if (rt6_dflt_pointer != match)
+ RT6_TRACE1(KERN_INFO
+ "changed default router: %p->%p\n",
+ rt6_dflt_pointer, match);
+ rt6_dflt_pointer = match;
+ }
+
+ if (!match) {
+ /*
+ * Last Resort: if no default routers found,
+ * use addrconf default route.
+ * We don't record this route.
+ */
+ for (sprt = ip6_routing_table.leaf;
+ sprt; sprt = sprt->u.next) {
+ if ((sprt->rt6i_flags & RTF_DEFAULT) &&
+ (!oif ||
+ (sprt->rt6i_dev &&
+ sprt->rt6i_dev->ifindex == oif))) {
+ match = sprt;
+ break;
}
- if (!match)
- match = rt6_dflt_pointer; /*XXX*/
+ }
+ if (!match) {
+ /* no default route. give up. */
+ match = &ip6_null_entry;
}
}
- if (rt6_dflt_pointer != match)
- RT6_TRACE1(KERN_INFO
- "changed default router: %p->%p\n",
- rt6_dflt_pointer, match);
- rt6_dflt_pointer = match;
return match;
}