add wildcard routing and routing statistics; also routing redirects
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Tue, 31 May 1983 09:49:49 +0000 (01:49 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Tue, 31 May 1983 09:49:49 +0000 (01:49 -0800)
can generate new routing table entries

SCCS-vsn: sys/net/route.c 4.20
SCCS-vsn: sys/net/route.h 4.10

usr/src/sys/net/route.c
usr/src/sys/net/route.h

index 611f26e..ee9058a 100644 (file)
@@ -1,4 +1,4 @@
-/*     route.c 4.19    83/04/05        */
+/*     route.c 4.20    83/05/30        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../net/route.h"
 
 int    rttrash;                /* routes not in table but not freed */
 #include "../net/route.h"
 
 int    rttrash;                /* routes not in table but not freed */
+struct sockaddr wildcard;      /* zero valued cookie for wildcard searches */
+
 /*
  * Packet routing routines.
  */
 rtalloc(ro)
        register struct route *ro;
 {
 /*
  * Packet routing routines.
  */
 rtalloc(ro)
        register struct route *ro;
 {
-       register struct rtentry *rt, *rtmin;
+       register struct rtentry *rt;
        register struct mbuf *m;
        register unsigned hash;
        register struct mbuf *m;
        register unsigned hash;
-       register int (*match)();
-       struct afhash h;
        struct sockaddr *dst = &ro->ro_dst;
        struct sockaddr *dst = &ro->ro_dst;
+       int (*match)(), doinghost;
+       struct afhash h;
        u_int af = dst->sa_family;
        u_int af = dst->sa_family;
+       struct rtentry *rtmin;
+       struct mbuf **table;
 
        if (ro->ro_rt && ro->ro_rt->rt_ifp)                     /* XXX */
                return;
        if (af >= AF_MAX)
                return;
        (*afswitch[af].af_hash)(dst, &h);
 
        if (ro->ro_rt && ro->ro_rt->rt_ifp)                     /* XXX */
                return;
        if (af >= AF_MAX)
                return;
        (*afswitch[af].af_hash)(dst, &h);
-       rtmin = 0, hash = h.afh_hosthash;
-       for (m = rthost[hash % RTHASHSIZ]; m; m = m->m_next) {
-               rt = mtod(m, struct rtentry *);
-               if (rt->rt_hash != hash)
-                       continue;
-               if ((rt->rt_flags & RTF_UP) == 0 ||
-                   (rt->rt_ifp->if_flags & IFF_UP) == 0)
-                       continue;
-               if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst, sizeof (*dst)))
-                       continue;
-               if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
-                       rtmin = rt;
-       }
-       if (rtmin) 
-               goto found;
-
-       hash = h.afh_nethash;
+       rtmin = 0;
        match = afswitch[af].af_netmatch;
        match = afswitch[af].af_netmatch;
-       for (m = rtnet[hash % RTHASHSIZ]; m; m = m->m_next) {
+       hash = h.afh_hosthash, table = rthost, doinghost = 1;
+again:
+       for (m = table[hash % RTHASHSIZ]; m; m = m->m_next) {
                rt = mtod(m, struct rtentry *);
                if (rt->rt_hash != hash)
                        continue;
                if ((rt->rt_flags & RTF_UP) == 0 ||
                    (rt->rt_ifp->if_flags & IFF_UP) == 0)
                        continue;
                rt = mtod(m, struct rtentry *);
                if (rt->rt_hash != hash)
                        continue;
                if ((rt->rt_flags & RTF_UP) == 0 ||
                    (rt->rt_ifp->if_flags & IFF_UP) == 0)
                        continue;
-               if (rt->rt_dst.sa_family != af || !(*match)(&rt->rt_dst, dst))
-                       continue;
+               if (doinghost) {
+                       if (bcmp((caddr_t)&rt->rt_dst, (caddr_t)dst,
+                           sizeof (*dst)))
+                               continue;
+               } else {
+                       if (rt->rt_dst.sa_family != af ||
+                           !(*match)(&rt->rt_dst, dst))
+                               continue;
+               }
                if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
                        rtmin = rt;
        }
                if (rtmin == 0 || rt->rt_use < rtmin->rt_use)
                        rtmin = rt;
        }
-found:
+       if (rtmin == 0 && doinghost) {
+               doinghost = 0;
+               hash = h.afh_nethash, table = rtnet;
+               goto again;
+       }
+       /*
+        * Check for wildcard gateway, by convention network 0.
+        */
+       if (rtmin == 0 && dst != &wildcard) {
+               dst = &wildcard, hash = 0;
+               goto again;
+       }
        ro->ro_rt = rtmin;
        ro->ro_rt = rtmin;
-       if (rtmin)
-               rtmin->rt_refcnt++;
+       if (rtmin == 0) {
+               rtstat.rts_unreach++;
+               return;
+       }
+       rtmin->rt_refcnt++;
+       if (dst == &wildcard)
+               rtstat.rts_wildcard++;
 }
 
 rtfree(rt)
 }
 
 rtfree(rt)
@@ -91,7 +104,7 @@ rtfree(rt)
  *
  * Should notify all parties with a reference to
  * the route that it's changed (so, for instance,
  *
  * Should notify all parties with a reference to
  * the route that it's changed (so, for instance,
