svn commit: r234877 - head/sys/net80211

Monthadar Al Jaberi monthadar at FreeBSD.org
Tue May 1 15:47:31 UTC 2012


Author: monthadar
Date: Tue May  1 15:47:30 2012
New Revision: 234877
URL: http://svn.freebsd.org/changeset/base/234877

Log:
  Implemented so that Mesh forwarding information lifetime is dynamic.
  
   * Introduced ieee80211_mesh_rt_update that updates a route with the
   maximum(lifetime left, new lifetime);
   * Modified ieee80211_mesh_route struct by adding a lock that will be used
   by both ieee80211_mesh_rt_update and precursor code (added in future commit);
   * Modified in ieee80211_hwmp.c HWMP code to use new ieee80211_mesh_rt_update;
   * Modified mesh_rt_flush_invalid to use new ieee80211_mesh_rt_update;
   * mesh_rt_flush also checks that lifetime == 0, this gives route discovery
   a change to complete;
   * Modified mesh_recv_mgmt case IEEE80211_FC0_SUBTYPE_BEACON:
   when ever we received a beacon from a neighbor we update route lifetime;
  
  Approved by: adrian

Modified:
  head/sys/net80211/ieee80211_ddb.c
  head/sys/net80211/ieee80211_hwmp.c
  head/sys/net80211/ieee80211_mesh.c
  head/sys/net80211/ieee80211_mesh.h

Modified: head/sys/net80211/ieee80211_ddb.c
==============================================================================
--- head/sys/net80211/ieee80211_ddb.c	Tue May  1 15:42:41 2012	(r234876)
+++ head/sys/net80211/ieee80211_ddb.c	Tue May  1 15:47:30 2012	(r234877)
@@ -870,8 +870,10 @@ _db_show_mesh(const struct ieee80211_mes
 	TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
 		db_printf("entry %d:\tdest: %6D nexthop: %6D metric: %u", i,
 		    rt->rt_dest, ":", rt->rt_nexthop, ":", rt->rt_metric);
+
 		db_printf("\tlifetime: %u lastseq: %u priv: %p\n",
-		    rt->rt_lifetime, rt->rt_lastmseq, rt->rt_priv);
+		    ieee80211_mesh_rt_update(rt, 0),
+		    rt->rt_lastmseq, rt->rt_priv);
 		i++;
 	}
 }

Modified: head/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- head/sys/net80211/ieee80211_hwmp.c	Tue May  1 15:42:41 2012	(r234876)
+++ head/sys/net80211/ieee80211_hwmp.c	Tue May  1 15:47:30 2012	(r234877)
@@ -143,9 +143,6 @@ typedef uint32_t ieee80211_hwmp_seq;
 #define	HWMP_SEQ_GT(a, b)	((int32_t)((a)-(b)) > 0)
 #define	HWMP_SEQ_GEQ(a, b)	((int32_t)((a)-(b)) >= 0)
 
-/* The longer one of the lifetime should be stored as new lifetime */
-#define MESH_ROUTE_LIFETIME_MAX(a, b)	(a > b ? a : b)
-
 /*
  * Private extension of ieee80211_mesh_route.
  */
@@ -938,7 +935,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 	/* Data creation and update of forwarding information
 	 * according to Table 11C-8 for originator mesh STA.
 	 */
-	if(HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
+	if (HWMP_SEQ_GT(preq->preq_origseq, hrorig->hr_seq) ||
 	    (HWMP_SEQ_EQ(preq->preq_origseq, hrorig->hr_seq) &&
 	    preq->preq_metric < rtorig->rt_metric)) {
 		hrorig->hr_seq = preq->preq_origseq;
@@ -946,8 +943,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 		rtorig->rt_metric = preq->preq_metric +
 			ms->ms_pmetric->mpm_metric(ni);
 		rtorig->rt_nhops  = preq->preq_hopcount + 1;
-		rtorig->rt_lifetime  = MESH_ROUTE_LIFETIME_MAX(
-		    preq->preq_lifetime, rtorig->rt_lifetime);
+		ieee80211_mesh_rt_update(rtorig, preq->preq_lifetime);
 		/* path to orig is valid now */
 		rtorig->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
 	}else if(hrtarg != NULL &&
@@ -1124,7 +1120,7 @@ hwmp_recv_preq(struct ieee80211vap *vap,
 				}
 			}
 			rt->rt_metric = preq->preq_metric;
-			rt->rt_lifetime = preq->preq_lifetime;
+			ieee80211_mesh_rt_update(rt, preq->preq_lifetime);
 			hrorig = IEEE80211_MESH_ROUTE_PRIV(rt,
 			    struct ieee80211_hwmp_route);
 			hrorig->hr_seq = preq->preq_origseq;
@@ -1221,7 +1217,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 			}
 			IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
 			rt->rt_nhops = prep->prep_hopcount;
