svn commit: r195407 - projects/mesh11s/sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Mon Jul 6 14:02:27 UTC 2009


Author: rpaulo
Date: Mon Jul  6 14:02:27 2009
New Revision: 195407
URL: http://svn.freebsd.org/changeset/base/195407

Log:
  Implement modularized path selection. This makes the HWMP code self
  contained (everything is static).
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_hwmp.c
  projects/mesh11s/sys/net80211/ieee80211_hwmp.h
  projects/mesh11s/sys/net80211/ieee80211_mesh.c
  projects/mesh11s/sys/net80211/ieee80211_mesh.h
  projects/mesh11s/sys/net80211/ieee80211_output.c

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Mon Jul  6 12:19:59 2009	(r195406)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.c	Mon Jul  6 14:02:27 2009	(r195407)
@@ -64,7 +64,11 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_hwmp.h>
 #include <net80211/ieee80211_input.h>
 
-static int	ieee80211_hwmp_send_action(struct ieee80211_node *,
+static void	hwmp_vattach(struct ieee80211vap *);
+static void	hwmp_vdetach(struct ieee80211vap *);
+static int	hwmp_newstate(struct ieee80211vap *,
+		    enum ieee80211_state, int);
+static int	hwmp_send_action(struct ieee80211_node *,
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    uint8_t *, size_t);
@@ -107,6 +111,10 @@ static inline int hwmp_send_rann(struct 
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    struct ieee80211_meshrann_ie *);
+static struct ieee80211_node *
+		hwmp_discover(struct ieee80211vap *,
+		    const uint8_t [IEEE80211_ADDR_LEN], struct mbuf *);
+static void	hwmp_peerdown(struct ieee80211_node *);
 
 static int	ieee80211_hwmp_targetonly = 0;
 static int	ieee80211_hwmp_replyforward = 1;
@@ -162,6 +170,18 @@ static	ieee80211_recv_action_func hwmp_r
 static	ieee80211_recv_action_func hwmp_recv_action_meshpath_perr;
 static	ieee80211_recv_action_func hwmp_recv_action_meshpath_rann;
 
+static const struct ieee80211_mesh_proto_path mesh_proto_hwmp = {
+	.mpp_descr	= "HWMP",
+	.mpp_ie		= IEEE80211_MESHCONF_HWMP,
+	.mpp_discover	= hwmp_discover,
+	.mpp_peerdown	= hwmp_peerdown,
+	.mpp_vattach	= hwmp_vattach,
+	.mpp_vdetach	= hwmp_vdetach,
+	.mpp_newstate	= hwmp_newstate,
+	.mpp_privlen	= sizeof(struct ieee80211_hwmp_route),
+};
+
+
 static void
 ieee80211_hwmp_init(void)
 {
@@ -176,11 +196,16 @@ ieee80211_hwmp_init(void)
 	    IEEE80211_ACTION_MESHPATH_ERR, hwmp_recv_action_meshpath_perr);
 	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_MESHPATH,
 	    IEEE80211_ACTION_MESHPATH_RANN, hwmp_recv_action_meshpath_rann);
+
+	/*
+	 * Register HWMP.
+	 */
+	ieee80211_mesh_register_proto_path(&mesh_proto_hwmp);
 }
 SYSINIT(wlan_hwmp, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_hwmp_init, NULL);
 
 void
-ieee80211_hwmp_vattach(struct ieee80211vap *vap)
+hwmp_vattach(struct ieee80211vap *vap)
 {
 	struct ieee80211_hwmp_state *hs;
 
@@ -195,12 +220,12 @@ ieee80211_hwmp_vattach(struct ieee80211v
 	}
 	hs->hs_maxhops = IEEE80211_HWMP_DEFAULT_MAXHOPS;
 	hs->hs_ttl = IEEE80211_HWMP_DEFAULT_TTL;
-	callout_init(&hs->hs_roottimer, CALLOUT_MPSAFE);                                        
+	callout_init(&hs->hs_roottimer, CALLOUT_MPSAFE);
 	vap->iv_hwmp = hs;
 }
 
 void
