Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : #include <linux/ieee80211.h> 3 : : #include <linux/export.h> 4 : : #include <net/cfg80211.h> 5 : : #include "nl80211.h" 6 : : #include "core.h" 7 : : #include "rdev-ops.h" 8 : : 9 : : /* Default values, timeouts in ms */ 10 : : #define MESH_TTL 31 11 : : #define MESH_DEFAULT_ELEMENT_TTL 31 12 : : #define MESH_MAX_RETR 3 13 : : #define MESH_RET_T 100 14 : : #define MESH_CONF_T 100 15 : : #define MESH_HOLD_T 100 16 : : 17 : : #define MESH_PATH_TIMEOUT 5000 18 : : #define MESH_RANN_INTERVAL 5000 19 : : #define MESH_PATH_TO_ROOT_TIMEOUT 6000 20 : : #define MESH_ROOT_INTERVAL 5000 21 : : #define MESH_ROOT_CONFIRMATION_INTERVAL 2000 22 : : #define MESH_DEFAULT_PLINK_TIMEOUT 1800 /* timeout in seconds */ 23 : : 24 : : /* 25 : : * Minimum interval between two consecutive PREQs originated by the same 26 : : * interface 27 : : */ 28 : : #define MESH_PREQ_MIN_INT 10 29 : : #define MESH_PERR_MIN_INT 100 30 : : #define MESH_DIAM_TRAVERSAL_TIME 50 31 : : 32 : : #define MESH_RSSI_THRESHOLD 0 33 : : 34 : : /* 35 : : * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds 36 : : * before timing out. This way it will remain ACTIVE and no data frames 37 : : * will be unnecessarily held in the pending queue. 38 : : */ 39 : : #define MESH_PATH_REFRESH_TIME 1000 40 : : #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) 41 : : 42 : : /* Default maximum number of established plinks per interface */ 43 : : #define MESH_MAX_ESTAB_PLINKS 32 44 : : 45 : : #define MESH_MAX_PREQ_RETRIES 4 46 : : 47 : : #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50 48 : : 49 : : #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units (=TUs) */ 50 : : #define MESH_DEFAULT_DTIM_PERIOD 2 51 : : #define MESH_DEFAULT_AWAKE_WINDOW 10 /* in 1024 us units (=TUs) */ 52 : : 53 : : const struct mesh_config default_mesh_config = { 54 : : .dot11MeshRetryTimeout = MESH_RET_T, 55 : : .dot11MeshConfirmTimeout = MESH_CONF_T, 56 : : .dot11MeshHoldingTimeout = MESH_HOLD_T, 57 : : .dot11MeshMaxRetries = MESH_MAX_RETR, 58 : : .dot11MeshTTL = MESH_TTL, 59 : : .element_ttl = MESH_DEFAULT_ELEMENT_TTL, 60 : : .auto_open_plinks = true, 61 : : .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS, 62 : : .dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX, 63 : : .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT, 64 : : .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT, 65 : : .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT, 66 : : .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME, 67 : : .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES, 68 : : .path_refresh_time = MESH_PATH_REFRESH_TIME, 69 : : .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, 70 : : .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, 71 : : .dot11MeshGateAnnouncementProtocol = false, 72 : : .dot11MeshForwarding = true, 73 : : .rssi_threshold = MESH_RSSI_THRESHOLD, 74 : : .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED, 75 : : .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT, 76 : : .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL, 77 : : .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, 78 : : .power_mode = NL80211_MESH_POWER_ACTIVE, 79 : : .dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW, 80 : : .plink_timeout = MESH_DEFAULT_PLINK_TIMEOUT, 81 : : }; 82 : : 83 : : const struct mesh_setup default_mesh_setup = { 84 : : /* cfg80211_join_mesh() will pick a channel if needed */ 85 : : .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, 86 : : .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, 87 : : .path_metric = IEEE80211_PATH_METRIC_AIRTIME, 88 : : .auth_id = 0, /* open */ 89 : : .ie = NULL, 90 : : .ie_len = 0, 91 : : .is_secure = false, 92 : : .user_mpm = false, 93 : : .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL, 94 : : .dtim_period = MESH_DEFAULT_DTIM_PERIOD, 95 : : }; 96 : : 97 : 0 : int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, 98 : : struct net_device *dev, 99 : : struct mesh_setup *setup, 100 : : const struct mesh_config *conf) 101 : : { 102 : 0 : struct wireless_dev *wdev = dev->ieee80211_ptr; 103 : : int err; 104 : : 105 : : BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); 106 : : 107 : : ASSERT_WDEV_LOCK(wdev); 108 : : 109 : 0 : if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) 110 : : return -EOPNOTSUPP; 111 : : 112 : 0 : if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) && 113 : 0 : setup->is_secure) 114 : : return -EOPNOTSUPP; 115 : : 116 : 0 : if (wdev->mesh_id_len) 117 : : return -EALREADY; 118 : : 119 : 0 : if (!setup->mesh_id_len) 120 : : return -EINVAL; 121 : : 122 : 0 : if (!rdev->ops->join_mesh) 123 : : return -EOPNOTSUPP; 124 : : 125 : 0 : if (!setup->chandef.chan) { 126 : : /* if no channel explicitly given, use preset channel */ 127 : 0 : setup->chandef = wdev->preset_chandef; 128 : : } 129 : : 130 : 0 : if (!setup->chandef.chan) { 131 : : /* if we don't have that either, use the first usable channel */ 132 : : enum nl80211_band band; 133 : : 134 : 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) { 135 : : struct ieee80211_supported_band *sband; 136 : : struct ieee80211_channel *chan; 137 : : int i; 138 : : 139 : 0 : sband = rdev->wiphy.bands[band]; 140 : 0 : if (!sband) 141 : 0 : continue; 142 : : 143 : 0 : for (i = 0; i < sband->n_channels; i++) { 144 : 0 : chan = &sband->channels[i]; 145 : 0 : if (chan->flags & (IEEE80211_CHAN_NO_IR | 146 : : IEEE80211_CHAN_DISABLED | 147 : : IEEE80211_CHAN_RADAR)) 148 : 0 : continue; 149 : 0 : setup->chandef.chan = chan; 150 : 0 : break; 151 : : } 152 : : 153 : 0 : if (setup->chandef.chan) 154 : : break; 155 : : } 156 : : 157 : : /* no usable channel ... */ 158 : 0 : if (!setup->chandef.chan) 159 : : return -EINVAL; 160 : : 161 : 0 : setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT; 162 : 0 : setup->chandef.center_freq1 = setup->chandef.chan->center_freq; 163 : : } 164 : : 165 : : /* 166 : : * check if basic rates are available otherwise use mandatory rates as 167 : : * basic rates 168 : : */ 169 : 0 : if (!setup->basic_rates) { 170 : : enum nl80211_bss_scan_width scan_width; 171 : 0 : struct ieee80211_supported_band *sband = 172 : 0 : rdev->wiphy.bands[setup->chandef.chan->band]; 173 : : 174 : 0 : if (setup->chandef.chan->band == NL80211_BAND_2GHZ) { 175 : : int i; 176 : : 177 : : /* 178 : : * Older versions selected the mandatory rates for 179 : : * 2.4 GHz as well, but were broken in that only 180 : : * 1 Mbps was regarded as a mandatory rate. Keep 181 : : * using just 1 Mbps as the default basic rate for 182 : : * mesh to be interoperable with older versions. 183 : : */ 184 : 0 : for (i = 0; i < sband->n_bitrates; i++) { 185 : 0 : if (sband->bitrates[i].bitrate == 10) { 186 : 0 : setup->basic_rates = BIT(i); 187 : 0 : break; 188 : : } 189 : : } 190 : : } else { 191 : : scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); 192 : 0 : setup->basic_rates = ieee80211_mandatory_rates(sband, 193 : : scan_width); 194 : : } 195 : : } 196 : : 197 : 0 : err = cfg80211_chandef_dfs_required(&rdev->wiphy, 198 : 0 : &setup->chandef, 199 : : NL80211_IFTYPE_MESH_POINT); 200 : 0 : if (err < 0) 201 : : return err; 202 : 0 : if (err > 0 && !setup->userspace_handles_dfs) 203 : : return -EINVAL; 204 : : 205 : 0 : if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef, 206 : : NL80211_IFTYPE_MESH_POINT)) 207 : : return -EINVAL; 208 : : 209 : 0 : err = rdev_join_mesh(rdev, dev, conf, setup); 210 : 0 : if (!err) { 211 : 0 : memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); 212 : 0 : wdev->mesh_id_len = setup->mesh_id_len; 213 : 0 : wdev->chandef = setup->chandef; 214 : 0 : wdev->beacon_interval = setup->beacon_interval; 215 : : } 216 : : 217 : 0 : return err; 218 : : } 219 : : 220 : 0 : int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, 221 : : struct wireless_dev *wdev, 222 : : struct cfg80211_chan_def *chandef) 223 : : { 224 : : int err; 225 : : 226 : : /* 227 : : * Workaround for libertas (only!), it puts the interface 228 : : * into mesh mode but doesn't implement join_mesh. Instead, 229 : : * it is configured via sysfs and then joins the mesh when 230 : : * you set the channel. Note that the libertas mesh isn't 231 : : * compatible with 802.11 mesh. 232 : : */ 233 : 0 : if (rdev->ops->libertas_set_mesh_channel) { 234 : 0 : if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) 235 : : return -EINVAL; 236 : : 237 : 0 : if (!netif_running(wdev->netdev)) 238 : : return -ENETDOWN; 239 : : 240 : 0 : err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, 241 : : chandef->chan); 242 : 0 : if (!err) 243 : 0 : wdev->chandef = *chandef; 244 : : 245 : 0 : return err; 246 : : } 247 : : 248 : 0 : if (wdev->mesh_id_len) 249 : : return -EBUSY; 250 : : 251 : 0 : wdev->preset_chandef = *chandef; 252 : 0 : return 0; 253 : : } 254 : : 255 : 0 : int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, 256 : : struct net_device *dev) 257 : : { 258 : 0 : struct wireless_dev *wdev = dev->ieee80211_ptr; 259 : : int err; 260 : : 261 : : ASSERT_WDEV_LOCK(wdev); 262 : : 263 : 0 : if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) 264 : : return -EOPNOTSUPP; 265 : : 266 : 0 : if (!rdev->ops->leave_mesh) 267 : : return -EOPNOTSUPP; 268 : : 269 : 0 : if (!wdev->mesh_id_len) 270 : : return -ENOTCONN; 271 : : 272 : 0 : err = rdev_leave_mesh(rdev, dev); 273 : 0 : if (!err) { 274 : 0 : wdev->conn_owner_nlportid = 0; 275 : 0 : wdev->mesh_id_len = 0; 276 : 0 : wdev->beacon_interval = 0; 277 : 0 : memset(&wdev->chandef, 0, sizeof(wdev->chandef)); 278 : 0 : rdev_set_qos_map(rdev, dev, NULL); 279 : 0 : cfg80211_sched_dfs_chan_update(rdev); 280 : : } 281 : : 282 : 0 : return err; 283 : : } 284 : : 285 : 0 : int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, 286 : : struct net_device *dev) 287 : : { 288 : 0 : struct wireless_dev *wdev = dev->ieee80211_ptr; 289 : : int err; 290 : : 291 : : wdev_lock(wdev); 292 : 0 : err = __cfg80211_leave_mesh(rdev, dev); 293 : : wdev_unlock(wdev); 294 : : 295 : 0 : return err; 296 : : }