Subject: link state + arrival/departure routing socket messages
To: None <tech-net@netbsd.org>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-net
Date: 03/02/2000 10:26:42
Hi folks...

One of the things that routing daemons like is to know when an interface's
link goes down or comes back up.  They might also like to know when new
interfaces arrive on the system (this is also useful for e.g. DHCP).

The obvious place to put link state is in the current "info" message,
but doing so would require we either:

	(1) Break binary compatibility.
  -- or --
	(2) Version the message again.

I don't think it's worth versioning the message again; the new "info"
message is marked as "1.5 and later", so I think we should just bust
the binary compat with -current.

For the arrival/departure issue, I've created a new message type.  See
the diffs for more info.

While I haven't added support for actually frobbing the link state in
the interface info or sending the arrival/departure messages, I think
we should get these parts in before 1.5 at least, so that the data
structures are defined and ready to go for when the guts are actually
implemented.

Comments?

        -- Jason R. Thorpe <thorpej@nas.nasa.gov>

Index: net/if.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.c,v
retrieving revision 1.56
diff -c -r1.56 if.c
*** if.c	2000/02/06 16:43:33	1.56
--- if.c	2000/03/02 17:43:55
***************
*** 331,336 ****
--- 331,338 ----
  	if (ifp->if_snd.ifq_maxlen == 0)
  	    ifp->if_snd.ifq_maxlen = ifqmaxlen;
  	ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
+ 
+ 	IF_LINK_STATE_INIT(ifp);
  }
  
  /*
Index: net/if.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.h,v
retrieving revision 1.44
diff -c -r1.44 if.h
*** if.h	2000/02/01 22:52:05	1.44
--- if.h	2000/03/02 17:43:55
***************
*** 116,129 ****
  struct ether_header;
  
  /*
   * Structure defining statistics and other data kept regarding a network
   * interface.
   */
