2008-02-23 17:17:08 +03:00
/*
2009-11-10 02:46:58 +03:00
* Copyright ( c ) 2008 , 2009 open80211s Ltd .
2008-02-23 17:17:08 +03:00
* Authors : Luis Carlos Cobo < luisca @ cozybit . com >
* Javier Cardona < javier @ cozybit . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# ifndef IEEE80211S_H
# define IEEE80211S_H
2008-02-23 17:17:19 +03:00
# include <linux/types.h>
2008-02-23 17:17:08 +03:00
# include <linux/jhash.h>
2008-02-23 17:17:19 +03:00
# include "ieee80211_i.h"
2008-02-23 17:17:08 +03:00
/* Data structures */
/**
* enum mesh_path_flags - mac80211 mesh path flags
*
*
*
2009-01-19 14:50:32 +03:00
* @ MESH_PATH_ACTIVE : the mesh path can be used for forwarding
* @ MESH_PATH_RESOLVING : the discovery process is running for this mesh path
2009-11-10 02:46:55 +03:00
* @ MESH_PATH_SN_VALID : the mesh path contains a valid destination sequence
2013-02-15 17:40:31 +04:00
* number
2008-02-23 17:17:08 +03:00
* @ MESH_PATH_FIXED : the mesh path has been manually set and should not be
2013-02-15 17:40:31 +04:00
* modified
2008-02-23 17:17:08 +03:00
* @ MESH_PATH_RESOLVED : the mesh path can has been resolved
2011-11-04 08:11:10 +04:00
* @ MESH_PATH_REQ_QUEUED : there is an unsent path request for this destination
2013-02-15 17:40:31 +04:00
* already queued up , waiting for the discovery process to start .
2008-02-23 17:17:08 +03:00
*
2009-01-19 14:50:32 +03:00
* MESH_PATH_RESOLVED is used by the mesh path timer to
2008-02-23 17:17:08 +03:00
* decide when to stop or cancel the mesh path discovery .
*/
enum mesh_path_flags {
MESH_PATH_ACTIVE = BIT ( 0 ) ,
MESH_PATH_RESOLVING = BIT ( 1 ) ,
2009-11-10 02:46:55 +03:00
MESH_PATH_SN_VALID = BIT ( 2 ) ,
2008-02-23 17:17:08 +03:00
MESH_PATH_FIXED = BIT ( 3 ) ,
MESH_PATH_RESOLVED = BIT ( 4 ) ,
2011-11-04 08:11:10 +04:00
MESH_PATH_REQ_QUEUED = BIT ( 5 ) ,
2008-02-23 17:17:08 +03:00
} ;
2009-08-10 23:15:52 +04:00
/**
* enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
*
*
*
* @ MESH_WORK_HOUSEKEEPING : run the periodic mesh housekeeping tasks
* @ MESH_WORK_GROW_MPATH_TABLE : the mesh path table is full and needs
* to grow .
* @ MESH_WORK_GROW_MPP_TABLE : the mesh portals table is full and needs to
* grow
2009-11-10 02:46:56 +03:00
* @ MESH_WORK_ROOT : the mesh root station needs to send a frame
2012-03-31 22:31:32 +04:00
* @ MESH_WORK_DRIFT_ADJUST : time to compensate for clock drift relative to other
* mesh nodes
2013-06-14 02:54:41 +04:00
* @ MESH_WORK_MBSS_CHANGED : rebuild beacon and notify driver of BSS changes
2009-08-10 23:15:52 +04:00
*/
enum mesh_deferred_task_flags {
MESH_WORK_HOUSEKEEPING ,
MESH_WORK_GROW_MPATH_TABLE ,
MESH_WORK_GROW_MPP_TABLE ,
2009-11-10 02:46:56 +03:00
MESH_WORK_ROOT ,
2012-03-31 22:31:32 +04:00
MESH_WORK_DRIFT_ADJUST ,
2013-06-14 02:54:41 +04:00
MESH_WORK_MBSS_CHANGED ,
2009-08-10 23:15:52 +04:00
} ;
2008-02-23 17:17:08 +03:00
/**
* struct mesh_path - mac80211 mesh path structure
*
* @ dst : mesh path destination mac address
2008-08-03 04:04:37 +04:00
* @ sdata : mesh subif
2008-02-23 17:17:08 +03:00
* @ next_hop : mesh neighbor to which frames for this destination will be
2013-02-15 17:40:31 +04:00
* forwarded
2008-02-23 17:17:08 +03:00
* @ timer : mesh path discovery timer
* @ frame_queue : pending queue for frames sent to this destination while the
2013-02-15 17:40:31 +04:00
* path is unresolved
2009-11-10 02:46:55 +03:00
* @ sn : target sequence number
2008-02-23 17:17:08 +03:00
* @ metric : current metric to this destination
* @ hop_count : hops to destination
* @ exp_time : in jiffies , when the path will expire or when it expired
* @ discovery_timeout : timeout ( lapse in jiffies ) used for the last discovery
2013-02-15 17:40:31 +04:00
* retry
2008-02-23 17:17:08 +03:00
* @ discovery_retries : number of discovery retries
* @ flags : mesh path flags , as specified on & enum mesh_path_flags
2011-08-30 00:23:05 +04:00
* @ state_lock : mesh path state lock used to protect changes to the
* mpath itself . No need to take this lock when adding or removing
* an mpath to a hash bucket on a path table .
2012-02-28 18:00:06 +04:00
* @ rann_snd_addr : the RANN sender address
2012-03-23 14:48:51 +04:00
* @ rann_metric : the aggregated path metric towards the root node
2012-06-13 22:06:10 +04:00
* @ last_preq_to_root : Timestamp of last PREQ sent to root
2012-02-28 18:00:06 +04:00
* @ is_root : the destination station of this path is a root node
2011-08-10 03:45:08 +04:00
* @ is_gate : the destination station of this path is a mesh gate
2008-02-23 17:17:08 +03:00
*
*
2008-08-03 04:04:37 +04:00
* The combination of dst and sdata is unique in the mesh path table . Since the
2008-02-25 18:27:46 +03:00
* next_hop STA is only protected by RCU as well , deleting the STA must also
* remove / substitute the mesh_path structure and wait until that is no longer
* reachable before destroying the STA completely .
2008-02-23 17:17:08 +03:00
*/
struct mesh_path {
u8 dst [ ETH_ALEN ] ;
2008-09-22 09:30:32 +04:00
u8 mpp [ ETH_ALEN ] ; /* used for MPP or MAP */
2008-08-03 04:04:37 +04:00
struct ieee80211_sub_if_data * sdata ;
2011-05-13 16:15:49 +04:00
struct sta_info __rcu * next_hop ;
2008-02-23 17:17:08 +03:00
struct timer_list timer ;
struct sk_buff_head frame_queue ;
struct rcu_head rcu ;
2009-11-10 02:46:55 +03:00
u32 sn ;
2008-02-23 17:17:08 +03:00
u32 metric ;
u8 hop_count ;
unsigned long exp_time ;
u32 discovery_timeout ;
u8 discovery_retries ;
enum mesh_path_flags flags ;
spinlock_t state_lock ;
2012-02-28 18:00:06 +04:00
u8 rann_snd_addr [ ETH_ALEN ] ;
2012-03-23 14:48:51 +04:00
u32 rann_metric ;
2012-06-13 22:06:10 +04:00
unsigned long last_preq_to_root ;
2012-02-28 18:00:06 +04:00
bool is_root ;
2011-08-10 03:45:08 +04:00
bool is_gate ;
2008-02-23 17:17:08 +03:00
} ;
/**
* struct mesh_table
*
* @ hash_buckets : array of hash buckets of the table
* @ hashwlock : array of locks to protect write operations , one per bucket
* @ hash_mask : 2 ^ size_order - 1 , used to compute hash idx
* @ hash_rnd : random value used for hash computations
* @ entries : number of entries in the table
* @ free_node : function to free nodes of the table
2010-08-06 23:11:15 +04:00
* @ copy_node : function to copy nodes of the table
2008-02-23 17:17:08 +03:00
* @ size_order : determines size of the table , there will be 2 ^ size_order hash
* buckets
* @ mean_chain_len : maximum average length for the hash buckets ' list , if it is
* reached , the table will grow
2011-08-10 03:45:08 +04:00
* @ known_gates : list of known mesh gates and their mpaths by the station . The
* gate ' s mpath may or may not be resolved and active .
*
2011-05-14 13:00:52 +04:00
* rcu_head : RCU head to free the table
2008-02-23 17:17:08 +03:00
*/
struct mesh_table {
/* Number of buckets will be 2^N */
struct hlist_head * hash_buckets ;
spinlock_t * hashwlock ; /* One per bucket, for add/del */
unsigned int hash_mask ; /* (2^size_order) - 1 */
__u32 hash_rnd ; /* Used for hash generation */
atomic_t entries ; /* Up to MAX_MESH_NEIGHBOURS */
void ( * free_node ) ( struct hlist_node * p , bool free_leafs ) ;
2008-05-07 19:47:01 +04:00
int ( * copy_node ) ( struct hlist_node * p , struct mesh_table * newtbl ) ;
2008-02-23 17:17:08 +03:00
int size_order ;
int mean_chain_len ;
2011-08-10 03:45:08 +04:00
struct hlist_head * known_gates ;
spinlock_t gates_lock ;
2011-05-14 13:00:52 +04:00
struct rcu_head rcu_head ;
2008-02-23 17:17:08 +03:00
} ;
/* Recent multicast cache */
/* RMC_BUCKETS must be a power of 2, maximum 256 */
# define RMC_BUCKETS 256
# define RMC_QUEUE_MAX_LEN 4
# define RMC_TIMEOUT (3 * HZ)
/**
* struct rmc_entry - entry in the Recent Multicast Cache
*
* @ seqnum : mesh sequence number of the frame
* @ exp_time : expiration time of the entry , in jiffies
* @ sa : source address of the frame
*
* The Recent Multicast Cache keeps track of the latest multicast frames that
* have been received by a mesh interface and discards received multicast frames
* that are found in the cache .
*/
struct rmc_entry {
struct list_head list ;
u32 seqnum ;
unsigned long exp_time ;
u8 sa [ ETH_ALEN ] ;
} ;
struct mesh_rmc {
2012-12-18 06:41:57 +04:00
struct list_head bucket [ RMC_BUCKETS ] ;
2008-04-23 23:15:29 +04:00
u32 idx_mask ;
2008-02-23 17:17:08 +03:00
} ;
2011-08-12 06:35:15 +04:00
# define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
2008-02-23 17:17:08 +03:00
# define MESH_PATH_EXPIRE (600 * HZ)
/* Default maximum number of plinks per interface */
# define MESH_MAX_PLINKS 256
/* Maximum number of paths per interface */
# define MESH_MAX_MPATHS 1024
2012-08-10 05:15:40 +04:00
/* Number of frames buffered per destination for unresolved destinations */
# define MESH_FRAME_QUEUE_LEN 10
2008-02-23 17:17:08 +03:00
/* Public interfaces */
/* Various */
2009-08-10 23:15:48 +04:00
int ieee80211_fill_mesh_addresses ( struct ieee80211_hdr * hdr , __le16 * fc ,
2009-11-17 15:34:04 +03:00
const u8 * da , const u8 * sa ) ;
2013-02-15 17:40:31 +04:00
int ieee80211_new_mesh_header ( struct ieee80211_sub_if_data * sdata ,
struct ieee80211s_hdr * meshhdr ,
const char * addr4or5 , const char * addr6 ) ;
int mesh_rmc_check ( struct ieee80211_sub_if_data * sdata ,
const u8 * addr , struct ieee80211s_hdr * mesh_hdr ) ;
2012-04-19 06:23:43 +04:00
bool mesh_matches_local ( struct ieee80211_sub_if_data * sdata ,
struct ieee802_11_elems * ie ) ;
2008-09-11 02:01:49 +04:00
void mesh_ids_set_default ( struct ieee80211_if_mesh * mesh ) ;
2013-02-15 17:40:31 +04:00
int mesh_add_meshconf_ie ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_add_meshid_ie ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_add_rsn_ie ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_add_vendor_ies ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_add_ht_cap_ie ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_add_ht_oper_ie ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
2008-08-03 04:04:37 +04:00
void mesh_rmc_free ( struct ieee80211_sub_if_data * sdata ) ;
int mesh_rmc_init ( struct ieee80211_sub_if_data * sdata ) ;
2008-02-23 17:17:08 +03:00
void ieee80211s_init ( void ) ;
2009-08-18 04:15:55 +04:00
void ieee80211s_update_metric ( struct ieee80211_local * local ,
2013-02-15 17:40:31 +04:00
struct sta_info * sta , struct sk_buff * skb ) ;
2008-02-23 17:17:19 +03:00
void ieee80211_mesh_init_sdata ( struct ieee80211_sub_if_data * sdata ) ;
2013-02-14 23:20:13 +04:00
int ieee80211_start_mesh ( struct ieee80211_sub_if_data * sdata ) ;
2008-09-11 02:01:49 +04:00
void ieee80211_stop_mesh ( struct ieee80211_sub_if_data * sdata ) ;
2009-11-10 02:46:57 +03:00
void ieee80211_mesh_root_setup ( struct ieee80211_if_mesh * ifmsh ) ;
2012-09-30 19:07:19 +04:00
const struct ieee80211_mesh_sync_ops * ieee80211_mesh_sync_ops_get ( u8 method ) ;
2013-02-14 23:20:13 +04:00
/* wrapper for ieee80211_bss_info_change_notify() */
void ieee80211_mbss_info_change_notify ( struct ieee80211_sub_if_data * sdata ,
u32 changed ) ;
2008-02-23 17:17:19 +03:00
2013-01-30 21:14:08 +04:00
/* mesh power save */
2013-02-14 00:14:19 +04:00
u32 ieee80211_mps_local_status_update ( struct ieee80211_sub_if_data * sdata ) ;
u32 ieee80211_mps_set_sta_local_pm ( struct sta_info * sta ,
enum nl80211_mesh_power_mode pm ) ;
2013-01-30 21:14:08 +04:00
void ieee80211_mps_set_frame_flags ( struct ieee80211_sub_if_data * sdata ,
struct sta_info * sta ,
struct ieee80211_hdr * hdr ) ;
void ieee80211_mps_sta_status_update ( struct sta_info * sta ) ;
void ieee80211_mps_rx_h_sta_process ( struct sta_info * sta ,
struct ieee80211_hdr * hdr ) ;
void ieee80211_mpsp_trigger_process ( u8 * qc , struct sta_info * sta ,
bool tx , bool acked ) ;
void ieee80211_mps_frame_release ( struct sta_info * sta ,
struct ieee802_11_elems * elems ) ;
2008-02-23 17:17:08 +03:00
/* Mesh paths */
2013-02-15 17:40:31 +04:00
int mesh_nexthop_lookup ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
int mesh_nexthop_resolve ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
2008-08-03 04:04:37 +04:00
void mesh_path_start_discovery ( struct ieee80211_sub_if_data * sdata ) ;
2013-02-15 17:40:31 +04:00
struct mesh_path * mesh_path_lookup ( struct ieee80211_sub_if_data * sdata ,
const u8 * dst ) ;
struct mesh_path * mpp_path_lookup ( struct ieee80211_sub_if_data * sdata ,
const u8 * dst ) ;
int mpp_path_add ( struct ieee80211_sub_if_data * sdata ,
const u8 * dst , const u8 * mpp ) ;
struct mesh_path *
mesh_path_lookup_by_idx ( struct ieee80211_sub_if_data * sdata , int idx ) ;
2008-02-23 17:17:08 +03:00
void mesh_path_fix_nexthop ( struct mesh_path * mpath , struct sta_info * next_hop ) ;
2008-08-03 04:04:37 +04:00
void mesh_path_expire ( struct ieee80211_sub_if_data * sdata ) ;
void mesh_rx_path_sel_frame ( struct ieee80211_sub_if_data * sdata ,
2013-02-15 17:40:31 +04:00
struct ieee80211_mgmt * mgmt , size_t len ) ;
2013-03-29 17:38:39 +04:00
struct mesh_path *
mesh_path_add ( struct ieee80211_sub_if_data * sdata , const u8 * dst ) ;
2011-08-10 03:45:08 +04:00
int mesh_path_add_gate ( struct mesh_path * mpath ) ;
int mesh_path_send_to_gates ( struct mesh_path * mpath ) ;
int mesh_gate_num ( struct ieee80211_sub_if_data * sdata ) ;
2013-02-15 17:40:31 +04:00
2008-02-23 17:17:08 +03:00
/* Mesh plinks */
2012-04-19 06:23:43 +04:00
void mesh_neighbour_update ( struct ieee80211_sub_if_data * sdata ,
2013-02-15 17:40:31 +04:00
u8 * hw_addr , struct ieee802_11_elems * ie ) ;
2008-08-03 04:04:37 +04:00
bool mesh_peer_accepts_plinks ( struct ieee802_11_elems * ie ) ;
2012-08-08 09:58:43 +04:00
u32 mesh_accept_plinks_update ( struct ieee80211_sub_if_data * sdata ) ;
2008-02-23 17:17:08 +03:00
void mesh_plink_broken ( struct sta_info * sta ) ;
2013-02-06 22:17:21 +04:00
u32 mesh_plink_deactivate ( struct sta_info * sta ) ;
2013-02-14 00:14:19 +04:00
u32 mesh_plink_open ( struct sta_info * sta ) ;
u32 mesh_plink_block ( struct sta_info * sta ) ;
2008-08-03 04:04:37 +04:00
void mesh_rx_plink_frame ( struct ieee80211_sub_if_data * sdata ,
struct ieee80211_mgmt * mgmt , size_t len ,
struct ieee80211_rx_status * rx_status ) ;
2013-02-06 22:17:21 +04:00
void mesh_sta_cleanup ( struct sta_info * sta ) ;
2008-02-23 17:17:08 +03:00
/* Private interfaces */
/* Mesh tables */
2009-08-10 23:15:52 +04:00
void mesh_mpath_table_grow ( void ) ;
void mesh_mpp_table_grow ( void ) ;
2008-02-23 17:17:08 +03:00
/* Mesh paths */
2013-02-15 17:40:31 +04:00
int mesh_path_error_tx ( struct ieee80211_sub_if_data * sdata ,
u8 ttl , const u8 * target , __le32 target_sn ,
__le16 target_rcode , const u8 * ra ) ;
2008-02-23 17:17:08 +03:00
void mesh_path_assign_nexthop ( struct mesh_path * mpath , struct sta_info * sta ) ;
void mesh_path_flush_pending ( struct mesh_path * mpath ) ;
void mesh_path_tx_pending ( struct mesh_path * mpath ) ;
int mesh_pathtbl_init ( void ) ;
void mesh_pathtbl_unregister ( void ) ;
2013-02-15 17:40:31 +04:00
int mesh_path_del ( struct ieee80211_sub_if_data * sdata , const u8 * addr ) ;
2008-02-23 17:17:08 +03:00
void mesh_path_timer ( unsigned long data ) ;
void mesh_path_flush_by_nexthop ( struct sta_info * sta ) ;
2013-02-15 17:40:31 +04:00
void mesh_path_discard_frame ( struct ieee80211_sub_if_data * sdata ,
struct sk_buff * skb ) ;
2009-11-10 02:46:56 +03:00
void mesh_path_tx_root_frame ( struct ieee80211_sub_if_data * sdata ) ;
2008-02-23 17:17:08 +03:00
2011-08-12 06:35:15 +04:00
bool mesh_action_is_path_sel ( struct ieee80211_mgmt * mgmt ) ;
2009-08-07 18:17:38 +04:00
extern int mesh_paths_generation ;
2008-02-23 17:17:19 +03:00
# ifdef CONFIG_MAC80211_MESH
2013-01-07 19:04:49 +04:00
static inline
u32 mesh_plink_inc_estab_count ( struct ieee80211_sub_if_data * sdata )
{
atomic_inc ( & sdata - > u . mesh . estab_plinks ) ;
2013-05-30 01:32:36 +04:00
return mesh_accept_plinks_update ( sdata ) | BSS_CHANGED_BEACON ;
2013-01-07 19:04:49 +04:00
}
static inline
u32 mesh_plink_dec_estab_count ( struct ieee80211_sub_if_data * sdata )
{
atomic_dec ( & sdata - > u . mesh . estab_plinks ) ;
2013-05-30 01:32:36 +04:00
return mesh_accept_plinks_update ( sdata ) | BSS_CHANGED_BEACON ;
2013-01-07 19:04:49 +04:00
}
2008-02-23 17:17:08 +03:00
static inline int mesh_plink_free_count ( struct ieee80211_sub_if_data * sdata )
{
2008-09-11 02:01:49 +04:00
return sdata - > u . mesh . mshcfg . dot11MeshMaxPeerLinks -
2012-10-10 00:27:47 +04:00
atomic_read ( & sdata - > u . mesh . estab_plinks ) ;
2008-02-23 17:17:08 +03:00
}
static inline bool mesh_plink_availables ( struct ieee80211_sub_if_data * sdata )
{
2008-02-25 18:27:46 +03:00
return ( min_t ( long , mesh_plink_free_count ( sdata ) ,
2008-02-23 17:17:08 +03:00
MESH_MAX_PLINKS - sdata - > local - > num_sta ) ) > 0 ;
}
static inline void mesh_path_activate ( struct mesh_path * mpath )
{
mpath - > flags | = MESH_PATH_ACTIVE | MESH_PATH_RESOLVED ;
}
2010-12-17 04:37:50 +03:00
static inline bool mesh_path_sel_is_hwmp ( struct ieee80211_sub_if_data * sdata )
{
return sdata - > u . mesh . mesh_pp_id = = IEEE80211_PATH_PROTOCOL_HWMP ;
}
2008-09-11 02:01:49 +04:00
void ieee80211_mesh_notify_scan_completed ( struct ieee80211_local * local ) ;
2012-04-24 15:18:28 +04:00
void mesh_path_flush_by_iface ( struct ieee80211_sub_if_data * sdata ) ;
2012-03-31 22:31:32 +04:00
void mesh_sync_adjust_tbtt ( struct ieee80211_sub_if_data * sdata ) ;
2013-02-15 17:40:31 +04:00
void ieee80211s_stop ( void ) ;
2008-02-23 17:17:19 +03:00
# else
2008-09-11 02:01:49 +04:00
static inline void
ieee80211_mesh_notify_scan_completed ( struct ieee80211_local * local ) { }
2010-12-17 04:37:50 +03:00
static inline bool mesh_path_sel_is_hwmp ( struct ieee80211_sub_if_data * sdata )
{ return false ; }
2012-04-24 15:18:28 +04:00
static inline void mesh_path_flush_by_iface ( struct ieee80211_sub_if_data * sdata )
{ }
2013-02-15 17:40:31 +04:00
static inline void ieee80211s_stop ( void ) { }
2008-02-23 17:17:19 +03:00
# endif
2008-02-23 17:17:08 +03:00
# endif /* IEEE80211S_H */