Lines Matching +full:max +full:- +full:rx +full:- +full:timeout +full:- +full:ms

1 /*- 
2 * SPDX-License-Identifier: BSD-2-Clause
103 * Timeout values come from the specification and are in milliseconds.
107 static int ieee80211_mesh_gateint = -1;
111 "mesh gate interval (ms)");
112 static int ieee80211_mesh_retrytimeout = -1;
116 "Retry timeout (msec)");
117 static int ieee80211_mesh_holdingtimeout = -1;
122 "Holding state timeout (msec)");
123 static int ieee80211_mesh_confirmtimeout = -1;
127 "Confirm state timeout (msec)");
128 static int ieee80211_mesh_backofftimeout = -1;
132 "Backoff timeout (msec). This is to throutles peering forever when "
183 mesh_rt_find_locked(struct ieee80211_mesh_state *ms,
188 MESH_RT_LOCK_ASSERT(ms);
190 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
191 if (IEEE80211_ADDR_EQ(dest, rt->rt_dest))
201 struct ieee80211_mesh_state *ms = vap->iv_mesh;
207 MESH_RT_LOCK_ASSERT(ms);
210 ms->ms_ppath->mpp_privlen, M_80211_MESH_RT,
213 rt->rt_vap = vap;
214 IEEE80211_ADDR_COPY(rt->rt_dest, dest);
215 rt->rt_priv = (void *)ALIGN(&rt[1]);
217 callout_init(&rt->rt_discovery, 1);
218 rt->rt_updtime = ticks; /* create time */
219 TAILQ_INSERT_TAIL(&ms->ms_routes, rt, rt_next);
228 struct ieee80211_mesh_state *ms = vap->iv_mesh;
231 MESH_RT_LOCK(ms);
232 rt = mesh_rt_find_locked(ms, dest);
233 MESH_RT_UNLOCK(ms);
241 struct ieee80211_mesh_state *ms = vap->iv_mesh;
246 KASSERT(!IEEE80211_ADDR_EQ(vap->iv_myaddr, dest),
249 MESH_RT_LOCK(ms);
251 MESH_RT_UNLOCK(ms);
272 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY && rt->rt_nhops == 0) {
274 return rt->rt_lifetime;
277 timesince = ticks_to_msecs(now - rt->rt_updtime);
278 rt->rt_updtime = now;
279 if (timesince >= rt->rt_lifetime) {
281 rt->rt_lifetime = new_lifetime;
284 rt->rt_flags &= ~IEEE80211_MESHRT_FLAGS_VALID;
285 rt->rt_lifetime = 0;
289 rt->rt_lifetime = rt->rt_lifetime - timesince;
290 rt->rt_lifetime = MESH_ROUTE_LIFETIME_MAX(
291 new_lifetime, rt->rt_lifetime);
293 lifetime = rt->rt_lifetime;
306 struct ieee80211_mesh_state *ms = vap->iv_mesh;
309 MESH_RT_LOCK(ms);
310 rt = mesh_rt_find_locked(ms, dest);
316 vap->iv_stats.is_mesh_rtaddfailed++;
320 IEEE80211_ADDR_COPY(rt->rt_mesh_gate, vap->iv_myaddr);
321 IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
322 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
325 } else if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
326 KASSERT(rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY,
328 struct ieee80211com *ic = vap->iv_ic;
337 IEEE80211_ADDR_COPY(rt->rt_nexthop, vap->iv_myaddr);
338 rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID
341 ieee80211_ageq_drain_node(&ic->ic_stageq,
345 MESH_RT_UNLOCK(ms);
349 mesh_rt_del(struct ieee80211_mesh_state *ms, struct ieee80211_mesh_route *rt)
351 TAILQ_REMOVE(&ms->ms_routes, rt, rt_next);
357 callout_drain(&rt->rt_discovery);
366 struct ieee80211_mesh_state *ms = vap->iv_mesh;
369 MESH_RT_LOCK(ms);
370 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
371 if (IEEE80211_ADDR_EQ(rt->rt_dest, dest)) {
372 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
373 ms->ms_ppath->mpp_senderror(vap, dest, rt,
376 ms->ms_ppath->mpp_senderror(vap, dest, rt,
379 mesh_rt_del(ms, rt);
380 MESH_RT_UNLOCK(ms);
384 MESH_RT_UNLOCK(ms);
390 struct ieee80211_mesh_state *ms = vap->iv_mesh;
393 if (ms == NULL)
395 MESH_RT_LOCK(ms);
396 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next)
397 mesh_rt_del(ms, rt);
398 MESH_RT_UNLOCK(ms);
405 struct ieee80211_mesh_state *ms = vap->iv_mesh;
408 MESH_RT_LOCK(ms);
409 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
410 if (IEEE80211_ADDR_EQ(rt->rt_nexthop, peer))
411 mesh_rt_del(ms, rt);
413 MESH_RT_UNLOCK(ms);
423 struct ieee80211_mesh_state *ms = vap->iv_mesh;
426 if (ms == NULL)
428 MESH_RT_LOCK(ms);
429 TAILQ_FOREACH_SAFE(rt, &ms->ms_routes, rt_next, next) {
431 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_DISCOVER)
434 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
435 mesh_rt_del(ms, rt);
437 MESH_RT_UNLOCK(ms);
443 int i, firstempty = -1;
446 if (strncmp(mpp->mpp_descr, mesh_proto_paths[i].mpp_descr,
449 if (!mesh_proto_paths[i].mpp_active && firstempty == -1)
463 int i, firstempty = -1;
466 if (strncmp(mpm->mpm_descr, mesh_proto_metrics[i].mpm_descr,
469 if (!mesh_proto_metrics[i].mpm_active && firstempty == -1)
482 struct ieee80211_mesh_state *ms = vap->iv_mesh;
487 ms->ms_ppath = &mesh_proto_paths[i];
497 struct ieee80211_mesh_state *ms = vap->iv_mesh;
502 ms->ms_pmetric = &mesh_proto_metrics[i];
512 struct ieee80211_mesh_state *ms = vap->iv_mesh;
520 if (ms->ms_flags & IEEE80211_MESHFLAGS_ROOT ||
521 (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) == 0) {
522 callout_drain(&ms->ms_gatetimer);
525 callout_reset(&ms->ms_gatetimer, ieee80211_mesh_gateint,
533 struct ieee80211_mesh_state *ms = vap->iv_mesh;
538 gann.gann_ttl = ms->ms_ttl;
539 IEEE80211_ADDR_COPY(gann.gann_addr, vap->iv_myaddr);
540 gann.gann_seq = ms->ms_gateseq++;
543 IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, vap->iv_bss,
546 ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
611 ic->ic_vattach[IEEE80211_M_MBSS] = mesh_vattach;
622 struct ieee80211com *ic = ni->ni_ic;
625 if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED) {
626 args[0] = ni->ni_mlpid;
627 args[1] = ni->ni_mllid;
634 callout_drain(&ni->ni_mltimer);
636 ieee80211_ageq_drain_node(&ic->ic_stageq,
637 (void *)(uintptr_t) ieee80211_mac_hash(ic, ni->ni_macaddr));
643 struct ieee80211_mesh_state *ms = vap->iv_mesh;
645 callout_drain(&ms->ms_cleantimer);
646 ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_vdetach_peers,
649 MESH_RT_LOCK_DESTROY(ms);
650 ms->ms_ppath->mpp_vdetach(vap);
651 IEEE80211_FREE(vap->iv_mesh, M_80211_VAP);
652 vap->iv_mesh = NULL;
658 struct ieee80211_mesh_state *ms;
659 vap->iv_newstate = mesh_newstate;
660 vap->iv_input = mesh_input;
661 vap->iv_opdetach = mesh_vdetach;
662 vap->iv_recv_mgmt = mesh_recv_mgmt;
663 vap->iv_recv_ctl = mesh_recv_ctl;
664 ms = IEEE80211_MALLOC(sizeof(struct ieee80211_mesh_state), M_80211_VAP,
666 if (ms == NULL) {
670 vap->iv_mesh = ms;
671 ms->ms_seq = 0;
672 ms->ms_flags = (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_FWD);
673 ms->ms_ttl = IEEE80211_MESH_DEFAULT_TTL;
674 TAILQ_INIT(&ms->ms_known_gates);
675 TAILQ_INIT(&ms->ms_routes);
676 MESH_RT_LOCK_INIT(ms, "MBSS");
677 callout_init(&ms->ms_cleantimer, 1);
678 callout_init(&ms->ms_gatetimer, 1);
679 ms->ms_gateseq = 0;
681 KASSERT(ms->ms_pmetric, ("ms_pmetric == NULL"));
683 KASSERT(ms->ms_ppath, ("ms_ppath == NULL"));
684 ms->ms_ppath->mpp_vattach(vap);
693 struct ieee80211_mesh_state *ms = vap->iv_mesh;
694 struct ieee80211com *ic = vap->iv_ic;
700 ostate = vap->iv_state;
701 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n",
704 vap->iv_state = nstate; /* state transition */
707 ni = vap->iv_bss; /* NB: no reference held */
709 callout_drain(&ms->ms_cleantimer);
710 callout_drain(&ms->ms_gatetimer);
722 ieee80211_iterate_nodes(&ic->ic_sta,
729 /* NB: optimize INIT -> INIT case */
737 if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
738 !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan) &&
739 ms->ms_idlen != 0) {
744 ieee80211_create_ibss(vap, vap->iv_des_chan);
754 if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
756 vap->iv_scanreq_flags,
757 vap->iv_scanreq_duration,
758 vap->iv_scanreq_mindwell,
759 vap->iv_scanreq_maxdwell,
760 vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
761 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
783 * back to do a RUN->RUN state change.
787 ic->ic_curchan, vap->iv_flags_ht));
803 ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap);
810 ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
811 ieee80211_htchanflags(ni->ni_chan)));
820 ether_sprintf(ni->ni_meshid));
821 ieee80211_print_essid(ni->ni_meshid,
822 ni->ni_meshidlen);
825 ieee80211_chan2ieee(ic, ic->ic_curchan));
833 callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
841 ms->ms_ppath->mpp_newstate(vap, ostate, arg);
849 struct ieee80211_mesh_state *ms = vap->iv_mesh;
852 callout_reset(&ms->ms_cleantimer, ms->ms_ppath->mpp_inact,
865 struct ieee80211_mesh_state *ms = vap->iv_mesh;
869 MESH_RT_LOCK(ms);
870 TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) {
871 if (IEEE80211_ADDR_EQ(gr->gr_addr, addr)) {
880 "%s", "stored new gate information from pro-PREQ.");
884 IEEE80211_ADDR_COPY(gr->gr_addr, addr);
885 TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
887 gr->gr_route = rt;
889 MESH_RT_UNLOCK(ms);
900 struct ieee80211vap *vap = ni->ni_vap;
901 struct ieee80211_mesh_state *ms = vap->iv_mesh;
913 ni, "peer link: %s -> %s",
914 meshlinkstates[ni->ni_mlstate], meshlinkstates[state]);
918 ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
919 KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
920 ms->ms_neighbors++;
922 } else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
924 KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
925 ms->ms_neighbors--;
928 ni->ni_mlstate = state;
931 ms->ms_ppath->mpp_peerdown(ni);
934 ieee80211_mesh_discover(vap, ni->ni_macaddr, NULL);
950 if (*r == ni->ni_mllid)
962 ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, mesh_checkid, &r);
963 maxiter--;
985 vap->iv_stats.is_mesh_rtaddfailed++;
990 rt->rt_lastmseq = seq;
993 if (IEEE80211_MESH_SEQ_GEQ(rt->rt_lastmseq, seq)) {
996 rt->rt_lastmseq = seq;
1013 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
1015 "%s: !valid, flags 0x%x", __func__, rt->rt_flags);
1019 if (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) {
1020 rt = ieee80211_mesh_rt_find(vap, rt->rt_mesh_gate);
1022 if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
1025 rt->rt_flags);
1030 return ieee80211_find_txnode(vap, rt->rt_nexthop);
1037 struct ifnet *ifp = vap->iv_ifp;
1040 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
1042 ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest);
1070 struct ieee80211com *ic = vap->iv_ic;
1071 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1078 KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER,
1082 MESH_RT_LOCK(ms);
1084 m = ieee80211_ageq_remove(&ic->ic_stageq,
1086 ieee80211_mac_hash(ic, rt_dest->rt_dest));
1088 TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, gr_next) {
1089 rt_gate = gr->gr_route;
1092 rt_dest->rt_dest,
1094 gr->gr_addr, ":");
1097 if ((rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0)
1099 KASSERT(rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_GATE,
1101 KASSERT((rt_gate->rt_flags &
1109 rt_dest->rt_flags = IEEE80211_MESHRT_FLAGS_PROXY |
1111 rt_dest->rt_ext_seq = 1; /* random value */
1112 IEEE80211_ADDR_COPY(rt_dest->rt_mesh_gate, rt_gate->rt_dest);
1113 IEEE80211_ADDR_COPY(rt_dest->rt_nexthop, rt_gate->rt_nexthop);
1114 rt_dest->rt_metric = rt_gate->rt_metric;
1115 rt_dest->rt_nhops = rt_gate->rt_nhops;
1116 ieee80211_mesh_rt_update(rt_dest, ms->ms_ppath->mpp_inact);
1117 MESH_RT_UNLOCK(ms);
1121 next = mcopy->m_nextpkt;
1122 mcopy->m_nextpkt = NULL;
1124 rt_dest->rt_dest,
1126 mcopy->m_pkthdr.len);
1129 MESH_RT_LOCK(ms);
1131 rt_dest->rt_flags = 0; /* Mark invalid */
1133 MESH_RT_UNLOCK(ms);
1144 struct ieee80211com *ic = vap->iv_ic;
1145 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1146 struct ifnet *ifp = vap->iv_ifp;
1155 /* This is called from the RX path - don't hold this lock */
1163 if (mc->mc_ttl < 1) {
1166 vap->iv_stats.is_mesh_fwd_ttl++;
1169 if (!(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
1172 vap->iv_stats.is_mesh_fwd_disabled++;
1179 vap->iv_stats.is_mesh_fwd_nobuf++;
1188 vap->iv_stats.is_mesh_fwd_tooshort++;
1197 whcopy->i_fc[1] &= ~IEEE80211_FC1_RETRY;
1198 IEEE80211_ADDR_COPY(whcopy->i_addr2, vap->iv_myaddr);
1199 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1200 ni = ieee80211_ref_node(vap->iv_bss);
1201 mcopy->m_flags |= M_MCAST;
1203 ni = ieee80211_mesh_find_txnode(vap, whcopy->i_addr3);
1213 ms->ms_ppath->mpp_senderror(vap, whcopy->i_addr3, NULL,
1215 vap->iv_stats.is_mesh_fwd_nopath++;
1219 IEEE80211_ADDR_COPY(whcopy->i_addr1, ni->ni_macaddr);
1221 KASSERT(mccopy->mc_ttl > 0, ("%s called with wrong ttl", __func__));
1222 mccopy->mc_ttl--;
1228 MPASS((mcopy->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0);
1229 mcopy->m_pkthdr.rcvif = (void *) ni;
1239 * to do here; we'll have to re-think this soon.
1251 #define WHDIR(wh) ((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK)
1261 if (m->m_len < hdrlen + sizeof(*llc) &&
1265 vap->iv_stats.is_rx_tooshort++;
1270 mc = (const struct ieee80211_meshcntl_ae10 *)&b[hdrlen - meshdrlen];
1273 ("bogus dir, fc 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1276 if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP &&
1277 llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 &&
1278 llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
1280 !(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
1281 llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
1282 m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
1285 m_adj(m, hdrlen - sizeof(*eh));
1288 ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
1290 IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr1);
1292 IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr3);
1294 IEEE80211_ADDR_COPY(eh->ether_shost,
1295 MC01(mc)->mc_addr4);
1300 vap->iv_stats.is_mesh_badae++;
1306 IEEE80211_ADDR_COPY(eh->ether_dhost, wh->i_addr3);
1307 IEEE80211_ADDR_COPY(eh->ether_shost, wh->i_addr4);
1309 IEEE80211_ADDR_COPY(eh->ether_dhost, mc->mc_addr5);
1310 IEEE80211_ADDR_COPY(eh->ether_shost, mc->mc_addr6);
1315 vap->iv_stats.is_mesh_badae++;
1329 eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh));
1337 * Return non-zero if the unicast mesh data frame should be processed
1345 int ae = mc->mc_flags & 3;
1347 KASSERT((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS,
1348 ("bad dir 0x%x:0x%x", wh->i_fc[0], wh->i_fc[1]));
1355 ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
1358 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY));
1360 return IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_myaddr);
1374 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1377 /* This is called from the RX path - don't hold this lock */
1378 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
1385 * o lifetime of precursor of addr3 (addr2) is max(init, curr)
1386 * o lifetime of precursor of addr4 (nexthop) is max(init, curr)
1390 rt_meshda = ieee80211_mesh_rt_find(vap, qwh->i_addr3);
1392 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, qwh->i_addr2,
1393 "no route to meshDA(%6D)", qwh->i_addr3, ":");
1401 return (-1);
1405 ms->ms_ppath->mpp_inact));
1408 rt_meshsa = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
1411 ms->ms_ppath->mpp_inact));
1432 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1436 /* This is called from the RX path - don't hold this lock */
1437 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
1445 * o lifetime of precursor entry is max(init, curr)
1449 rt = ieee80211_mesh_rt_find(vap, qwh->i_addr4);
1451 ieee80211_mesh_rt_update(rt, ticks_to_msecs(ms->ms_ppath->mpp_inact));
1454 ae = mc10->mc_flags & IEEE80211_MESH_AE_MASK;
1458 if (IEEE80211_ADDR_EQ(mc10->mc_addr5, qwh->i_addr3)) {
1462 rt = ieee80211_mesh_rt_find(vap, mc10->mc_addr5);
1464 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) &&
1465 (rt->rt_flags & IEEE80211_MESHRT_FLAGS_PROXY) == 0) {
1467 * Forward on another mesh-path, according to
1470 IEEE80211_ADDR_COPY(qwh->i_addr3, mc10->mc_addr5);
1479 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, qwh->i_addr2,
1481 mc10->mc_addr6, ":", mc10->mc_addr5, ":");
1499 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1501 /* This is called from the RX path - don't hold this lock */
1502 IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
1506 if(mc->mc_ttl > 0) {
1507 if (mc->mc_flags & IEEE80211_MESH_AE_01) {
1514 if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE &&
1515 ms->ms_flags & IEEE80211_MESHFLAGS_FWD) {
1517 MC01(mc)->mc_addr4, "%s",
1532 struct ieee80211vap *vap = ni->ni_vap;
1533 struct ieee80211com *ic = ni->ni_ic;
1534 struct ifnet *ifp = vap->iv_ifp;
1544 ni->ni_inact = ni->ni_inact_reload;
1547 type = -1; /* undefined */
1549 /* This is called from the RX path - don't hold this lock */
1552 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
1554 ni->ni_macaddr, NULL,
1555 "too short (1): len %u", m->m_pkthdr.len);
1556 vap->iv_stats.is_rx_tooshort++;
1560 * Bit of a cheat here, we use a pointer for a 3-address
1569 ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]);
1570 vap->iv_stats.is_rx_badversion++;
1573 dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
1574 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1575 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1576 if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
1577 IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
1578 ni->ni_noise = nf;
1584 ic->ic_wme.wme_hipri_traffic++;
1585 if (! ieee80211_check_rxseq(ni, wh, wh->i_addr1, rxs))
1597 if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1600 vap->iv_stats.is_rx_acl++;
1606 if (ni == vap->iv_bss)
1608 if (ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
1610 ni->ni_macaddr, NULL,
1612 ni->ni_mlstate);
1613 vap->iv_stats.is_mesh_nolink++;
1620 vap->iv_stats.is_rx_wrongdir++;
1628 vap->iv_stats.is_rx_badsubtype++;
1635 * Mesh Control field is not present in sub-sequent
1639 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1663 * an unfragmented MSDU, an A-MSDU, or the first
1669 ni->ni_macaddr, NULL,
1671 vap->iv_stats.is_rx_elem_missing++; /* XXX: kinda */
1676 if (m->m_len < hdrspace + sizeof(struct ieee80211_meshcntl) &&
1680 ni->ni_macaddr, NULL,
1682 vap->iv_stats.is_rx_tooshort++;
1692 ae = mc->mc_flags & IEEE80211_MESH_AE_MASK;
1699 (m->m_len < hdrspace) &&
1702 ni->ni_macaddr, NULL,
1704 vap->iv_stats.is_rx_tooshort++;
1709 seq = le32dec(mc->mc_seq);
1710 if (IEEE80211_IS_MULTICAST(wh->i_addr1))
1711 addr = wh->i_addr3;
1713 addr = MC01(mc)->mc_addr4;
1715 addr = ((struct ieee80211_qosframe_addr4 *)wh)->i_addr4;
1716 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, addr)) {
1719 vap->iv_stats.is_rx_wrongbss++; /* XXX kinda */
1723 vap->iv_stats.is_rx_dup++;
1728 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1729 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr3))
1732 else if (IEEE80211_IS_MULTICAST(wh->i_addr3))
1759 ni->ni_macaddr, "data", "%s", "decap error");
1760 vap->iv_stats.is_rx_decap++;
1772 vap->iv_stats.is_rx_mgmt++;
1777 vap->iv_stats.is_rx_wrongdir++;
1780 if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
1782 ni->ni_macaddr, "mgt", "too short: len %u",
1783 m->m_pkthdr.len);
1784 vap->iv_stats.is_rx_tooshort++;
1789 (vap->iv_ic->ic_flags & IEEE80211_F_SCAN)) ||
1793 ether_sprintf(wh->i_addr2), rssi);
1799 vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
1802 vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
1805 vap->iv_stats.is_rx_ctl++;
1831 struct ieee80211vap *vap = ni->ni_vap;
1832 struct ieee80211_mesh_state *ms = vap->iv_mesh;
1833 struct ieee80211com *ic = ni->ni_ic;
1834 struct ieee80211_channel *rxchan = ic->ic_curchan;
1841 efrm = mtod(m0, uint8_t *) + m0->m_len;
1863 vap->iv_stats.is_rx_beacon++; /* XXX remove */
1870 if (ic->ic_flags & IEEE80211_F_SCAN) {
1871 if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
1881 ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
1889 if (vap->iv_state != IEEE80211_S_RUN)
1892 * Ignore non-mesh STAs.
1899 vap->iv_stats.is_mesh_wrongmesh++;
1905 if (memcmp(scan.meshid+2, ms->ms_id, ms->ms_idlen) != 0 ||
1909 vap->iv_stats.is_mesh_wrongmesh++;
1915 if (vap->iv_acl != NULL && !vap->iv_acl->iac_check(vap, wh)) {
1918 vap->iv_stats.is_rx_acl++;
1924 if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) {
1933 if (ni != vap->iv_bss &&
1934 (ms->ms_flags & IEEE80211_MESHFLAGS_AP)) {
1935 switch (ni->ni_mlstate) {
1941 if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
1944 ni->ni_mlpid = mesh_generateid(vap);
1945 if (ni->ni_mlpid == 0)
1948 args[0] = ni->ni_mlpid;
1952 ni->ni_mlrcnt = 0;
1962 rt = ieee80211_mesh_rt_find(vap, wh->i_addr2);
1966 ms->ms_ppath->mpp_inact));
1980 if (vap->iv_state != IEEE80211_S_RUN) {
1983 ieee80211_state_name[vap->iv_state]);
1984 vap->iv_stats.is_rx_mgtdiscard++;
1987 if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
1991 vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */
2002 while (efrm - frm > 1) {
2003 IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
2024 IEEE80211_RATE_MAXSIZE - rates[1], return);
2029 IEEE80211_VERIFY_SSID(vap->iv_bss, meshid, return);
2033 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
2038 * only a bare-bones rate set, communicate this to
2041 ieee80211_send_proberesp(vap, wh->i_addr2, 0);
2047 if (ni == vap->iv_bss) {
2050 vap->iv_stats.is_rx_mgtdiscard++;
2051 } else if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, wh->i_addr1) &&
2052 !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2055 vap->iv_stats.is_rx_mgtdiscard++;
2056 } else if (vap->iv_state != IEEE80211_S_RUN) {
2059 ieee80211_state_name[vap->iv_state]);
2060 vap->iv_stats.is_rx_mgtdiscard++;
2063 (void)ic->ic_recv_action(ni, wh, frm, efrm);
2078 vap->iv_stats.is_rx_mgtdiscard++;
2084 vap->iv_stats.is_rx_badsubtype++;
2109 struct ieee80211vap *vap = ni->ni_vap;
2116 while (efrm - frm > 1) {
2117 IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return NULL);
2128 mp->peer_len = mpie->peer_len;
2129 mp->peer_proto = le16dec(&mpie->peer_proto);
2130 mp->peer_llinkid = le16dec(&mpie->peer_llinkid);
2133 mp->peer_linkid =
2134 le16dec(&mpie->peer_linkid);
2138 if (mpie->peer_len ==
2140 mp->peer_linkid = 0;
2141 mp->peer_rcode =
2142 le16dec(&mpie->peer_linkid);
2144 mp->peer_linkid =
2145 le16dec(&mpie->peer_linkid);
2146 mp->peer_rcode =
2147 le16dec(&mpie->peer_rcode);
2197 vap->iv_stats.is_rx_mgtdiscard++;
2198 switch (ni->ni_mlstate) {
2207 args[0] = ni->ni_mlpid;
2208 args[1] = ni->ni_mllid;
2237 struct ieee80211vap *vap = ni->ni_vap;
2238 struct ieee80211_mesh_state *ms = vap->iv_mesh;
2252 "recv PEER OPEN, lid 0x%x", meshpeer->peer_llinkid);
2254 switch (ni->ni_mlstate) {
2257 if (ms->ms_neighbors >= IEEE80211_MESH_MAX_NEIGHBORS) {
2258 args[0] = meshpeer->peer_llinkid;
2270 ni->ni_mllid = meshpeer->peer_llinkid;
2271 ni->ni_mlpid = mesh_generateid(vap);
2272 if (ni->ni_mlpid == 0)
2274 args[0] = ni->ni_mlpid;
2280 args[0] = ni->ni_mlpid;
2281 args[1] = ni->ni_mllid;
2290 if (ni->ni_mllid != meshpeer->peer_llinkid) {
2291 args[0] = ni->ni_mllid;
2292 args[1] = ni->ni_mlpid;
2303 args[0] = ni->ni_mlpid;
2304 args[1] = ni->ni_mllid;
2311 ni->ni_mllid = meshpeer->peer_llinkid;
2313 args[0] = ni->ni_mlpid;
2314 args[1] = ni->ni_mllid;
2319 /* NB: don't setup/clear any timeout */
2322 if (ni->ni_mlpid != meshpeer->peer_linkid ||
2323 ni->ni_mllid != meshpeer->peer_llinkid) {
2324 args[0] = ni->ni_mlpid;
2325 args[1] = ni->ni_mllid;
2337 ni->ni_mllid = meshpeer->peer_llinkid;
2338 args[0] = ni->ni_mlpid;
2339 args[1] = ni->ni_mllid;
2347 if (ni->ni_mllid != meshpeer->peer_llinkid) {
2348 args[0] = ni->ni_mllid;
2349 args[1] = ni->ni_mlpid;
2359 args[0] = ni->ni_mlpid;
2360 args[1] = ni->ni_mllid;
2367 args[0] = ni->ni_mlpid;
2368 args[1] = meshpeer->peer_llinkid;
2385 struct ieee80211vap *vap = ni->ni_vap;
2399 meshpeer->peer_llinkid, meshpeer->peer_linkid);
2401 switch (ni->ni_mlstate) {
2411 args[0] = ni->ni_mlpid;
2412 args[1] = meshpeer->peer_llinkid;
2421 if (ni->ni_mllid != meshpeer->peer_llinkid) {
2422 args[0] = ni->ni_mlpid;
2423 args[1] = ni->ni_mllid;
2437 ni->ni_mlstate);
2438 vap->iv_stats.is_rx_mgtdiscard++;
2466 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
2469 switch (ni->ni_mlstate) {
2477 args[0] = ni->ni_mlpid;
2478 args[1] = ni->ni_mllid;
2508 if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
2522 * Returns -1 if parsing fails, otherwise 0.
2529 struct ieee80211vap *vap = ni->ni_vap;
2532 while (efrm - frm > 1) {
2533 IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return -1);
2538 ie->gann_ie = gannie->gann_ie;
2539 ie->gann_len = gannie->gann_len;
2540 ie->gann_flags = gannie->gann_flags;
2541 ie->gann_hopcount = gannie->gann_hopcount;
2542 ie->gann_ttl = gannie->gann_ttl;
2543 IEEE80211_ADDR_COPY(ie->gann_addr, gannie->gann_addr);
2544 ie->gann_seq = le32dec(&gannie->gann_seq);
2545 ie->gann_interval = le16dec(&gannie->gann_interval);
2562 struct ieee80211vap *vap = ni->ni_vap;
2563 struct ieee80211_mesh_state *ms = vap->iv_mesh;
2573 ni->ni_macaddr, NULL, "%s",
2575 vap->iv_stats.is_rx_mgtdiscard++;
2579 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, ie.gann_addr))
2582 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_MESH, ni->ni_macaddr,
2586 if (ms == NULL)
2588 MESH_RT_LOCK(ms);
2589 TAILQ_FOREACH_SAFE(gr, &ms->ms_known_gates, gr_next, next) {
2590 if (!IEEE80211_ADDR_EQ(gr->gr_addr, ie.gann_addr))
2592 if (ie.gann_seq <= gr->gr_lastseq) {
2594 ni->ni_macaddr, NULL,
2596 ie.gann_seq, gr->gr_lastseq);
2597 MESH_RT_UNLOCK(ms);
2611 IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr);
2612 TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
2614 gr->gr_lastseq = ie.gann_seq;
2617 rt_gate = mesh_rt_find_locked(ms, gr->gr_addr);
2619 rt_gate->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) {
2620 gr->gr_route = rt_gate;
2621 rt_gate->rt_flags |= IEEE80211_MESHRT_FLAGS_GATE;
2624 MESH_RT_UNLOCK(ms);
2627 if ((ie.gann_ttl - 1) < 1 && !(ms->ms_flags & IEEE80211_MESHFLAGS_FWD))
2631 pgann.gann_ttl = ie.gann_ttl - 1;
2639 ieee80211_send_action(vap->iv_bss, IEEE80211_ACTION_CAT_MESH,
2651 struct ieee80211vap *vap = ni->ni_vap;
2652 struct ieee80211com *ic = ni->ni_ic;
2658 if (vap->iv_state == IEEE80211_S_CAC) {
2661 vap->iv_stats.is_tx_badstate++;
2677 m->m_flags |= M_ENCAP; /* mark encapsulated */
2681 params.ibp_rate0 = ni->ni_txparms->mgmtrate;
2685 params.ibp_try0 = ni->ni_txparms->maxretry;
2686 params.ibp_power = ni->ni_txpower;
2712 struct ieee80211vap *vap = ni->ni_vap;
2713 struct ieee80211com *ic = ni->ni_ic;
2724 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2728 ic->ic_headroom + sizeof(struct ieee80211_frame),
2732 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
2751 ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
2752 rs = ieee80211_get_suprates(ic, ic->ic_curchan);
2759 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2760 return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2762 vap->iv_stats.is_tx_nobuf++;
2772 struct ieee80211vap *vap = ni->ni_vap;
2773 struct ieee80211com *ic = ni->ni_ic;
2785 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2789 ic->ic_headroom + sizeof(struct ieee80211_frame),
2795 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)
2816 ADDSHORT(frm, ieee80211_getcapinfo(vap, ni->ni_chan));
2819 rs = ieee80211_get_suprates(ic, ic->ic_curchan);
2827 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2828 return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2830 vap->iv_stats.is_tx_nobuf++;
2840 struct ieee80211vap *vap = ni->ni_vap;
2841 struct ieee80211com *ic = ni->ni_ic;
2852 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2856 ic->ic_headroom + sizeof(struct ieee80211_frame),
2876 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2877 return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2879 vap->iv_stats.is_tx_nobuf++;
2889 struct ieee80211vap *vap = ni->ni_vap;
2890 struct ieee80211com *ic = ni->ni_ic;
2895 if (ie->lm_flags & IEEE80211_MESH_LMETRIC_FLAGS_REQ) {
2901 ie->lm_metric);
2905 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2909 ic->ic_headroom + sizeof(struct ieee80211_frame),
2923 ie->lm_flags, ie->lm_metric);
2924 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2925 return mesh_send_action(ni, vap->iv_myaddr, ni->ni_macaddr, m);
2927 vap->iv_stats.is_tx_nobuf++;
2937 struct ieee80211vap *vap = ni->ni_vap;
2938 struct ieee80211com *ic = ni->ni_ic;
2945 ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2949 ic->ic_headroom + sizeof(struct ieee80211_frame),
2963 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2964 return mesh_send_action(ni, vap->iv_myaddr, broadcastaddr, m);
2966 vap->iv_stats.is_tx_nobuf++;
2975 switch (ni->ni_mlstate) {
2977 ni->ni_mltval = ieee80211_mesh_holdingtimeout;
2980 ni->ni_mltval = ieee80211_mesh_confirmtimeout;
2983 ni->ni_mltval = 0;
2986 ni->ni_mltval = ieee80211_mesh_retrytimeout;
2989 if (ni->ni_mltval)
2990 callout_reset(&ni->ni_mltimer, ni->ni_mltval,
3003 ni->ni_mltval += r % ni->ni_mltval;
3004 callout_reset(&ni->ni_mltimer, ni->ni_mltval, mesh_peer_timeout_cb,
3011 callout_drain(&ni->ni_mltimer);
3019 /* After backoff timeout, try to peer automatically again. */
3020 ni->ni_mlhcnt = 0;
3024 * Mesh Peer Link Management FSM timeout handling.
3032 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_MESH,
3033 ni, "mesh link timeout, state %d, retry counter %d",
3034 ni->ni_mlstate, ni->ni_mlrcnt);
3036 switch (ni->ni_mlstate) {
3042 if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
3043 args[0] = ni->ni_mlpid;
3048 ni->ni_mlrcnt = 0;
3052 args[0] = ni->ni_mlpid;
3056 ni->ni_mlrcnt++;
3061 args[0] = ni->ni_mlpid;
3070 ni->ni_mlhcnt++;
3071 if (ni->ni_mlhcnt >= ieee80211_mesh_maxholding)
3072 callout_reset(&ni->ni_mlhtimer,
3083 struct ieee80211_mesh_state *ms = vap->iv_mesh;
3085 if (ie == NULL || ie[1] != ms->ms_idlen)
3087 return memcmp(ms->ms_id, ie + 2, ms->ms_idlen);
3098 const struct ieee80211_mesh_state *ms = vap->iv_mesh;
3102 if (meshconf->conf_pselid != ms->ms_ppath->mpp_ie) {
3105 meshconf->conf_pselid);
3108 if (meshconf->conf_pmetid != ms->ms_pmetric->mpm_ie) {
3111 meshconf->conf_pmetid);
3114 if (meshconf->conf_ccid != 0) {
3117 meshconf->conf_ccid);
3120 if (meshconf->conf_syncid != IEEE80211_MESHCONF_SYNC_NEIGHOFF) {
3123 meshconf->conf_syncid);
3126 if (meshconf->conf_authid != 0) {
3129 meshconf->conf_pselid);
3133 if (!(meshconf->conf_cap & IEEE80211_MESHCONF_CAP_AP)) {
3135 "not accepting peers: 0x%x\n", meshconf->conf_cap);
3149 meshpeer->peer_len < IEEE80211_MPM_BASE_SZ ||
3150 meshpeer->peer_len > IEEE80211_MPM_MAX_SZ)
3152 if (meshpeer->peer_proto != IEEE80211_MPPID_MPM) {
3156 meshpeer->peer_proto);
3161 if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ)
3165 if (meshpeer->peer_len != IEEE80211_MPM_BASE_SZ + 2)
3169 if (meshpeer->peer_len < IEEE80211_MPM_BASE_SZ + 2)
3171 if (meshpeer->peer_len == (IEEE80211_MPM_BASE_SZ + 2) &&
3172 meshpeer->peer_linkid != 0)
3174 if (meshpeer->peer_rcode == 0)
3187 struct ieee80211_mesh_state *ms = vap->iv_mesh;
3189 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mbss vap"));
3192 *frm++ = ms->ms_idlen;
3193 memcpy(frm, ms->ms_id, ms->ms_idlen);
3194 return frm + ms->ms_idlen;
3205 const struct ieee80211_mesh_state *ms = vap->iv_mesh;
3208 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
3212 *frm++ = ms->ms_ppath->mpp_ie; /* path selection */
3213 *frm++ = ms->ms_pmetric->mpm_ie; /* link metric */
3218 *frm = (ms->ms_neighbors > IEEE80211_MESH_MAX_NEIGHBORS ?
3219 IEEE80211_MESH_MAX_NEIGHBORS : ms->ms_neighbors) << 1;
3220 if (ms->ms_flags & IEEE80211_MESHFLAGS_GATE)
3224 if (ms->ms_flags & IEEE80211_MESHFLAGS_AP)
3226 if (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)
3277 * Max 802.11s overhead.
3294 struct ieee80211com *ic = ni->ni_ic;
3295 struct ifnet *ifp = ni->ni_vap->iv_ifp;
3301 rate = ni->ni_txrate;
3302 overhead = ieee80211_compute_duration(ic->ic_rt,
3303 ifp->if_mtu + IEEE80211_MESH_MAXOVERHEAD, rate, 0) << M_BITS;
3306 errrate = (((ifp->if_get_counter(ifp, IFCOUNTER_OERRORS) +
3307 ifp->if_get_counter(ifp, IFCOUNTER_IERRORS)) / 100) << M_BITS)
3310 ((1 << S_FACTOR) / ((1 << M_BITS) - errrate));
3338 *frm++ = ie->gann_flags;
3339 *frm++ = ie->gann_hopcount;
3340 *frm++ = ie->gann_ttl;
3341 IEEE80211_ADDR_COPY(frm, ie->gann_addr);
3343 ADDWORD(frm, ie->gann_seq);
3344 ADDSHORT(frm, ie->gann_interval);
3351 * Initialize any mesh-specific node state.
3356 ni->ni_flags |= IEEE80211_NODE_QOS;
3357 callout_init(&ni->ni_mltimer, 1);
3358 callout_init(&ni->ni_mlhtimer, 1);
3362 * Cleanup any mesh-specific node state.
3367 struct ieee80211vap *vap = ni->ni_vap;
3368 struct ieee80211_mesh_state *ms = vap->iv_mesh;
3370 callout_drain(&ni->ni_mltimer);
3371 callout_drain(&ni->ni_mlhtimer);
3372 /* NB: short-circuit callbacks after mesh_vdetach */
3373 if (vap->iv_mesh != NULL)
3374 ms->ms_ppath->mpp_peerdown(ni);
3380 ni->ni_meshidlen = ie[1];
3381 memcpy(ni->ni_meshid, ie + 2, ie[1]);
3385 * Setup mesh-specific node state on neighbor discovery.
3392 ieee80211_parse_meshid(ni, sp->meshid);
3399 KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
3401 if (isset(bo->bo_flags, IEEE80211_BEACON_MESHCONF)) {
3402 (void)ieee80211_add_meshconf(bo->bo_meshconf, vap);
3403 clrbit(bo->bo_flags, IEEE80211_BEACON_MESHCONF);
3410 struct ieee80211_mesh_state *ms = vap->iv_mesh;
3418 if (vap->iv_opmode != IEEE80211_M_MBSS)
3422 switch (ireq->i_type) {
3424 ireq->i_len = ms->ms_idlen;
3425 memcpy(tmpmeshid, ms->ms_id, ireq->i_len);
3426 error = copyout(tmpmeshid, ireq->i_data, ireq->i_len);
3429 ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_AP) != 0;
3432 ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_FWD) != 0;
3435 ireq->i_val = (ms->ms_flags & IEEE80211_MESHFLAGS_GATE) != 0;
3438 ireq->i_val = ms->ms_ttl;
3441 switch (ireq->i_val) {
3444 MESH_RT_LOCK(ms);
3445 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
3448 MESH_RT_UNLOCK(ms);
3449 if (len > ireq->i_len || ireq->i_len < sizeof(*imr)) {
3450 ireq->i_len = len;
3453 ireq->i_len = len;
3460 MESH_RT_LOCK(ms);
3461 TAILQ_FOREACH(rt, &ms->ms_routes, rt_next) {
3466 IEEE80211_ADDR_COPY(imr->imr_dest,
3467 rt->rt_dest);
3468 IEEE80211_ADDR_COPY(imr->imr_nexthop,
3469 rt->rt_nexthop);
3470 imr->imr_metric = rt->rt_metric;
3471 imr->imr_nhops = rt->rt_nhops;
3472 imr->imr_lifetime =
3474 imr->imr_lastmseq = rt->rt_lastmseq;
3475 imr->imr_flags = rt->rt_flags; /* last */
3478 MESH_RT_UNLOCK(ms);
3479 error = copyout(p, (uint8_t *)ireq->i_data,
3480 ireq->i_len);
3492 len = strlen(ms->ms_pmetric->mpm_descr);
3493 if (ireq->i_len < len)
3495 ireq->i_len = len;
3496 error = copyout(ms->ms_pmetric->mpm_descr,
3497 (uint8_t *)ireq->i_data, len);
3500 len = strlen(ms->ms_ppath->mpp_descr);
3501 if (ireq->i_len < len)
3503 ireq->i_len = len;
3504 error = copyout(ms->ms_ppath->mpp_descr,
3505 (uint8_t *)ireq->i_data, len);
3518 struct ieee80211_mesh_state *ms = vap->iv_mesh;
3524 if (vap->iv_opmode != IEEE80211_M_MBSS)
3528 switch (ireq->i_type) {
3530 if (ireq->i_val != 0 || ireq->i_len > IEEE80211_MESHID_LEN)
3532 error = copyin(ireq->i_data, tmpmeshid, ireq->i_len);
3535 memset(ms->ms_id, 0, IEEE80211_NWID_LEN);
3536 ms->ms_idlen = ireq->i_len;
3537 memcpy(ms->ms_id, tmpmeshid, ireq->i_len);
3541 if (ireq->i_val)
3542 ms->ms_flags |= IEEE80211_MESHFLAGS_AP;
3544 ms->ms_flags &= ~IEEE80211_MESHFLAGS_AP;
3548 if (ireq->i_val)
3549 ms->ms_flags |= IEEE80211_MESHFLAGS_FWD;
3551 ms->ms_flags &= ~IEEE80211_MESHFLAGS_FWD;
3555 if (ireq->i_val)
3556 ms->ms_flags |= IEEE80211_MESHFLAGS_GATE;
3558 ms->ms_flags &= ~IEEE80211_MESHFLAGS_GATE;
3561 ms->ms_ttl = (uint8_t) ireq->i_val;
3564 switch (ireq->i_val) {
3571 error = copyin(ireq->i_data, tmpaddr,
3575 if (IEEE80211_ADDR_EQ(vap->iv_myaddr, tmpaddr) ||
3581 error = copyin(ireq->i_data, tmpaddr,
3592 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));
3600 error = copyin(ireq->i_data, tmpproto, sizeof(tmpproto));