Blame view
net/mac80211/mesh.h
13.1 KB
d2912cb15
|
1 |
/* SPDX-License-Identifier: GPL-2.0-only */ |
ccf80ddfe
|
2 |
/* |
264d9b7d8
|
3 |
* Copyright (c) 2008, 2009 open80211s Ltd. |
ccf80ddfe
|
4 5 |
* Authors: Luis Carlos Cobo <luisca@cozybit.com> * Javier Cardona <javier@cozybit.com> |
ccf80ddfe
|
6 7 8 9 |
*/ #ifndef IEEE80211S_H #define IEEE80211S_H |
902acc789
|
10 |
#include <linux/types.h> |
ccf80ddfe
|
11 |
#include <linux/jhash.h> |
902acc789
|
12 |
#include "ieee80211_i.h" |
ccf80ddfe
|
13 |
|
ccf80ddfe
|
14 15 16 17 18 19 |
/* Data structures */ /** * enum mesh_path_flags - mac80211 mesh path flags * |
eb80ed8d1
|
20 21 |
* @MESH_PATH_ACTIVE: the mesh path can be used for forwarding * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path |
d19b3bf63
|
22 |
* @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence |
bf7cd94dc
|
23 |
* number |
ccf80ddfe
|
24 |
* @MESH_PATH_FIXED: the mesh path has been manually set and should not be |
bf7cd94dc
|
25 |
* modified |
ccf80ddfe
|
26 |
* @MESH_PATH_RESOLVED: the mesh path can has been resolved |
f3011cf9d
|
27 |
* @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination |
bf7cd94dc
|
28 |
* already queued up, waiting for the discovery process to start. |
749329594
|
29 30 |
* @MESH_PATH_DELETED: the mesh path has been deleted and should no longer * be used |
ccf80ddfe
|
31 |
* |
eb80ed8d1
|
32 |
* MESH_PATH_RESOLVED is used by the mesh path timer to |
ccf80ddfe
|
33 34 35 36 37 |
* decide when to stop or cancel the mesh path discovery. */ enum mesh_path_flags { MESH_PATH_ACTIVE = BIT(0), MESH_PATH_RESOLVING = BIT(1), |
d19b3bf63
|
38 |
MESH_PATH_SN_VALID = BIT(2), |
ccf80ddfe
|
39 40 |
MESH_PATH_FIXED = BIT(3), MESH_PATH_RESOLVED = BIT(4), |
f3011cf9d
|
41 |
MESH_PATH_REQ_QUEUED = BIT(5), |
749329594
|
42 |
MESH_PATH_DELETED = BIT(6), |
ccf80ddfe
|
43 44 45 |
}; /** |
18889231e
|
46 47 48 49 50 |
* enum mesh_deferred_task_flags - mac80211 mesh deferred tasks * * * * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks |
e304bfd30
|
51 |
* @MESH_WORK_ROOT: the mesh root station needs to send a frame |
dbf498fba
|
52 53 |
* @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other * mesh nodes |
f81a9deda
|
54 |
* @MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes |
18889231e
|
55 56 57 |
*/ enum mesh_deferred_task_flags { MESH_WORK_HOUSEKEEPING, |
e304bfd30
|
58 |
MESH_WORK_ROOT, |
dbf498fba
|
59 |
MESH_WORK_DRIFT_ADJUST, |
f81a9deda
|
60 |
MESH_WORK_MBSS_CHANGED, |
18889231e
|
61 62 63 |
}; /** |
ccf80ddfe
|
64 65 66 |
* struct mesh_path - mac80211 mesh path structure * * @dst: mesh path destination mac address |
68bb54b47
|
67 68 |
* @mpp: mesh proxy mac address * @rhash: rhashtable list pointer |
b4c3fbe63
|
69 |
* @walk_list: linked list containing all mesh_path objects. |
68bb54b47
|
70 |
* @gate_list: list pointer for known gates list |
f698d856f
|
71 |
* @sdata: mesh subif |
ccf80ddfe
|
72 |
* @next_hop: mesh neighbor to which frames for this destination will be |
bf7cd94dc
|
73 |
* forwarded |
ccf80ddfe
|
74 75 |
* @timer: mesh path discovery timer * @frame_queue: pending queue for frames sent to this destination while the |
bf7cd94dc
|
76 |
* path is unresolved |
68bb54b47
|
77 |
* @rcu: rcu head for freeing mesh path |
d19b3bf63
|
78 |
* @sn: target sequence number |
ccf80ddfe
|
79 80 81 82 |
* @metric: current metric to this destination * @hop_count: hops to destination * @exp_time: in jiffies, when the path will expire or when it expired * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery |
bf7cd94dc
|
83 |
* retry |
ccf80ddfe
|
84 85 |
* @discovery_retries: number of discovery retries * @flags: mesh path flags, as specified on &enum mesh_path_flags |
f5e50cd07
|
86 87 88 |
* @state_lock: mesh path state lock used to protect changes to the * mpath itself. No need to take this lock when adding or removing * an mpath to a hash bucket on a path table. |
3d045a544
|
89 |
* @rann_snd_addr: the RANN sender address |
d2a079fd4
|
90 |
* @rann_metric: the aggregated path metric towards the root node |
728b19e5f
|
91 |
* @last_preq_to_root: Timestamp of last PREQ sent to root |
3d045a544
|
92 |
* @is_root: the destination station of this path is a root node |
5ee68e5b3
|
93 |
* @is_gate: the destination station of this path is a mesh gate |
540bbcb93
|
94 |
* @path_change_count: the number of path changes to destination |
ccf80ddfe
|
95 96 |
* * |
68bb54b47
|
97 98 99 100 |
* The dst address is unique in the mesh path table. Since the mesh_path is * protected by RCU, deleting the next_hop STA must remove / substitute the * mesh_path structure and wait until that is no longer reachable before * destroying the STA completely. |
ccf80ddfe
|
101 102 103 |
*/ struct mesh_path { u8 dst[ETH_ALEN]; |
79617deee
|
104 |
u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ |
60854fd94
|
105 |
struct rhash_head rhash; |
b4c3fbe63
|
106 |
struct hlist_node walk_list; |
947c2a0ec
|
107 |
struct hlist_node gate_list; |
f698d856f
|
108 |
struct ieee80211_sub_if_data *sdata; |
40b275b69
|
109 |
struct sta_info __rcu *next_hop; |
ccf80ddfe
|
110 111 112 |
struct timer_list timer; struct sk_buff_head frame_queue; struct rcu_head rcu; |
d19b3bf63
|
113 |
u32 sn; |
ccf80ddfe
|
114 115 116 117 118 119 120 |
u32 metric; u8 hop_count; unsigned long exp_time; u32 discovery_timeout; u8 discovery_retries; enum mesh_path_flags flags; spinlock_t state_lock; |
3d045a544
|
121 |
u8 rann_snd_addr[ETH_ALEN]; |
d2a079fd4
|
122 |
u32 rann_metric; |
728b19e5f
|
123 |
unsigned long last_preq_to_root; |
3d045a544
|
124 |
bool is_root; |
5ee68e5b3
|
125 |
bool is_gate; |
540bbcb93
|
126 |
u32 path_change_count; |
ccf80ddfe
|
127 128 129 130 131 |
}; /** * struct mesh_table * |
5ee68e5b3
|
132 133 |
* @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. |
68bb54b47
|
134 135 |
* @gates_lock: protects updates to known_gates * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr |
b4c3fbe63
|
136 137 |
* @walk_head: linked list containging all mesh_path objects * @walk_lock: lock protecting walk_head |
68bb54b47
|
138 |
* @entries: number of entries in the table |
ccf80ddfe
|
139 140 |
*/ struct mesh_table { |
18b27ff7d
|
141 |
struct hlist_head known_gates; |
5ee68e5b3
|
142 |
spinlock_t gates_lock; |
60854fd94
|
143 |
struct rhashtable rhead; |
b4c3fbe63
|
144 145 |
struct hlist_head walk_head; spinlock_t walk_lock; |
3257523be
|
146 |
atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */ |
ccf80ddfe
|
147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
}; /* Recent multicast cache */ /* RMC_BUCKETS must be a power of 2, maximum 256 */ #define RMC_BUCKETS 256 #define RMC_QUEUE_MAX_LEN 4 #define RMC_TIMEOUT (3 * HZ) /** * struct rmc_entry - entry in the Recent Multicast Cache * * @seqnum: mesh sequence number of the frame * @exp_time: expiration time of the entry, in jiffies * @sa: source address of the frame |
68bb54b47
|
161 |
* @list: hashtable list pointer |
ccf80ddfe
|
162 163 164 165 166 167 |
* * The Recent Multicast Cache keeps track of the latest multicast frames that * have been received by a mesh interface and discards received multicast frames * that are found in the cache. */ struct rmc_entry { |
47a0489ce
|
168 |
struct hlist_node list; |
ccf80ddfe
|
169 |
unsigned long exp_time; |
3257523be
|
170 |
u32 seqnum; |
ccf80ddfe
|
171 172 173 174 |
u8 sa[ETH_ALEN]; }; struct mesh_rmc { |
47a0489ce
|
175 |
struct hlist_head bucket[RMC_BUCKETS]; |
51ceddade
|
176 |
u32 idx_mask; |
ccf80ddfe
|
177 |
}; |
25d49e4d6
|
178 |
#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
ccf80ddfe
|
179 |
|
ccf80ddfe
|
180 |
#define MESH_PATH_EXPIRE (600 * HZ) |
ccf80ddfe
|
181 182 183 184 185 |
/* Default maximum number of plinks per interface */ #define MESH_MAX_PLINKS 256 /* Maximum number of paths per interface */ #define MESH_MAX_MPATHS 1024 |
4bd4c2dd8
|
186 187 |
/* Number of frames buffered per destination for unresolved destinations */ #define MESH_FRAME_QUEUE_LEN 10 |
ccf80ddfe
|
188 189 |
/* Public interfaces */ /* Various */ |
3c5772a52
|
190 |
int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
15ff63653
|
191 |
const u8 *da, const u8 *sa); |
5edfcee5e
|
192 193 194 |
unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, struct ieee80211s_hdr *meshhdr, const char *addr4or5, const char *addr6); |
bf7cd94dc
|
195 196 |
int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, const u8 *addr, struct ieee80211s_hdr *mesh_hdr); |
f743ff490
|
197 198 |
bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, struct ieee802_11_elems *ie); |
472dbc45d
|
199 |
void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
bf7cd94dc
|
200 201 202 203 204 205 206 207 208 209 210 211 |
int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
c85fb53c4
|
212 213 214 215 |
int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
60ad72da5
|
216 217 218 219 |
int mesh_add_he_cap_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 ie_len); int mesh_add_he_oper_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
f698d856f
|
220 221 |
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
ccf80ddfe
|
222 |
void ieee80211s_init(void); |
bfc32e6a9
|
223 |
void ieee80211s_update_metric(struct ieee80211_local *local, |
c42055105
|
224 225 |
struct sta_info *sta, struct ieee80211_tx_status *st); |
902acc789
|
226 |
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
0371a08fb
|
227 |
void ieee80211_mesh_teardown_sdata(struct ieee80211_sub_if_data *sdata); |
2b5e19677
|
228 |
int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); |
472dbc45d
|
229 |
void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); |
63c5723bc
|
230 |
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); |
8ba7acf37
|
231 |
const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method); |
2b5e19677
|
232 233 234 |
/* wrapper for ieee80211_bss_info_change_notify() */ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); |
902acc789
|
235 |
|
3f52b7e32
|
236 |
/* mesh power save */ |
39886b618
|
237 238 239 |
u32 ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata); u32 ieee80211_mps_set_sta_local_pm(struct sta_info *sta, enum nl80211_mesh_power_mode pm); |
3f52b7e32
|
240 241 242 243 244 245 246 247 248 249 |
void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_hdr *hdr); void ieee80211_mps_sta_status_update(struct sta_info *sta); void ieee80211_mps_rx_h_sta_process(struct sta_info *sta, struct ieee80211_hdr *hdr); void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, bool tx, bool acked); void ieee80211_mps_frame_release(struct sta_info *sta, struct ieee802_11_elems *elems); |
ccf80ddfe
|
250 |
/* Mesh paths */ |
bf7cd94dc
|
251 252 253 254 |
int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
f698d856f
|
255 |
void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
bf7cd94dc
|
256 257 258 259 260 261 262 263 |
struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst); struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst); int mpp_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst, const u8 *mpp); struct mesh_path * mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx); |
a2db2ed3f
|
264 265 |
struct mesh_path * mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx); |
ccf80ddfe
|
266 |
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
f698d856f
|
267 |
void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
f698d856f
|
268 |
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
bf7cd94dc
|
269 |
struct ieee80211_mgmt *mgmt, size_t len); |
ae76eef02
|
270 271 |
struct mesh_path * mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); |
5ee68e5b3
|
272 273 274 275 |
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); |
ab60633c7
|
276 277 |
u32 airtime_link_metric_get(struct ieee80211_local *local, struct sta_info *sta); |
bf7cd94dc
|
278 |
|
ccf80ddfe
|
279 |
/* Mesh plinks */ |
f743ff490
|
280 |
void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, |
ecbc12ad6
|
281 282 |
u8 *hw_addr, struct ieee802_11_elems *ie, struct ieee80211_rx_status *rx_status); |
f698d856f
|
283 |
bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
df3238189
|
284 |
u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
4c02d62fa
|
285 |
void mesh_plink_timer(struct timer_list *t); |
ccf80ddfe
|
286 |
void mesh_plink_broken(struct sta_info *sta); |
45b5028e8
|
287 |
u32 mesh_plink_deactivate(struct sta_info *sta); |
39886b618
|
288 289 |
u32 mesh_plink_open(struct sta_info *sta); u32 mesh_plink_block(struct sta_info *sta); |
f698d856f
|
290 291 292 |
void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status); |
45b5028e8
|
293 |
void mesh_sta_cleanup(struct sta_info *sta); |
ccf80ddfe
|
294 295 |
/* Private interfaces */ |
ccf80ddfe
|
296 |
/* Mesh paths */ |
bf7cd94dc
|
297 |
int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
f63f8421d
|
298 299 |
u8 ttl, const u8 *target, u32 target_sn, u16 target_rcode, const u8 *ra); |
ccf80ddfe
|
300 301 302 |
void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); void mesh_path_flush_pending(struct mesh_path *mpath); void mesh_path_tx_pending(struct mesh_path *mpath); |
2bdaf386f
|
303 304 |
int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata); void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata); |
bf7cd94dc
|
305 |
int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); |
34f11cd32
|
306 |
void mesh_path_timer(struct timer_list *t); |
ccf80ddfe
|
307 |
void mesh_path_flush_by_nexthop(struct sta_info *sta); |
bf7cd94dc
|
308 309 |
void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
e304bfd30
|
310 |
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
ccf80ddfe
|
311 |
|
25d49e4d6
|
312 |
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); |
f5ea9120b
|
313 |
|
902acc789
|
314 |
#ifdef CONFIG_MAC80211_MESH |
1617bab8d
|
315 316 317 318 |
static inline u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_inc(&sdata->u.mesh.estab_plinks); |
e05ecccdf
|
319 |
return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON; |
1617bab8d
|
320 321 322 323 324 325 |
} static inline u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) { atomic_dec(&sdata->u.mesh.estab_plinks); |
e05ecccdf
|
326 |
return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON; |
1617bab8d
|
327 |
} |
ccf80ddfe
|
328 329 |
static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) { |
472dbc45d
|
330 |
return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - |
1258d9761
|
331 |
atomic_read(&sdata->u.mesh.estab_plinks); |
ccf80ddfe
|
332 333 334 335 |
} static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) { |
d0709a651
|
336 |
return (min_t(long, mesh_plink_free_count(sdata), |
ccf80ddfe
|
337 338 339 340 341 342 343 |
MESH_MAX_PLINKS - sdata->local->num_sta)) > 0; } static inline void mesh_path_activate(struct mesh_path *mpath) { mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED; } |
c7108a711
|
344 345 346 347 |
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) { return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; } |
94c514fe2
|
348 |
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
445cd452f
|
349 |
void mesh_sync_adjust_tsf(struct ieee80211_sub_if_data *sdata); |
bf7cd94dc
|
350 |
void ieee80211s_stop(void); |
902acc789
|
351 |
#else |
c7108a711
|
352 353 |
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) { return false; } |
94c514fe2
|
354 355 |
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) {} |
bf7cd94dc
|
356 |
static inline void ieee80211s_stop(void) {} |
902acc789
|
357 |
#endif |
ccf80ddfe
|
358 |
#endif /* IEEE80211S_H */ |