Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Portions
0004  * Copyright (C) 2022 Intel Corporation
0005  */
0006 #include <linux/ieee80211.h>
0007 #include <linux/export.h>
0008 #include <net/cfg80211.h>
0009 #include "nl80211.h"
0010 #include "core.h"
0011 #include "rdev-ops.h"
0012 
0013 /* Default values, timeouts in ms */
0014 #define MESH_TTL        31
0015 #define MESH_DEFAULT_ELEMENT_TTL 31
0016 #define MESH_MAX_RETR       3
0017 #define MESH_RET_T      100
0018 #define MESH_CONF_T         100
0019 #define MESH_HOLD_T         100
0020 
0021 #define MESH_PATH_TIMEOUT   5000
0022 #define MESH_RANN_INTERVAL      5000
0023 #define MESH_PATH_TO_ROOT_TIMEOUT      6000
0024 #define MESH_ROOT_INTERVAL     5000
0025 #define MESH_ROOT_CONFIRMATION_INTERVAL 2000
0026 #define MESH_DEFAULT_PLINK_TIMEOUT  1800 /* timeout in seconds */
0027 
0028 /*
0029  * Minimum interval between two consecutive PREQs originated by the same
0030  * interface
0031  */
0032 #define MESH_PREQ_MIN_INT   10
0033 #define MESH_PERR_MIN_INT   100
0034 #define MESH_DIAM_TRAVERSAL_TIME 50
0035 
0036 #define MESH_RSSI_THRESHOLD 0
0037 
0038 /*
0039  * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
0040  * before timing out.  This way it will remain ACTIVE and no data frames
0041  * will be unnecessarily held in the pending queue.
0042  */
0043 #define MESH_PATH_REFRESH_TIME          1000
0044 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
0045 
0046 /* Default maximum number of established plinks per interface */
0047 #define MESH_MAX_ESTAB_PLINKS   32
0048 
0049 #define MESH_MAX_PREQ_RETRIES   4
0050 
0051 #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50
0052 
0053 #define MESH_DEFAULT_BEACON_INTERVAL    1000    /* in 1024 us units (=TUs) */
0054 #define MESH_DEFAULT_DTIM_PERIOD    2
0055 #define MESH_DEFAULT_AWAKE_WINDOW   10  /* in 1024 us units (=TUs) */
0056 
0057 const struct mesh_config default_mesh_config = {
0058     .dot11MeshRetryTimeout = MESH_RET_T,
0059     .dot11MeshConfirmTimeout = MESH_CONF_T,
0060     .dot11MeshHoldingTimeout = MESH_HOLD_T,
0061     .dot11MeshMaxRetries = MESH_MAX_RETR,
0062     .dot11MeshTTL = MESH_TTL,
0063     .element_ttl = MESH_DEFAULT_ELEMENT_TTL,
0064     .auto_open_plinks = true,
0065     .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
0066     .dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX,
0067     .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
0068     .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
0069     .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT,
0070     .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
0071     .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
0072     .path_refresh_time = MESH_PATH_REFRESH_TIME,
0073     .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
0074     .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
0075     .dot11MeshGateAnnouncementProtocol = false,
0076     .dot11MeshForwarding = true,
0077     .rssi_threshold = MESH_RSSI_THRESHOLD,
0078     .ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED,
0079     .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
0080     .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
0081     .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
0082     .power_mode = NL80211_MESH_POWER_ACTIVE,
0083     .dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW,
0084     .plink_timeout = MESH_DEFAULT_PLINK_TIMEOUT,
0085     .dot11MeshNolearn = false,
0086 };
0087 
0088 const struct mesh_setup default_mesh_setup = {
0089     /* cfg80211_join_mesh() will pick a channel if needed */
0090     .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
0091     .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
0092     .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
0093     .auth_id = 0, /* open */
0094     .ie = NULL,
0095     .ie_len = 0,
0096     .is_secure = false,
0097     .user_mpm = false,
0098     .beacon_interval = MESH_DEFAULT_BEACON_INTERVAL,
0099     .dtim_period = MESH_DEFAULT_DTIM_PERIOD,
0100 };
0101 
0102 int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
0103              struct net_device *dev,
0104              struct mesh_setup *setup,
0105              const struct mesh_config *conf)
0106 {
0107     struct wireless_dev *wdev = dev->ieee80211_ptr;
0108     int err;
0109 
0110     BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
0111 
0112     ASSERT_WDEV_LOCK(wdev);
0113 
0114     if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
0115         return -EOPNOTSUPP;
0116 
0117     if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
0118           setup->is_secure)
0119         return -EOPNOTSUPP;
0120 
0121     if (wdev->u.mesh.id_len)
0122         return -EALREADY;
0123 
0124     if (!setup->mesh_id_len)
0125         return -EINVAL;
0126 
0127     if (!rdev->ops->join_mesh)
0128         return -EOPNOTSUPP;
0129 
0130     if (!setup->chandef.chan) {
0131         /* if no channel explicitly given, use preset channel */
0132         setup->chandef = wdev->u.mesh.preset_chandef;
0133     }
0134 
0135     if (!setup->chandef.chan) {
0136         /* if we don't have that either, use the first usable channel */
0137         enum nl80211_band band;
0138 
0139         for (band = 0; band < NUM_NL80211_BANDS; band++) {
0140             struct ieee80211_supported_band *sband;
0141             struct ieee80211_channel *chan;
0142             int i;
0143 
0144             sband = rdev->wiphy.bands[band];
0145             if (!sband)
0146                 continue;
0147 
0148             for (i = 0; i < sband->n_channels; i++) {
0149                 chan = &sband->channels[i];
0150                 if (chan->flags & (IEEE80211_CHAN_NO_IR |
0151                            IEEE80211_CHAN_DISABLED |
0152                            IEEE80211_CHAN_RADAR))
0153                     continue;
0154                 setup->chandef.chan = chan;
0155                 break;
0156             }
0157 
0158             if (setup->chandef.chan)
0159                 break;
0160         }
0161 
0162         /* no usable channel ... */
0163         if (!setup->chandef.chan)
0164             return -EINVAL;
0165 
0166         setup->chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
0167         setup->chandef.center_freq1 = setup->chandef.chan->center_freq;
0168     }
0169 
0170     /*
0171      * check if basic rates are available otherwise use mandatory rates as
0172      * basic rates
0173      */
0174     if (!setup->basic_rates) {
0175         enum nl80211_bss_scan_width scan_width;
0176         struct ieee80211_supported_band *sband =
0177                 rdev->wiphy.bands[setup->chandef.chan->band];
0178 
0179         if (setup->chandef.chan->band == NL80211_BAND_2GHZ) {
0180             int i;
0181 
0182             /*
0183              * Older versions selected the mandatory rates for
0184              * 2.4 GHz as well, but were broken in that only
0185              * 1 Mbps was regarded as a mandatory rate. Keep
0186              * using just 1 Mbps as the default basic rate for
0187              * mesh to be interoperable with older versions.
0188              */
0189             for (i = 0; i < sband->n_bitrates; i++) {
0190                 if (sband->bitrates[i].bitrate == 10) {
0191                     setup->basic_rates = BIT(i);
0192                     break;
0193                 }
0194             }
0195         } else {
0196             scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
0197             setup->basic_rates = ieee80211_mandatory_rates(sband,
0198                                        scan_width);
0199         }
0200     }
0201 
0202     err = cfg80211_chandef_dfs_required(&rdev->wiphy,
0203                         &setup->chandef,
0204                         NL80211_IFTYPE_MESH_POINT);
0205     if (err < 0)
0206         return err;
0207     if (err > 0 && !setup->userspace_handles_dfs)
0208         return -EINVAL;
0209 
0210     if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef,
0211                      NL80211_IFTYPE_MESH_POINT))
0212         return -EINVAL;
0213 
0214     err = rdev_join_mesh(rdev, dev, conf, setup);
0215     if (!err) {
0216         memcpy(wdev->u.mesh.id, setup->mesh_id, setup->mesh_id_len);
0217         wdev->u.mesh.id_len = setup->mesh_id_len;
0218         wdev->u.mesh.chandef = setup->chandef;
0219         wdev->u.mesh.beacon_interval = setup->beacon_interval;
0220     }
0221 
0222     return err;
0223 }
0224 
0225 int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
0226                   struct wireless_dev *wdev,
0227                   struct cfg80211_chan_def *chandef)
0228 {
0229     int err;
0230 
0231     /*
0232      * Workaround for libertas (only!), it puts the interface
0233      * into mesh mode but doesn't implement join_mesh. Instead,
0234      * it is configured via sysfs and then joins the mesh when
0235      * you set the channel. Note that the libertas mesh isn't
0236      * compatible with 802.11 mesh.
0237      */
0238     if (rdev->ops->libertas_set_mesh_channel) {
0239         if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
0240             return -EINVAL;
0241 
0242         if (!netif_running(wdev->netdev))
0243             return -ENETDOWN;
0244 
0245         err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
0246                              chandef->chan);
0247         if (!err)
0248             wdev->u.mesh.chandef = *chandef;
0249 
0250         return err;
0251     }
0252 
0253     if (wdev->u.mesh.id_len)
0254         return -EBUSY;
0255 
0256     wdev->u.mesh.preset_chandef = *chandef;
0257     return 0;
0258 }
0259 
0260 int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
0261               struct net_device *dev)
0262 {
0263     struct wireless_dev *wdev = dev->ieee80211_ptr;
0264     int err;
0265 
0266     ASSERT_WDEV_LOCK(wdev);
0267 
0268     if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
0269         return -EOPNOTSUPP;
0270 
0271     if (!rdev->ops->leave_mesh)
0272         return -EOPNOTSUPP;
0273 
0274     if (!wdev->u.mesh.id_len)
0275         return -ENOTCONN;
0276 
0277     err = rdev_leave_mesh(rdev, dev);
0278     if (!err) {
0279         wdev->conn_owner_nlportid = 0;
0280         wdev->u.mesh.id_len = 0;
0281         wdev->u.mesh.beacon_interval = 0;
0282         memset(&wdev->u.mesh.chandef, 0,
0283                sizeof(wdev->u.mesh.chandef));
0284         rdev_set_qos_map(rdev, dev, NULL);
0285         cfg80211_sched_dfs_chan_update(rdev);
0286     }
0287 
0288     return err;
0289 }
0290 
0291 int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
0292             struct net_device *dev)
0293 {
0294     struct wireless_dev *wdev = dev->ieee80211_ptr;
0295     int err;
0296 
0297     wdev_lock(wdev);
0298     err = __cfg80211_leave_mesh(rdev, dev);
0299     wdev_unlock(wdev);
0300 
0301     return err;
0302 }