text: /*
   * Copyright (c) 1998-2001
   * University of Southern California/Information Sciences Institute.
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the name of the project nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  /*
   *  $Id: mrt.h,v 1.16 2001/09/10 20:31:36 pavlin Exp $
   */
  
  #define MRTF_SPT		0x0001	/* iif toward source		    */
  #define MRTF_WC			0x0002	/* (*,G) entry			    */
  #define MRTF_RP			0x0004	/* iif toward RP		    */
  #define MRTF_NEW		0x0008	/* new created routing entry	    */
  #define MRTF_IIF_REGISTER	0x0020	/* ???				    */
  #define MRTF_REGISTER		0x0080	/* ???				    */
  #define MRTF_KERNEL_CACHE	0x0200	/* a mirror for the kernel cache    */
  #define MRTF_NULL_OIF		0x0400	/* null oif cache..	???	    */
  #define MRTF_REG_SUPP		0x0800	/* register suppress	???	    */
  #define MRTF_ASSERTED		0x1000	/* upstream is not that of src ???  */
  #define MRTF_SG			0x2000	/* (S,G) pure, not hanging off of (*,G)*/
  #define MRTF_PMBR		0x4000	/* (*,*,RP) entry (for interop)	    */
  #define MRTF_MFC_CLONE_SG	0x8000	/* clone (S,G) MFC from (*,G) or (*,*,RP) */
  
  /* Macro to duplicate oif info (oif bits, timers) */
  #define VOIF_COPY(from, to)						\
      do {								\
  	PIMD_VIFM_COPY((from)->joined_oifs, (to)->joined_oifs);		\
  	PIMD_VIFM_COPY((from)->oifs, (to)->oifs);			\
  	PIMD_VIFM_COPY((from)->leaves, (to)->leaves);			\
  	PIMD_VIFM_COPY((from)->pruned_oifs, (to)->pruned_oifs);		\
  	PIMD_VIFM_COPY((from)->asserted_oifs, (to)->asserted_oifs);	\
  	memcpy((to)->vif_timers, (from)->vif_timers,			\
  	       numvifs * sizeof((from)->vif_timers[0]));		\
  	memcpy((to)->vif_deletion_delay, (from)->vif_deletion_delay,	\
  	       numvifs * sizeof((from)->vif_deletion_delay[0]));	\
      } while (0)
  
  #define FREE_MRTENTRY(mrtentry_ptr)				\
      do {							\
  	kernel_cache_t *curr;					\
  	kernel_cache_t *next;					\
  								\
  	if ((mrtentry_ptr)->vif_timers)				\
  	    free((mrtentry_ptr)->vif_timers);			\
  	if ((mrtentry_ptr)->vif_deletion_delay)			\
  	    free((mrtentry_ptr)->vif_deletion_delay);		\
  	curr = (mrtentry_ptr)->kernel_cache;			\
  	while (curr) {						\
  	    next = curr->next;					\
  	    free(curr);						\
  	    curr = next;					\
  	}							\
  	free(mrtentry_ptr);					\
      } while (0)
  
  
  /*
   * The complicated structure used by the more complicated Join/Prune
   * message building
   */
  typedef struct build_jp_message_ {
      struct build_jp_message_ *next; /* Used to chain the free entries       */
      uint8_t *jp_message;       /* The Join/Prune message                     */
      uint32_t jp_message_size;  /* Size of the Join/Prune message (in bytes)  */
      uint16_t holdtime;	      /* Join/Prune message holdtime field	    */
      uint32_t curr_group;	      /* Current group address			    */
      uint8_t  curr_group_msklen;/* Current group masklen			    */
      uint8_t *join_list;	      /* The working area for the join addresses    */
      uint32_t join_list_size;   /* The size of the join_list (in bytes)       */
      uint16_t join_addr_number; /* Number of the join addresses in join_list  */
      uint8_t *prune_list;       /* The working area for the prune addresses   */
      uint32_t prune_list_size;  /* The size of the prune_list (in bytes)      */
      uint16_t prune_addr_number;/* Number of the prune addresses in prune_list*/
      uint8_t *rp_list_join;     /* The working area for RP join addresses     */
      uint32_t rp_list_join_size;/* The size of the rp_list_join (in bytes)    */
      uint16_t rp_list_join_number;/* Number of RP addresses in rp_list_join   */
      uint8_t *rp_list_prune;     /* The working area for RP prune addresses   */
      uint32_t rp_list_prune_size;/* The size of the rp_list_prune (in bytes)  */
      uint16_t rp_list_prune_number;/* Number of RP addresses in rp_list_prune */
      uint8_t *num_groups_ptr;   /* Pointer to number_of_groups in jp_message  */
  } build_jp_message_t;
  
  
  typedef struct pim_nbr_entry {
      struct pim_nbr_entry *next;		  /* link to next neighbor	    */
      struct pim_nbr_entry *prev;		  /* link to prev neighbor	    */
      uint32_t		  address;	  /* neighbor address		    */
      int8_t                dr_prio_present;/* If set, this neighbor has prio */
      uint32_t              dr_prio;	  /* DR priority: 1 (default)       */
      uint32_t              genid;	  /* Cached generation ID           */
      vifi_t		  vifi;		  /* which interface		    */
      uint16_t		  timer;	  /* for timing out neighbor	    */
      time_t		  uptime;	  /* time since first hello	    */
      build_jp_message_t *build_jp_message; /* A structure for fairly
  					   * complicated Join/Prune
  					   * message construction.
  					   */
  } pim_nbr_entry_t;
  
  
  typedef struct srcentry {
      struct srcentry	 *next;		/* link to next entry		    */
      struct srcentry	 *prev;		/* link to prev entry		    */
      uint32_t		  address;	/* source or RP address		    */
      struct mrtentry	 *mrtlink;	/* link to routing entries	    */
      vifi_t		  incoming;	/* incoming vif			    */
      struct pim_nbr_entry *upstream;	/* upstream router		    */
      uint32_t		  metric;	/* Unicast Routing Metric to the source */
      uint32_t		  preference;	/* The metric preference (for assers)*/
      struct cand_rp	 *cand_rp;	/* Used if this is rpentry_t	    */
      uint16_t		 adv_holdtime;	/* rpentry_t: RP advertized holdtime*/
  } srcentry_t;
  typedef srcentry_t rpentry_t;
  
  
  /* (RP<->group) matching table related structures */
  typedef struct cand_rp {
      struct cand_rp	*next;	       /* Next candidate RP		    */
      struct cand_rp	*prev;	       /* Previous candidate RP		    */
      struct rp_grp_entry *rp_grp_next;  /* The rp_grp_entry chain for that RP*/
      rpentry_t		*rpentry;      /* Pointer to the RP entry	    */
  } cand_rp_t;
  
  typedef struct grp_mask {
      struct grp_mask	*next;
      struct grp_mask	*prev;
      struct rp_grp_entry *grp_rp_next;
      uint32_t		 group_addr;
      uint32_t		 group_mask;
      uint32_t		 hash_mask;
      uint16_t		 fragment_tag;	  /* Used for garbage collection    */
      uint8_t		 group_rp_number; /* Used when assembling segments  */
  } grp_mask_t;
  
  typedef struct rp_grp_entry {
      struct rp_grp_entry *rp_grp_next; /* Next entry for same RP		 */
      struct rp_grp_entry *rp_grp_prev; /* Prev entry for same RP		 */
      struct rp_grp_entry *grp_rp_next; /* Next entry for same grp prefix	 */
      struct rp_grp_entry *grp_rp_prev; /* Prev entry for same grp prefix	 */
      struct grpentry	*grplink;     /* Link to all grps via this entry */
      uint16_t		 holdtime;    /* The RP holdtime		 */
      uint16_t		 fragment_tag; /* The fragment tag from the
  					* received BSR message		 */
      uint8_t		 priority;    /* The RP priority		 */
      grp_mask_t		*group;	      /* Pointer to (group,mask) entry	 */
      cand_rp_t		*rp;	      /* Pointer to the RP		 */
  } rp_grp_entry_t;
  
  
  typedef struct grpentry {
      struct grpentry	*next;	       /* link to next entry		    */
      struct grpentry	*prev;	       /* link to prev entry		    */
      struct grpentry	*rpnext;       /* next grp for the same RP	    */
      struct grpentry	*rpprev;       /* prev grp for the same RP	    */
      uint32_t		 group;	       /* subnet group of multicasts	    */
      uint32_t		 rpaddr;       /* The IP address of the RP	    */
      struct mrtentry	*mrtlink;      /* link to (S,G) routing entries	    */
      rp_grp_entry_t	*active_rp_grp;/* Pointer to the active rp_grp entry*/
      struct mrtentry	*grp_route;    /* Pointer to the (*,G) routing entry*/
  } grpentry_t;
  
  typedef struct mrtentry {
      struct mrtentry	  *grpnext;	/* next entry of same group	    */
      struct mrtentry	  *grpprev;	/* prev entry of same group	    */
      struct mrtentry	  *srcnext;	/* next entry of same source	    */
      struct mrtentry	  *srcprev;	/* prev entry of same source	    */
      struct grpentry	  *group;	/* pointer to group entry	    */
      struct srcentry	  *source;	/* pointer to source entry (or RP)  */
      vifi_t		  incoming;	/* the iif (either toward S or RP)  */
      uint8_t		  oifs[MAXVIFS];		/* The current result oifs	    */
      uint8_t		  joined_oifs[MAXVIFS];		/* The joined oifs (Join received)  */
      uint8_t		  pruned_oifs[MAXVIFS]; 	/* The pruned oifs (Prune received) */
      uint8_t		  asserted_oifs[MAXVIFS];	/* The asserted oifs (lost Assert)  */
      uint8_t		  leaves[MAXVIFS];		/* Has directly connected members   */
      struct pim_nbr_entry *upstream;	/* upstream router, needed because
  					 * of the asserts it may be different
  					 * than the source (or RP) upstream
  					 * router.
  					 */
      uint32_t		 metric;	/* Routing Metric for this entry    */
      uint32_t		 preference;	/* The metric preference value	    */
      uint32_t		 pmbr_addr;	/* The PMBR address (for interop)   */
      uint16_t		*vif_timers;	/* vifs timer list		    */
      uint16_t		*vif_deletion_delay; /* vifs deletion delay list    */
      uint16_t		 flags;		/* The MRTF_* flags		    */
      uint16_t		 timer;		/* entry timer			    */
      uint16_t		 jp_timer;	/* The Join/Prune timer		    */
      uint16_t		 rs_timer;	/* Register-Suppression Timer	    */
      u_int		 assert_timer;
      u_int		 assert_rate_timer;
      struct kernel_cache *kernel_cache;	/* List of the kernel cache entries */
  #ifdef RSRR
      struct rsrr_cache	*rsrr_cache;	/* Used to save RSRR requests for
  					 * route change notification. */
  #endif /* RSRR */
  } mrtentry_t;
  
  
  /*
   * Used to get forwarded data related counts (number of packet, number of
   * bits, etc)
   */
  struct sg_count {
      uint32_t  pktcnt;     /*  Number of packets for (s,g) */
      uint32_t  bytecnt;    /*  Number of bytes for (s,g)   */
      uint32_t  wrong_if;   /*  Number of packets received on wrong iif for (s,g) */
  };
  
  struct vif_count {
      uint32_t  icount;     /* Input packet count on vif    */
      uint32_t  ocount;     /* Output packet count on vif   */
      uint32_t  ibytes;     /* Input byte count on vif      */
      uint32_t  obytes;     /* Output byte count on vif     */
  };
  
  /*
   * Structure to keep track of existing (S,G) MFC entries in the kernel
   * for particular (*,G) or (*,*,RP) entry. We must keep track for
   * each active source which doesn't have (S,G) entry in the daemon's
   * routing table. We need to keep track of such sources for two reasons:
   *
   *    (1) If the kernel does not support (*,G) MFC entries (currently, the
   * "official" mcast code doesn't), we must know all installed (s,G) entries
   * in the kernel and modify them if the iif or oif for the (*,G) changes.
   *
   *    (2) By checking periodically the traffic coming from the shared tree,
   * we can either delete the idle sources or switch to the shortest path.
   *
   * Note that even if we have (*,G) implemented in the kernel, we still
   * need to have this structure because of (2)
   */
  typedef struct kernel_cache {
      struct kernel_cache *next;
      struct kernel_cache *prev;
      uint32_t		 source;
      uint32_t		 group;
      struct sg_count      sg_count; /* The (s,g) data retated counters (see above) */
  } kernel_cache_t;
  
  /**
   * Local Variables:
   *  indent-tabs-mode: t
   *  c-file-style: "ellemtel"
   *  c-basic-offset: 4
   * End:
   */
  