Skip to content

Commit

Permalink
mac80211: update mesh path selection frame format
Browse files Browse the repository at this point in the history
Make mesh path selection frames Mesh Action category, remove outdated
Mesh Path Selection category and defines, use updated reason codes, add
mesh_action_is_path_sel for readability, and update/correct path
selection IEs.

Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Thomas Pedersen authored and John W. Linville committed Aug 22, 2011
1 parent 36c704f commit 25d49e4
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 48 deletions.
4 changes: 1 addition & 3 deletions include/linux/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ struct ieee80211_rann_ie {
u8 rann_ttl;
u8 rann_addr[6];
u32 rann_seq;
u32 rann_interval;
u32 rann_metric;
} __attribute__ ((packed));

Expand Down Expand Up @@ -1269,9 +1270,6 @@ enum ieee80211_category {
WLAN_CATEGORY_MULTIHOP_ACTION = 14,
WLAN_CATEGORY_SELF_PROTECTED = 15,
WLAN_CATEGORY_WMM = 17,
/* TODO: remove MESH_PATH_SEL after mesh is updated
* to current 802.11s draft */
WLAN_CATEGORY_MESH_PATH_SEL = 32,
WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
};
Expand Down
20 changes: 14 additions & 6 deletions net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
#include "ieee80211_i.h"
#include "mesh.h"

#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)

#define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01
#define MESHCONF_CAPAB_FORWARDING 0x08

Expand All @@ -27,6 +23,17 @@
int mesh_allocated;
static struct kmem_cache *rm_cache;

#ifdef CONFIG_MAC80211_MESH
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
{
return (mgmt->u.action.u.mesh_action.action_code ==
WLAN_MESH_ACTION_HWMP_PATH_SELECTION);
}
#else
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt)
{ return false; }
#endif

void ieee80211s_init(void)
{
mesh_pathtbl_init();
Expand Down Expand Up @@ -671,8 +678,9 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
break;
}
break;
case WLAN_CATEGORY_MESH_PATH_SEL:
mesh_rx_path_sel_frame(sdata, mgmt, len);
case WLAN_CATEGORY_MESH_ACTION:
if (mesh_action_is_path_sel(mgmt))
mesh_rx_path_sel_frame(sdata, mgmt, len);
break;
}
}
Expand Down
12 changes: 4 additions & 8 deletions net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ struct mesh_rmc {
u32 idx_mask;
};

#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
#define IEEE80211_MESH_RANN_INTERVAL (1 * HZ)

#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */

Expand All @@ -177,14 +180,6 @@ struct mesh_rmc {
/* Maximum number of paths per interface */
#define MESH_MAX_MPATHS 1024

/* Pending ANA approval */
#define MESH_PATH_SEL_ACTION 0

/* PERR reason codes */
#define PEER_RCODE_UNSPECIFIED 11
#define PERR_RCODE_NO_ROUTE 12
#define PERR_RCODE_DEST_UNREACH 13

/* Public interfaces */
/* Various */
int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
Expand Down Expand Up @@ -276,6 +271,7 @@ void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);

bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
extern int mesh_paths_generation;

#ifdef CONFIG_MAC80211_MESH
Expand Down
61 changes: 37 additions & 24 deletions net/mac80211/mesh_hwmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)
#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_SN(x) u32_field_get(x, 9, 0)
#define PREP_IE_ORIG_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
#define PREP_IE_ORIG_SN(x) u32_field_get(x, 27, AE_F_SET(x))
#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_TARGET_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
#define PREP_IE_TARGET_SN(x) u32_field_get(x, 27, AE_F_SET(x))
#define PREP_IE_TARGET_ADDR(x) (x + 3)
#define PREP_IE_TARGET_SN(x) u32_field_get(x, 9, 0)

#define PERR_IE_TTL(x) (*(x))
#define PERR_IE_TARGET_FLAGS(x) (*(x + 2))
Expand Down Expand Up @@ -132,8 +132,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
/* BSSID == SA */
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
mgmt->u.action.u.mesh_action.action_code =
WLAN_MESH_ACTION_HWMP_PATH_SELECTION;