-ieee80211_hwmp_vdetach(struct ieee80211vap *vap)
+hwmp_vdetach(struct ieee80211vap *vap)
 {
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
 
@@ -211,7 +236,7 @@ ieee80211_hwmp_vdetach(struct ieee80211v
 } 
 
 int
-ieee80211_hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
+hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
 {
 	enum ieee80211_state nstate = vap->iv_state;
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
@@ -347,7 +372,7 @@ hwmp_recv_action_meshpath_rann(struct ie
 }
 
 static int
-ieee80211_hwmp_send_action(struct ieee80211_node *ni,
+hwmp_send_action(struct ieee80211_node *ni,
     const uint8_t sa[IEEE80211_ADDR_LEN],
     const uint8_t da[IEEE80211_ADDR_LEN],
     uint8_t *ie, size_t len)
@@ -680,9 +705,9 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		 */
 		rt = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
 		if (rt == NULL)
-			ieee80211_hwmp_discover(vap, preq->preq_origaddr, NULL);
+			hwmp_discover(vap, preq->preq_origaddr, NULL);
 		else if (IEEE80211_ADDR_EQ(rt->rt_nexthop, invalidaddr))
-			ieee80211_hwmp_discover(vap, rt->rt_dest, NULL);
+			hwmp_discover(vap, rt->rt_dest, NULL);
 		return;
 	}
 	/*
@@ -701,8 +726,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		IEEE80211_ADDR_COPY(rootmac, preq->preq_origaddr);
 		rt = ieee80211_mesh_rt_find(vap, rootmac);
 		if (rt == NULL)
-			rt = ieee80211_mesh_rt_add(vap, rootmac,
-			    sizeof(struct ieee80211_hwmp_route));
+			rt = ieee80211_mesh_rt_add(vap, rootmac);
 		/*
 		 * Reply with a PREP if we don't have a path to the root
 		 * or if the root sent us a proactive PREQ.
@@ -724,7 +748,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 			hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
 			    broadcastaddr, &prep);
 		}
-		ieee80211_hwmp_discover(vap, rootmac, NULL);
+		hwmp_discover(vap, rootmac, NULL);
 		return;
 	}
 	rt = ieee80211_mesh_rt_find(vap, PREQ_TADDR(0));
@@ -801,8 +825,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		 */
 		} else if (preq->preq_ttl > 1) {
 			if (rt == NULL)
-				rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0),
-				    sizeof(struct ieee80211_hwmp_route));
+				rt = ieee80211_mesh_rt_add(vap, PREQ_TADDR(0));
 			hr = IEEE80211_MESH_ROUTE_PRIV(rt,
 			    struct ieee80211_hwmp_route);
 			rt->rt_metric = preq->preq_metric;