-			rt->rt_lifetime = prep->prep_lifetime;
+			ieee80211_mesh_rt_update(rt, prep->prep_lifetime);
 			rt->rt_metric = prep->prep_metric;
 			rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
 			IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
@@ -1300,7 +1296,7 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 			    rt->rt_metric, prep->prep_metric);
 			IEEE80211_ADDR_COPY(rt->rt_nexthop, wh->i_addr2);
 			rt->rt_nhops = prep->prep_hopcount + 1;
-			rt->rt_lifetime = prep->prep_lifetime;
+			ieee80211_mesh_rt_update(rt, prep->prep_lifetime);
 			rt->rt_metric = metric;
 			rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
 		} else {
@@ -1594,8 +1590,9 @@ hwmp_discover(struct ieee80211vap *vap,
 			if (hr->hr_origseq == 0)
 				hr->hr_origseq = ++hs->hs_seq;
 			rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
-			rt->rt_lifetime =
-			    ticks_to_msecs(ieee80211_hwmp_pathtimeout);
+			/* XXX: special discovery timeout, larger lifetime? */
+			ieee80211_mesh_rt_update(rt,
+			    ticks_to_msecs(ieee80211_hwmp_pathtimeout));
 			/* XXX check preq retries */
 			sendpreq = 1;
 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP, dest,
@@ -1613,7 +1610,8 @@ hwmp_discover(struct ieee80211vap *vap,
 			preq.preq_id = ++hs->hs_preqid;
 			IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
 			preq.preq_origseq = hr->hr_origseq;
-			preq.preq_lifetime = rt->rt_lifetime;
+			preq.preq_lifetime =
+			    ticks_to_msecs(ieee80211_hwmp_pathtimeout);
 			preq.preq_metric = rt->rt_metric;
 			preq.preq_tcount = 1;
 			IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest);

Modified: head/sys/net80211/ieee80211_mesh.c
==============================================================================
--- head/sys/net80211/ieee80211_mesh.c	Tue May  1 15:42:41 2012	(r234876)
+++ head/sys/net80211/ieee80211_mesh.c	Tue May  1 15:47:30 2012	(r234877)
@@ -138,6 +138,10 @@ static const struct ieee80211_mesh_proto
 static struct ieee80211_mesh_proto_path		mesh_proto_paths[4];
 static struct ieee80211_mesh_proto_metric	mesh_proto_metrics[4];
 
+#define	RT_ENTRY_LOCK(rt)	mtx_lock(&(rt)->rt_lock)
+#define	RT_ENTRY_LOCK_ASSERT(rt) mtx_assert(&(rt)->rt_lock, MA_OWNED)
+#define	RT_ENTRY_UNLOCK(rt)	mtx_unlock(&(rt)->rt_lock)
+
 #define	MESH_RT_LOCK(ms)	mtx_lock(&(ms)->ms_rt_lock)
 #define	MESH_RT_LOCK_ASSERT(ms)	mtx_assert(&(ms)->ms_rt_lock, MA_OWNED)
 #define	MESH_RT_UNLOCK(ms)	mtx_unlock(&(ms)->ms_rt_lock)
@@ -146,6 +150,9 @@ MALLOC_DEFINE(M_80211_MESH_PREQ, "80211p
 MALLOC_DEFINE(M_80211_MESH_PREP, "80211prep", "802.11 MESH Path Reply frame");
 MALLOC_DEFINE(M_80211_MESH_PERR, "80211perr", "802.11 MESH Path Error frame");
 
+/* The longer one of the lifetime should be stored as new lifetime */
+#define MESH_ROUTE_LIFETIME_MAX(a, b)	(a > b ? a : b)
+
 MALLOC_DEFINE(M_80211_MESH_RT, "80211mesh", "802.11s routing table");
 
 /*
@@ -183,7 +190,8 @@ mesh_rt_add_locked(struct ieee80211_mesh
 	if (rt != NULL) {
 		IEEE80211_ADDR_COPY(rt->rt_dest, dest);
 		rt->rt_priv = (void *)ALIGN(&rt[1]);
-		rt->rt_crtime = ticks;
+		mtx_init(&rt->rt_lock, "MBSS_RT", "802.11s route entry", MTX_DEF);
+		rt->rt_updtime = ticks;	/* create time */
 		TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
 	}
 	return rt;
@@ -221,6 +229,41 @@ ieee80211_mesh_rt_add(struct ieee80211va
 }
 
 /*
+ * Update the route lifetime and returns the updated lifetime.
+ * If new_lifetime is zero and route is timedout it will be invalidated.
+ * new_lifetime is in msec
+ */
+int
+ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int new_lifetime)
+{
+	int timesince, now;
+	uint32_t lifetime = 0;
+
+	now = ticks;
+	RT_ENTRY_LOCK(rt);
+	timesince = ticks_to_msecs(now - rt->rt_updtime);
+	rt->rt_updtime = now;
+	if (timesince >= rt->rt_lifetime) {
+		if (new_lifetime != 0) {
+			rt->rt_lifetime = new_lifetime;
+		}
+		else {
+			rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
+			rt->rt_lifetime = 0;
+		}
+	} else {
+		/* update what is left of lifetime */
+		rt->rt_lifetime = rt->rt_lifetime - timesince;
+		rt->rt_lifetime  = MESH_ROUTE_LIFETIME_MAX(
+			new_lifetime, rt->rt_lifetime);
+	}
+	lifetime = rt->rt_lifetime;
+	RT_ENTRY_UNLOCK(rt);
+
+	return lifetime;
+}
+
+/*
  * Add a proxy route (as needed) for the specified destination.
  */
 void
@@ -271,6 +314,12 @@ static __inline void
 mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
 {
 	TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
+	/*
+	 * Grab the lock before destroying it, to be sure no one else
+	 * is holding the route.
+	 */
+	RT_ENTRY_LOCK(rt);
+	mtx_destroy(&rt->rt_lock);
 	free(rt, M_80211_MESH_RT);
 }
 
@@ -335,8 +384,13 @@ mesh_rt_flush_invalid(struct ieee80211va
 		return;
 	MESH_RT_LOCK(ms);
 	TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
+		ieee80211_mesh_rt_update(rt, 0);
+		/*
+		 * NB: we check for lifetime == 0 so that we give a chance
+		 * for route discovery to complete.
+		 */
 		if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0 &&
-		    ticks - rt->rt_crtime >= ms->ms_ppath->mpp_inact)
+		    rt->rt_lifetime == 0)
 			mesh_rt_del(ms, rt);
 	}
 	MESH_RT_UNLOCK(ms);
