Esempio n. 1
0
static void
hwmp_rootmode_cb(void *arg)
{
	struct ieee80211vap *vap = (struct ieee80211vap *)arg;
	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
	struct ieee80211_mesh_state *ms = vap->iv_mesh;
	struct ieee80211_meshpreq_ie preq;

	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
	    "%s", "send broadcast PREQ");

	preq.preq_flags = IEEE80211_MESHPREQ_FLAGS_AM;
	if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
		preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PR;
	if (hs->hs_rootmode == IEEE80211_HWMP_ROOTMODE_PROACTIVE)
		preq.preq_flags |= IEEE80211_MESHPREQ_FLAGS_PP;
	preq.preq_hopcount = 0;
	preq.preq_ttl = ms->ms_ttl;
	preq.preq_id = ++hs->hs_preqid;
	IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
	preq.preq_origseq = ++hs->hs_seq;
	preq.preq_lifetime = ticks_to_msecs(ieee80211_hwmp_roottimeout);
	preq.preq_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
	preq.preq_tcount = 1;
	IEEE80211_ADDR_COPY(PREQ_TADDR(0), broadcastaddr);
	PREQ_TFLAGS(0) = IEEE80211_MESHPREQ_TFLAGS_TO |
	    IEEE80211_MESHPREQ_TFLAGS_RF;
	PREQ_TSEQ(0) = 0;
	vap->iv_stats.is_hwmp_rootreqs++;
	hwmp_send_preq(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &preq);
	hwmp_rootmode_setup(vap);
}
Esempio n. 2
0
static struct ieee80211_node *
hwmp_discover(struct ieee80211vap *vap,
    const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m)
{
	struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
	struct ieee80211_mesh_state *ms = vap->iv_mesh;
	struct ieee80211_mesh_route *rt = NULL;
	struct ieee80211_hwmp_route *hr;
	struct ieee80211_meshpreq_ie preq;
	struct ieee80211_node *ni;
	int sendpreq = 0;
#ifdef IEEE80211_DEBUG
	char ethstr[ETHER_ADDRSTRLEN + 1];
#endif

	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS,
	    ("not a mesh vap, opmode %d", vap->iv_opmode));

	KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
	    ("%s: discovering self!", __func__));

	ni = NULL;
	if (!IEEE80211_IS_MULTICAST(dest)) {
		rt = ieee80211_mesh_rt_find(vap, dest);
		if (rt == NULL) {
			rt = ieee80211_mesh_rt_add(vap, dest);
			if (rt == NULL) {
				IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
				    ni, "unable to add discovery path to %s",
				    kether_ntoa(dest, ethstr));
				vap->iv_stats.is_mesh_rtaddfailed++;
				goto done;
			}
		}
		hr = IEEE80211_MESH_ROUTE_PRIV(rt,
		    struct ieee80211_hwmp_route);
		if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
			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 check preq retries */
			sendpreq = 1;
			if (m != NULL) {
				IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
				    dest, "%s",
				    "start path discovery (src <none>)");
			} else {
				IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_HWMP,
				    dest,
				    "start path discovery (src %s)",
				    kether_ntoa(
					    mtod(m, struct ether_header *)->ether_shost,
					    ethstr));
			}
			/*
			 * Try to discover the path for this node.
			 */
			preq.preq_flags = 0;
			preq.preq_hopcount = 0;
			preq.preq_ttl = ms->ms_ttl;
			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_metric = rt->rt_metric;
			preq.preq_tcount = 1;
			IEEE80211_ADDR_COPY(PREQ_TADDR(0), dest);
			PREQ_TFLAGS(0) = 0;
			if (ieee80211_hwmp_targetonly)
				PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_TO;
			if (ieee80211_hwmp_replyforward)
				PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_RF;
			PREQ_TFLAGS(0) |= IEEE80211_MESHPREQ_TFLAGS_USN;
			PREQ_TSEQ(0) = 0;
			/* XXX check return value */
			hwmp_send_preq(vap->iv_bss, vap->iv_myaddr,
			    broadcastaddr, &preq);
		}
		if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID)
			ni = ieee80211_find_txnode(vap, rt->rt_nexthop);
	} else {