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-04-27 09:19:18 +04:00
# include <asm/unaligned.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
2008-02-23 17:17:08 +03:00
* number
* @ MESH_PATH_FIXED : the mesh path has been manually set and should not be
* modified
* @ MESH_PATH_RESOLVED : the mesh path can has been resolved
*
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 ) ,
} ;
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
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 ,
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
* forwarded
* @ timer : mesh path discovery timer
* @ frame_queue : pending queue for frames sent to this destination while the
* 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
* retry
* @ discovery_retries : number of discovery retries
* @ flags : mesh path flags , as specified on & enum mesh_path_flags
2009-08-10 23:15:46 +04:00
* @ state_lock : mesh path state lock
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 ;
2008-02-23 17:17:08 +03:00
struct sta_info * next_hop ;
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 ;
} ;
/**
* 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
* @ copy_node : fuction to copy nodes of the table
* @ 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
*/
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 ;
} ;
/* 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 {
struct rmc_entry bucket [ RMC_BUCKETS ] ;
2008-04-23 23:15:29 +04:00
u32 idx_mask ;
2008-02-23 17:17:08 +03:00
} ;
/*
* MESH_CFG_COMP_LEN Includes :
* - Active path selection protocol ID .
* - Active path selection metric ID .
* - Congestion control mode identifier .
* - Channel precedence .
* Does not include mesh capabilities , which may vary across nodes in the same
* mesh
*/
2008-10-28 13:12:57 +03:00
# define MESH_CFG_CMP_LEN (IEEE80211_MESH_CONFIG_LEN - 2)
2008-02-23 17:17:08 +03:00
/* Default values, timeouts in ms */
2009-11-10 02:46:40 +03:00
# define MESH_TTL 31
2008-02-23 17:17:08 +03:00
# 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
/* Minimum interval between two consecutive PREQs originated by the same
* interface
*/
# define MESH_PREQ_MIN_INT 10
# define MESH_DIAM_TRAVERSAL_TIME 50
/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
* expiration
*/
# define MESH_PATH_REFRESH_TIME 1000
# define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
2009-08-10 23:15:51 +04:00
# define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
2008-02-23 17:17:08 +03:00
# define MESH_MAX_PREQ_RETRIES 4
# define MESH_PATH_EXPIRE (600 * HZ)
/* Default maximum number of established plinks per interface */
# define MESH_MAX_ESTAB_PLINKS 32
/* Default maximum number of plinks per interface */
# define MESH_MAX_PLINKS 256
/* Maximum number of paths per interface */
# define MESH_MAX_MPATHS 1024
/* Pending ANA approval */
2009-11-10 02:46:43 +03:00
# define MESH_PLINK_CATEGORY 30
2008-02-23 17:17:08 +03:00
# define MESH_PATH_SEL_CATEGORY 32
2009-11-10 02:46:44 +03:00
# define MESH_PATH_SEL_ACTION 0
2008-02-23 17:17:08 +03:00
2009-11-10 02:46:50 +03:00
/* PERR reason codes */
# define PEER_RCODE_UNSPECIFIED 11
# define PERR_RCODE_NO_ROUTE 12
# define PERR_RCODE_DEST_UNREACH 13
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 ,
char * da , char * sa ) ;
2008-02-23 17:17:08 +03:00
int ieee80211_new_mesh_header ( struct ieee80211s_hdr * meshhdr ,
2009-08-10 23:15:48 +04:00
struct ieee80211_sub_if_data * sdata , char * addr4 ,
char * addr5 , char * addr6 ) ;
2008-02-23 17:17:08 +03:00
int mesh_rmc_check ( u8 * addr , struct ieee80211s_hdr * mesh_hdr ,
2008-08-03 04:04:37 +04:00
struct ieee80211_sub_if_data * sdata ) ;
bool mesh_matches_local ( struct ieee802_11_elems * ie ,
struct ieee80211_sub_if_data * sdata ) ;
2008-09-11 02:01:49 +04:00
void mesh_ids_set_default ( struct ieee80211_if_mesh * mesh ) ;
2008-08-03 04:04:37 +04:00
void mesh_mgmt_ies_add ( struct sk_buff * skb ,
struct ieee80211_sub_if_data * sdata ) ;
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 ,
struct sta_info * stainfo , struct sk_buff * skb ) ;
2008-02-23 17:17:08 +03:00
void ieee80211s_stop ( void ) ;
2008-02-23 17:17:19 +03:00
void ieee80211_mesh_init_sdata ( struct ieee80211_sub_if_data * sdata ) ;
2008-09-11 02:01:49 +04:00
ieee80211_rx_result
2009-06-17 15:13:00 +04:00
ieee80211_mesh_rx_mgmt ( struct ieee80211_sub_if_data * sdata , struct sk_buff * skb ) ;
2008-09-11 02:01:49 +04:00
void ieee80211_start_mesh ( struct ieee80211_sub_if_data * sdata ) ;
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 ) ;
2008-02-23 17:17:19 +03:00
2008-02-23 17:17:08 +03:00
/* Mesh paths */
2008-08-03 04:04:37 +04:00
int mesh_nexthop_lookup ( struct sk_buff * skb ,
struct ieee80211_sub_if_data * sdata ) ;
void mesh_path_start_discovery ( struct ieee80211_sub_if_data * sdata ) ;
struct mesh_path * mesh_path_lookup ( u8 * dst ,
struct ieee80211_sub_if_data * sdata ) ;
2008-09-22 09:30:32 +04:00
struct mesh_path * mpp_path_lookup ( u8 * dst ,
struct ieee80211_sub_if_data * sdata ) ;
int mpp_path_add ( u8 * dst , u8 * mpp , struct ieee80211_sub_if_data * sdata ) ;
2008-08-03 04:04:37 +04:00
struct mesh_path * mesh_path_lookup_by_idx ( int idx ,
struct ieee80211_sub_if_data * sdata ) ;
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_path_flush ( struct ieee80211_sub_if_data * sdata ) ;
void mesh_rx_path_sel_frame ( struct ieee80211_sub_if_data * sdata ,
struct ieee80211_mgmt * mgmt , size_t len ) ;
int mesh_path_add ( u8 * dst , struct ieee80211_sub_if_data * sdata ) ;
2008-02-23 17:17:08 +03:00
/* Mesh plinks */
2009-01-21 17:13:48 +03:00
void mesh_neighbour_update ( u8 * hw_addr , u32 rates ,
2008-08-03 04:04:37 +04:00
struct ieee80211_sub_if_data * sdata , bool add ) ;
bool mesh_peer_accepts_plinks ( struct ieee802_11_elems * ie ) ;
2008-02-25 18:27:46 +03:00
void 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 ) ;
void mesh_plink_deactivate ( struct sta_info * sta ) ;
int mesh_plink_open ( struct sta_info * sta ) ;
void 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 ) ;
2008-02-23 17:17:08 +03:00
/* Private interfaces */
/* Mesh tables */
struct mesh_table * mesh_table_alloc ( int size_order ) ;
void mesh_table_free ( struct mesh_table * tbl , bool free_leafs ) ;
2009-08-10 23:15:52 +04:00
void mesh_mpath_table_grow ( void ) ;
void mesh_mpp_table_grow ( void ) ;
2008-08-03 04:04:37 +04:00
u32 mesh_table_hash ( u8 * addr , struct ieee80211_sub_if_data * sdata ,
struct mesh_table * tbl ) ;
2008-02-23 17:17:08 +03:00
/* Mesh paths */
2009-11-10 02:46:55 +03:00
int mesh_path_error_tx ( u8 ttl , u8 * target , __le32 target_sn , __le16 target_rcode ,
2009-11-10 02:46:50 +03:00
u8 * ra , struct ieee80211_sub_if_data * sdata ) ;
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 ) ;
2008-08-03 04:04:37 +04:00
int mesh_path_del ( u8 * addr , struct ieee80211_sub_if_data * sdata ) ;
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 ) ;
2008-08-03 04:04:37 +04:00
void mesh_path_discard_frame ( struct sk_buff * skb ,
struct ieee80211_sub_if_data * sdata ) ;
2009-05-17 13:40:42 +04:00
void mesh_path_quiesce ( struct ieee80211_sub_if_data * sdata ) ;
void mesh_path_restart ( struct ieee80211_sub_if_data * sdata ) ;
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
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
extern int mesh_allocated ;
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 -
atomic_read ( & sdata - > u . mesh . mshstats . 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 ;
}
# define for_each_mesh_entry(x, p, node, i) \
for ( i = 0 ; i < = x - > hash_mask ; i + + ) \
hlist_for_each_entry_rcu ( node , p , & x - > hash_buckets [ i ] , list )
2008-09-11 02:01:49 +04:00
void ieee80211_mesh_notify_scan_completed ( struct ieee80211_local * local ) ;
2009-05-17 13:40:42 +04:00
void ieee80211_mesh_quiesce ( struct ieee80211_sub_if_data * sdata ) ;
void ieee80211_mesh_restart ( struct ieee80211_sub_if_data * sdata ) ;
void mesh_plink_quiesce ( struct sta_info * sta ) ;
void mesh_plink_restart ( struct sta_info * sta ) ;
2008-02-23 17:17:19 +03:00
# else
# define mesh_allocated 0
2008-09-11 02:01:49 +04:00
static inline void
ieee80211_mesh_notify_scan_completed ( struct ieee80211_local * local ) { }
2009-05-17 13:40:42 +04:00
static inline void ieee80211_mesh_quiesce ( struct ieee80211_sub_if_data * sdata )
{ }
static inline void ieee80211_mesh_restart ( struct ieee80211_sub_if_data * sdata )
{ }
static inline void mesh_plink_quiesce ( struct sta_info * sta ) { }
static inline void mesh_plink_restart ( struct sta_info * sta ) { }
2008-02-23 17:17:19 +03:00
# endif
2008-02-23 17:17:08 +03:00
# endif /* IEEE80211S_H */