1 #include <linux/ieee80211.h>
2 #include <linux/export.h>
3 #include <net/cfg80211.h>
7 /* Default values, timeouts in ms */
9 #define MESH_DEFAULT_ELEMENT_TTL 31
10 #define MESH_MAX_RETR 3
11 #define MESH_RET_T 100
12 #define MESH_CONF_T 100
13 #define MESH_HOLD_T 100
15 #define MESH_PATH_TIMEOUT 5000
16 #define MESH_RANN_INTERVAL 5000
17 #define MESH_PATH_TO_ROOT_TIMEOUT 6000
18 #define MESH_ROOT_INTERVAL 5000
19 #define MESH_ROOT_CONFIRMATION_INTERVAL 2000
22 * Minimum interval between two consecutive PREQs originated by the same
25 #define MESH_PREQ_MIN_INT 10
26 #define MESH_PERR_MIN_INT 100
27 #define MESH_DIAM_TRAVERSAL_TIME 50
29 #define MESH_RSSI_THRESHOLD 0
32 * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
33 * before timing out. This way it will remain ACTIVE and no data frames
34 * will be unnecessarily held in the pending queue.
36 #define MESH_PATH_REFRESH_TIME 1000
37 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
39 /* Default maximum number of established plinks per interface */
40 #define MESH_MAX_ESTAB_PLINKS 32
42 #define MESH_MAX_PREQ_RETRIES 4
44 #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50
46 const struct mesh_config default_mesh_config
= {
47 .dot11MeshRetryTimeout
= MESH_RET_T
,
48 .dot11MeshConfirmTimeout
= MESH_CONF_T
,
49 .dot11MeshHoldingTimeout
= MESH_HOLD_T
,
50 .dot11MeshMaxRetries
= MESH_MAX_RETR
,
51 .dot11MeshTTL
= MESH_TTL
,
52 .element_ttl
= MESH_DEFAULT_ELEMENT_TTL
,
53 .auto_open_plinks
= true,
54 .dot11MeshMaxPeerLinks
= MESH_MAX_ESTAB_PLINKS
,
55 .dot11MeshNbrOffsetMaxNeighbor
= MESH_SYNC_NEIGHBOR_OFFSET_MAX
,
56 .dot11MeshHWMPactivePathTimeout
= MESH_PATH_TIMEOUT
,
57 .dot11MeshHWMPpreqMinInterval
= MESH_PREQ_MIN_INT
,
58 .dot11MeshHWMPperrMinInterval
= MESH_PERR_MIN_INT
,
59 .dot11MeshHWMPnetDiameterTraversalTime
= MESH_DIAM_TRAVERSAL_TIME
,
60 .dot11MeshHWMPmaxPREQretries
= MESH_MAX_PREQ_RETRIES
,
61 .path_refresh_time
= MESH_PATH_REFRESH_TIME
,
62 .min_discovery_timeout
= MESH_MIN_DISCOVERY_TIMEOUT
,
63 .dot11MeshHWMPRannInterval
= MESH_RANN_INTERVAL
,
64 .dot11MeshGateAnnouncementProtocol
= false,
65 .dot11MeshForwarding
= true,
66 .rssi_threshold
= MESH_RSSI_THRESHOLD
,
67 .ht_opmode
= IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED
,
68 .dot11MeshHWMPactivePathToRootTimeout
= MESH_PATH_TO_ROOT_TIMEOUT
,
69 .dot11MeshHWMProotInterval
= MESH_ROOT_INTERVAL
,
70 .dot11MeshHWMPconfirmationInterval
= MESH_ROOT_CONFIRMATION_INTERVAL
,
73 const struct mesh_setup default_mesh_setup
= {
74 /* cfg80211_join_mesh() will pick a channel if needed */
76 .channel_type
= NL80211_CHAN_NO_HT
,
77 .sync_method
= IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET
,
78 .path_sel_proto
= IEEE80211_PATH_PROTOCOL_HWMP
,
79 .path_metric
= IEEE80211_PATH_METRIC_AIRTIME
,
85 int __cfg80211_join_mesh(struct cfg80211_registered_device
*rdev
,
86 struct net_device
*dev
,
87 struct mesh_setup
*setup
,
88 const struct mesh_config
*conf
)
90 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
93 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN
!= IEEE80211_MAX_MESH_ID_LEN
);
95 ASSERT_WDEV_LOCK(wdev
);
97 if (dev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_MESH_POINT
)
100 if (!(rdev
->wiphy
.flags
& WIPHY_FLAG_MESH_AUTH
) &&
104 if (wdev
->mesh_id_len
)
107 if (!setup
->mesh_id_len
)
110 if (!rdev
->ops
->join_mesh
)
113 if (!setup
->channel
) {
114 /* if no channel explicitly given, use preset channel */
115 setup
->channel
= wdev
->preset_chan
;
116 setup
->channel_type
= wdev
->preset_chantype
;
119 if (!setup
->channel
) {
120 /* if we don't have that either, use the first usable channel */
121 enum ieee80211_band band
;
123 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
124 struct ieee80211_supported_band
*sband
;
125 struct ieee80211_channel
*chan
;
128 sband
= rdev
->wiphy
.bands
[band
];
132 for (i
= 0; i
< sband
->n_channels
; i
++) {
133 chan
= &sband
->channels
[i
];
134 if (chan
->flags
& (IEEE80211_CHAN_NO_IBSS
|
135 IEEE80211_CHAN_PASSIVE_SCAN
|
136 IEEE80211_CHAN_DISABLED
|
137 IEEE80211_CHAN_RADAR
))
139 setup
->channel
= chan
;
147 /* no usable channel ... */
151 setup
->channel_type
= NL80211_CHAN_NO_HT
;
154 if (!cfg80211_can_beacon_sec_chan(&rdev
->wiphy
, setup
->channel
,
155 setup
->channel_type
))
158 err
= cfg80211_can_use_chan(rdev
, wdev
, setup
->channel
,
163 err
= rdev
->ops
->join_mesh(&rdev
->wiphy
, dev
, conf
, setup
);
165 memcpy(wdev
->ssid
, setup
->mesh_id
, setup
->mesh_id_len
);
166 wdev
->mesh_id_len
= setup
->mesh_id_len
;
167 wdev
->channel
= setup
->channel
;
173 int cfg80211_join_mesh(struct cfg80211_registered_device
*rdev
,
174 struct net_device
*dev
,
175 struct mesh_setup
*setup
,
176 const struct mesh_config
*conf
)
178 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
181 mutex_lock(&rdev
->devlist_mtx
);
183 err
= __cfg80211_join_mesh(rdev
, dev
, setup
, conf
);
185 mutex_unlock(&rdev
->devlist_mtx
);
190 int cfg80211_set_mesh_freq(struct cfg80211_registered_device
*rdev
,
191 struct wireless_dev
*wdev
, int freq
,
192 enum nl80211_channel_type channel_type
)
194 struct ieee80211_channel
*channel
;
197 channel
= rdev_freq_to_chan(rdev
, freq
, channel_type
);
198 if (!channel
|| !cfg80211_can_beacon_sec_chan(&rdev
->wiphy
,
205 * Workaround for libertas (only!), it puts the interface
206 * into mesh mode but doesn't implement join_mesh. Instead,
207 * it is configured via sysfs and then joins the mesh when
208 * you set the channel. Note that the libertas mesh isn't
209 * compatible with 802.11 mesh.
211 if (rdev
->ops
->libertas_set_mesh_channel
) {
212 if (channel_type
!= NL80211_CHAN_NO_HT
)
215 if (!netif_running(wdev
->netdev
))
218 err
= cfg80211_can_use_chan(rdev
, wdev
, channel
,
223 err
= rdev
->ops
->libertas_set_mesh_channel(&rdev
->wiphy
,
227 wdev
->channel
= channel
;
232 if (wdev
->mesh_id_len
)
235 wdev
->preset_chan
= channel
;
236 wdev
->preset_chantype
= channel_type
;
240 void cfg80211_notify_new_peer_candidate(struct net_device
*dev
,
241 const u8
*macaddr
, const u8
* ie
, u8 ie_len
, gfp_t gfp
)
243 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
245 if (WARN_ON(wdev
->iftype
!= NL80211_IFTYPE_MESH_POINT
))
248 nl80211_send_new_peer_candidate(wiphy_to_dev(wdev
->wiphy
), dev
,
249 macaddr
, ie
, ie_len
, gfp
);
251 EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate
);
253 static int __cfg80211_leave_mesh(struct cfg80211_registered_device
*rdev
,
254 struct net_device
*dev
)
256 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
259 ASSERT_WDEV_LOCK(wdev
);
261 if (dev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_MESH_POINT
)
264 if (!rdev
->ops
->leave_mesh
)
267 if (!wdev
->mesh_id_len
)
270 err
= rdev
->ops
->leave_mesh(&rdev
->wiphy
, dev
);
272 wdev
->mesh_id_len
= 0;
273 wdev
->channel
= NULL
;
279 int cfg80211_leave_mesh(struct cfg80211_registered_device
*rdev
,
280 struct net_device
*dev
)
282 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
286 err
= __cfg80211_leave_mesh(rdev
, dev
);