@@ -1338,6 +1392,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_frame *wh;
+	struct ieee80211_mesh_route *rt;
 	uint8_t *frm, *efrm;
 
 	wh = mtod(m0, struct ieee80211_frame *);
@@ -1430,20 +1485,40 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 		 * XXX backoff on repeated failure
 		 */
 		if (ni != vap->iv_bss &&
-		    (ms->ms_flags & IEEE80211_MESHFLAGS_AP) &&
-		    ni->ni_mlstate == IEEE80211_NODE_MESH_IDLE) {
-			uint16_t args[1];
-
-			ni->ni_mlpid = mesh_generateid(vap);
-			if (ni->ni_mlpid == 0)
-				return;
-			mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
-			args[0] = ni->ni_mlpid;
-			ieee80211_send_action(ni,
-			    IEEE80211_ACTION_CAT_SELF_PROT,
-			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
-			ni->ni_mlrcnt = 0;
-			mesh_peer_timeout_setup(ni);
+		    (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
+			switch (ni->ni_mlstate) {
+			case IEEE80211_NODE_MESH_IDLE:
+			{
+				uint16_t args[1];
+
+				ni->ni_mlpid = mesh_generateid(vap);
+				if (ni->ni_mlpid == 0)
+					return;
+				mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENSNT);
+				args[0] = ni->ni_mlpid;
+				ieee80211_send_action(ni,
+				IEEE80211_ACTION_CAT_SELF_PROT,
+				IEEE80211_ACTION_MESHPEERING_OPEN, args);
+				ni->ni_mlrcnt = 0;
+				mesh_peer_timeout_setup(ni);
+				break;
+			}
+			case IEEE80211_NODE_MESH_ESTABLISHED:
+			{
+				/*
+				 * Valid beacon from a peer mesh STA
+				 * bump TA lifetime
+				 */
+				rt = ieee80211_mesh_rt_find(vap, wh->i_addr2);
+				if(rt != NULL) {
+					ieee80211_mesh_rt_update(rt,
+					    ms->ms_ppath->mpp_inact);
+				}
+				break;
+			}
+			default:
+				break; /* ignore */
+			}
 		}
 		break;
 	}
