/* $Header: ip_mroute.h,v 1.4.98.1 95/07/20 10:51:31 root Exp $ */

#ifndef _NETINET_IP_MROUTE_INCLUDED
#define _NETINET_IP_MROUTE_INCLUDED

/*
 * Definitions for IP multicast forwarding.
 *
 * Written by David Waitzman, BBN Labs, August 1988.
 * Modified by Steve Deering, Stanford, February 1989.
 * Modified by Ajit Thyagarajan, PARC, August 1993.
 * Modified by Ajit Thyagarajan, PARC, August 1994.
 *
 * MROUTING 1.5
 */

/*HP* move to h/ioctl.h at a later time */
/* MULTICAST */
#define	SIOCSETRTINFO	_IOWR('r', 13, struct fullrtentry) /* change aux info */
#define	SIOCGETRTINFO	_IOWR('r', 14, struct fullrtentry) /* read aux info */
#define SIOCGETVIFCNT	_IOWR('r', 15, struct sioc_vif_req)/* get vif pkt cnt */
#define SIOCGETSGCNT	_IOWR('r', 16, struct sioc_sg_req) /* get s,g pkt cnt */
#define	SIOCGETVIFINF	_IOWR('r', 17, struct vif_conf)    /* read m/c vifs  */
/* MULTICAST */
/*HP* end h/ioctl.h */

#ifdef _KERNEL

/*HP* move to net/netmp.h at a later time */
/* these must be higher order than SOCKET_LOCK because
 * they may be acquired after SOCKET_LOCK.
 *
 * VIF_GLOBALS_LOCK must be higher order because it
 * may be acquired after MFC_GLOBALS_LOCK.
 *
 */
#define MFC_GLOBALS_LOCK_ORDER  175  /* higher than SOCK_LOCK_ORDER */
#define VIF_GLOBALS_LOCK_ORDER  180  /* higher than MFC_GLOBALS_LOCK_ORDER */
/*HP* end net/netmp.h */

/*HP*/
#ifdef _KERNEL_BUILD
#include "../net/netmp.h"
#else
#include <net/netmp.h>
#endif /* _KERNEL_BUILD */

#endif /* _KERNEL */

/*HP*/
#ifdef _KERNEL_BUILD
#include "../h/socket.h"
#include "../h/ioctl.h"
#include "../net/if.h"
#else
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#endif /* _KERNEL_BUILD */

/*
 * DVMRP-specific setsockopt commands.
 */
#define DVMRP_INIT		100
#define DVMRP_DONE		101
#define DVMRP_ADD_VIF		102
#define DVMRP_DEL_VIF		103
#define DVMRP_ADD_MFC		104
#define DVMRP_DEL_MFC		105


#if BSD >= 199103 
#define GET_TIME(t)	microtime(&t)
#elif defined(__sun__) || defined(hpux)
#define GET_TIME(t)	uniqtime(&t)
#else
#define GET_TIME(t)	((t) = time)
#endif

/*
 * Types and macros for handling bitmaps with one bit per virtual interface.
 */
#define MAXVIFS 32
typedef u_long vifbitmap_t;
typedef u_short vifi_t;		/* type of a vif index */

#define	VIFM_SET(n, m)			((m) |=  (1 << (n)))
#define	VIFM_CLR(n, m)			((m) &= ~(1 << (n)))
#define	VIFM_ISSET(n, m)		((m) &   (1 << (n)))
#define VIFM_CLRALL(m)			((m) = 0x00000000)
#define VIFM_COPY(mfrom, mto)		((mto) = (mfrom))
#define VIFM_SAME(m1, m2)		((m1) == (m2))
								  
/*
 * Argument structure for DVMRP_ADD_VIF.
 * (DVMRP_DEL_VIF takes a single vifi_t argument.)
 */
