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

Commit 5ee68e5b authored by Javier Cardona's avatar Javier Cardona Committed by John W. Linville
Browse files

mac80211: mesh gate implementation



In this implementation, a mesh gate is a root node with a certain bit
set in its RANN flags. The mpath to this root node is marked as a path
to a gate, and added to our list of known gates for this if_mesh. Once a
path discovery process fails, we forward the unresolved frames to a
known gate. Thanks to Luis Rodriguez for refactoring and bug fix help.

Signed-off-by: default avatarJavier Cardona <javier@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 00e3f25c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -633,6 +633,10 @@ struct ieee80211_rann_ie {
	u32 rann_metric;
} __attribute__ ((packed));

enum ieee80211_rann_flags {
	RANN_FLAG_IS_GATE = 1 << 0,
};

#define WLAN_SA_QUERY_TR_ID_LEN 2

struct ieee80211_mgmt {
+1 −0
Original line number Diff line number Diff line
@@ -514,6 +514,7 @@ struct ieee80211_if_mesh {
	struct mesh_config mshcfg;
	u32 mesh_seqnum;
	bool accepting_plinks;
	int num_gates;
	const u8 *ie;
	u8 ie_len;
	enum {
+2 −1
Original line number Diff line number Diff line
@@ -545,7 +545,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

	/* use atomic bitops in case both timers fire at the same time */
	/* use atomic bitops in case all timers fire at the same time */

	if (del_timer_sync(&ifmsh->housekeeping_timer))
		set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
@@ -752,6 +752,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
	ifmsh->accepting_plinks = true;
	ifmsh->preq_id = 0;
	ifmsh->sn = 0;
	ifmsh->num_gates = 0;
	atomic_set(&ifmsh->mpaths, 0);
	mesh_rmc_init(sdata);
	ifmsh->last_preq = jiffies;
+11 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ enum mesh_deferred_task_flags {
 * @discovery_retries: number of discovery retries
 * @flags: mesh path flags, as specified on &enum mesh_path_flags
 * @state_lock: mesh path state lock
 * @is_gate: the destination station of this path is a mesh gate
 *
 *
 * The combination of dst and sdata is unique in the mesh path table. Since the
@@ -104,6 +105,7 @@ struct mesh_path {
	u8 discovery_retries;
	enum mesh_path_flags flags;
	spinlock_t state_lock;
	bool is_gate;
};

/**
@@ -120,6 +122,9 @@ struct mesh_path {
 *	buckets
 * @mean_chain_len: maximum average length for the hash buckets' list, if it is
 *	reached, the table will grow
 * @known_gates: list of known mesh gates and their mpaths by the station. The
 * gate's mpath may or may not be resolved and active.
 *
 * rcu_head: RCU head to free the table
 */
struct mesh_table {
@@ -133,6 +138,8 @@ struct mesh_table {
	int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
	int size_order;
	int mean_chain_len;
	struct hlist_head *known_gates;
	spinlock_t gates_lock;

	struct rcu_head rcu_head;
};
@@ -236,6 +243,10 @@ void mesh_path_flush(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
		struct ieee80211_mgmt *mgmt, size_t len);
int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata);

int mesh_path_add_gate(struct mesh_path *mpath);
int mesh_path_send_to_gates(struct mesh_path *mpath);
int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
/* Mesh plinks */
void mesh_neighbour_update(u8 *hw_addr, u32 rates,
		struct ieee80211_sub_if_data *sdata,
+33 −8
Original line number Diff line number Diff line
@@ -696,6 +696,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
	u8 *orig_addr;
	u32 orig_sn, metric;
	u32 interval = cpu_to_le32(IEEE80211_MESH_RANN_INTERVAL);
	bool root_is_gate;

	ttl = rann->rann_ttl;
	if (ttl <= 1) {
@@ -704,12 +705,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
	}
	ttl--;
	flags = rann->rann_flags;
	root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
	orig_addr = rann->rann_addr;
	orig_sn = rann->rann_seq;
	hopcount = rann->rann_hopcount;
	hopcount++;
	metric = rann->rann_metric;
	mhwmp_dbg("received RANN from %pM\n", orig_addr);

	/*  Ignore our own RANNs */
	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0)
		return;

	mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr,
			root_is_gate);

	rcu_read_lock();
	mpath = mesh_path_lookup(orig_addr, sdata);
@@ -721,9 +729,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
			sdata->u.mesh.mshstats.dropped_frames_no_route++;
			return;
		}
		mesh_queue_preq(mpath,
				PREQ_Q_F_START | PREQ_Q_F_REFRESH);
	}

	if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) ||
	     time_after(jiffies, mpath->exp_time - 1*HZ)) &&
	     !(mpath->flags & MESH_PATH_FIXED)) {
		mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name,
							       orig_addr);
		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
	}

	if (mpath->sn < orig_sn) {
		mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,
				       cpu_to_le32(orig_sn),
@@ -733,6 +748,9 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
				       0, sdata);
		mpath->sn = orig_sn;
	}
	if (root_is_gate)
		mesh_path_add_gate(mpath);

	rcu_read_unlock();
}

@@ -994,25 +1012,32 @@ void mesh_path_timer(unsigned long data)
{
	struct mesh_path *mpath = (void *) data;
	struct ieee80211_sub_if_data *sdata = mpath->sdata;
	int ret;

	if (sdata->local->quiescing)
		return;

	spin_lock_bh(&mpath->state_lock);
	if (mpath->flags & MESH_PATH_RESOLVED ||
			(!(mpath->flags & MESH_PATH_RESOLVING)))
			(!(mpath->flags & MESH_PATH_RESOLVING))) {
		mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
	else if (mpath->discovery_retries < max_preq_retries(sdata)) {
		spin_unlock_bh(&mpath->state_lock);
	} else if (mpath->discovery_retries < max_preq_retries(sdata)) {
		++mpath->discovery_retries;
		mpath->discovery_timeout *= 2;
		spin_unlock_bh(&mpath->state_lock);
		mesh_queue_preq(mpath, 0);
	} else {
		mpath->flags = 0;
		mpath->exp_time = jiffies;
		spin_unlock_bh(&mpath->state_lock);
		if (!mpath->is_gate && mesh_gate_num(sdata) > 0) {
			ret = mesh_path_send_to_gates(mpath);
			if (ret)
				mhwmp_dbg("no gate was reachable");
		} else
			mesh_path_flush_pending(mpath);
	}

	spin_unlock_bh(&mpath->state_lock);
}

void
Loading