V8/usr/sys/chaosld/chrtimer.c

#include "ch.h"
#include "chroute.h"
#if NCHROUTE > 0
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/chaos.h"
#include "../chaosld/types.h"
#include "../chaosld/constants.h"
#include "../chaosld/globals.h"
#include "../chaosld/chrouteld.h"

/*
 * Clock level processing.
 *	ch_rtimer should be called each clock tick (HZ per second)
 *	at a priority equal to or higher than LOCK.
 *
 * Terminology:
 *    Route aging:	Increase the cost of transmitting over gateways so we
 *			will use another gateway if the current gateway goes
 *			down.
 *    Route broadcast:	If we are connected to more than one subnet, broad
 *			cast our bridge status every BRIDGERATE seconds.
 *
 * These rates might want to vary with the cost of getting to the host.
 *
 * Since these rates are dependent on a run-time variable
 * (This is a good idea if you think about it long enough),
 * We might want to initialize specific variables at run-time to
 * avoid recalculation if the profile of chclock is disturbing.
 */
#define MINRATE		ROUTERATE	/* Minimum of following rates */

#define ROUTERATE	(hz<<2)	   /* Route aging rate */
#define BRIDGERATE	(hz*15)	   /* Routing broadcast rate */

extern int NChropen;
extern int Chrtimer;
extern struct chroute Chroute[];
int Chnobridge;
chtime Chrclock;


ch_rtimer()
{
     int aging;			   /* are we aging routing this time? */
     int sending;		   /* are we sending routing this time? */
     static chtime nextclock = 1;  /* next time to do anything */
     static chtime nextroute = 1;  /* next time to age routing */
     static chtime nextbridge = 1; /* next time to send routing */

     Chrtimer = 1;
     ++Chrclock;
     if (cmp_lt(Chrclock, nextclock))
	  goto leave;
     if (cmp_gt(Chrclock, nextroute)) {
          aging = 1;
          nextroute += ROUTERATE;
     } else
	  aging = 0;
     if (cmp_gt(Chrclock, nextbridge)) {
          sending = 1;
          nextbridge += BRIDGERATE;
     } else
	  sending = 0;
     debug(DNOCLK,goto leave);

     if (aging)
	  chroutage();
     if (sending && !ch_busy)
	  chbridge();

leave:
     if (NChropen == 0)
	  Chrtimer = 0;
     else
	  timeout(ch_rtimer, (caddr_t)0, 1);
}


/*
 * Increase the cost of accessing a subnet via a gateway
 */
chroutage()
{
     register struct chroute *r;

     for (r = Chroute; r < &Chroute[CHNSUBNET]; r++)
          if ((r->rt_type == CHBRIDGE || r->rt_type == CHDIRECT) &&
              r->rt_cost < HIGH_COST)
               r->rt_cost++;
}


/*
 * Send routing packets on all directly connected subnets, unless we are on
 * only one.
 */
chbridge()
{
     register struct chroute *r;
     register struct packet *pkt;
     register struct rut_data rd;
     register int ndirect;
     register int n;

     if (Chnobridge)
          return;
     /*
      * Count the number of subnets to which we are directly connected.
      * If not more than one, then we are not a bridge and shouldn't
      * send out routing packets at all.
      * While we're at it, count the number of subnets we know we
      * have any access to.  This number determines the size of the
      * routine packet we need to send, if any.
      */
     n = ndirect = 0;
     for (r = Chroute; r < &Chroute[CHNSUBNET]; r++)
          if (r->rt_cost < HIGH_COST)
               switch(r->rt_type) {
               case CHDIRECT:
                    ndirect++;
               default:
                    n++;
                    break;
               case CHNOPATH:
                    ;     
               }
     if (ndirect <= 1 || (pkt = new_packet()) == NOPKT)
          return;
     /*
      * Build the routing packet to send out on each directly connected
      * subnet.  It is complete except for the cost of the directly
      * connected subnet we are sending it out on.  This cost must be
      * added to each entry in the packet each time it is sent.
      */
     pkt->pk_op = RUTOP;
     for (n = 0, r = Chroute; r < &Chroute[CHNSUBNET]; r++, n++)
          if (r->rt_cost < HIGH_COST && r->rt_type != CHNOPATH) {
               rd.rd_subnet = n;
               rd.rd_cost = r->rt_cost;
               append_packet(pkt, &rd, sizeof(rd));
          }
     flatten(pkt);
     /*
      * Now send out this packet on each directly connected subnet.
      * ndirect becomes zero on last such subnet.
      */
     for (r = Chroute; r < &Chroute[CHNSUBNET]; r++)
          if (r->rt_type == CHDIRECT && r->rt_cost < HIGH_COST)
               sendrut(pkt, r->rt_path.ifp, r->rt_cost, --ndirect);
}
#endif