2010-12-03 09:20:44 +01:00
# include <linux/ieee80211.h>
2011-07-15 11:47:34 -04:00
# include <linux/export.h>
2010-12-03 09:20:44 +01:00
# include <net/cfg80211.h>
2011-04-07 15:08:34 -07:00
# include "nl80211.h"
2010-12-03 09:20:44 +01:00
# include "core.h"
/* Default values, timeouts in ms */
# define MESH_TTL 31
# define MESH_DEFAULT_ELEMENT_TTL 31
# define MESH_MAX_RETR 3
# define MESH_RET_T 100
# define MESH_CONF_T 100
# define MESH_HOLD_T 100
# define MESH_PATH_TIMEOUT 5000
2011-08-09 16:45:10 -07:00
# define MESH_RANN_INTERVAL 5000
2010-12-03 09:20:44 +01:00
/*
* Minimum interval between two consecutive PREQs originated by the same
* interface
*/
# define MESH_PREQ_MIN_INT 10
2011-11-24 17:15:24 -08:00
# define MESH_PERR_MIN_INT 100
2010-12-03 09:20:44 +01:00
# define MESH_DIAM_TRAVERSAL_TIME 50
2012-02-28 17:04:08 -08:00
# define MESH_RSSI_THRESHOLD 0
2010-12-03 09:20:44 +01:00
/*
* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
* before timing out . This way it will remain ACTIVE and no data frames
* will be unnecessarily held in the pending queue .
*/
# define MESH_PATH_REFRESH_TIME 1000
# define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
/* Default maximum number of established plinks per interface */
# define MESH_MAX_ESTAB_PLINKS 32
# define MESH_MAX_PREQ_RETRIES 4
2012-03-31 11:31:33 -07:00
# define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50
2010-12-03 09:20:44 +01:00
const struct mesh_config default_mesh_config = {
. dot11MeshRetryTimeout = MESH_RET_T ,
. dot11MeshConfirmTimeout = MESH_CONF_T ,
. dot11MeshHoldingTimeout = MESH_HOLD_T ,
. dot11MeshMaxRetries = MESH_MAX_RETR ,
. dot11MeshTTL = MESH_TTL ,
. element_ttl = MESH_DEFAULT_ELEMENT_TTL ,
. auto_open_plinks = true ,
. dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS ,
2012-03-31 11:31:33 -07:00
. dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX ,
2010-12-03 09:20:44 +01:00
. dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT ,
. dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT ,
2011-11-24 17:15:24 -08:00
. dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT ,
2010-12-03 09:20:44 +01:00
. dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME ,
. dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES ,
. path_refresh_time = MESH_PATH_REFRESH_TIME ,
. min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT ,
2011-08-09 16:45:10 -07:00
. dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL ,
2011-08-09 16:45:11 -07:00
. dot11MeshGateAnnouncementProtocol = false ,
2012-01-21 01:02:16 +08:00
. dot11MeshForwarding = true ,
2012-02-28 17:04:08 -08:00
. rssi_threshold = MESH_RSSI_THRESHOLD ,
2012-04-30 14:20:32 -07:00
. ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED ,
2010-12-03 09:20:44 +01:00
} ;
2010-12-16 17:37:49 -08:00
const struct mesh_setup default_mesh_setup = {
2012-03-31 11:31:33 -07:00
. sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET ,
2010-12-16 17:37:49 -08:00
. path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP ,
. path_metric = IEEE80211_PATH_METRIC_AIRTIME ,
2011-04-07 15:08:27 -07:00
. ie = NULL ,
. ie_len = 0 ,
2011-04-07 15:08:29 -07:00
. is_secure = false ,
2010-12-16 17:37:49 -08:00
} ;
2010-12-03 09:20:44 +01:00
int __cfg80211_join_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev ,
2010-12-16 17:37:49 -08:00
const struct mesh_setup * setup ,
2010-12-03 09:20:44 +01:00
const struct mesh_config * conf )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
int err ;
BUILD_BUG_ON ( IEEE80211_MAX_SSID_LEN ! = IEEE80211_MAX_MESH_ID_LEN ) ;
ASSERT_WDEV_LOCK ( wdev ) ;
if ( dev - > ieee80211_ptr - > iftype ! = NL80211_IFTYPE_MESH_POINT )
return - EOPNOTSUPP ;
2011-04-07 15:08:28 -07:00
if ( ! ( rdev - > wiphy . flags & WIPHY_FLAG_MESH_AUTH ) & &
setup - > is_secure )
return - EOPNOTSUPP ;
2010-12-03 09:20:44 +01:00
if ( wdev - > mesh_id_len )
return - EALREADY ;
2010-12-16 17:37:49 -08:00
if ( ! setup - > mesh_id_len )
2010-12-03 09:20:44 +01:00
return - EINVAL ;
if ( ! rdev - > ops - > join_mesh )
return - EOPNOTSUPP ;
2010-12-16 17:37:49 -08:00
err = rdev - > ops - > join_mesh ( & rdev - > wiphy , dev , conf , setup ) ;
2010-12-03 09:20:44 +01:00
if ( ! err ) {
2010-12-16 17:37:49 -08:00
memcpy ( wdev - > ssid , setup - > mesh_id , setup - > mesh_id_len ) ;
wdev - > mesh_id_len = setup - > mesh_id_len ;
2010-12-03 09:20:44 +01:00
}
return err ;
}
int cfg80211_join_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev ,
2010-12-16 17:37:49 -08:00
const struct mesh_setup * setup ,
2010-12-03 09:20:44 +01:00
const struct mesh_config * conf )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
int err ;
wdev_lock ( wdev ) ;
2010-12-16 17:37:49 -08:00
err = __cfg80211_join_mesh ( rdev , dev , setup , conf ) ;
2010-12-03 09:20:44 +01:00
wdev_unlock ( wdev ) ;
return err ;
}
2011-04-07 15:08:34 -07:00
void cfg80211_notify_new_peer_candidate ( struct net_device * dev ,
const u8 * macaddr , const u8 * ie , u8 ie_len , gfp_t gfp )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
if ( WARN_ON ( wdev - > iftype ! = NL80211_IFTYPE_MESH_POINT ) )
return ;
nl80211_send_new_peer_candidate ( wiphy_to_dev ( wdev - > wiphy ) , dev ,
macaddr , ie , ie_len , gfp ) ;
}
EXPORT_SYMBOL ( cfg80211_notify_new_peer_candidate ) ;
2010-12-03 09:20:44 +01:00
static int __cfg80211_leave_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
int err ;
ASSERT_WDEV_LOCK ( wdev ) ;
if ( dev - > ieee80211_ptr - > iftype ! = NL80211_IFTYPE_MESH_POINT )
return - EOPNOTSUPP ;
if ( ! rdev - > ops - > leave_mesh )
return - EOPNOTSUPP ;
if ( ! wdev - > mesh_id_len )
return - ENOTCONN ;
err = rdev - > ops - > leave_mesh ( & rdev - > wiphy , dev ) ;
if ( ! err )
wdev - > mesh_id_len = 0 ;
return err ;
}
int cfg80211_leave_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
int err ;
wdev_lock ( wdev ) ;
err = __cfg80211_leave_mesh ( rdev , dev ) ;
wdev_unlock ( wdev ) ;
return err ;
}