X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fmac80211%2Fmesh_hwmp.c;h=71fe609612303a2d9d6fc11e263845df26438256;hb=d4e2675a61890a84849a24affedf80d5cae8b199;hp=c2f40ef418cfd42207df28805e9ea41d68080d07;hpb=dc0b0f7d1e34b797b98e4d16122b3ea6f775154c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index c2f40ef..71fe609 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -9,8 +9,6 @@ #include "mesh.h" -#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype) - #define TEST_FRAME_LEN 8192 #define MAX_METRIC 0xffffffff #define ARITH_SHIFT 8 @@ -24,40 +22,41 @@ /* Reply and forward */ #define MP_F_RF 0x2 +static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) +{ + if (ae) + offset += 6; + return get_unaligned_le32(preq_elem + offset); +} + /* HWMP IE processing macros */ -#define AE_F (1<<6) -#define AE_F_SET(x) (*x & AE_F) -#define PREQ_IE_FLAGS(x) (*(x)) -#define PREQ_IE_HOPCOUNT(x) (*(x + 1)) -#define PREQ_IE_TTL(x) (*(x + 2)) -#define PREQ_IE_PREQ_ID(x) le32_to_cpu(*((u32 *) (x + 3))) -#define PREQ_IE_ORIG_ADDR(x) (x + 7) -#define PREQ_IE_ORIG_DSN(x) le32_to_cpu(*((u32 *) (x + 13))) -#define PREQ_IE_LIFETIME(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 23 : x + 17))) -#define PREQ_IE_METRIC(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 27 : x + 21))) -#define PREQ_IE_DST_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26)) -#define PREQ_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27) -#define PREQ_IE_DST_DSN(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 39 : x + 33))) - - -#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) -#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) -#define PREP_IE_TTL(x) PREQ_IE_TTL(x) -#define PREP_IE_ORIG_ADDR(x) (x + 3) -#define PREP_IE_ORIG_DSN(x) le32_to_cpu(*((u32 *) (x + 9))) -#define PREP_IE_LIFETIME(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 19 : x + 13))) -#define PREP_IE_METRIC(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 23 : x + 17))) -#define PREP_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) -#define PREP_IE_DST_DSN(x) le32_to_cpu(*((u32 *) \ - (AE_F_SET(x) ? x + 33 : x + 27))) - -#define PERR_IE_DST_ADDR(x) (x + 2) -#define PERR_IE_DST_DSN(x) le32_to_cpu(*((u32 *) (x + 8))) +#define AE_F (1<<6) +#define AE_F_SET(x) (*x & AE_F) +#define PREQ_IE_FLAGS(x) (*(x)) +#define PREQ_IE_HOPCOUNT(x) (*(x + 1)) +#define PREQ_IE_TTL(x) (*(x + 2)) +#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0) +#define PREQ_IE_ORIG_ADDR(x) (x + 7) +#define PREQ_IE_ORIG_DSN(x) u32_field_get(x, 13, 0); +#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x)); +#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x)); +#define PREQ_IE_DST_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26)) +#define PREQ_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27) +#define PREQ_IE_DST_DSN(x) u32_field_get(x, 33, AE_F_SET(x)); + + +#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x) +#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x) +#define PREP_IE_TTL(x) PREQ_IE_TTL(x) +#define PREP_IE_ORIG_ADDR(x) (x + 3) +#define PREP_IE_ORIG_DSN(x) u32_field_get(x, 9, 0); +#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x)); +#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x)); +#define PREP_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21) +#define PREP_IE_DST_DSN(x) u32_field_get(x, 27, AE_F_SET(x)); + +#define PERR_IE_DST_ADDR(x) (x + 2) +#define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0); #define TU_TO_EXP_TIME(x) (jiffies + msecs_to_jiffies(x * 1024 / 1000)) #define MSEC_TO_TU(x) (x*1000/1024) @@ -65,14 +64,14 @@ #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) #define net_traversal_jiffies(s) \ - msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) + msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) #define default_lifetime(s) \ - MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) + MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout) #define min_preq_int_jiff(s) \ - (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) -#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) + (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval)) +#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) #define disc_timeout_jiff(s) \ - msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) + msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) enum mpath_frame_type { MPATH_PREQ = 0, @@ -83,9 +82,9 @@ enum mpath_frame_type { static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, - __le32 metric, __le32 preq_id, struct net_device *dev) + __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -100,11 +99,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = action; @@ -121,7 +120,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, *pos++ = WLAN_EID_PREP; break; default: - kfree(skb); + kfree_skb(skb); return -ENOTSUPP; break; } @@ -150,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); return 0; } @@ -162,9 +161,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, * @ra: node this frame is addressed to */ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, - struct net_device *dev) + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); struct ieee80211_mgmt *mgmt; u8 *pos; @@ -179,11 +178,11 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); memcpy(mgmt->da, ra, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; @@ -199,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, pos += ETH_ALEN; memcpy(pos, &dst_dsn, 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_tx_skb(sdata, skb, 0); return 0; } @@ -219,12 +218,16 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, if (sta->fail_avg >= 100) return MAX_METRIC; + + if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) + return MAX_METRIC; + err = (sta->fail_avg << ARITH_SHIFT) / 100; /* bitrate is in units of 100 Kbps, while we need rate in units of * 1Mbps. This will be corrected on tx_time computation. */ - rate = sband->bitrates[sta->txrate_idx].bitrate; + rate = sband->bitrates[sta->last_tx_rate.idx].bitrate; tx_time = (device_constant + 10 * test_frame_len / rate); estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; @@ -234,7 +237,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, /** * hwmp_route_info_get - Update routing info to originator and transmitter * - * @dev: local mesh interface + * @sdata: local mesh subif * @mgmt: mesh management frame * @hwmp_ie: hwmp information element (PREP or PREQ) * @@ -247,11 +250,11 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, * Notes: this function is the only place (besides user-provided info) where * path routing information is updated. */ -static u32 hwmp_route_info_get(struct net_device *dev, +static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *hwmp_ie) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct mesh_path *mpath; struct sta_info *sta; bool fresh_info; @@ -294,7 +297,6 @@ static u32 hwmp_route_info_get(struct net_device *dev, orig_metric = PREP_IE_METRIC(hwmp_ie); break; default: - sta_info_put(sta); rcu_read_unlock(); return 0; } @@ -303,14 +305,14 @@ static u32 hwmp_route_info_get(struct net_device *dev, new_metric = MAX_METRIC; exp_time = TU_TO_EXP_TIME(orig_lifetime); - if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { /* This MP is the originator, we are not interested in this * frame, except for updating transmitter's path info. */ process = false; fresh_info = false; } else { - mpath = mesh_path_lookup(orig_addr, dev); + mpath = mesh_path_lookup(orig_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_FIXED) @@ -326,11 +328,10 @@ static u32 hwmp_route_info_get(struct net_device *dev, } } } else { - mesh_path_add(orig_addr, dev); - mpath = mesh_path_lookup(orig_addr, dev); + mesh_path_add(orig_addr, sdata); + mpath = mesh_path_lookup(orig_addr, sdata); if (!mpath) { rcu_read_unlock(); - sta_info_put(sta); return 0; } spin_lock_bh(&mpath->state_lock); @@ -360,7 +361,7 @@ static u32 hwmp_route_info_get(struct net_device *dev, else { fresh_info = true; - mpath = mesh_path_lookup(ta, dev); + mpath = mesh_path_lookup(ta, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if ((mpath->flags & MESH_PATH_FIXED) || @@ -368,11 +369,10 @@ static u32 hwmp_route_info_get(struct net_device *dev, (last_hop_metric > mpath->metric))) fresh_info = false; } else { - mesh_path_add(ta, dev); - mpath = mesh_path_lookup(ta, dev); + mesh_path_add(ta, sdata); + mpath = mesh_path_lookup(ta, sdata); if (!mpath) { rcu_read_unlock(); - sta_info_put(sta); return 0; } spin_lock_bh(&mpath->state_lock); @@ -391,17 +391,15 @@ static u32 hwmp_route_info_get(struct net_device *dev, spin_unlock_bh(&mpath->state_lock); } - sta_info_put(sta); rcu_read_unlock(); return process ? new_metric : 0; } -static void hwmp_preq_frame_process(struct net_device *dev, +static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *preq_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 dst_flags, ttl; @@ -416,19 +414,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); dst_flags = PREQ_IE_DST_F(preq_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { forward = false; reply = true; metric = 0; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - dst_dsn = ++ifsta->dsn; - ifsta->last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + dst_dsn = ++ifmsh->dsn; + ifmsh->last_dsn_update = jiffies; } } else { rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || DSN_LT(mpath->dsn, dst_dsn)) { @@ -450,15 +448,15 @@ static void hwmp_preq_frame_process(struct net_device *dev, if (reply) { lifetime = PREQ_IE_LIFETIME(preq_elem); - ttl = ifsta->mshcfg.dot11MeshTTL; + ttl = ifmsh->mshcfg.dot11MeshTTL; if (ttl != 0) mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, - __cpu_to_le32(dst_dsn), 0, orig_addr, - __cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, - __cpu_to_le32(lifetime), __cpu_to_le32(metric), - 0, dev); + cpu_to_le32(dst_dsn), 0, orig_addr, + cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, + cpu_to_le32(lifetime), cpu_to_le32(metric), + 0, sdata); else - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; } if (forward) { @@ -468,7 +466,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, ttl = PREQ_IE_TTL(preq_elem); lifetime = PREQ_IE_LIFETIME(preq_elem); if (ttl <= 1) { - ifsta->mshstats.dropped_frames_ttl++; + ifmsh->mshstats.dropped_frames_ttl++; return; } --ttl; @@ -476,21 +474,20 @@ static void hwmp_preq_frame_process(struct net_device *dev, preq_id = PREQ_IE_PREQ_ID(preq_elem); hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, - __cpu_to_le32(orig_dsn), dst_flags, dst_addr, - __cpu_to_le32(dst_dsn), dev->broadcast, - hopcount, ttl, __cpu_to_le32(lifetime), - __cpu_to_le32(metric), __cpu_to_le32(preq_id), - dev); - ifsta->mshstats.fwded_frames++; + cpu_to_le32(orig_dsn), dst_flags, dst_addr, + cpu_to_le32(dst_dsn), sdata->dev->broadcast, + hopcount, ttl, cpu_to_le32(lifetime), + cpu_to_le32(metric), cpu_to_le32(preq_id), + sdata); + ifmsh->mshstats.fwded_frames++; } } -static void hwmp_prep_frame_process(struct net_device *dev, +static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *prep_elem, u32 metric) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct mesh_path *mpath; u8 *dst_addr, *orig_addr; u8 ttl, hopcount, flags; @@ -504,18 +501,18 @@ static void hwmp_prep_frame_process(struct net_device *dev, * replies */ dst_addr = PREP_IE_DST_ADDR(prep_elem); - if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) /* destination, no forwarding required */ return; ttl = PREP_IE_TTL(prep_elem); if (ttl <= 1) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; return; } rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) spin_lock_bh(&mpath->state_lock); else @@ -524,7 +521,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, spin_unlock_bh(&mpath->state_lock); goto fail; } - memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); + memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); spin_unlock_bh(&mpath->state_lock); --ttl; flags = PREP_IE_FLAGS(prep_elem); @@ -535,21 +532,21 @@ static void hwmp_prep_frame_process(struct net_device *dev, orig_dsn = PREP_IE_ORIG_DSN(prep_elem); mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, - __cpu_to_le32(orig_dsn), 0, dst_addr, - __cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, - __cpu_to_le32(lifetime), __cpu_to_le32(metric), - 0, dev); + cpu_to_le32(orig_dsn), 0, dst_addr, + cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl, + cpu_to_le32(lifetime), cpu_to_le32(metric), + 0, sdata); rcu_read_unlock(); - sdata->u.sta.mshstats.fwded_frames++; + sdata->u.mesh.mshstats.fwded_frames++; return; fail: rcu_read_unlock(); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; return; } -static void hwmp_perr_frame_process(struct net_device *dev, +static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, u8 *perr_elem) { struct mesh_path *mpath; @@ -560,18 +557,18 @@ static void hwmp_perr_frame_process(struct net_device *dev, dst_addr = PERR_IE_DST_ADDR(perr_elem); dst_dsn = PERR_IE_DST_DSN(perr_elem); rcu_read_lock(); - mpath = mesh_path_lookup(dst_addr, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (mpath) { spin_lock_bh(&mpath->state_lock); if (mpath->flags & MESH_PATH_ACTIVE && - memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 && + memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && (!(mpath->flags & MESH_PATH_DSN_VALID) || DSN_GT(dst_dsn, mpath->dsn))) { mpath->flags &= ~MESH_PATH_ACTIVE; mpath->dsn = dst_dsn; spin_unlock_bh(&mpath->state_lock); - mesh_path_error_tx(dst_addr, dst_dsn, dev->broadcast, - dev); + mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), + sdata->dev->broadcast, sdata); } else spin_unlock_bh(&mpath->state_lock); } @@ -580,7 +577,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, -void mesh_rx_path_sel_frame(struct net_device *dev, +void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -588,6 +585,10 @@ void mesh_rx_path_sel_frame(struct net_device *dev, size_t baselen; u32 last_hop_metric; + /* need action_code */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) + return; + baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, len - baselen, &elems); @@ -597,25 +598,25 @@ void mesh_rx_path_sel_frame(struct net_device *dev, if (!elems.preq || elems.preq_len != 37) /* Right now we support just 1 destination and no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); if (!last_hop_metric) return; - hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric); + hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); break; case MPATH_PREP: if (!elems.prep || elems.prep_len != 31) /* Right now we support no AE */ return; - last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep); + last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); if (!last_hop_metric) return; - hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric); + hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); break; case MPATH_PERR: if (!elems.perr || elems.perr_len != 12) /* Right now we support only one destination per PERR */ return; - hwmp_perr_frame_process(dev, mgmt, elems.perr); + hwmp_perr_frame_process(sdata, mgmt, elems.perr); default: return; } @@ -633,9 +634,8 @@ void mesh_rx_path_sel_frame(struct net_device *dev, */ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(mpath->dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_sub_if_data *sdata = mpath->sdata; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); @@ -644,9 +644,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) return; } - spin_lock(&ifsta->mesh_preq_queue_lock); - if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { + spin_unlock(&ifmsh->mesh_preq_queue_lock); kfree(preq_node); if (printk_ratelimit()) printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); @@ -656,55 +656,53 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) memcpy(preq_node->dst, mpath->dst, ETH_ALEN); preq_node->flags = flags; - list_add_tail(&preq_node->list, &ifsta->preq_queue.list); - ++ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); + ++ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); - if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) - queue_work(sdata->local->hw.workqueue, &ifsta->work); + if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) + queue_work(sdata->local->hw.workqueue, &ifmsh->work); - else if (time_before(jiffies, ifsta->last_preq)) { + else if (time_before(jiffies, ifmsh->last_preq)) { /* avoid long wait if did not send preqs for a long time * and jiffies wrapped around */ - ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; - queue_work(sdata->local->hw.workqueue, &ifsta->work); + ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; + queue_work(sdata->local->hw.workqueue, &ifmsh->work); } else - mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + + mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + min_preq_int_jiff(sdata)); } /** * mesh_path_start_discovery - launch a path discovery from the PREQ queue * - * @dev: local mesh interface + * @sdata: local mesh subif */ -void mesh_path_start_discovery(struct net_device *dev) +void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = - IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_if_sta *ifsta = &sdata->u.sta; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct mesh_preq_queue *preq_node; struct mesh_path *mpath; u8 ttl, dst_flags; u32 lifetime; - spin_lock(&ifsta->mesh_preq_queue_lock); - if (!ifsta->preq_queue_len || - time_before(jiffies, ifsta->last_preq + + spin_lock(&ifmsh->mesh_preq_queue_lock); + if (!ifmsh->preq_queue_len || + time_before(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) { - spin_unlock(&ifsta->mesh_preq_queue_lock); + spin_unlock(&ifmsh->mesh_preq_queue_lock); return; } - preq_node = list_first_entry(&ifsta->preq_queue.list, + preq_node = list_first_entry(&ifmsh->preq_queue.list, struct mesh_preq_queue, list); list_del(&preq_node->list); - --ifsta->preq_queue_len; - spin_unlock(&ifsta->mesh_preq_queue_lock); + --ifmsh->preq_queue_len; + spin_unlock(&ifmsh->mesh_preq_queue_lock); rcu_read_lock(); - mpath = mesh_path_lookup(preq_node->dst, dev); + mpath = mesh_path_lookup(preq_node->dst, sdata); if (!mpath) goto enddiscovery; @@ -726,18 +724,18 @@ void mesh_path_start_discovery(struct net_device *dev) goto enddiscovery; } - ifsta->last_preq = jiffies; + ifmsh->last_preq = jiffies; - if (time_after(jiffies, ifsta->last_dsn_update + + if (time_after(jiffies, ifmsh->last_dsn_update + net_traversal_jiffies(sdata)) || - time_before(jiffies, ifsta->last_dsn_update)) { - ++ifsta->dsn; - sdata->u.sta.last_dsn_update = jiffies; + time_before(jiffies, ifmsh->last_dsn_update)) { + ++ifmsh->dsn; + sdata->u.mesh.last_dsn_update = jiffies; } lifetime = default_lifetime(sdata); - ttl = sdata->u.sta.mshcfg.dot11MeshTTL; + ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; if (ttl == 0) { - sdata->u.sta.mshstats.dropped_frames_ttl++; + sdata->u.mesh.mshstats.dropped_frames_ttl++; spin_unlock_bh(&mpath->state_lock); goto enddiscovery; } @@ -748,11 +746,11 @@ void mesh_path_start_discovery(struct net_device *dev) dst_flags = MP_F_RF; spin_unlock_bh(&mpath->state_lock); - mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr, - __cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, - __cpu_to_le32(mpath->dsn), dev->broadcast, 0, - ttl, __cpu_to_le32(lifetime), 0, - __cpu_to_le32(ifsta->preq_id++), dev); + mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, + cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, + cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, + ttl, cpu_to_le32(lifetime), 0, + cpu_to_le32(ifmsh->preq_id++), sdata); mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); enddiscovery: @@ -763,32 +761,32 @@ enddiscovery: /** * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame * - * @next_hop: output argument for next hop address - * @skb: frame to be sent - * @dev: network device the frame will be sent through + * @skb: 802.11 frame to be sent + * @sdata: network subif the frame will be sent through * * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is * found, the function will start a path discovery and queue the frame so it is * sent when the path is resolved. This means the caller must not free the skb * in this case. */ -int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, - struct net_device *dev) +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sk_buff *skb_to_free = NULL; struct mesh_path *mpath; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u8 *dst_addr = hdr->addr3; int err = 0; rcu_read_lock(); - mpath = mesh_path_lookup(skb->data, dev); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { - mesh_path_add(skb->data, dev); - mpath = mesh_path_lookup(skb->data, dev); + mesh_path_add(dst_addr, sdata); + mpath = mesh_path_lookup(dst_addr, sdata); if (!mpath) { dev_kfree_skb(skb); - sdata->u.sta.mshstats.dropped_frames_no_route++; + sdata->u.mesh.mshstats.dropped_frames_no_route++; err = -ENOSPC; goto endlookup; } @@ -796,14 +794,15 @@ int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, if (mpath->flags & MESH_PATH_ACTIVE) { if (time_after(jiffies, mpath->exp_time - - msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) - && skb->pkt_type != PACKET_OTHERHOST + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) + && !memcmp(sdata->dev->dev_addr, hdr->addr4, + ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) && !(mpath->flags & MESH_PATH_FIXED)) { mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); } - memcpy(next_hop, mpath->next_hop->addr, + memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); } else { if (!(mpath->flags & MESH_PATH_RESOLVING)) { @@ -819,7 +818,7 @@ int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb, skb_queue_tail(&mpath->frame_queue, skb); if (skb_to_free) - mesh_path_discard_frame(skb_to_free, dev); + mesh_path_discard_frame(skb_to_free, sdata); err = -ENOENT; } @@ -832,7 +831,6 @@ void mesh_path_timer(unsigned long data) { struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; - bool delete = false; rcu_read_lock(); mpath = (struct mesh_path *) data; @@ -840,11 +838,8 @@ void mesh_path_timer(unsigned long data) if (!mpath) goto endmpathtimer; spin_lock_bh(&mpath->state_lock); - sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); - if (mpath->flags & MESH_PATH_DELETE) { - mpath->flags = 0; - delete = true; - } else if (mpath->flags & MESH_PATH_RESOLVED || + sdata = mpath->sdata; + if (mpath->flags & MESH_PATH_RESOLVED || (!(mpath->flags & MESH_PATH_RESOLVING))) mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); else if (mpath->discovery_retries < max_preq_retries(sdata)) { @@ -860,6 +855,4 @@ void mesh_path_timer(unsigned long data) spin_unlock_bh(&mpath->state_lock); endmpathtimer: rcu_read_unlock(); - if (delete) - mesh_path_del(mpath->dst, mpath->dev); }