struct vifctl {
    vifi_t	    vifc_vifi;	    	/* the index of the vif to be added  */
    u_char	    vifc_flags;     	/* VIFF_ flags defined below         */
    u_char	    vifc_threshold; 	/* min ttl required to forward on vif*/
    u_int	    vifc_rate_limit;    /* max rate           		     */
    struct in_addr  vifc_lcl_addr;  	/* local interface address           */
    struct in_addr  vifc_rmt_addr;  	/* remote address (tunnels only)     */
};

#define VIFF_TUNNEL	  0x1	    	/* vif represents a tunnel end-point */
#define VIFF_SRCRT	  0x2	    	/* tunnel uses IP src routing	     */


/*
 * Argument structure for DVMRP_ADD_MFC
 * (mfcc_tos to be added at a future point)
 */
struct mfcctl {
    struct in_addr  mfcc_origin;		/* subnet origin of mcasts   */
    struct in_addr  mfcc_mcastgrp; 		/* multicast group associated*/
    struct in_addr  mfcc_originmask;		/* subnet mask for origin    */
    vifi_t	    mfcc_parent;   		/* incoming vif              */
    u_char	    mfcc_ttls[MAXVIFS]; 	/* forwarding ttls on vifs   */
};

/*
 * Argument structure for DVMRP_DEL_MFC
 */
struct delmfcctl {
    struct in_addr  mfcc_origin;    /* subnet origin of multicasts      */
    struct in_addr  mfcc_mcastgrp;  /* multicast group assoc. w/ origin */
};

/*
 * Argument structure used by RSVP daemon to get vif information
 */
struct vif_req {
    u_char         v_flags;         /* VIFF_ flags defined above           */
    u_char         v_threshold;     /* min ttl required to forward on vif  */
    struct in_addr v_lcl_addr;      /* local interface address             */
    struct in_addr v_rmt_addr; 
    char           v_if_name[IFNAMSIZ];  /* if name */
};

struct vif_conf {
    u_int          vifc_len;
    u_int          vifc_num;
    struct vif_req *vifc_req;
};

/*
 * The kernel's multicast routing statistics.
 */
struct mrtstat {
    u_long	mrts_mfc_lookups;	/* # forw. cache hash table hits   */
    u_long	mrts_mfc_misses;	/* # forw. cache hash table misses */
    u_long	mrts_upcalls;		/* # calls to mrouted              */
    u_long	mrts_no_route;		/* no route for packet's origin    */
    u_long	mrts_bad_tunnel;	/* malformed tunnel options        */
    u_long	mrts_cant_tunnel;	/* no room for tunnel options      */
    u_long	mrts_wrong_if;		/* arrived on wrong interface	   */
    u_long	mrts_upq_ovflw;		/* upcall Q overflow		   */
    u_long	mrts_cache_cleanups;	/* # entries with no upcalls 	   */
    u_long  	mrts_drop_sel;     	/* pkts dropped selectively        */
    u_long  	mrts_q_overflow;    	/* pkts dropped - Q overflow       */
    u_long  	mrts_pkt2large;     	/* pkts dropped - size > BKT SIZE  */
};

/*
 * Argument structure used by mrouted to get src-grp pkt counts
 */
struct sioc_sg_req {
    struct in_addr src;
    struct in_addr grp;
    u_long count;
};

/*
 * Argument structure used by mrouted to get vif pkt counts
 */
struct sioc_vif_req {
    vifi_t vifi;
    u_long icount;
    u_long ocount;
};
    
/*
 * The kernel's virtual-interface structure.
 */
struct vif {
    u_char   		v_flags;     	/* VIFF_ flags defined above         */
    u_char   		v_threshold;	/* min ttl required to forward on vif*/
    u_int      		v_rate_limit; 	/* max rate			     */
    struct tbf 	       *v_tbf;       	/* token bucket structure at intf.   */
    struct in_addr 	v_lcl_addr;   	/* local interface address           */
    struct in_addr 	v_rmt_addr;   	/* remote address (tunnels only)     */
    struct ifnet       *v_ifp;	     	/* pointer to interface              */
    u_long		v_pkt_in;	/* # pkts in on interface            */
    u_long		v_pkt_out;	/* # pkts out on interface           */
};