switch (action) {
case MPATH_PREQ:
Expand Down Expand Up @@ -163,29 +164,37 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
*pos++ = flags;
*pos++ = hop_count;
*pos++ = ttl;
if (action == MPATH_PREQ) {
memcpy(pos, &preq_id, 4);
if (action == MPATH_PREP) {
memcpy(pos, target, ETH_ALEN);
pos += ETH_ALEN;
memcpy(pos, &target_sn, 4);
pos += 4;
}
memcpy(pos, orig_addr, ETH_ALEN);
pos += ETH_ALEN;
memcpy(pos, &orig_sn, 4);
pos += 4;
if (action != MPATH_RANN) {
memcpy(pos, &lifetime, 4);
} else {
if (action == MPATH_PREQ) {
memcpy(pos, &preq_id, 4);
pos += 4;
}
memcpy(pos, orig_addr, ETH_ALEN);
pos += ETH_ALEN;
memcpy(pos, &orig_sn, 4);
pos += 4;
}
memcpy(pos, &lifetime, 4); /* interval for RANN */
pos += 4;
memcpy(pos, &metric, 4);
pos += 4;
if (action == MPATH_PREQ) {
/* destination count */
*pos++ = 1;
*pos++ = 1; /* destination count */
*pos++ = target_flags;
}
if (action != MPATH_RANN) {
memcpy(pos, target, ETH_ALEN);
pos += ETH_ALEN;
memcpy(pos, &target_sn, 4);
pos += 4;
} else if (action == MPATH_PREP) {
memcpy(pos, orig_addr, ETH_ALEN);
pos += ETH_ALEN;
memcpy(pos, &orig_sn, 4);
pos += 4;
}

ieee80211_tx_skb(sdata, skb);
Expand Down Expand Up @@ -224,9 +233,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,

memcpy(mgmt->da, ra, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
/* BSSID is left zeroed, wildcard value */
mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL;
mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION;
/* BSSID == SA */
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
mgmt->u.action.u.mesh_action.action_code =
WLAN_MESH_ACTION_HWMP_PATH_SELECTION;
ie_len = 15;
pos = skb_put(skb, 2 + ie_len);
*pos++ = WLAN_EID_PERR;
Expand Down Expand Up @@ -683,6 +694,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
u8 ttl, flags, hopcount;
u8 *orig_addr;
u32 orig_sn, metric;
u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);

ttl = rann->rann_ttl;
if (ttl <= 1) {
Expand Down Expand Up @@ -715,7 +727,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
cpu_to_le32(orig_sn),
0, NULL, 0, broadcast_addr,
hopcount, ttl, 0,
hopcount, ttl, interval,
cpu_to_le32(metric + mpath->metric),
0, sdata);
mpath->sn = orig_sn;
Expand Down Expand Up @@ -1006,10 +1018,11 @@ void
mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);

mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr,
cpu_to_le32(++ifmsh->sn),
0, NULL, 0, broadcast_addr,
0, sdata->u.mesh.mshcfg.element_ttl,
0, 0, 0, sdata);
interval, 0, 0, sdata);
}
8 changes: 4 additions & 4 deletions net/mac80211/mesh_pathtbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ void mesh_plink_broken(struct sta_info *sta)
struct hlist_node *p;
struct ieee80211_sub_if_data *sdata = sta->sdata;
int i;
__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);

rcu_read_lock();
tbl = rcu_dereference(mesh_paths);
Expand All @@ -553,8 +554,7 @@ void mesh_plink_broken(struct sta_info *sta)
spin_unlock_bh(&mpath->state_lock);
mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,
mpath->dst, cpu_to_le32(mpath->sn),
cpu_to_le16(PERR_RCODE_DEST_UNREACH),
bcast, sdata);
reason, bcast, sdata);
} else
spin_unlock_bh(&mpath->state_lock);
}
Expand Down Expand Up @@ -699,6 +699,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
struct mesh_path *mpath;
u32 sn = 0;
__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);

if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {
u8 *ra, *da;
Expand All @@ -709,8 +710,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
if (mpath)
sn = ++mpath->sn;
mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data,
cpu_to_le32(sn),
cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata);
cpu_to_le32(sn), reason, ra, sdata);
}

kfree_skb(skb);
Expand Down
5 changes: 2 additions & 3 deletions net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2241,9 +2241,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
case WLAN_CATEGORY_MESH_ACTION:
if (!ieee80211_vif_is_mesh(&sdata->vif))
break;
goto queue;
case WLAN_CATEGORY_MESH_PATH_SEL:
if (!mesh_path_sel_is_hwmp(sdata))
if (mesh_action_is_path_sel(mgmt) &&
(!mesh_path_sel_is_hwmp(sdata)))
break;
goto queue;
}
Expand Down

0 comments on commit 25d49e4

Please sign in to comment.