132176cfdSRui Paulo /*-
232176cfdSRui Paulo  * Copyright (c) 2009 The FreeBSD Foundation
332176cfdSRui Paulo  * All rights reserved.
432176cfdSRui Paulo  *
532176cfdSRui Paulo  * This software was developed by Rui Paulo under sponsorship from the
632176cfdSRui Paulo  * FreeBSD Foundation.
732176cfdSRui Paulo  *
832176cfdSRui Paulo  * Redistribution and use in source and binary forms, with or without
932176cfdSRui Paulo  * modification, are permitted provided that the following conditions
1032176cfdSRui Paulo  * are met:
1132176cfdSRui Paulo  * 1. Redistributions of source code must retain the above copyright
1232176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer.
1332176cfdSRui Paulo  * 2. Redistributions in binary form must reproduce the above copyright
1432176cfdSRui Paulo  *    notice, this list of conditions and the following disclaimer in the
1532176cfdSRui Paulo  *    documentation and/or other materials provided with the distribution.
1632176cfdSRui Paulo  *
1732176cfdSRui Paulo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1832176cfdSRui Paulo  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1932176cfdSRui Paulo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2032176cfdSRui Paulo  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2132176cfdSRui Paulo  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2232176cfdSRui Paulo  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2332176cfdSRui Paulo  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2432176cfdSRui Paulo  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2532176cfdSRui Paulo  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2632176cfdSRui Paulo  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2732176cfdSRui Paulo  * SUCH DAMAGE.
2832176cfdSRui Paulo  *
29085ff963SMatthew Dillon  * $FreeBSD$
3032176cfdSRui Paulo  */
3132176cfdSRui Paulo #ifndef _NET80211_IEEE80211_MESH_H_
3232176cfdSRui Paulo #define _NET80211_IEEE80211_MESH_H_
3332176cfdSRui Paulo 
3432176cfdSRui Paulo #define	IEEE80211_MESH_DEFAULT_TTL	31
35085ff963SMatthew Dillon #define	IEEE80211_MESH_MAX_NEIGHBORS	15
3632176cfdSRui Paulo 
3732176cfdSRui Paulo /*
3832176cfdSRui Paulo  * NB: all structures are __packed  so sizeof works on arm, et. al.
3932176cfdSRui Paulo  */
4032176cfdSRui Paulo /*
4132176cfdSRui Paulo  * 802.11s Information Elements.
4232176cfdSRui Paulo */
4332176cfdSRui Paulo /* Mesh Configuration */
44085ff963SMatthew Dillon #define IEEE80211_MESH_CONF_SZ		(7)
4532176cfdSRui Paulo struct ieee80211_meshconf_ie {
4632176cfdSRui Paulo 	uint8_t		conf_ie;	/* IEEE80211_ELEMID_MESHCONF */
4732176cfdSRui Paulo 	uint8_t		conf_len;
4832176cfdSRui Paulo 	uint8_t		conf_pselid;	/* Active Path Sel. Proto. ID */
4932176cfdSRui Paulo 	uint8_t		conf_pmetid;	/* Active Metric Identifier */
5032176cfdSRui Paulo 	uint8_t		conf_ccid;	/* Congestion Control Mode ID  */
5132176cfdSRui Paulo 	uint8_t		conf_syncid;	/* Sync. Protocol ID */
5232176cfdSRui Paulo 	uint8_t		conf_authid;	/* Auth. Protocol ID */
5332176cfdSRui Paulo 	uint8_t		conf_form;	/* Formation Information */
54085ff963SMatthew Dillon 	uint8_t		conf_cap;
5532176cfdSRui Paulo } __packed;
5632176cfdSRui Paulo 
5732176cfdSRui Paulo /* Hybrid Wireless Mesh Protocol */
58085ff963SMatthew Dillon enum {
59085ff963SMatthew Dillon 	/* 0 reserved */
60085ff963SMatthew Dillon 	IEEE80211_MESHCONF_PATH_HWMP		= 1,
61085ff963SMatthew Dillon 	/* 2-254 reserved */
62085ff963SMatthew Dillon 	IEEE80211_MESHCONF_PATH_VENDOR		= 255,
63085ff963SMatthew Dillon };
64085ff963SMatthew Dillon 
6532176cfdSRui Paulo /* Airtime Link Metric */
66085ff963SMatthew Dillon enum {
67085ff963SMatthew Dillon 	/* 0 reserved */
68085ff963SMatthew Dillon 	IEEE80211_MESHCONF_METRIC_AIRTIME	= 1,
69085ff963SMatthew Dillon 	/* 2-254 reserved */
70085ff963SMatthew Dillon 	IEEE80211_MESHCONF_METRIC_VENDOR	= 255,
71085ff963SMatthew Dillon };
72085ff963SMatthew Dillon 
7332176cfdSRui Paulo /* Congestion Control */
74085ff963SMatthew Dillon enum {
75085ff963SMatthew Dillon 	IEEE80211_MESHCONF_CC_DISABLED		= 0,
76085ff963SMatthew Dillon 	IEEE80211_MESHCONF_CC_SIG		= 1,
77085ff963SMatthew Dillon 	/* 2-254 reserved */
78085ff963SMatthew Dillon 	IEEE80211_MESHCONF_CC_VENDOR		= 255,
79085ff963SMatthew Dillon };
80085ff963SMatthew Dillon 
8132176cfdSRui Paulo /* Neighbour Offset */
82085ff963SMatthew Dillon enum {
83085ff963SMatthew Dillon 	/* 0 reserved */
84085ff963SMatthew Dillon 	IEEE80211_MESHCONF_SYNC_NEIGHOFF	= 1,
85085ff963SMatthew Dillon 	/* 2-254 rserved */
86085ff963SMatthew Dillon 	IEEE80211_MESHCONF_SYNC_VENDOR		= 255,
87085ff963SMatthew Dillon };
88085ff963SMatthew Dillon 
89085ff963SMatthew Dillon /* Authentication Protocol Identifier */
90085ff963SMatthew Dillon enum {
91085ff963SMatthew Dillon 
92085ff963SMatthew Dillon 	IEEE80211_MESHCONF_AUTH_DISABLED	= 0,
9332176cfdSRui Paulo 	/* Simultaneous Authenticaction of Equals */
94085ff963SMatthew Dillon 	IEEE80211_MESHCONF_AUTH_SEA		= 1,
95085ff963SMatthew Dillon 	IEEE80211_MESHCONF_AUTH_8021X		= 2, /* IEEE 802.1X */
96085ff963SMatthew Dillon 	/* 3-254 reserved */
97085ff963SMatthew Dillon 	IEEE80211_MESHCONF_AUTH_VENDOR		= 255,
98085ff963SMatthew Dillon };
99085ff963SMatthew Dillon 
100085ff963SMatthew Dillon /* Mesh Formation Info */
101085ff963SMatthew Dillon #define	IEEE80211_MESHCONF_FORM_GATE	0x01 	/* Connected to Gate */
102085ff963SMatthew Dillon #define	IEEE80211_MESHCONF_FORM_NNEIGH_MASK 0x7E /* Number of Neighbours */
103085ff963SMatthew Dillon #define	IEEE80211_MESHCONF_FORM_SA	0xF0 	/* indicating 802.1X auth */
104085ff963SMatthew Dillon 
105085ff963SMatthew Dillon /* Mesh Capability */
10632176cfdSRui Paulo #define	IEEE80211_MESHCONF_CAP_AP	0x01	/* Accepting Peers */
10732176cfdSRui Paulo #define	IEEE80211_MESHCONF_CAP_MCCAS	0x02	/* MCCA supported */
10832176cfdSRui Paulo #define	IEEE80211_MESHCONF_CAP_MCCAE	0x04	/* MCCA enabled */
10932176cfdSRui Paulo #define	IEEE80211_MESHCONF_CAP_FWRD 	0x08	/* forwarding enabled */
11032176cfdSRui Paulo #define	IEEE80211_MESHCONF_CAP_BTR	0x10	/* Beacon Timing Report Enab */
111085ff963SMatthew Dillon #define	IEEE80211_MESHCONF_CAP_TBTT	0x20	/* TBTT Adjusting  */
112085ff963SMatthew Dillon #define	IEEE80211_MESHCONF_CAP_PSL	0x40	/* Power Save Level */
113085ff963SMatthew Dillon /* 0x80 reserved */
11432176cfdSRui Paulo 
11532176cfdSRui Paulo /* Mesh Identifier */
11632176cfdSRui Paulo struct ieee80211_meshid_ie {
11732176cfdSRui Paulo 	uint8_t		id_ie;		/* IEEE80211_ELEMID_MESHID */
11832176cfdSRui Paulo 	uint8_t		id_len;
11932176cfdSRui Paulo } __packed;
12032176cfdSRui Paulo 
12132176cfdSRui Paulo /* Link Metric Report */
12232176cfdSRui Paulo struct ieee80211_meshlmetric_ie {
123085ff963SMatthew Dillon 	uint8_t		lm_ie;	/* IEEE80211_ACTION_MESH_LMETRIC */
12432176cfdSRui Paulo 	uint8_t		lm_len;
125085ff963SMatthew Dillon 	uint8_t		lm_flags;
126085ff963SMatthew Dillon #define	IEEE80211_MESH_LMETRIC_FLAGS_REQ	0x01	/* Request */
127085ff963SMatthew Dillon 	/*
128085ff963SMatthew Dillon 	 * XXX: this field should be variable in size and depend on
129085ff963SMatthew Dillon 	 * the active active path selection metric identifier
130085ff963SMatthew Dillon 	 */
13132176cfdSRui Paulo 	uint32_t	lm_metric;
13232176cfdSRui Paulo #define	IEEE80211_MESHLMETRIC_INITIALVAL	0
13332176cfdSRui Paulo } __packed;
13432176cfdSRui Paulo 
13532176cfdSRui Paulo /* Congestion Notification */
13632176cfdSRui Paulo struct ieee80211_meshcngst_ie {
13732176cfdSRui Paulo 	uint8_t		cngst_ie;	/* IEEE80211_ELEMID_MESHCNGST */
13832176cfdSRui Paulo 	uint8_t		cngst_len;
13932176cfdSRui Paulo 	uint16_t	cngst_timer[4];	/* Expiration Timers: AC_BK,
14032176cfdSRui Paulo 					   AC_BE, AC_VI, AC_VO */
14132176cfdSRui Paulo } __packed;
14232176cfdSRui Paulo 
14332176cfdSRui Paulo /* Peer Link Management */
144085ff963SMatthew Dillon #define IEEE80211_MPM_BASE_SZ	(4)
145085ff963SMatthew Dillon #define IEEE80211_MPM_MAX_SZ	(8)
14632176cfdSRui Paulo struct ieee80211_meshpeer_ie {
14732176cfdSRui Paulo 	uint8_t		peer_ie;	/* IEEE80211_ELEMID_MESHPEER */
14832176cfdSRui Paulo 	uint8_t		peer_len;
149085ff963SMatthew Dillon 	uint16_t	peer_proto;	/* Peer Management Protocol */
15032176cfdSRui Paulo 	uint16_t	peer_llinkid;	/* Local Link ID */
15132176cfdSRui Paulo 	uint16_t	peer_linkid;	/* Peer Link ID */
15232176cfdSRui Paulo 	uint16_t	peer_rcode;
15332176cfdSRui Paulo } __packed;
15432176cfdSRui Paulo 
155085ff963SMatthew Dillon /* Mesh Peering Protocol Identifier field value */
15632176cfdSRui Paulo enum {
157085ff963SMatthew Dillon 	IEEE80211_MPPID_MPM		= 0,	/* Mesh peering management */
158085ff963SMatthew Dillon 	IEEE80211_MPPID_AUTH_MPM	= 1,	/* Auth. mesh peering exchange */
159085ff963SMatthew Dillon 	/* 2-65535 reserved */
16032176cfdSRui Paulo };
16132176cfdSRui Paulo 
16232176cfdSRui Paulo #ifdef notyet
16332176cfdSRui Paulo /* Mesh Channel Switch Annoucement */
16432176cfdSRui Paulo struct ieee80211_meshcsa_ie {
16532176cfdSRui Paulo 	uint8_t		csa_ie;		/* IEEE80211_ELEMID_MESHCSA */
16632176cfdSRui Paulo 	uint8_t		csa_len;
16732176cfdSRui Paulo 	uint8_t		csa_mode;
16832176cfdSRui Paulo 	uint8_t		csa_newclass;	/* New Regulatory Class */
16932176cfdSRui Paulo 	uint8_t		csa_newchan;
17032176cfdSRui Paulo 	uint8_t		csa_precvalue;	/* Precedence Value */
17132176cfdSRui Paulo 	uint8_t		csa_count;
17232176cfdSRui Paulo } __packed;
17332176cfdSRui Paulo 
17432176cfdSRui Paulo /* Mesh TIM */
17532176cfdSRui Paulo /* Equal to the non Mesh version */
17632176cfdSRui Paulo 
17732176cfdSRui Paulo /* Mesh Awake Window */
17832176cfdSRui Paulo struct ieee80211_meshawakew_ie {
17932176cfdSRui Paulo 	uint8_t		awakew_ie;		/* IEEE80211_ELEMID_MESHAWAKEW */
18032176cfdSRui Paulo 	uint8_t		awakew_len;
18132176cfdSRui Paulo 	uint8_t		awakew_windowlen;	/* in TUs */
18232176cfdSRui Paulo } __packed;
18332176cfdSRui Paulo 
18432176cfdSRui Paulo /* Mesh Beacon Timing */
18532176cfdSRui Paulo struct ieee80211_meshbeacont_ie {
18632176cfdSRui Paulo 	uint8_t		beacont_ie;		/* IEEE80211_ELEMID_MESHBEACONT */
18732176cfdSRui Paulo 	uint8_t		beacont_len;
18832176cfdSRui Paulo 	struct {
18932176cfdSRui Paulo 		uint8_t		mp_aid;		/* Least Octet of AID */
19032176cfdSRui Paulo 		uint16_t	mp_btime;	/* Beacon Time */
19132176cfdSRui Paulo 		uint16_t	mp_bint;	/* Beacon Interval */
19232176cfdSRui Paulo 	} __packed mp[1];			/* NB: variable size */
19332176cfdSRui Paulo } __packed;
19432176cfdSRui Paulo #endif
19532176cfdSRui Paulo 
196085ff963SMatthew Dillon /* Gate (GANN) Annoucement */
197085ff963SMatthew Dillon /*
198085ff963SMatthew Dillon  * NB: these macros used for the length in the IEs does not include 2 bytes
199085ff963SMatthew Dillon  * for _ie and _len fields as is defined by the standard.
200085ff963SMatthew Dillon  */
201085ff963SMatthew Dillon #define	IEEE80211_MESHGANN_BASE_SZ 	(15)
202085ff963SMatthew Dillon struct ieee80211_meshgann_ie {
203085ff963SMatthew Dillon 	uint8_t		gann_ie;		/* IEEE80211_ELEMID_MESHGANN */
204085ff963SMatthew Dillon 	uint8_t		gann_len;
205085ff963SMatthew Dillon 	uint8_t		gann_flags;
206085ff963SMatthew Dillon 	uint8_t		gann_hopcount;
207085ff963SMatthew Dillon 	uint8_t		gann_ttl;
208085ff963SMatthew Dillon 	uint8_t		gann_addr[IEEE80211_ADDR_LEN];
209085ff963SMatthew Dillon 	uint32_t	gann_seq;		/* GANN Sequence Number */
210085ff963SMatthew Dillon 	uint16_t	gann_interval;		/* GANN Interval */
21132176cfdSRui Paulo } __packed;
21232176cfdSRui Paulo 
21332176cfdSRui Paulo /* Root (MP) Annoucement */
214085ff963SMatthew Dillon #define	IEEE80211_MESHRANN_BASE_SZ 	(21)
21532176cfdSRui Paulo struct ieee80211_meshrann_ie {
21632176cfdSRui Paulo 	uint8_t		rann_ie;		/* IEEE80211_ELEMID_MESHRANN */
21732176cfdSRui Paulo 	uint8_t		rann_len;
21832176cfdSRui Paulo 	uint8_t		rann_flags;
219085ff963SMatthew Dillon #define	IEEE80211_MESHRANN_FLAGS_GATE	0x01	/* Mesh Gate */
22032176cfdSRui Paulo 	uint8_t		rann_hopcount;
22132176cfdSRui Paulo 	uint8_t		rann_ttl;
22232176cfdSRui Paulo 	uint8_t		rann_addr[IEEE80211_ADDR_LEN];
22332176cfdSRui Paulo 	uint32_t	rann_seq;		/* HWMP Sequence Number */
224085ff963SMatthew Dillon 	uint32_t	rann_interval;
22532176cfdSRui Paulo 	uint32_t	rann_metric;
22632176cfdSRui Paulo } __packed;
22732176cfdSRui Paulo 
22832176cfdSRui Paulo /* Mesh Path Request */
229085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_BASE_SZ 		(26)
230085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_BASE_SZ_AE 		(32)
231085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_TRGT_SZ 		(11)
232085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_TCNT_OFFSET		(27)
233085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_TCNT_OFFSET_AE	(33)
23432176cfdSRui Paulo struct ieee80211_meshpreq_ie {
23532176cfdSRui Paulo 	uint8_t		preq_ie;	/* IEEE80211_ELEMID_MESHPREQ */
23632176cfdSRui Paulo 	uint8_t		preq_len;
23732176cfdSRui Paulo 	uint8_t		preq_flags;
238085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_FLAGS_GATE	0x01	/* Mesh Gate */
239085ff963SMatthew Dillon #define	IEEE80211_MESHPREQ_FLAGS_AM	0x02	/* 0 = bcast / 1 = ucast */
24032176cfdSRui Paulo #define	IEEE80211_MESHPREQ_FLAGS_PP	0x04	/* Proactive PREP */
24132176cfdSRui Paulo #define	IEEE80211_MESHPREQ_FLAGS_AE	0x40	/* Address Extension */
24232176cfdSRui Paulo 	uint8_t		preq_hopcount;
24332176cfdSRui Paulo 	uint8_t		preq_ttl;
24432176cfdSRui Paulo 	uint32_t	preq_id;
24532176cfdSRui Paulo 	uint8_t		preq_origaddr[IEEE80211_ADDR_LEN];
24632176cfdSRui Paulo 	uint32_t	preq_origseq;	/* HWMP Sequence Number */
247085ff963SMatthew Dillon 	/* NB: may have Originator External Address */
248085ff963SMatthew Dillon 	uint8_t		preq_orig_ext_addr[IEEE80211_ADDR_LEN];
24932176cfdSRui Paulo 	uint32_t	preq_lifetime;
25032176cfdSRui Paulo 	uint32_t	preq_metric;
25132176cfdSRui Paulo 	uint8_t		preq_tcount;	/* target count */
25232176cfdSRui Paulo 	struct {
25332176cfdSRui Paulo 		uint8_t		target_flags;
25432176cfdSRui Paulo #define	IEEE80211_MESHPREQ_TFLAGS_TO	0x01	/* Target Only */
25532176cfdSRui Paulo #define	IEEE80211_MESHPREQ_TFLAGS_USN	0x04	/* Unknown HWMP seq number */
25632176cfdSRui Paulo 		uint8_t		target_addr[IEEE80211_ADDR_LEN];
25732176cfdSRui Paulo 		uint32_t	target_seq;	/* HWMP Sequence Number */
25832176cfdSRui Paulo 	} __packed preq_targets[1];		/* NB: variable size */
25932176cfdSRui Paulo } __packed;
26032176cfdSRui Paulo 
26132176cfdSRui Paulo /* Mesh Path Reply */
262085ff963SMatthew Dillon #define	IEEE80211_MESHPREP_BASE_SZ 	(31)
263085ff963SMatthew Dillon #define	IEEE80211_MESHPREP_BASE_SZ_AE 	(37)
26432176cfdSRui Paulo struct ieee80211_meshprep_ie {
26532176cfdSRui Paulo 	uint8_t		prep_ie;	/* IEEE80211_ELEMID_MESHPREP */
26632176cfdSRui Paulo 	uint8_t		prep_len;
26732176cfdSRui Paulo 	uint8_t		prep_flags;
268085ff963SMatthew Dillon #define	IEEE80211_MESHPREP_FLAGS_AE	0x40	/* Address Extension */
26932176cfdSRui Paulo 	uint8_t		prep_hopcount;
27032176cfdSRui Paulo 	uint8_t		prep_ttl;
27132176cfdSRui Paulo 	uint8_t		prep_targetaddr[IEEE80211_ADDR_LEN];
27232176cfdSRui Paulo 	uint32_t	prep_targetseq;
273085ff963SMatthew Dillon 	/* NB: May have Target External Address */
274085ff963SMatthew Dillon 	uint8_t		prep_target_ext_addr[IEEE80211_ADDR_LEN];
27532176cfdSRui Paulo 	uint32_t	prep_lifetime;
27632176cfdSRui Paulo 	uint32_t	prep_metric;
27732176cfdSRui Paulo 	uint8_t		prep_origaddr[IEEE80211_ADDR_LEN];
27832176cfdSRui Paulo 	uint32_t	prep_origseq;	/* HWMP Sequence Number */
27932176cfdSRui Paulo } __packed;
28032176cfdSRui Paulo 
28132176cfdSRui Paulo /* Mesh Path Error */
282085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_MAXDEST	(19)
283085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_NDEST_OFFSET	(3)
284085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_BASE_SZ 	(2)
285085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_DEST_SZ 	(13)
286085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_DEST_SZ_AE 	(19)
28732176cfdSRui Paulo struct ieee80211_meshperr_ie {
28832176cfdSRui Paulo 	uint8_t		perr_ie;	/* IEEE80211_ELEMID_MESHPERR */
28932176cfdSRui Paulo 	uint8_t		perr_len;
29032176cfdSRui Paulo 	uint8_t		perr_ttl;
29132176cfdSRui Paulo 	uint8_t		perr_ndests;	/* Number of Destinations */
29232176cfdSRui Paulo 	struct {
29332176cfdSRui Paulo 		uint8_t		dest_flags;
294085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_DFLAGS_USN	0x01	/* XXX: not part of standard */
295085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_DFLAGS_RC	0x02	/* XXX: not part of standard */
296085ff963SMatthew Dillon #define	IEEE80211_MESHPERR_FLAGS_AE	0x40	/* Address Extension */
29732176cfdSRui Paulo 		uint8_t		dest_addr[IEEE80211_ADDR_LEN];
29832176cfdSRui Paulo 		uint32_t	dest_seq;	/* HWMP Sequence Number */
299085ff963SMatthew Dillon 		/* NB: May have Destination External Address */
300085ff963SMatthew Dillon 		uint8_t		dest_ext_addr[IEEE80211_ADDR_LEN];
30132176cfdSRui Paulo 		uint16_t	dest_rcode;
30232176cfdSRui Paulo 	} __packed perr_dests[1];		/* NB: variable size */
30332176cfdSRui Paulo } __packed;
30432176cfdSRui Paulo 
30532176cfdSRui Paulo #ifdef notyet
30632176cfdSRui Paulo /* Mesh Proxy Update */
30732176cfdSRui Paulo struct ieee80211_meshpu_ie {
30832176cfdSRui Paulo 	uint8_t		pu_ie;		/* IEEE80211_ELEMID_MESHPU */
30932176cfdSRui Paulo 	uint8_t		pu_len;
31032176cfdSRui Paulo 	uint8_t		pu_flags;
31132176cfdSRui Paulo #define	IEEE80211_MESHPU_FLAGS_MASK		0x1
31232176cfdSRui Paulo #define	IEEE80211_MESHPU_FLAGS_DEL		0x0
31332176cfdSRui Paulo #define	IEEE80211_MESHPU_FLAGS_ADD		0x1
31432176cfdSRui Paulo 	uint8_t		pu_seq;		/* PU Sequence Number */
31532176cfdSRui Paulo 	uint8_t		pu_addr[IEEE80211_ADDR_LEN];
31632176cfdSRui Paulo 	uint8_t		pu_naddr;	/* Number of Proxied Addresses */
31732176cfdSRui Paulo 	/* NB: proxied address follows */
31832176cfdSRui Paulo } __packed;
31932176cfdSRui Paulo 
32032176cfdSRui Paulo /* Mesh Proxy Update Confirmation */
32132176cfdSRui Paulo struct ieee80211_meshpuc_ie {
32232176cfdSRui Paulo 	uint8_t		puc_ie;		/* IEEE80211_ELEMID_MESHPUC */
32332176cfdSRui Paulo 	uint8_t		puc_len;
32432176cfdSRui Paulo 	uint8_t		puc_flags;
32532176cfdSRui Paulo 	uint8_t		puc_seq;	/* PU Sequence Number */
32632176cfdSRui Paulo 	uint8_t		puc_daddr[IEEE80211_ADDR_LEN];
32732176cfdSRui Paulo } __packed;
32832176cfdSRui Paulo #endif
32932176cfdSRui Paulo 
33032176cfdSRui Paulo /*
33132176cfdSRui Paulo  * 802.11s Action Frames
332085ff963SMatthew Dillon  * XXX: these are wrong, and some of them should be
333085ff963SMatthew Dillon  * under MESH category while PROXY is under MULTIHOP category.
33432176cfdSRui Paulo  */
33532176cfdSRui Paulo #define	IEEE80211_ACTION_CAT_INTERWORK		15
33632176cfdSRui Paulo #define	IEEE80211_ACTION_CAT_RESOURCE		16
33732176cfdSRui Paulo #define	IEEE80211_ACTION_CAT_PROXY		17
33832176cfdSRui Paulo 
33932176cfdSRui Paulo /*
34032176cfdSRui Paulo  * Mesh Peering Action codes.
34132176cfdSRui Paulo  */
34232176cfdSRui Paulo enum {
343085ff963SMatthew Dillon 	/* 0 reserved */
344085ff963SMatthew Dillon 	IEEE80211_ACTION_MESHPEERING_OPEN	= 1,
345085ff963SMatthew Dillon 	IEEE80211_ACTION_MESHPEERING_CONFIRM	= 2,
346085ff963SMatthew Dillon 	IEEE80211_ACTION_MESHPEERING_CLOSE	= 3,
347085ff963SMatthew Dillon 	/* 4-255 reserved */
34832176cfdSRui Paulo };
34932176cfdSRui Paulo 
35032176cfdSRui Paulo /*
351085ff963SMatthew Dillon  * Mesh Action code.
35232176cfdSRui Paulo  */
35332176cfdSRui Paulo enum {
354085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_LMETRIC	= 0,	/* Mesh Link Metric Report */
355085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_HWMP	= 1,	/* HWMP Mesh Path Selection */
356085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_GANN	= 2,	/* Gate Announcement */
357085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_CC	= 3,	/* Congestion Control */
358085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_MCCA_SREQ	= 4,	/* MCCA Setup Request */
359085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_MCCA_SREP	= 5,	/* MCCA Setup Reply */
360085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_MCCA_AREQ	= 6,	/* MCCA Advertisement Req. */
361085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_MCCA_ADVER =7,	/* MCCA Advertisement */
362085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_MCCA_TRDOWN = 8,	/* MCCA Teardown */
363085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_TBTT_REQ	= 9,	/* TBTT Adjustment Request */
364085ff963SMatthew Dillon 	IEEE80211_ACTION_MESH_TBTT_RES	= 10,	/* TBTT Adjustment Response */
365085ff963SMatthew Dillon 	/* 11-255 reserved */
36632176cfdSRui Paulo };
36732176cfdSRui Paulo 
36832176cfdSRui Paulo /*
36932176cfdSRui Paulo  * Different mesh control structures based on the AE
37032176cfdSRui Paulo  * (Address Extension) bits.
37132176cfdSRui Paulo  */
37232176cfdSRui Paulo struct ieee80211_meshcntl {
37332176cfdSRui Paulo 	uint8_t		mc_flags;	/* Address Extension 00 */
37432176cfdSRui Paulo 	uint8_t		mc_ttl;		/* TTL */
37532176cfdSRui Paulo 	uint8_t		mc_seq[4];	/* Sequence No. */
37632176cfdSRui Paulo 	/* NB: more addresses may follow */
37732176cfdSRui Paulo } __packed;
37832176cfdSRui Paulo 
37932176cfdSRui Paulo struct ieee80211_meshcntl_ae01 {
38032176cfdSRui Paulo 	uint8_t		mc_flags;	/* Address Extension 01 */
38132176cfdSRui Paulo 	uint8_t		mc_ttl;		/* TTL */
38232176cfdSRui Paulo 	uint8_t		mc_seq[4];	/* Sequence No. */
38332176cfdSRui Paulo 	uint8_t		mc_addr4[IEEE80211_ADDR_LEN];
38432176cfdSRui Paulo } __packed;
38532176cfdSRui Paulo 
38632176cfdSRui Paulo struct ieee80211_meshcntl_ae10 {
38732176cfdSRui Paulo 	uint8_t		mc_flags;	/* Address Extension 10 */
38832176cfdSRui Paulo 	uint8_t		mc_ttl;		/* TTL */
38932176cfdSRui Paulo 	uint8_t		mc_seq[4];	/* Sequence No. */
39032176cfdSRui Paulo 	uint8_t		mc_addr5[IEEE80211_ADDR_LEN];
39132176cfdSRui Paulo 	uint8_t		mc_addr6[IEEE80211_ADDR_LEN];
39232176cfdSRui Paulo } __packed;
39332176cfdSRui Paulo 
394085ff963SMatthew Dillon #define IEEE80211_MESH_AE_MASK		0x03
395085ff963SMatthew Dillon enum {
396085ff963SMatthew Dillon 	IEEE80211_MESH_AE_00		= 0,	/* MC has no AE subfield */
397085ff963SMatthew Dillon 	IEEE80211_MESH_AE_01		= 1,	/* MC contain addr4 */
398085ff963SMatthew Dillon 	IEEE80211_MESH_AE_10		= 2,	/* MC contain addr5 & addr6 */
399085ff963SMatthew Dillon 	IEEE80211_MESH_AE_11		= 3,	/* RESERVED */
400085ff963SMatthew Dillon };
401085ff963SMatthew Dillon 
40232176cfdSRui Paulo #ifdef _KERNEL
403*805c8e8eSzrj #ifdef MALLOC_DECLARE
404085ff963SMatthew Dillon MALLOC_DECLARE(M_80211_MESH_PREQ);
405085ff963SMatthew Dillon MALLOC_DECLARE(M_80211_MESH_PREP);
406085ff963SMatthew Dillon MALLOC_DECLARE(M_80211_MESH_PERR);
407085ff963SMatthew Dillon 
40832176cfdSRui Paulo MALLOC_DECLARE(M_80211_MESH_RT);
409085ff963SMatthew Dillon MALLOC_DECLARE(M_80211_MESH_GT_RT);
410*805c8e8eSzrj #endif
411085ff963SMatthew Dillon /*
412085ff963SMatthew Dillon  * Basic forwarding information:
413085ff963SMatthew Dillon  * o Destination MAC
414085ff963SMatthew Dillon  * o Next-hop MAC
415085ff963SMatthew Dillon  * o Precursor list (not implemented yet)
416085ff963SMatthew Dillon  * o Path timeout
417085ff963SMatthew Dillon  * The rest is part of the active Mesh path selection protocol.
418085ff963SMatthew Dillon  * XXX: to be moved out later.
419085ff963SMatthew Dillon  */
42032176cfdSRui Paulo struct ieee80211_mesh_route {
42132176cfdSRui Paulo 	TAILQ_ENTRY(ieee80211_mesh_route)	rt_next;
422085ff963SMatthew Dillon 	struct ieee80211vap	*rt_vap;
423c3bc1bd4SImre Vadász 	ieee80211_rte_lock_t	rt_lock;	/* fine grained route lock */
424085ff963SMatthew Dillon 	struct callout		rt_discovery;	/* discovery timeout */
425085ff963SMatthew Dillon 	int			rt_updtime;	/* last update time */
42632176cfdSRui Paulo 	uint8_t			rt_dest[IEEE80211_ADDR_LEN];
427085ff963SMatthew Dillon 	uint8_t			rt_mesh_gate[IEEE80211_ADDR_LEN]; /* meshDA */
42832176cfdSRui Paulo 	uint8_t			rt_nexthop[IEEE80211_ADDR_LEN];
42932176cfdSRui Paulo 	uint32_t		rt_metric;	/* path metric */
43032176cfdSRui Paulo 	uint16_t		rt_nhops;	/* number of hops */
43132176cfdSRui Paulo 	uint16_t		rt_flags;
432085ff963SMatthew Dillon #define	IEEE80211_MESHRT_FLAGS_DISCOVER	0x01	/* path discovery */
433085ff963SMatthew Dillon #define	IEEE80211_MESHRT_FLAGS_VALID	0x02	/* path discovery complete */
434085ff963SMatthew Dillon #define	IEEE80211_MESHRT_FLAGS_PROXY	0x04	/* proxy entry */
435085ff963SMatthew Dillon #define	IEEE80211_MESHRT_FLAGS_GATE	0x08	/* mesh gate entry */
436085ff963SMatthew Dillon 	uint32_t		rt_lifetime;	/* route timeout */
43732176cfdSRui Paulo 	uint32_t		rt_lastmseq;	/* last seq# seen dest */
438085ff963SMatthew Dillon 	uint32_t		rt_ext_seq;	/* proxy seq number */
43932176cfdSRui Paulo 	void			*rt_priv;	/* private data */
44032176cfdSRui Paulo };
44132176cfdSRui Paulo #define	IEEE80211_MESH_ROUTE_PRIV(rt, cast)	((cast *)rt->rt_priv)
44232176cfdSRui Paulo 
443085ff963SMatthew Dillon /*
444085ff963SMatthew Dillon  * Stored information about known mesh gates.
445085ff963SMatthew Dillon  */
446085ff963SMatthew Dillon struct ieee80211_mesh_gate_route {
447085ff963SMatthew Dillon 	TAILQ_ENTRY(ieee80211_mesh_gate_route)	gr_next;
448085ff963SMatthew Dillon 	uint8_t				gr_addr[IEEE80211_ADDR_LEN];
449085ff963SMatthew Dillon 	uint32_t			gr_lastseq;
450085ff963SMatthew Dillon 	struct ieee80211_mesh_route 	*gr_route;
451085ff963SMatthew Dillon };
452085ff963SMatthew Dillon 
45332176cfdSRui Paulo #define	IEEE80211_MESH_PROTO_DSZ	12	/* description size */
45432176cfdSRui Paulo /*
45532176cfdSRui Paulo  * Mesh Path Selection Protocol.
45632176cfdSRui Paulo  */
45732176cfdSRui Paulo enum ieee80211_state;
45832176cfdSRui Paulo struct ieee80211_mesh_proto_path {
45932176cfdSRui Paulo 	uint8_t		mpp_active;
46032176cfdSRui Paulo 	char 		mpp_descr[IEEE80211_MESH_PROTO_DSZ];
46132176cfdSRui Paulo 	uint8_t		mpp_ie;
46232176cfdSRui Paulo 	struct ieee80211_node *
46332176cfdSRui Paulo 	    		(*mpp_discover)(struct ieee80211vap *,
46432176cfdSRui Paulo 				const uint8_t [IEEE80211_ADDR_LEN],
46532176cfdSRui Paulo 				struct mbuf *);
46632176cfdSRui Paulo 	void		(*mpp_peerdown)(struct ieee80211_node *);
467085ff963SMatthew Dillon 	void		(*mpp_senderror)(struct ieee80211vap *,
468085ff963SMatthew Dillon 				const uint8_t [IEEE80211_ADDR_LEN],
469085ff963SMatthew Dillon 				struct ieee80211_mesh_route *, int);
47032176cfdSRui Paulo 	void		(*mpp_vattach)(struct ieee80211vap *);
47132176cfdSRui Paulo 	void		(*mpp_vdetach)(struct ieee80211vap *);
47232176cfdSRui Paulo 	int		(*mpp_newstate)(struct ieee80211vap *,
47332176cfdSRui Paulo 			    enum ieee80211_state, int);
47432176cfdSRui Paulo 	const size_t	mpp_privlen;	/* size required in the routing table
47532176cfdSRui Paulo 					   for private data */
47632176cfdSRui Paulo 	int		mpp_inact;	/* inact. timeout for invalid routes
47732176cfdSRui Paulo 					   (ticks) */
47832176cfdSRui Paulo };
47932176cfdSRui Paulo 
48032176cfdSRui Paulo /*
48132176cfdSRui Paulo  * Mesh Link Metric Report Protocol.
48232176cfdSRui Paulo  */
48332176cfdSRui Paulo struct ieee80211_mesh_proto_metric {
48432176cfdSRui Paulo 	uint8_t		mpm_active;
48532176cfdSRui Paulo 	char		mpm_descr[IEEE80211_MESH_PROTO_DSZ];
48632176cfdSRui Paulo 	uint8_t		mpm_ie;
48732176cfdSRui Paulo 	uint32_t	(*mpm_metric)(struct ieee80211_node *);
48832176cfdSRui Paulo };
48932176cfdSRui Paulo 
49032176cfdSRui Paulo #ifdef notyet
49132176cfdSRui Paulo /*
49232176cfdSRui Paulo  * Mesh Authentication Protocol.
49332176cfdSRui Paulo  */
49432176cfdSRui Paulo struct ieee80211_mesh_proto_auth {
49532176cfdSRui Paulo 	uint8_t		mpa_ie[4];
49632176cfdSRui Paulo };
49732176cfdSRui Paulo 
49832176cfdSRui Paulo struct ieee80211_mesh_proto_congestion {
49932176cfdSRui Paulo };
50032176cfdSRui Paulo 
50132176cfdSRui Paulo struct ieee80211_mesh_proto_sync {
50232176cfdSRui Paulo };
50332176cfdSRui Paulo #endif
50432176cfdSRui Paulo 
50532176cfdSRui Paulo typedef uint32_t ieee80211_mesh_seq;
50632176cfdSRui Paulo #define	IEEE80211_MESH_SEQ_LEQ(a, b)	((int32_t)((a)-(b)) <= 0)
50732176cfdSRui Paulo #define	IEEE80211_MESH_SEQ_GEQ(a, b)	((int32_t)((a)-(b)) >= 0)
50832176cfdSRui Paulo 
50932176cfdSRui Paulo struct ieee80211_mesh_state {
51032176cfdSRui Paulo 	int				ms_idlen;
51132176cfdSRui Paulo 	uint8_t				ms_id[IEEE80211_MESHID_LEN];
51232176cfdSRui Paulo 	ieee80211_mesh_seq		ms_seq;	/* seq no for meshcntl */
51332176cfdSRui Paulo 	uint16_t			ms_neighbors;
51432176cfdSRui Paulo 	uint8_t				ms_ttl;	/* mesh ttl set in packets */
51532176cfdSRui Paulo #define IEEE80211_MESHFLAGS_AP		0x01	/* accept peers */
516085ff963SMatthew Dillon #define IEEE80211_MESHFLAGS_GATE	0x02	/* mesh gate role */
51732176cfdSRui Paulo #define IEEE80211_MESHFLAGS_FWD		0x04	/* forward packets */
518085ff963SMatthew Dillon #define IEEE80211_MESHFLAGS_ROOT	0x08	/* configured as root */
51932176cfdSRui Paulo 	uint8_t				ms_flags;
520c3bc1bd4SImre Vadász 	ieee80211_rt_lock_t		ms_rt_lock;
52132176cfdSRui Paulo 	struct callout			ms_cleantimer;
522085ff963SMatthew Dillon 	struct callout			ms_gatetimer;
523085ff963SMatthew Dillon 	ieee80211_mesh_seq		ms_gateseq;
524085ff963SMatthew Dillon 	TAILQ_HEAD(, ieee80211_mesh_gate_route) ms_known_gates;
52532176cfdSRui Paulo 	TAILQ_HEAD(, ieee80211_mesh_route)  ms_routes;
52632176cfdSRui Paulo 	struct ieee80211_mesh_proto_metric *ms_pmetric;
52732176cfdSRui Paulo 	struct ieee80211_mesh_proto_path   *ms_ppath;
52832176cfdSRui Paulo };
52932176cfdSRui Paulo void		ieee80211_mesh_attach(struct ieee80211com *);
53032176cfdSRui Paulo void		ieee80211_mesh_detach(struct ieee80211com *);
53132176cfdSRui Paulo 
53232176cfdSRui Paulo struct ieee80211_mesh_route *
53332176cfdSRui Paulo 		ieee80211_mesh_rt_find(struct ieee80211vap *,
53432176cfdSRui Paulo 		    const uint8_t [IEEE80211_ADDR_LEN]);
53532176cfdSRui Paulo struct ieee80211_mesh_route *
53632176cfdSRui Paulo                 ieee80211_mesh_rt_add(struct ieee80211vap *,
53732176cfdSRui Paulo 		    const uint8_t [IEEE80211_ADDR_LEN]);
53832176cfdSRui Paulo void		ieee80211_mesh_rt_del(struct ieee80211vap *,
53932176cfdSRui Paulo 		    const uint8_t [IEEE80211_ADDR_LEN]);
54032176cfdSRui Paulo void		ieee80211_mesh_rt_flush(struct ieee80211vap *);
54132176cfdSRui Paulo void		ieee80211_mesh_rt_flush_peer(struct ieee80211vap *,
54232176cfdSRui Paulo 		    const uint8_t [IEEE80211_ADDR_LEN]);
543085ff963SMatthew Dillon int		ieee80211_mesh_rt_update(struct ieee80211_mesh_route *rt, int);
54432176cfdSRui Paulo void		ieee80211_mesh_proxy_check(struct ieee80211vap *,
54532176cfdSRui Paulo 		    const uint8_t [IEEE80211_ADDR_LEN]);
54632176cfdSRui Paulo 
54732176cfdSRui Paulo int		ieee80211_mesh_register_proto_path(const
54832176cfdSRui Paulo 		    struct ieee80211_mesh_proto_path *);
54932176cfdSRui Paulo int		ieee80211_mesh_register_proto_metric(const
55032176cfdSRui Paulo 		    struct ieee80211_mesh_proto_metric *);
55132176cfdSRui Paulo 
55232176cfdSRui Paulo uint8_t *	ieee80211_add_meshid(uint8_t *, struct ieee80211vap *);
55332176cfdSRui Paulo uint8_t *	ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *);
55432176cfdSRui Paulo uint8_t *	ieee80211_add_meshpeer(uint8_t *, uint8_t, uint16_t, uint16_t,
55532176cfdSRui Paulo 		    uint16_t);
556085ff963SMatthew Dillon uint8_t *	ieee80211_add_meshlmetric(uint8_t *, uint8_t, uint32_t);
557085ff963SMatthew Dillon uint8_t *	ieee80211_add_meshgate(uint8_t *,
558085ff963SMatthew Dillon 		    struct ieee80211_meshgann_ie *);
55932176cfdSRui Paulo 
56032176cfdSRui Paulo void		ieee80211_mesh_node_init(struct ieee80211vap *,
56132176cfdSRui Paulo 		    struct ieee80211_node *);
56232176cfdSRui Paulo void		ieee80211_mesh_node_cleanup(struct ieee80211_node *);
56332176cfdSRui Paulo void		ieee80211_parse_meshid(struct ieee80211_node *,
56432176cfdSRui Paulo 		    const uint8_t *);
56532176cfdSRui Paulo struct ieee80211_scanparams;
56632176cfdSRui Paulo void		ieee80211_mesh_init_neighbor(struct ieee80211_node *,
56732176cfdSRui Paulo 		   const struct ieee80211_frame *,
56832176cfdSRui Paulo 		   const struct ieee80211_scanparams *);
56932176cfdSRui Paulo void		ieee80211_mesh_update_beacon(struct ieee80211vap *,
57032176cfdSRui Paulo 		    struct ieee80211_beacon_offsets *);
571085ff963SMatthew Dillon struct ieee80211_mesh_gate_route *
572085ff963SMatthew Dillon 		ieee80211_mesh_mark_gate(struct ieee80211vap *,
573085ff963SMatthew Dillon 		    const uint8_t *, struct ieee80211_mesh_route *);
574085ff963SMatthew Dillon void		ieee80211_mesh_forward_to_gates(struct ieee80211vap *,
575085ff963SMatthew Dillon 		    struct ieee80211_mesh_route *);
576085ff963SMatthew Dillon struct ieee80211_node *
577085ff963SMatthew Dillon 		ieee80211_mesh_find_txnode(struct ieee80211vap *,
578085ff963SMatthew Dillon 		    const uint8_t [IEEE80211_ADDR_LEN]);
57932176cfdSRui Paulo 
58032176cfdSRui Paulo /*
58132176cfdSRui Paulo  * Return non-zero if proxy operation is enabled.
58232176cfdSRui Paulo  */
58332176cfdSRui Paulo static __inline int
ieee80211_mesh_isproxyena(struct ieee80211vap * vap)58432176cfdSRui Paulo ieee80211_mesh_isproxyena(struct ieee80211vap *vap)
58532176cfdSRui Paulo {
58632176cfdSRui Paulo 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
58732176cfdSRui Paulo 	return (ms->ms_flags &
588085ff963SMatthew Dillon 	    (IEEE80211_MESHFLAGS_AP | IEEE80211_MESHFLAGS_GATE)) != 0;
58932176cfdSRui Paulo }
59032176cfdSRui Paulo 
59132176cfdSRui Paulo /*
59232176cfdSRui Paulo  * Process an outbound frame: if a path is known to the
59332176cfdSRui Paulo  * destination then return a reference to the next hop
59432176cfdSRui Paulo  * for immediate transmission.  Otherwise initiate path
59532176cfdSRui Paulo  * discovery and, if possible queue the packet to be
59632176cfdSRui Paulo  * sent when path discovery completes.
59732176cfdSRui Paulo  */
59832176cfdSRui Paulo static __inline struct ieee80211_node *
ieee80211_mesh_discover(struct ieee80211vap * vap,const uint8_t dest[IEEE80211_ADDR_LEN],struct mbuf * m)59932176cfdSRui Paulo ieee80211_mesh_discover(struct ieee80211vap *vap,
60032176cfdSRui Paulo     const uint8_t dest[IEEE80211_ADDR_LEN], struct mbuf *m)
60132176cfdSRui Paulo {
60232176cfdSRui Paulo 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
60332176cfdSRui Paulo 	return ms->ms_ppath->mpp_discover(vap, dest, m);
60432176cfdSRui Paulo }
60532176cfdSRui Paulo 
60632176cfdSRui Paulo #endif /* _KERNEL */
60732176cfdSRui Paulo #endif /* !_NET80211_IEEE80211_MESH_H_ */
608