/*
 * The kernel's multicast forwarding cache entry structure 
 * (A field for the type of service (mfc_tos) is to be added 
 * at a future point)
 */
struct mfc {
    struct in_addr  mfc_origin;	 		/* subnet origin of mcasts   */
    struct in_addr  mfc_mcastgrp;  		/* multicast group associated*/
    struct in_addr  mfc_originmask;		/* subnet mask for origin    */
    vifi_t	    mfc_parent; 		/* incoming vif              */
    u_char	    mfc_ttls[MAXVIFS]; 		/* forwarding ttls on vifs   */
    u_long	    mfc_pkt_cnt;		/* pkt count for src-grp     */
    u_long	    mfc_state;			/*HP* see MFCS consts below  */
};

/*HP* mfc_state flags */
#define MFCS_TIMERRUNNING 0x00000001  /* timeout() scheduled  */
#define MFCS_ISDELETED    0x00000002  /* delayed mfc deletion */

/*
 * Argument structure used for pkt info. while upcall is made
 */
struct rtdetq {
    struct mbuf 	*m;
    struct ifnet	*ifp;
    u_long		tunnel_src;
    struct ip_moptions *imo;
};

#define MFCHASHSIZ	1024  /*HP* netstat:mroute.c depends on this! */
#define MFCTBLSIZ	256
#if (MFCTBLSIZ & (MFCTBLSIZ - 1)) == 0	  /* from sys:route.h */
#define MFCHASHMOD(h)	((h) & (MFCTBLSIZ - 1))
#else
#define MFCHASHMOD(h)	((h) % MFCTBLSIZ)
#endif

#define MAX_UPQ	4		/* max. no of pkts in upcall Q */

/*
 * Token Bucket filter code 
 */
#define MAX_BKT_SIZE    10000             /* 10K bytes size 		*/
#define MAXQSIZE        10                /* max # of pkts in queue 	*/

/*
 * queue structure at each vif
 */
struct pkt_queue 
{
    u_long pkt_len;               /* length of packet in queue 	*/
    struct mbuf *pkt_m;           /* pointer to packet mbuf	*/
    struct ip  *pkt_ip;           /* pointer to ip header	*/
};

/*
 * the token bucket filter at each vif
 */
struct tbf
{
    u_long last_pkt_t;	/* arr. time of last pkt 	*/
    u_long n_tok;      	/* no of tokens in bucket 	*/
    u_long q_len;    	/* length of queue at this vif	*/
};

#ifdef _KERNEL

/*HP*/
#define VIF_GLOBALS_LOCKINIT() {                             \
   b_initsema(&vif_globals_lock, 1,                          \
              (VIF_GLOBALS_LOCK_ORDER | SEMA_DEADLOCK_SAFE), \
              "LTYPE_VIF_GLOBALS");                          \
   }
#define VIF_GLOBALS_LOCK()     {if (!uniprocessor) b_psema(&vif_globals_lock);}
#define VIF_GLOBALS_UNLOCK()   {if (!uniprocessor) b_vsema(&vif_globals_lock);}
#define VIF_GLOBALS_ISLOCKED() (uniprocessor || b_owns_sema(&vif_globals_lock))

#define MFC_GLOBALS_LOCKINIT() {                             \
   b_initsema(&mfc_globals_lock, 1,                          \
              (MFC_GLOBALS_LOCK_ORDER | SEMA_DEADLOCK_SAFE), \
              "LTYPE_MFC_GLOBALS");                          \
   }
#define MFC_GLOBALS_LOCK()     {if (!uniprocessor) b_psema(&mfc_globals_lock);}
#define MFC_GLOBALS_UNLOCK()   {if (!uniprocessor) b_vsema(&mfc_globals_lock);}
#define MFC_GLOBALS_ISLOCKED() (uniprocessor || b_owns_sema(&mfc_globals_lock))

extern b_sema_t vif_globals_lock;
extern b_sema_t mfc_globals_lock;

#endif /* _KERNEL */

#endif /* _NETINET_IP_MROUTE_INCLUDED */
