2010-12-03 11:20:44 +03:00
# include <linux/ieee80211.h>
# include <net/cfg80211.h>
2011-04-08 02:08:34 +04:00
# include "nl80211.h"
2010-12-03 11:20:44 +03: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-10 03:45:10 +04:00
# define MESH_RANN_INTERVAL 5000
2010-12-03 11:20:44 +03:00
/*
* Minimum interval between two consecutive PREQs originated by the same
* interface
*/
# define MESH_PREQ_MIN_INT 10
# define MESH_DIAM_TRAVERSAL_TIME 50
/*
* 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
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 ,
. dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT ,
. dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT ,
. 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-10 03:45:10 +04:00
. dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL ,
2011-08-10 03:45:11 +04:00
. dot11MeshGateAnnouncementProtocol = false ,
2010-12-03 11:20:44 +03:00
} ;
2010-12-17 04:37:49 +03:00
const struct mesh_setup default_mesh_setup = {
. path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP ,
. path_metric = IEEE80211_PATH_METRIC_AIRTIME ,
2011-04-08 02:08:27 +04:00
. ie = NULL ,
. ie_len = 0 ,
2011-04-08 02:08:29 +04:00
. is_secure = false ,
2010-12-17 04:37:49 +03:00
} ;
2010-12-03 11:20:44 +03:00
int __cfg80211_join_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev ,
2010-12-17 04:37:49 +03:00
const struct mesh_setup * setup ,
2010-12-03 11:20:44 +03: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-08 02:08:28 +04:00
if ( ! ( rdev - > wiphy . flags & WIPHY_FLAG_MESH_AUTH ) & &
setup - > is_secure )
return - EOPNOTSUPP ;
2010-12-03 11:20:44 +03:00
if ( wdev - > mesh_id_len )
return - EALREADY ;
2010-12-17 04:37:49 +03:00
if ( ! setup - > mesh_id_len )
2010-12-03 11:20:44 +03:00
return - EINVAL ;
if ( ! rdev - > ops - > join_mesh )
return - EOPNOTSUPP ;
2010-12-17 04:37:49 +03:00
err = rdev - > ops - > join_mesh ( & rdev - > wiphy , dev , conf , setup ) ;
2010-12-03 11:20:44 +03:00
if ( ! err ) {
2010-12-17 04:37:49 +03:00
memcpy ( wdev - > ssid , setup - > mesh_id , setup - > mesh_id_len ) ;
wdev - > mesh_id_len = setup - > mesh_id_len ;
2010-12-03 11:20:44 +03:00
}
return err ;
}
int cfg80211_join_mesh ( struct cfg80211_registered_device * rdev ,
struct net_device * dev ,
2010-12-17 04:37:49 +03:00
const struct mesh_setup * setup ,
2010-12-03 11:20:44 +03:00
const struct mesh_config * conf )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
int err ;
wdev_lock ( wdev ) ;
2010-12-17 04:37:49 +03:00
err = __cfg80211_join_mesh ( rdev , dev , setup , conf ) ;
2010-12-03 11:20:44 +03:00
wdev_unlock ( wdev ) ;
return err ;
}
2011-04-08 02:08:34 +04: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 11:20:44 +03: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 ;
}