root/net/wireless/mesh.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __cfg80211_join_mesh
  2. cfg80211_set_mesh_channel
  3. __cfg80211_leave_mesh
  4. cfg80211_leave_mesh

   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 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         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         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
 110                 return -EOPNOTSUPP;
 111 
 112         if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
 113               setup->is_secure)
 114                 return -EOPNOTSUPP;
 115 
 116         if (wdev->mesh_id_len)
 117                 return -EALREADY;
 118 
 119         if (!setup->mesh_id_len)
 120                 return -EINVAL;
 121 
 122         if (!rdev->ops->join_mesh)
 123                 return -EOPNOTSUPP;
 124 
 125         if (!setup->chandef.chan) {
 126                 /* if no channel explicitly given, use preset channel */
 127                 setup->chandef = wdev->preset_chandef;
 128         }
 129 
 130         if (!setup->chandef.chan) {
 131                 /* if we don't have that either, use the first usable channel */
 132                 enum nl80211_band band;
 133 
 134                 for (band = 0; band < NUM_NL80211_BANDS; band++) {
 135                         struct ieee80211_supported_band *sband;
 136                         struct ieee80211_channel *chan;
 137                         int i;
 138 
 139                         sband = rdev->wiphy.bands[band];
 140                         if (!sband)
 141                                 continue;
 142 
 143                         for (i = 0; i < sband->n_channels; i++) {
 144                                 chan = &sband->channels[i];
 145                                 if (chan->flags & (IEEE80211_CHAN_NO_IR |
 146                                                    IEEE80211_CHAN_DISABLED |
 147                                                    IEEE80211_CHAN_RADAR))
 148                                         continue;
 149                                 setup->chandef.chan = chan;
 150                                 break;
 151                         }
 152 
 153                         if (setup->chandef.chan)
 154                                 break;
 155                 }
 156 
 157                 /* no usable channel ... */
 158                 if (!setup->chandef.chan)
 159                         return -EINVAL;
 160 
 161                 setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
 162                 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         if (!setup->basic_rates) {
 170                 enum nl80211_bss_scan_width scan_width;
 171                 struct ieee80211_supported_band *sband =
 172                                 rdev->wiphy.bands[setup->chandef.chan->band];
 173 
 174                 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                         for (i = 0; i < sband->n_bitrates; i++) {
 185                                 if (sband->bitrates[i].bitrate == 10) {
 186                                         setup->basic_rates = BIT(i);
 187                                         break;
 188                                 }
 189                         }
 190                 } else {
 191                         scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
 192                         setup->basic_rates = ieee80211_mandatory_rates(sband,
 193                                                                        scan_width);
 194                 }
 195         }
 196 
 197         err = cfg80211_chandef_dfs_required(&rdev->wiphy,
 198                                             &setup->chandef,
 199                                             NL80211_IFTYPE_MESH_POINT);
 200         if (err < 0)
 201                 return err;
 202         if (err > 0 && !setup->userspace_handles_dfs)
 203                 return -EINVAL;
 204 
 205         if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef,
 206                                      NL80211_IFTYPE_MESH_POINT))
 207                 return -EINVAL;
 208 
 209         err = rdev_join_mesh(rdev, dev, conf, setup);
 210         if (!err) {
 211                 memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
 212                 wdev->mesh_id_len = setup->mesh_id_len;
 213                 wdev->chandef = setup->chandef;
 214                 wdev->beacon_interval = setup->beacon_interval;
 215         }
 216 
 217         return err;
 218 }
 219 
 220 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         if (rdev->ops->libertas_set_mesh_channel) {
 234                 if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
 235                         return -EINVAL;
 236 
 237                 if (!netif_running(wdev->netdev))
 238                         return -ENETDOWN;
 239 
 240                 err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
 241                                                      chandef->chan);
 242                 if (!err)
 243                         wdev->chandef = *chandef;
 244 
 245                 return err;
 246         }
 247 
 248         if (wdev->mesh_id_len)
 249                 return -EBUSY;
 250 
 251         wdev->preset_chandef = *chandef;
 252         return 0;
 253 }
 254 
 255 int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
 256                           struct net_device *dev)
 257 {
 258         struct wireless_dev *wdev = dev->ieee80211_ptr;
 259         int err;
 260 
 261         ASSERT_WDEV_LOCK(wdev);
 262 
 263         if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
 264                 return -EOPNOTSUPP;
 265 
 266         if (!rdev->ops->leave_mesh)
 267                 return -EOPNOTSUPP;
 268 
 269         if (!wdev->mesh_id_len)
 270                 return -ENOTCONN;
 271 
 272         err = rdev_leave_mesh(rdev, dev);
 273         if (!err) {
 274                 wdev->conn_owner_nlportid = 0;
 275                 wdev->mesh_id_len = 0;
 276                 wdev->beacon_interval = 0;
 277                 memset(&wdev->chandef, 0, sizeof(wdev->chandef));
 278                 rdev_set_qos_map(rdev, dev, NULL);
 279                 cfg80211_sched_dfs_chan_update(rdev);
 280         }
 281 
 282         return err;
 283 }
 284 
 285 int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
 286                         struct net_device *dev)
 287 {
 288         struct wireless_dev *wdev = dev->ieee80211_ptr;
 289         int err;
 290 
 291         wdev_lock(wdev);
 292         err = __cfg80211_leave_mesh(rdev, dev);
 293         wdev_unlock(wdev);
 294 
 295         return err;
 296 }

/* [<][>][^][v][top][bottom][index][help] */