Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25d49e4d authored by Thomas Pedersen's avatar Thomas Pedersen Committed by John W. Linville
Browse files

mac80211: update mesh path selection frame format



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: default avatarThomas Pedersen <thomas@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 36c704fd
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -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));

@@ -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,
};
+14 −6
Original line number Diff line number Diff line
@@ -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

@@ -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();
@@ -671,7 +678,8 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
			break;
		}
		break;
	case WLAN_CATEGORY_MESH_PATH_SEL:
	case WLAN_CATEGORY_MESH_ACTION:
		if (mesh_action_is_path_sel(mgmt))
			mesh_rx_path_sel_frame(sdata, mgmt, len);
		break;
	}
+4 −8
Original line number Diff line number Diff line
@@ -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 */

@@ -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,
@@ -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
+37 −24
Original line number Diff line number Diff line
@@ -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))
@@ -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:
@@ -163,6 +164,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
	*pos++ = flags;
	*pos++ = hop_count;
	*pos++ = ttl;
	if (action == MPATH_PREP) {
		memcpy(pos, target, ETH_ALEN);
		pos += ETH_ALEN;
		memcpy(pos, &target_sn, 4);
		pos += 4;
	} else {
		if (action == MPATH_PREQ) {
			memcpy(pos, &preq_id, 4);
			pos += 4;
@@ -171,21 +178,23 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
		pos += ETH_ALEN;
		memcpy(pos, &orig_sn, 4);
		pos += 4;
	if (action != MPATH_RANN) {
		memcpy(pos, &lifetime, 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);
@@ -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;
@@ -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) {
@@ -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;
@@ -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);
}
+4 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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);
	}
@@ -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;
@@ -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);
Loading