@@ -2701,15 +2776,16 @@ mesh_ioctl_get80211(struct ieee80211vap 
 					break;
 				imr = (struct ieee80211req_mesh_route *)
 				    (p + off);
-				imr->imr_flags = rt->rt_flags;
 				IEEE80211_ADDR_COPY(imr->imr_dest,
 				    rt->rt_dest);
 				IEEE80211_ADDR_COPY(imr->imr_nexthop,
 				    rt->rt_nexthop);
 				imr->imr_metric = rt->rt_metric;
 				imr->imr_nhops = rt->rt_nhops;
-				imr->imr_lifetime = rt->rt_lifetime;
+				imr->imr_lifetime =
+				    ieee80211_mesh_rt_update(rt, 0);
 				imr->imr_lastmseq = rt->rt_lastmseq;
+				imr->imr_flags = rt->rt_flags; /* last */
 				off += sizeof(*imr);
 			}
 			MESH_RT_UNLOCK(ms);

Modified: head/sys/net80211/ieee80211_mesh.h
==============================================================================
--- head/sys/net80211/ieee80211_mesh.h	Tue May  1 15:42:41 2012	(r234876)
+++ head/sys/net80211/ieee80211_mesh.h	Tue May  1 15:47:30 2012	(r234877)
@@ -409,9 +409,19 @@ MALLOC_DECLARE(M_80211_MESH_PREP);
 MALLOC_DECLARE(M_80211_MESH_PERR);
 
 MALLOC_DECLARE(M_80211_MESH_RT);
+/*
+ * Basic forwarding information:
+ * o Destination MAC
+ * o Next-hop MAC
+ * o Precursor list (not implemented yet)
+ * o Path timeout
+ * The rest is part of the active Mesh path selection protocol.
+ * XXX: to be moved out later.
+ */
 struct ieee80211_mesh_route {
 	TAILQ_ENTRY(ieee80211_mesh_route)	rt_next;
-	int			rt_crtime;	/* creation time */
+	struct mtx		rt_lock;	/* fine grained route lock */
+	int			rt_updtime;	/* last update time */
 	uint8_t			rt_dest[IEEE80211_ADDR_LEN];
 	uint8_t			rt_nexthop[IEEE80211_ADDR_LEN];
 	uint32_t		rt_metric;	/* path metric */
@@ -419,7 +429,7 @@ struct ieee80211_mesh_route {
 	uint16_t		rt_flags;
 #define	IEEE80211_MESHRT_FLAGS_VALID	0x01	/* patch discovery complete */
 #define	IEEE80211_MESHRT_FLAGS_PROXY	0x02	/* proxy entry */
-	uint32_t		rt_lifetime;
+	uint32_t		rt_lifetime;	/* route timeout */
 	uint32_t		rt_lastmseq;	/* last seq# seen dest */
 	void			*rt_priv;	/* private data */
 };
@@ -508,6 +518,7 @@ void		ieee80211_mesh_rt_del(struct ieee8
 void		ieee80211_mesh_rt_flush(struct ieee80211vap *);
 void		ieee80211_mesh_rt_flush_peer(struct ieee80211vap *,
 		    const uint8_t [IEEE80211_ADDR_LEN]);
+int		ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int);
 void		ieee80211_mesh_proxy_check(struct ieee80211vap *,
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 


More information about the svn-src-all mailing list