@@ -851,7 +874,7 @@ hwmp_send_preq(struct ieee80211_node *ni
 	 *     [tlv] mesh path request
 	 */
 	preq->preq_ie = IEEE80211_ELEMID_MESHPREQ;
-	return ieee80211_hwmp_send_action(ni, sa, da, (uint8_t *)preq,
+	return hwmp_send_action(ni, sa, da, (uint8_t *)preq,
 	    sizeof(struct ieee80211_meshpreq_ie));
 }
 
@@ -907,8 +930,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 		 * If we have no entry this could be a reply to a root PREQ.
 		 */
 		if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
-			rt = ieee80211_mesh_rt_add(vap, prep->prep_origaddr,
-			    sizeof(struct ieee80211_hwmp_route));
+			rt = ieee80211_mesh_rt_add(vap, prep->prep_origaddr);
 			IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
 			rt->rt_nhops = prep->prep_hopcount;
 			rt->rt_lifetime = prep->prep_lifetime;
@@ -995,14 +1017,14 @@ hwmp_send_prep(struct ieee80211_node *ni
 	 *     [tlv] mesh path reply
 	 */
 	prep->prep_ie = IEEE80211_ELEMID_MESHPREP;
-	return ieee80211_hwmp_send_action(ni, sa, da, (uint8_t *)prep,
+	return hwmp_send_action(ni, sa, da, (uint8_t *)prep,
 	    sizeof(struct ieee80211_meshprep_ie));
 }
 
 #define	PERR_DADDR(n)	perr.perr_dests[n].dest_addr
 #define	PERR_DSEQ(n)	perr.perr_dests[n].dest_seq
-void
-ieee80211_hwmp_peerdown(struct ieee80211_node *ni)
+static void
+hwmp_peerdown(struct ieee80211_node *ni)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_meshperr_ie perr;
@@ -1100,7 +1122,7 @@ hwmp_send_perr(struct ieee80211_node *ni
 	 *     [tlv] mesh path error
 	 */
 	perr->perr_ie = IEEE80211_ELEMID_MESHPERR;
-	return ieee80211_hwmp_send_action(ni, sa, da, (uint8_t *)perr,
+	return hwmp_send_action(ni, sa, da, (uint8_t *)perr,
 	    sizeof(struct ieee80211_meshperr_ie));
 }
 
@@ -1123,7 +1145,7 @@ hwmp_recv_rann(struct ieee80211vap *vap,
 	 * If we already know it, propagate the RANN element.
 	 */
 	if (rt == NULL) {
-		ieee80211_hwmp_discover(vap, rann->rann_addr, NULL);
+		hwmp_discover(vap, rann->rann_addr, NULL);
 		return;
 	}
 	hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
@@ -1154,15 +1176,15 @@ hwmp_send_rann(struct ieee80211_node *ni
 	 *     [tlv] root annoucement
 	 */
 	rann->rann_ie = IEEE80211_ELEMID_MESHRANN;
-	return ieee80211_hwmp_send_action(ni, sa, da, (uint8_t *)rann,
+	return hwmp_send_action(ni, sa, da, (uint8_t *)rann,
 	    sizeof(struct ieee80211_meshrann_ie));
 }
 
 #define	PREQ_TFLAGS(n)	preq.preq_targets[n].target_flags
 #define	PREQ_TADDR(n)	preq.preq_targets[n].target_addr
 #define	PREQ_TSEQ(n)	preq.preq_targets[n].target_seq
-struct ieee80211_node *
-ieee80211_hwmp_discover(struct ieee80211vap *vap,
+static struct ieee80211_node *
+hwmp_discover(struct ieee80211vap *vap,
     const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m)
 {
 	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
@@ -1182,8 +1204,7 @@ ieee80211_hwmp_discover(struct ieee80211
 	if (!IEEE80211_IS_MULTICAST(dest)) {
 		rt = ieee80211_mesh_rt_find(vap, dest);
 		if (rt == NULL) {
-			rt = ieee80211_mesh_rt_add(vap, dest,
-			    sizeof(struct ieee80211_hwmp_route));
+			rt = ieee80211_mesh_rt_add(vap, dest);
 			if (rt == NULL) {
 				/* XXX stat+msg */
 				goto done;

Modified: projects/mesh11s/sys/net80211/ieee80211_hwmp.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Mon Jul  6 12:19:59 2009	(r195406)
+++ projects/mesh11s/sys/net80211/ieee80211_hwmp.h	Mon Jul  6 14:02:27 2009	(r195407)
@@ -55,17 +55,6 @@ struct ieee80211_hwmp_state {
 	uint8_t			hs_maxhops;	/* max hop count */
 	uint8_t			hs_ttl;		/* HWMP ttl */
 };
-
-void		ieee80211_hwmp_vattach(struct ieee80211vap *);
-void		ieee80211_hwmp_vdetach(struct ieee80211vap *);
-int		ieee80211_hwmp_newstate(struct ieee80211vap *,
-		    enum ieee80211_state, int);
-void		ieee80211_hwmp_recv_action(struct ieee80211vap *,
-		    struct ieee80211_node *, struct mbuf *);
-struct ieee80211_node *
-		ieee80211_hwmp_discover(struct ieee80211vap *,
-		    const uint8_t [IEEE80211_ADDR_LEN], struct mbuf *);
-void		ieee80211_hwmp_peerdown(struct ieee80211_node *);
 #endif /* _KERNEL */
 
 #endif /* _NET80211_IEEE80211_HWMP_H_ */

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jul  6 12:19:59 2009	(r195406)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Jul  6 14:02:27 2009	(r195407)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_input.h>
 #include <net80211/ieee80211_mesh.h>
 
+static int	mesh_select_proto_path(struct ieee80211vap *, const char *);
 static int	mesh_select_proto_metric(struct ieee80211vap *, const char *);
 static void	mesh_vattach(struct ieee80211vap *);
 static int	mesh_newstate(struct ieee80211vap *, enum ieee80211_state, int);
@@ -147,7 +148,7 @@ ieee80211_mesh_rt_find(struct ieee80211v
 
 struct ieee80211_mesh_route *
 ieee80211_mesh_rt_add(struct ieee80211vap *vap,
-    const uint8_t dest[IEEE80211_ADDR_LEN], size_t privlen)
+    const uint8_t dest[IEEE80211_ADDR_LEN])
 {
         struct ieee80211_mesh_state *ms = vap->iv_mesh;
         struct ieee80211_mesh_route *rt;
@@ -164,7 +165,8 @@ ieee80211_mesh_rt_add(struct ieee80211va
         rt = malloc(sizeof(struct ieee80211_mesh_route), M_80211_MESH_RT,
             M_NOWAIT | M_ZERO);
         IEEE80211_ADDR_COPY(rt->rt_dest, dest);
-	rt->rt_priv = malloc(privlen, M_80211_MESH_RT, M_NOWAIT | M_ZERO);
+	rt->rt_priv = malloc(ms->ms_ppath->mpp_privlen, M_80211_MESH_RT,
+	    M_NOWAIT | M_ZERO);
         MESH_RT_LOCK(ms);
         TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
         MESH_RT_UNLOCK(ms);
@@ -178,7 +180,6 @@ ieee80211_mesh_rt_del(struct ieee80211va
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_mesh_route *rt, *next;
 
-	KASSERT(ms != NULL, ("no HWMP state"));
 	MESH_RT_LOCK(ms);
 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
 		if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
@@ -250,6 +251,23 @@ ieee80211_mesh_register_proto_metric(con
 }
 
 static int
+mesh_select_proto_path(struct ieee80211vap *vap, const char *name)
+{
+	struct ieee80211_mesh_state *ms = vap->iv_mesh;
+	int i;
+
+	for (i = 0; i < N(mesh_proto_paths); i++) {
+		if (strcmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
+			ms->ms_ppath = &mesh_proto_paths[i];
+			if (vap->iv_state == IEEE80211_S_RUN)
+				vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
+			return 0;
+		}
+	}
+	return ENOENT;
+}
+
+static int
 mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
 {
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
@@ -266,6 +284,7 @@ mesh_select_proto_metric(struct ieee8021
 	return ENOENT;
 }
 
+
 #undef	N
 
 static void
@@ -353,7 +372,7 @@ mesh_vdetach(struct ieee80211vap *vap)
 	    NULL);
 	ieee80211_mesh_rt_flush(vap);
 	mtx_destroy(&ms->ms_rt_lock);
-	ieee80211_hwmp_vdetach(vap);
+	ms->ms_ppath->mpp_vdetach(vap);
 	free(vap->iv_mesh, M_80211_VAP);
 	vap->iv_mesh = NULL;
 }
@@ -379,7 +398,10 @@ mesh_vattach(struct ieee80211vap *vap)
 	TAILQ_INIT(&ms->ms_routes);
 	mtx_init(&ms->ms_rt_lock, "MBSS", "802.11s routing table", MTX_DEF);
 	mesh_select_proto_metric(vap, "AIRTIME");
-	ieee80211_hwmp_vattach(vap);
+	KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
+	mesh_select_proto_path(vap, "HWMP");
+	KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
+	ms->ms_ppath->mpp_vattach(vap);
 }
 
 /*
@@ -533,7 +555,7 @@ mesh_newstate(struct ieee80211vap *vap, 
 	}
 
 	/* NB: ostate not nstate */
-	ieee80211_hwmp_newstate(vap, ostate, arg);
+	ms->ms_ppath->mpp_newstate(vap, ostate, arg);
 
 	return 0;
 }
@@ -563,6 +585,7 @@ static inline void
 mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 #ifdef IEEE80211_DEBUG
 	static const char *meshlinkstates[] = {
 		[IEEE80211_NODE_MESH_IDLE]		= "IDLE",
@@ -578,7 +601,7 @@ mesh_linkchange(struct ieee80211_node *n
 	    ni, "peer link: switching to state %s",
 	    meshlinkstates[ni->ni_mlstate]);
 	if (state == IEEE80211_NODE_MESH_HOLDING)
-		ieee80211_hwmp_peerdown(ni);
+		ms->ms_ppath->mpp_peerdown(ni);
 }
 
 /*
@@ -620,7 +643,7 @@ mesh_checkpseq(struct ieee80211vap *vap,
 
 	rt = ieee80211_mesh_rt_find(vap, source);
 	if (rt == NULL) {
-		rt = ieee80211_mesh_rt_add(vap, source, 12);
+		rt = ieee80211_mesh_rt_add(vap, source);
 		rt->rt_lastmseq = seq;
 		return 0;
 	}
@@ -2322,11 +2345,12 @@ void
 ieee80211_mesh_node_cleanup(struct ieee80211_node *ni)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 
 	callout_drain(&ni->ni_mltimer);
 	/* NB: short-circuit callbacks after mesh_vdetach */
 	if (vap->iv_mesh != NULL)
-		ieee80211_hwmp_peerdown(ni);
+		ms->ms_ppath->mpp_peerdown(ni);
 }
 
 void

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.h	Mon Jul  6 12:19:59 2009	(r195406)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.h	Mon Jul  6 14:02:27 2009	(r195407)
@@ -31,6 +31,8 @@
 #ifndef _NET80211_IEEE80211_MESH_H_
 #define _NET80211_IEEE80211_MESH_H_
 
+#include <net80211/ieee80211_proto.h>	/* for ieee80211_state */
+
 /*
  * 802.11s Information Elements.
 */
@@ -396,9 +398,14 @@ struct ieee80211_mesh_proto_path {
 	char 		mpp_descr[12];
 	uint8_t		mpp_ie[4];
 	struct ieee80211_node *
-	    		(*mpr_discover)(struct ieee80211vap *,
-				uint8_t [IEEE80211_ADDR_LEN],
+	    		(*mpp_discover)(struct ieee80211vap *,
+				const uint8_t [IEEE80211_ADDR_LEN],
 				struct mbuf *);
+	void		(*mpp_peerdown)(struct ieee80211_node *);
+	void		(*mpp_vattach)(struct ieee80211vap *);
+	void		(*mpp_vdetach)(struct ieee80211vap *);
+	int		(*mpp_newstate)(struct ieee80211vap *,
+			    enum ieee80211_state, int);
 	size_t		mpp_privlen;	/* size required in the routing table
 					   for private data */
 };
@@ -444,6 +451,8 @@ struct ieee80211_mesh_state {
 	   			ms_routes;
 	struct ieee80211_mesh_proto_metric
 	    			*ms_pmetric;
+	struct ieee80211_mesh_proto_path
+				*ms_ppath;
 };
 void		ieee80211_mesh_attach(struct ieee80211com *);
 void		ieee80211_mesh_detach(struct ieee80211com *);
@@ -453,7 +462,7 @@ struct ieee80211_mesh_route *
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 struct ieee80211_mesh_route *
                 ieee80211_mesh_rt_add(struct ieee80211vap *,
-		    const uint8_t [IEEE80211_ADDR_LEN], size_t);
+		    const uint8_t [IEEE80211_ADDR_LEN]);
 void		ieee80211_mesh_rt_del(struct ieee80211vap *,
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 void		ieee80211_mesh_rt_flush(struct ieee80211vap *);

Modified: projects/mesh11s/sys/net80211/ieee80211_output.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_output.c	Mon Jul  6 12:19:59 2009	(r195406)
+++ projects/mesh11s/sys/net80211/ieee80211_output.c	Mon Jul  6 14:02:27 2009	(r195407)
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
 #endif
 #include <net80211/ieee80211_wds.h>
 #include <net80211/ieee80211_mesh.h>
-#include <net80211/ieee80211_hwmp.h>
 
 #ifdef INET
 #include <netinet/in.h> 
@@ -240,11 +239,13 @@ ieee80211_start(struct ifnet *ifp)
 				continue;
 			}
 		} else {
-			ni = ieee80211_hwmp_discover(vap, eh->ether_dhost, m);
+			struct ieee80211_mesh_state *ms = vap->iv_mesh;
+
+			ni = ms->ms_ppath->mpp_discover(vap, eh->ether_dhost, m);
 			if (ni == NULL) {
 				/*
-				 * NB: ieee80211_hwmp_discover holds/disposes
-				 *     frame (e.g. queueing on path discovery.
+				 * NB: discover function holds/disposes
+				 *     frame (e.g. queueing on path discovery).
 				 */
 				ifp->if_oerrors++;
 				continue;


More information about the svn-src-projects mailing list