MFC r198230, r198242, r198260, r198346, r198369, r198384:
More mesh fixes to comply with latest draft.
This commit is contained in:
parent
4ee07662b1
commit
e22a16d5d3
@ -148,7 +148,7 @@ typedef uint32_t ieee80211_hwmp_seq;
|
||||
struct ieee80211_hwmp_route {
|
||||
ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/
|
||||
ieee80211_hwmp_seq hr_preqid; /* last PREQ ID seen from dst */
|
||||
ieee80211_hwmp_seq hr_targetseq; /* seq. no. on our latest PREQ*/
|
||||
ieee80211_hwmp_seq hr_origseq; /* seq. no. on our latest PREQ*/
|
||||
int hr_preqretries;
|
||||
};
|
||||
struct ieee80211_hwmp_state {
|
||||
@ -548,7 +548,7 @@ hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr)
|
||||
*frm++ = perr->perr_ttl;
|
||||
*frm++ = perr->perr_ndests;
|
||||
for (i = 0; i < perr->perr_ndests; i++) {
|
||||
*frm += perr->perr_dests[i].dest_flags;
|
||||
*frm++ = perr->perr_dests[i].dest_flags;
|
||||
IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr);
|
||||
frm += 6;
|
||||
ADDWORD(frm, perr->perr_dests[i].dest_seq);
|
||||
@ -653,6 +653,7 @@ hwmp_rootmode_rann_cb(void *arg)
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
|
||||
"%s", "send broadcast RANN");
|
||||
|
||||
rann.rann_flags = 0;
|
||||
if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
|
||||
rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR;
|
||||
rann.rann_hopcount = 0;
|
||||
@ -733,12 +734,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
prep.prep_flags = 0;
|
||||
prep.prep_hopcount = 0;
|
||||
prep.prep_ttl = ms->ms_ttl;
|
||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr, preq->preq_origaddr);
|
||||
prep.prep_targetseq = preq->preq_origseq;
|
||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
|
||||
prep.prep_targetseq = ++hs->hs_seq;
|
||||
prep.prep_lifetime = preq->preq_lifetime;
|
||||
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
||||
IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr);
|
||||
prep.prep_origseq = ++hs->hs_seq;
|
||||
IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr);
|
||||
prep.prep_origseq = preq->preq_origseq;
|
||||
hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
|
||||
/*
|
||||
* Build the reverse path, if we don't have it already.
|
||||
@ -784,13 +785,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
prep.prep_flags = 0;
|
||||
prep.prep_hopcount = 0;
|
||||
prep.prep_ttl = ms->ms_ttl;
|
||||
IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr);
|
||||
IEEE80211_ADDR_COPY(prep.prep_origaddr, rootmac);
|
||||
prep.prep_origseq = preq->preq_origseq;
|
||||
prep.prep_targetseq = ++hs->hs_seq;
|
||||
prep.prep_lifetime = preq->preq_lifetime;
|
||||
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr, rootmac);
|
||||
prep.prep_targetseq = PREQ_TSEQ(0);
|
||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr,
|
||||
vap->iv_myaddr);
|
||||
prep.prep_targetseq = ++hs->hs_seq;
|
||||
hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
|
||||
broadcastaddr, &prep);
|
||||
}
|
||||
@ -848,13 +849,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
prep.prep_hopcount = rt->rt_nhops + 1;
|
||||
prep.prep_ttl = ms->ms_ttl;
|
||||
IEEE80211_ADDR_COPY(&prep.prep_targetaddr,
|
||||
preq->preq_origaddr);
|
||||
PREQ_TADDR(0));
|
||||
prep.prep_targetseq = hrorig->hr_seq;
|
||||
prep.prep_lifetime = preq->preq_lifetime;
|
||||
prep.prep_metric = rt->rt_metric +
|
||||
ms->ms_pmetric->mpm_metric(ni);
|
||||
IEEE80211_ADDR_COPY(&prep.prep_origaddr,
|
||||
PREQ_TADDR(0));
|
||||
preq->preq_origaddr);
|
||||
prep.prep_origseq = hrorig->hr_seq;
|
||||
hwmp_send_prep(ni, vap->iv_myaddr,
|
||||
broadcastaddr, &prep);
|
||||
@ -951,19 +952,19 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
return;
|
||||
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"received PREP from %s", ether_sprintf(prep->prep_origaddr));
|
||||
"received PREP from %s", ether_sprintf(prep->prep_targetaddr));
|
||||
|
||||
rt = ieee80211_mesh_rt_find(vap, prep->prep_origaddr);
|
||||
rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr);
|
||||
if (rt == NULL) {
|
||||
/*
|
||||
* If we have no entry this could be a reply to a root PREQ.
|
||||
*/
|
||||
if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
|
||||
rt = ieee80211_mesh_rt_add(vap, prep->prep_origaddr);
|
||||
rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr);
|
||||
if (rt == NULL) {
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
|
||||
ni, "unable to add PREP path to %s",
|
||||
ether_sprintf(prep->prep_origaddr));
|
||||
ether_sprintf(prep->prep_targetaddr));
|
||||
vap->iv_stats.is_mesh_rtaddfailed++;
|
||||
return;
|
||||
}
|
||||
@ -974,7 +975,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"add root path to %s nhops %d metric %d (PREP)",
|
||||
ether_sprintf(prep->prep_origaddr),
|
||||
ether_sprintf(prep->prep_targetaddr),
|
||||
rt->rt_nhops, rt->rt_metric);
|
||||
return;
|
||||
}
|
||||
@ -984,30 +985,30 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
* Sequence number validation.
|
||||
*/
|
||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
||||
if (HWMP_SEQ_LEQ(prep->prep_origseq, hr->hr_seq)) {
|
||||
if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq)) {
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"discard PREP from %s, old seq no %u <= %u",
|
||||
ether_sprintf(prep->prep_origaddr),
|
||||
prep->prep_origseq, hr->hr_seq);
|
||||
ether_sprintf(prep->prep_targetaddr),
|
||||
prep->prep_targetseq, hr->hr_seq);
|
||||
return;
|
||||
}
|
||||
hr->hr_seq = prep->prep_origseq;
|
||||
hr->hr_seq = prep->prep_targetseq;
|
||||
/*
|
||||
* If it's NOT for us, propagate the PREP.
|
||||
*/
|
||||
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_targetaddr) &&
|
||||
if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) &&
|
||||
prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) {
|
||||
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
|
||||
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"propagate PREP from %s",
|
||||
ether_sprintf(prep->prep_origaddr));
|
||||
ether_sprintf(prep->prep_targetaddr));
|
||||
|
||||
memcpy(&pprep, prep, sizeof(pprep));
|
||||
pprep.prep_hopcount += 1;
|
||||
pprep.prep_ttl -= 1;
|
||||
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
|
||||
IEEE80211_ADDR_COPY(pprep.prep_origaddr, vap->iv_myaddr);
|
||||
IEEE80211_ADDR_COPY(pprep.prep_targetaddr, vap->iv_myaddr);
|
||||
hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
|
||||
}
|
||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
||||
@ -1015,9 +1016,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
/* NB: never clobber a proxy entry */;
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"discard PREP for %s, route is marked PROXY",
|
||||
ether_sprintf(prep->prep_origaddr));
|
||||
ether_sprintf(prep->prep_targetaddr));
|
||||
vap->iv_stats.is_hwmp_proxy++;
|
||||
} else if (prep->prep_targetseq == hr->hr_targetseq) {
|
||||
} else if (prep->prep_origseq == hr->hr_origseq) {
|
||||
/*
|
||||
* Check if we already have a path to this node.
|
||||
* If we do, check if this path reply contains a
|
||||
@ -1041,14 +1042,14 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
} else {
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"ignore PREP for %s, hopcount %d:%d metric %d:%d",
|
||||
ether_sprintf(prep->prep_origaddr),
|
||||
ether_sprintf(prep->prep_targetaddr),
|
||||
rt->rt_nhops, prep->prep_hopcount,
|
||||
rt->rt_metric, prep->prep_metric);
|
||||
}
|
||||
} else {
|
||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||
"discard PREP for %s, wrong seqno %u != %u",
|
||||
ether_sprintf(prep->prep_origaddr), prep->prep_targetseq,
|
||||
ether_sprintf(prep->prep_targetaddr), prep->prep_origseq,
|
||||
hr->hr_seq);
|
||||
vap->iv_stats.is_hwmp_wrongseq++;
|
||||
}
|
||||
@ -1114,6 +1115,7 @@ hwmp_peerdown(struct ieee80211_node *ni)
|
||||
"%s", "delete route entry");
|
||||
perr.perr_ttl = ms->ms_ttl;
|
||||
perr.perr_ndests = 1;
|
||||
PERR_DFLAGS(0) = 0;
|
||||
if (hr->hr_seq == 0)
|
||||
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
|
||||
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC;
|
||||
@ -1223,7 +1225,8 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
struct ieee80211_meshrann_ie prann;
|
||||
|
||||
if (ni == vap->iv_bss ||
|
||||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
|
||||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED ||
|
||||
IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr))
|
||||
return;
|
||||
|
||||
rt = ieee80211_mesh_rt_find(vap, rann->rann_addr);
|
||||
@ -1305,8 +1308,8 @@ hwmp_discover(struct ieee80211vap *vap,
|
||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt,
|
||||
struct ieee80211_hwmp_route);
|
||||
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
|
||||
if (hr->hr_targetseq == 0)
|
||||
hr->hr_targetseq = ++hs->hs_seq;
|
||||
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);
|
||||
@ -1324,7 +1327,7 @@ hwmp_discover(struct ieee80211vap *vap,
|
||||
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_targetseq;
|
||||
preq.preq_origseq = hr->hr_origseq;
|
||||
preq.preq_lifetime = rt->rt_lifetime;
|
||||
preq.preq_metric = rt->rt_metric;
|
||||
preq.preq_tcount = 1;
|
||||
|
@ -388,8 +388,6 @@ mesh_select_proto_path(struct ieee80211vap *vap, const char *name)
|
||||
for (i = 0; i < N(mesh_proto_paths); i++) {
|
||||
if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
|
||||
ms->ms_ppath = &mesh_proto_paths[i];
|
||||
if (vap->iv_state == IEEE80211_S_RUN)
|
||||
vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -405,8 +403,6 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name)
|
||||
for (i = 0; i < N(mesh_proto_metrics); i++) {
|
||||
if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
|
||||
ms->ms_pmetric = &mesh_proto_metrics[i];
|
||||
if (vap->iv_state == IEEE80211_S_RUN)
|
||||
vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -739,10 +735,12 @@ mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state)
|
||||
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
|
||||
KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
|
||||
ms->ms_neighbors++;
|
||||
ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
|
||||
} else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
|
||||
state != IEEE80211_NODE_MESH_ESTABLISHED) {
|
||||
KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
|
||||
ms->ms_neighbors--;
|
||||
ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
|
||||
}
|
||||
ni->ni_mlstate = state;
|
||||
switch (state) {
|
||||
@ -2552,6 +2550,18 @@ ieee80211_mesh_init_neighbor(struct ieee80211_node *ni,
|
||||
ieee80211_parse_meshid(ni, sp->meshid);
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_mesh_update_beacon(struct ieee80211vap *vap,
|
||||
struct ieee80211_beacon_offsets *bo)
|
||||
{
|
||||
KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
|
||||
|
||||
if (isset(bo->bo_flags, IEEE80211_BEACON_MESHCONF)) {
|
||||
(void)ieee80211_add_meshconf(bo->bo_meshconf, vap);
|
||||
clrbit(bo->bo_flags, IEEE80211_BEACON_MESHCONF);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
||||
{
|
||||
|
@ -470,6 +470,8 @@ struct ieee80211_scanparams;
|
||||
void ieee80211_mesh_init_neighbor(struct ieee80211_node *,
|
||||
const struct ieee80211_frame *,
|
||||
const struct ieee80211_scanparams *);
|
||||
void ieee80211_mesh_update_beacon(struct ieee80211vap *,
|
||||
struct ieee80211_beacon_offsets *);
|
||||
|
||||
/*
|
||||
* Return non-zero if proxy operation is enabled.
|
||||
|
@ -2658,6 +2658,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
|
||||
#ifdef IEEE80211_SUPPORT_MESH
|
||||
if (vap->iv_opmode == IEEE80211_M_MBSS) {
|
||||
frm = ieee80211_add_meshid(frm, vap);
|
||||
bo->bo_meshconf = frm;
|
||||
frm = ieee80211_add_meshconf(frm, vap);
|
||||
}
|
||||
#endif
|
||||
@ -2763,13 +2764,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
||||
*(uint16_t *)wh->i_dur = 0;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
|
||||
#ifdef IEEE80211_SUPPORT_MESH
|
||||
if (vap->iv_opmode == IEEE80211_M_MBSS) {
|
||||
static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, zerobssid);
|
||||
} else
|
||||
#endif
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
|
||||
*(uint16_t *)wh->i_seq = 0;
|
||||
|
||||
return m;
|
||||
@ -2874,6 +2869,11 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
||||
ieee80211_tdma_update_beacon(vap, bo);
|
||||
}
|
||||
#endif
|
||||
#ifdef IEEE80211_SUPPORT_MESH
|
||||
if (vap->iv_opmode == IEEE80211_M_MBSS)
|
||||
ieee80211_mesh_update_beacon(vap, bo);
|
||||
#endif
|
||||
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||
vap->iv_opmode == IEEE80211_M_MBSS) { /* NB: no IBSS support*/
|
||||
struct ieee80211_tim_ie *tie =
|
||||
@ -2927,6 +2927,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
||||
#endif
|
||||
#ifdef IEEE80211_TDMA_SUPPORT
|
||||
bo->bo_tdma += adjust;
|
||||
#endif
|
||||
#ifdef IEEE80211_MESH_SUPPORT
|
||||
bo->bo_meshconf += adjust;
|
||||
#endif
|
||||
bo->bo_appie += adjust;
|
||||
bo->bo_wme += adjust;
|
||||
@ -2978,6 +2981,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
||||
#endif
|
||||
#ifdef IEEE80211_TDMA_SUPPORT
|
||||
bo->bo_tdma += sizeof(*csa);
|
||||
#endif
|
||||
#ifdef IEEE80211_MESH_SUPPORT
|
||||
bo->bo_meshconf += sizeof(*csa);
|
||||
#endif
|
||||
bo->bo_appie += sizeof(*csa);
|
||||
bo->bo_csa_trailer_len += sizeof(*csa);
|
||||
|
@ -317,7 +317,8 @@ struct ieee80211_beacon_offsets {
|
||||
uint16_t bo_appie_len; /* AppIE length in bytes */
|
||||
uint16_t bo_csa_trailer_len;;
|
||||
uint8_t *bo_csa; /* start of CSA element */
|
||||
uint8_t *bo_spare[4];
|
||||
uint8_t *bo_meshconf; /* start of MESHCONF element */
|
||||
uint8_t *bo_spare[3];
|
||||
};
|
||||
struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *,
|
||||
struct ieee80211_beacon_offsets *);
|
||||
@ -345,6 +346,7 @@ enum {
|
||||
IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */
|
||||
IEEE80211_BEACON_TDMA = 9, /* TDMA Info */
|
||||
IEEE80211_BEACON_ATH = 10, /* ATH parameters */
|
||||
IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */
|
||||
};
|
||||
int ieee80211_beacon_update(struct ieee80211_node *,
|
||||
struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
|
||||
|
Loading…
x
Reference in New Issue
Block a user