/****************************************************************************** * * Copyright(c) 2007 - 2017 Realtek Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * *****************************************************************************/ #ifndef __RTW_MESH_PATHTBL_H_ #define __RTW_MESH_PATHTBL_H_ #ifndef DBG_RTW_MPATH #define DBG_RTW_MPATH 1 #endif #if DBG_RTW_MPATH #define RTW_MPATH_DBG(fmt, arg...) RTW_PRINT(fmt, ##arg) #else #define RTW_MPATH_DBG(fmt, arg...) do {} while (0) #endif /** * enum rtw_mesh_path_flags - mesh path flags * * @RTW_MESH_PATH_ACTIVE: the mesh path can be used for forwarding * @RTW_MESH_PATH_RESOLVING: the discovery process is running for this mesh path * @RTW_MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence * number * @RTW_MESH_PATH_FIXED: the mesh path has been manually set and should not be * modified * @RTW_MESH_PATH_RESOLVED: the mesh path can has been resolved * @RTW_MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination * already queued up, waiting for the discovery process to start. * @RTW_MESH_PATH_DELETED: the mesh path has been deleted and should no longer * be used * @RTW_MESH_PATH_ROOT_ADD_CHK: root additional check in root mode. * With this flag, It will try the last used rann_snd_addr * @RTW_MESH_PATH_PEER_AKA: only used toward a peer, only used in active keep * alive mechanism. PREQ's da = path dst * * RTW_MESH_PATH_RESOLVED is used by the mesh path timer to * decide when to stop or cancel the mesh path discovery. */ enum rtw_mesh_path_flags { RTW_MESH_PATH_ACTIVE = BIT(0), RTW_MESH_PATH_RESOLVING = BIT(1), RTW_MESH_PATH_SN_VALID = BIT(2), RTW_MESH_PATH_FIXED = BIT(3), RTW_MESH_PATH_RESOLVED = BIT(4), RTW_MESH_PATH_REQ_QUEUED = BIT(5), RTW_MESH_PATH_DELETED = BIT(6), RTW_MESH_PATH_ROOT_ADD_CHK = BIT(7), RTW_MESH_PATH_PEER_AKA = BIT(8), }; /** * struct rtw_mesh_path - mesh path structure * * @dst: mesh path destination mac address * @mpp: mesh proxy mac address * @rhash: rhashtable list pointer * @gate_list: list pointer for known gates list * @sdata: mesh subif * @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 * @rcu: rcu head for freeing mesh path * @sn: target sequence number * @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 rtw_mesh_path_flags * @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. * @rann_snd_addr: the RANN sender address * @rann_metric: the aggregated path metric towards the root node * @last_preq_to_root: Timestamp of last PREQ sent to root * @is_root: the destination station of this path is a root node * @is_gate: the destination station of this path is a mesh gate * * * The dst address is unique in the mesh path table. Since the mesh_path is * protected by RCU, deleting the next_hop STA must remove / substitute the * mesh_path structure and wait until that is no longer reachable before * destroying the STA completely. */ struct rtw_mesh_path { u8 dst[ETH_ALEN]; u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ rtw_rhash_head rhash; rtw_hlist_node gate_list; _adapter *adapter; struct sta_info __rcu *next_hop; _timer timer; _queue frame_queue; u32 frame_queue_len; rtw_rcu_head rcu; u32 sn; u32 metric; u8 hop_count; systime exp_time; systime discovery_timeout; systime gate_timeout; u32 gate_ann_int; /* gate announce interval */ u8 discovery_retries; enum rtw_mesh_path_flags flags; _lock state_lock; u8 rann_snd_addr[ETH_ALEN]; #ifdef CONFIG_RTW_MESH_ADD_ROOT_CHK u8 add_chk_rann_snd_addr[ETH_ALEN]; #endif u32 rann_metric; unsigned long last_preq_to_root; bool is_root; bool is_gate; bool gate_asked; }; /** * struct rtw_mesh_table * * @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. * @gates_lock: protects updates to known_gates * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr * @entries: number of entries in the table */ struct rtw_mesh_table { rtw_hlist_head known_gates; _lock gates_lock; rtw_rhashtable rhead; atomic_t entries; }; #define RTW_MESH_PATH_EXPIRE (600 * HZ) /* Maximum number of paths per interface */ #define RTW_MESH_MAX_MPATHS 1024 /* Number of frames buffered per destination for unresolved destinations */ #define RTW_MESH_FRAME_QUEUE_LEN 10 int rtw_mesh_nexthop_lookup(_adapter *adapter, const u8 *mda, const u8 *msa, u8 *ra); int rtw_mesh_nexthop_resolve(_adapter *adapter, struct xmit_frame *xframe); struct rtw_mesh_path *rtw_mesh_path_lookup(_adapter *adapter, const u8 *dst); struct rtw_mesh_path *rtw_mpp_path_lookup(_adapter *adapter, const u8 *dst); int rtw_mpp_path_add(_adapter *adapter, const u8 *dst, const u8 *mpp); void dump_mpp(void *sel, _adapter *adapter); struct rtw_mesh_path * rtw_mesh_path_lookup_by_idx(_adapter *adapter, int idx); struct rtw_mesh_path * rtw_mpp_path_lookup_by_idx(_adapter *adapter, int idx); void rtw_mesh_path_fix_nexthop(struct rtw_mesh_path *mpath, struct sta_info *next_hop); void rtw_mesh_path_expire(_adapter *adapter); struct rtw_mesh_path * rtw_mesh_path_add(_adapter *adapter, const u8 *dst); int rtw_mesh_path_add_gate(struct rtw_mesh_path *mpath); void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath); bool rtw_mesh_gate_search(struct rtw_mesh_table *tbl, const u8 *addr); int rtw_mesh_path_send_to_gates(struct rtw_mesh_path *mpath); int rtw_mesh_gate_num(_adapter *adapter); bool rtw_mesh_is_primary_gate(_adapter *adapter); void dump_known_gates(void *sel, _adapter *adapter); void rtw_mesh_plink_broken(struct sta_info *sta); void rtw_mesh_path_assign_nexthop(struct rtw_mesh_path *mpath, struct sta_info *sta); void rtw_mesh_path_flush_pending(struct rtw_mesh_path *mpath); void rtw_mesh_path_tx_pending(struct rtw_mesh_path *mpath); int rtw_mesh_pathtbl_init(_adapter *adapter); void rtw_mesh_pathtbl_unregister(_adapter *adapter); int rtw_mesh_path_del(_adapter *adapter, const u8 *addr); void rtw_mesh_path_flush_by_nexthop(struct sta_info *sta); void rtw_mesh_path_discard_frame(_adapter *adapter, struct xmit_frame *xframe); static inline void rtw_mesh_path_activate(struct rtw_mesh_path *mpath) { mpath->flags |= RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVED; } void rtw_mesh_path_flush_by_iface(_adapter *adapter); #endif /* __RTW_MESH_PATHTBL_H_ */