! struct	if_data {
  	/* generic interface information */
  	u_char	ifi_type;		/* ethernet, tokenring, etc. */
  	u_char	ifi_addrlen;		/* media address length */
  	u_char	ifi_hdrlen;		/* media header length */
  	u_quad_t ifi_mtu;		/* maximum transmission unit */
  	u_quad_t ifi_metric;		/* routing metric (external only) */
  	u_quad_t ifi_baudrate;		/* linespeed */
--- 116,140 ----
  struct ether_header;
  
  /*
+  * Values of a network interface's link state.
+  */
+ typedef enum {
+ 	LINK_STATE_INVALID,		/* link state invalid/not known */
+ 	LINK_STATE_DOWN,		/* link is down */
+ 	LINK_STATE_UP,			/* link is up */
+ } if_link_state_t;
+ 
+ /*
   * Structure defining statistics and other data kept regarding a network
   * interface.
   */
! struct if_data {
  	/* generic interface information */
  	u_char	ifi_type;		/* ethernet, tokenring, etc. */
  	u_char	ifi_addrlen;		/* media address length */
  	u_char	ifi_hdrlen;		/* media header length */
+ 	if_link_state_t ifi_link_state;	/* current link state */
+ 	if_link_state_t ifi_link_state_prev; /* previous link state */
  	u_quad_t ifi_mtu;		/* maximum transmission unit */
  	u_quad_t ifi_metric;		/* routing metric (external only) */
  	u_quad_t ifi_baudrate;		/* linespeed */
***************
*** 144,150 ****
  
  #ifdef COMPAT_14
  /* Pre-1.5 if_data struct */
! struct	if_data14 {
  	/* generic interface information */
  	u_char	ifi_type;		/* ethernet, tokenring, etc. */
  	u_char	ifi_addrlen;		/* media address length */
--- 155,161 ----
  
  #ifdef COMPAT_14
  /* Pre-1.5 if_data struct */
! struct if_data14 {
  	/* generic interface information */
  	u_char	ifi_type;		/* ethernet, tokenring, etc. */
  	u_char	ifi_addrlen;		/* media address length */
***************
*** 229,234 ****
--- 240,247 ----
  #define	if_addrlen	if_data.ifi_addrlen
  #define	if_hdrlen	if_data.ifi_hdrlen
  #define	if_metric	if_data.ifi_metric
+ #define	if_link_state	if_data.ifi_link_state
+ #define	if_link_state_prev if_data.ifi_link_state_prev
  #define	if_baudrate	if_data.ifi_baudrate
  #define	if_ipackets	if_data.ifi_ipackets
  #define	if_ierrors	if_data.ifi_ierrors
***************
*** 300,305 ****
--- 313,348 ----
  }
  
  #define	IFQ_MAXLEN	50
+ 
+ /*
+  * Interface link state manipulation.
+  */
+ #define	IF_LINK_STATE_INIT(ifp)						\
+ do {									\
+ 	/* XXX Default to UP? --thorpej */				\
+ 	(ifp)->if_link_state_prev =					\
+ 	(ifp)->if_link_state = LINK_STATE_INVALID;			\
+ } while (0)
+ 
+ #define	IF_LINK_STATE_SET(ifp, state)					\
+ do {									\
+ 	(ifp)->if_link_state_prev = (ifp)->if_link_state;		\
+ 	(ifp)->if_link_state = (state);					\
+ } while (0)
+ 
+ #define	IF_LINK_STATE_INVALIDATE(ifp)					\
+ do {									\
+ 	(ifp)->if_link_state = LINK_STATE_INVALID;			\
+ } while (0)
+ 
+ #define	IF_LINK_STATE_CAME_UP(ifp)					\
+ 	((ifp)->if_link_state_prev == LINK_STATE_DOWN &&		\
+ 	 (ifp)->if_link_state == LINK_STATE_UP)
+ 
+ #define	IF_LINK_STATE_WENT_DOWN(ifp)					\
+ 	((ifp)->if_link_state_prev == LINK_STATE_UP &&			\
+ 	 (ifp)->if_link_state == LINK_STATE_DOWN)
+ 
  #define	IFNET_SLOWHZ	1		/* granularity is 1 second */
  
  /*
***************
*** 387,392 ****
--- 430,450 ----
  	u_short	ifam_index;	/* index for associated ifp */
  	int	ifam_metric;	/* value of ifa_metric */
  };
+ 
+ /*
+  * Message format announcing the arrival or departure of a network interface.
+  */
+ struct if_announcemsghdr {
+ 	u_short	ifan_msglen;	/* to skip over non-understood messages */
+ 	u_char	ifan_version;	/* future binary compatibility */
+ 	u_char	ifan_type;	/* message type */
+ 	u_short	ifan_index;	/* index for associated ifp */
+ 	char	ifan_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ 	u_short	ifna_what;	/* what type of announcement */
+ };
+ 
+ #define	IFNA_ARRIVAL	0	/* interface arrival */
+ #define	IFNA_DEPARTURE	1	/* interface departure */
  
  /*
   * Interface request structure used for socket
Index: net/route.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/route.h,v
retrieving revision 1.20
diff -c -r1.20 route.h
*** route.h	1999/11/19 10:41:42	1.20
--- route.h	2000/03/02 17:43:58
***************
*** 186,192 ****
  #define RTM_NEWADDR	0xc	/* address being added to iface */
  #define RTM_DELADDR	0xd	/* address being removed from iface */
  #define RTM_OIFINFO	0xe	/* Old (pre-1.5) RTM_IFINFO message */
! #define RTM_IFINFO	0xf	/* iface going up/down etc. */
  
  #define RTV_MTU		0x1	/* init or lock _mtu */
  #define RTV_HOPCOUNT	0x2	/* init or lock _hopcount */
--- 186,193 ----
  #define RTM_NEWADDR	0xc	/* address being added to iface */
  #define RTM_DELADDR	0xd	/* address being removed from iface */
  #define RTM_OIFINFO	0xe	/* Old (pre-1.5) RTM_IFINFO message */
! #define RTM_IFINFO	0xf	/* iface/link going up/down etc. */
! #define	RTM_IFANNOUNCE	0x10	/* iface arrival/departure */
  
  #define RTV_MTU		0x1	/* init or lock _mtu */
  #define RTV_HOPCOUNT	0x2	/* init or lock _hopcount */