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]);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to