- * round trip time estimates may be recalculated),
+ * current round trip time estimates could be flushed),
  * but we have no back pointers at the moment.
  */
 rtredirect(dst, gateway)
  * but we have no back pointers at the moment.
  */
 rtredirect(dst, gateway)
@@ -101,30 +114,48 @@ rtredirect(dst, gateway)
        register struct rtentry *rt;
 
        /* verify the gateway is directly reachable */
        register struct rtentry *rt;
 
        /* verify the gateway is directly reachable */
-       if (if_ifwithnet(gateway) == 0)
+       if (if_ifwithnet(gateway) == 0) {
+               rtstat.rts_badredirect++;
                return;
                return;
+       }
        ro.ro_dst = *dst;
        ro.ro_dst = *dst;
-       ro.ro_rt = NULL;
+       ro.ro_rt = 0;
        rtalloc(&ro);
        rt = ro.ro_rt;
        rtalloc(&ro);
        rt = ro.ro_rt;
+       /*
+        * Create a new entry if the lookup failed.
+        * This is necessary for hosts which use routing
+        * redirects generated by smart gateways to dynamically
+        * build the routing tables.
+        */
+       if (rt == 0) {
+               rtinit(dst, gateway, RTF_GATEWAY);
+               rtstat.rts_dynamic++;
+               return;
+       }
        /*
         * Don't listen to the redirect if it's
         * for a route to an interface. 
        /*
         * Don't listen to the redirect if it's
         * for a route to an interface. 
-        *
-        * Should probably create a new entry when
-        * the lookup fails.  This will be necessary
-        * when wildcard routes are added.
         */
         */
-       if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) == 0)
+       if (rt->rt_flags & RTF_GATEWAY) {
+               /*
+                * Smash the current notion of the gateway to
+                * this destination.  This is probably not right,
+                * as it's conceivable a flurry of redirects could
+                * cause the gateway value to fluctuate wildly during
+                * dynamic routing reconfiguration.
+                */
+               rt->rt_gateway = *gateway;
+               rtfree(rt);
+               rtstat.rts_newgateway++;
                return;
                return;
-       rt->rt_gateway = *gateway;
-       rtfree(rt);
+       }
 }
 
 /*
  * Carry out a request to change the routing table.  Called by
 }
 
 /*
  * Carry out a request to change the routing table.  Called by
- * interfaces at boot time to make their ``local routes'' known
- * and for ioctl's.
+ * interfaces at boot time to make their ``local routes'' known,
+ * for ioctl's, and as the result of routing redirects.
  */
 rtrequest(req, entry)
        int req;
  */
 rtrequest(req, entry)
        int req;
index 223e3ce..f7d95ab 100644 (file)
@@ -1,14 +1,10 @@
-/*     route.h 4.9     83/05/12        */
+/*     route.h 4.10    83/05/30        */
 
 /*
  * Kernel resident routing tables.
  * 
  * The routing tables are initialized at boot time by
  * making entries for all directly connected interfaces.
 
 /*
  * Kernel resident routing tables.
  * 
  * The routing tables are initialized at boot time by
  * making entries for all directly connected interfaces.
- * Routing daemons can thereafter update the routing tables.
- *
- * TODO:
- *     keep statistics
  */
 
 /*
  */
 
 /*
@@ -41,18 +37,31 @@ struct rtentry {
        u_long  rt_use;                 /* raw # packets forwarded */
        struct  ifnet *rt_ifp;          /* the answer: interface to use */
 };
        u_long  rt_use;                 /* raw # packets forwarded */
        struct  ifnet *rt_ifp;          /* the answer: interface to use */
 };
-#ifdef KERNEL
-#define        RTHASHSIZ       7
-struct mbuf *rthost[RTHASHSIZ];
-struct mbuf *rtnet[RTHASHSIZ];
-#endif
 
 #define        RTF_UP          0x1             /* route useable */
 #define        RTF_GATEWAY     0x2             /* destination is a gateway */
 #define        RTF_HOST        0x4             /* host entry (net otherwise) */
 
 
 #define        RTF_UP          0x1             /* route useable */
 #define        RTF_GATEWAY     0x2             /* destination is a gateway */
 #define        RTF_HOST        0x4             /* host entry (net otherwise) */
 
+/*
+ * Routing statistics.
+ */
+struct rtstat {
+       short   rts_badredirect;        /* bogus redirect calls */
+       short   rts_dynamic;            /* routes created by redirects */
+       short   rts_newgateway;         /* routes modified by redirects */
+       short   rts_unreach;            /* lookups which failed */
+       short   rts_wildcard;           /* lookups satisfied by a wildcard */
+};
+
+#ifdef KERNEL
 #define        RTFREE(rt) \
        if ((rt)->rt_refcnt == 1) \
                rtfree(rt); \
        else \
                (rt)->rt_refcnt--;
 #define        RTFREE(rt) \
        if ((rt)->rt_refcnt == 1) \
                rtfree(rt); \
        else \
                (rt)->rt_refcnt--;
+
+#define        RTHASHSIZ       7
+struct mbuf *rthost[RTHASHSIZ];
+struct mbuf *rtnet[RTHASHSIZ];
+struct rtstat  rtstat;
+#endif