Merge branch 'batman-adv/next' of git://git.open-mesh.org/linux-merge
This commit is contained in:
commit
0e43182c0c
|
@ -22,6 +22,14 @@ Description:
|
||||||
mesh will be fragmented or silently discarded if the
|
mesh will be fragmented or silently discarded if the
|
||||||
packet size exceeds the outgoing interface MTU.
|
packet size exceeds the outgoing interface MTU.
|
||||||
|
|
||||||
|
What: /sys/class/net/<mesh_iface>/mesh/ap_isolation
|
||||||
|
Date: May 2011
|
||||||
|
Contact: Antonio Quartulli <ordex@autistici.org>
|
||||||
|
Description:
|
||||||
|
Indicates whether the data traffic going from a
|
||||||
|
wireless client to another wireless client will be
|
||||||
|
silently dropped.
|
||||||
|
|
||||||
What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
|
What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
|
||||||
Date: October 2010
|
Date: October 2010
|
||||||
Contact: Marek Lindner <lindner_marek@yahoo.de>
|
Contact: Marek Lindner <lindner_marek@yahoo.de>
|
||||||
|
|
|
@ -28,8 +28,7 @@
|
||||||
static inline int aggregated_packet(int buff_pos, int packet_len,
|
static inline int aggregated_packet(int buff_pos, int packet_len,
|
||||||
int tt_num_changes)
|
int tt_num_changes)
|
||||||
{
|
{
|
||||||
int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes *
|
int next_buff_pos = buff_pos + BAT_PACKET_LEN + tt_len(tt_num_changes);
|
||||||
sizeof(struct tt_change));
|
|
||||||
|
|
||||||
return (next_buff_pos <= packet_len) &&
|
return (next_buff_pos <= packet_len) &&
|
||||||
(next_buff_pos <= MAX_AGGREGATION_BYTES);
|
(next_buff_pos <= MAX_AGGREGATION_BYTES);
|
||||||
|
|
|
@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
|
||||||
BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
|
BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
|
||||||
BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
|
BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
|
||||||
BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
|
BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
|
||||||
|
BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
|
||||||
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
|
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
|
||||||
static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
|
static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
|
||||||
BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
|
BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
|
||||||
|
@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = {
|
||||||
&bat_attr_aggregated_ogms,
|
&bat_attr_aggregated_ogms,
|
||||||
&bat_attr_bonding,
|
&bat_attr_bonding,
|
||||||
&bat_attr_fragmentation,
|
&bat_attr_fragmentation,
|
||||||
|
&bat_attr_ap_isolation,
|
||||||
&bat_attr_vis_mode,
|
&bat_attr_vis_mode,
|
||||||
&bat_attr_gw_mode,
|
&bat_attr_gw_mode,
|
||||||
&bat_attr_orig_interval,
|
&bat_attr_orig_interval,
|
||||||
|
|
|
@ -97,12 +97,12 @@ static void bit_shift(unsigned long *seq_bits, int32_t n)
|
||||||
(seq_bits[i - word_num - 1] >>
|
(seq_bits[i - word_num - 1] >>
|
||||||
(WORD_BIT_SIZE-word_offset));
|
(WORD_BIT_SIZE-word_offset));
|
||||||
/* and the upper part of the right half and shift it left to
|
/* and the upper part of the right half and shift it left to
|
||||||
* it's position */
|
* its position */
|
||||||
/* for our example that would be: word[0] = 9800 + 0076 =
|
/* for our example that would be: word[0] = 9800 + 0076 =
|
||||||
* 9876 */
|
* 9876 */
|
||||||
}
|
}
|
||||||
/* now for our last word, i==word_num, we only have the it's "left"
|
/* now for our last word, i==word_num, we only have its "left" half.
|
||||||
* half. that's the 1000 word in our example.*/
|
* that's the 1000 word in our example.*/
|
||||||
|
|
||||||
seq_bits[i] = (seq_bits[i - word_num] << word_offset);
|
seq_bits[i] = (seq_bits[i - word_num] << word_offset);
|
||||||
|
|
||||||
|
|
|
@ -532,14 +532,14 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
|
||||||
pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
|
pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
|
||||||
|
|
||||||
/* Access the dhcp option lists. Each entry is made up by:
|
/* Access the dhcp option lists. Each entry is made up by:
|
||||||
* - octect 1: option type
|
* - octet 1: option type
|
||||||
* - octect 2: option data len (only if type != 255 and 0)
|
* - octet 2: option data len (only if type != 255 and 0)
|
||||||
* - octect 3: option data */
|
* - octet 3: option data */
|
||||||
while (*p != 255 && !ret) {
|
while (*p != 255 && !ret) {
|
||||||
/* p now points to the first octect: option type */
|
/* p now points to the first octet: option type */
|
||||||
if (*p == 53) {
|
if (*p == 53) {
|
||||||
/* type 53 is the message type option.
|
/* type 53 is the message type option.
|
||||||
* Jump the len octect and go to the data octect */
|
* Jump the len octet and go to the data octet */
|
||||||
if (pkt_len < 2)
|
if (pkt_len < 2)
|
||||||
goto out;
|
goto out;
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
|
@ -249,7 +249,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the first active interface becomes our primary interface or
|
* the first active interface becomes our primary interface or
|
||||||
* the next active interface after the old primay interface was removed
|
* the next active interface after the old primary interface was removed
|
||||||
*/
|
*/
|
||||||
primary_if = primary_if_get_selected(bat_priv);
|
primary_if = primary_if_get_selected(bat_priv);
|
||||||
if (!primary_if)
|
if (!primary_if)
|
||||||
|
@ -573,7 +573,7 @@ out:
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive a packet with the batman ethertype coming on a hard
|
/* incoming packets with the batman ethertype received on any active hard
|
||||||
* interface */
|
* interface */
|
||||||
static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
struct packet_type *ptype,
|
struct packet_type *ptype,
|
||||||
|
@ -681,6 +681,36 @@ err_out:
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function returns true if the interface represented by ifindex is a
|
||||||
|
* 802.11 wireless device */
|
||||||
|
bool is_wifi_iface(int ifindex)
|
||||||
|
{
|
||||||
|
struct net_device *net_device = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (ifindex == NULL_IFINDEX)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
net_device = dev_get_by_index(&init_net, ifindex);
|
||||||
|
if (!net_device)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WIRELESS_EXT
|
||||||
|
/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
|
||||||
|
* check for wireless_handlers != NULL */
|
||||||
|
if (net_device->wireless_handlers)
|
||||||
|
ret = true;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* cfg80211 drivers have to set ieee80211_ptr */
|
||||||
|
if (net_device->ieee80211_ptr)
|
||||||
|
ret = true;
|
||||||
|
out:
|
||||||
|
if (net_device)
|
||||||
|
dev_put(net_device);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct notifier_block hard_if_notifier = {
|
struct notifier_block hard_if_notifier = {
|
||||||
.notifier_call = hard_if_event,
|
.notifier_call = hard_if_event,
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,7 @@ void hardif_remove_interfaces(void);
|
||||||
int hardif_min_mtu(struct net_device *soft_iface);
|
int hardif_min_mtu(struct net_device *soft_iface);
|
||||||
void update_min_mtu(struct net_device *soft_iface);
|
void update_min_mtu(struct net_device *soft_iface);
|
||||||
void hardif_free_rcu(struct rcu_head *rcu);
|
void hardif_free_rcu(struct rcu_head *rcu);
|
||||||
|
bool is_wifi_iface(int ifindex);
|
||||||
|
|
||||||
static inline void hardif_free_ref(struct hard_iface *hard_iface)
|
static inline void hardif_free_ref(struct hard_iface *hard_iface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,19 +76,30 @@ static inline void hash_delete(struct hashtable_t *hash,
|
||||||
hash_destroy(hash);
|
hash_destroy(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adds data to the hashtable. returns 0 on success, -1 on error */
|
/**
|
||||||
|
* hash_add - adds data to the hashtable
|
||||||
|
* @hash: storage hash table
|
||||||
|
* @compare: callback to determine if 2 hash elements are identical
|
||||||
|
* @choose: callback calculating the hash index
|
||||||
|
* @data: data passed to the aforementioned callbacks as argument
|
||||||
|
* @data_node: to be added element
|
||||||
|
*
|
||||||
|
* Returns 0 on success, 1 if the element already is in the hash
|
||||||
|
* and -1 on error.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline int hash_add(struct hashtable_t *hash,
|
static inline int hash_add(struct hashtable_t *hash,
|
||||||
hashdata_compare_cb compare,
|
hashdata_compare_cb compare,
|
||||||
hashdata_choose_cb choose,
|
hashdata_choose_cb choose,
|
||||||
const void *data, struct hlist_node *data_node)
|
const void *data, struct hlist_node *data_node)
|
||||||
{
|
{
|
||||||
int index;
|
int index, ret = -1;
|
||||||
struct hlist_head *head;
|
struct hlist_head *head;
|
||||||
struct hlist_node *node;
|
struct hlist_node *node;
|
||||||
spinlock_t *list_lock; /* spinlock to protect write access */
|
spinlock_t *list_lock; /* spinlock to protect write access */
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
goto err;
|
goto out;
|
||||||
|
|
||||||
index = choose(data, hash->size);
|
index = choose(data, hash->size);
|
||||||
head = &hash->table[index];
|
head = &hash->table[index];
|
||||||
|
@ -99,6 +110,7 @@ static inline int hash_add(struct hashtable_t *hash,
|
||||||
if (!compare(node, data))
|
if (!compare(node, data))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
goto err_unlock;
|
goto err_unlock;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -108,12 +120,13 @@ static inline int hash_add(struct hashtable_t *hash,
|
||||||
hlist_add_head_rcu(data_node, head);
|
hlist_add_head_rcu(data_node, head);
|
||||||
spin_unlock_bh(list_lock);
|
spin_unlock_bh(list_lock);
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
|
||||||
err_unlock:
|
err_unlock:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
err:
|
out:
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* removes data from hash, if found. returns pointer do data on success, so you
|
/* removes data from hash, if found. returns pointer do data on success, so you
|
||||||
|
|
|
@ -107,7 +107,7 @@ int mesh_init(struct net_device *soft_iface)
|
||||||
if (tt_init(bat_priv) < 1)
|
if (tt_init(bat_priv) < 1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
tt_local_add(soft_iface, soft_iface->dev_addr);
|
tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
|
||||||
|
|
||||||
if (vis_init(bat_priv) < 1)
|
if (vis_init(bat_priv) < 1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
#define PURGE_TIMEOUT 200
|
#define PURGE_TIMEOUT 200
|
||||||
#define TT_LOCAL_TIMEOUT 3600 /* in seconds */
|
#define TT_LOCAL_TIMEOUT 3600 /* in seconds */
|
||||||
#define TT_CLIENT_ROAM_TIMEOUT 600
|
#define TT_CLIENT_ROAM_TIMEOUT 600
|
||||||
/* sliding packet range of received originator messages in squence numbers
|
/* sliding packet range of received originator messages in sequence numbers
|
||||||
* (should be a multiple of our word size) */
|
* (should be a multiple of our word size) */
|
||||||
#define TQ_LOCAL_WINDOW_SIZE 64
|
#define TQ_LOCAL_WINDOW_SIZE 64
|
||||||
#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
|
#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
|
||||||
|
@ -62,6 +62,8 @@
|
||||||
|
|
||||||
#define NO_FLAGS 0
|
#define NO_FLAGS 0
|
||||||
|
|
||||||
|
#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
|
||||||
|
|
||||||
#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
|
#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
|
||||||
|
|
||||||
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
||||||
|
@ -133,7 +135,7 @@ enum dbg_level {
|
||||||
#include <linux/mutex.h> /* mutex */
|
#include <linux/mutex.h> /* mutex */
|
||||||
#include <linux/module.h> /* needed by all modules */
|
#include <linux/module.h> /* needed by all modules */
|
||||||
#include <linux/netdevice.h> /* netdevice */
|
#include <linux/netdevice.h> /* netdevice */
|
||||||
#include <linux/etherdevice.h> /* ethernet address classifaction */
|
#include <linux/etherdevice.h> /* ethernet address classification */
|
||||||
#include <linux/if_ether.h> /* ethernet header */
|
#include <linux/if_ether.h> /* ethernet header */
|
||||||
#include <linux/poll.h> /* poll_table */
|
#include <linux/poll.h> /* poll_table */
|
||||||
#include <linux/kthread.h> /* kernel threads */
|
#include <linux/kthread.h> /* kernel threads */
|
||||||
|
|
|
@ -252,7 +252,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
|
||||||
|
|
||||||
hash_added = hash_add(bat_priv->orig_hash, compare_orig,
|
hash_added = hash_add(bat_priv->orig_hash, compare_orig,
|
||||||
choose_orig, orig_node, &orig_node->hash_entry);
|
choose_orig, orig_node, &orig_node->hash_entry);
|
||||||
if (hash_added < 0)
|
if (hash_added != 0)
|
||||||
goto free_bcast_own_sum;
|
goto free_bcast_own_sum;
|
||||||
|
|
||||||
return orig_node;
|
return orig_node;
|
||||||
|
|
|
@ -84,6 +84,7 @@ enum tt_query_flags {
|
||||||
enum tt_client_flags {
|
enum tt_client_flags {
|
||||||
TT_CLIENT_DEL = 1 << 0,
|
TT_CLIENT_DEL = 1 << 0,
|
||||||
TT_CLIENT_ROAM = 1 << 1,
|
TT_CLIENT_ROAM = 1 << 1,
|
||||||
|
TT_CLIENT_WIFI = 1 << 2,
|
||||||
TT_CLIENT_NOPURGE = 1 << 8,
|
TT_CLIENT_NOPURGE = 1 << 8,
|
||||||
TT_CLIENT_NEW = 1 << 9,
|
TT_CLIENT_NEW = 1 << 9,
|
||||||
TT_CLIENT_PENDING = 1 << 10
|
TT_CLIENT_PENDING = 1 << 10
|
||||||
|
|
|
@ -64,66 +64,6 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_transtable(struct bat_priv *bat_priv,
|
|
||||||
struct orig_node *orig_node,
|
|
||||||
const unsigned char *tt_buff,
|
|
||||||
uint8_t tt_num_changes, uint8_t ttvn,
|
|
||||||
uint16_t tt_crc)
|
|
||||||
{
|
|
||||||
uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
|
|
||||||
bool full_table = true;
|
|
||||||
|
|
||||||
/* the ttvn increased by one -> we can apply the attached changes */
|
|
||||||
if (ttvn - orig_ttvn == 1) {
|
|
||||||
/* the OGM could not contain the changes because they were too
|
|
||||||
* many to fit in one frame or because they have already been
|
|
||||||
* sent TT_OGM_APPEND_MAX times. In this case send a tt
|
|
||||||
* request */
|
|
||||||
if (!tt_num_changes) {
|
|
||||||
full_table = false;
|
|
||||||
goto request_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
|
|
||||||
(struct tt_change *)tt_buff);
|
|
||||||
|
|
||||||
/* Even if we received the crc into the OGM, we prefer
|
|
||||||
* to recompute it to spot any possible inconsistency
|
|
||||||
* in the global table */
|
|
||||||
orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
|
|
||||||
|
|
||||||
/* The ttvn alone is not enough to guarantee consistency
|
|
||||||
* because a single value could repesent different states
|
|
||||||
* (due to the wrap around). Thus a node has to check whether
|
|
||||||
* the resulting table (after applying the changes) is still
|
|
||||||
* consistent or not. E.g. a node could disconnect while its
|
|
||||||
* ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
|
|
||||||
* checking the CRC value is mandatory to detect the
|
|
||||||
* inconsistency */
|
|
||||||
if (orig_node->tt_crc != tt_crc)
|
|
||||||
goto request_table;
|
|
||||||
|
|
||||||
/* Roaming phase is over: tables are in sync again. I can
|
|
||||||
* unset the flag */
|
|
||||||
orig_node->tt_poss_change = false;
|
|
||||||
} else {
|
|
||||||
/* if we missed more than one change or our tables are not
|
|
||||||
* in sync anymore -> request fresh tt data */
|
|
||||||
if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
|
|
||||||
request_table:
|
|
||||||
bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
|
|
||||||
"Need to retrieve the correct information "
|
|
||||||
"(ttvn: %u last_ttvn: %u crc: %u last_crc: "
|
|
||||||
"%u num_changes: %u)\n", orig_node->orig, ttvn,
|
|
||||||
orig_ttvn, tt_crc, orig_node->tt_crc,
|
|
||||||
tt_num_changes);
|
|
||||||
send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
|
|
||||||
full_table);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void update_route(struct bat_priv *bat_priv,
|
static void update_route(struct bat_priv *bat_priv,
|
||||||
struct orig_node *orig_node,
|
struct orig_node *orig_node,
|
||||||
struct neigh_node *neigh_node)
|
struct neigh_node *neigh_node)
|
||||||
|
@ -228,7 +168,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
|
||||||
if (!neigh_node)
|
if (!neigh_node)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* if orig_node is direct neighbour update neigh_node last_valid */
|
/* if orig_node is direct neighbor update neigh_node last_valid */
|
||||||
if (orig_node == orig_neigh_node)
|
if (orig_node == orig_neigh_node)
|
||||||
neigh_node->last_valid = jiffies;
|
neigh_node->last_valid = jiffies;
|
||||||
|
|
||||||
|
@ -473,7 +413,7 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
if (router && (router->tq_avg > neigh_node->tq_avg))
|
if (router && (router->tq_avg > neigh_node->tq_avg))
|
||||||
goto update_tt;
|
goto update_tt;
|
||||||
|
|
||||||
/* if the TQ is the same and the link not more symetric we
|
/* if the TQ is the same and the link not more symmetric we
|
||||||
* won't consider it either */
|
* won't consider it either */
|
||||||
if (router && (neigh_node->tq_avg == router->tq_avg)) {
|
if (router && (neigh_node->tq_avg == router->tq_avg)) {
|
||||||
orig_node_tmp = router->orig_node;
|
orig_node_tmp = router->orig_node;
|
||||||
|
@ -500,10 +440,9 @@ update_tt:
|
||||||
if (((batman_packet->orig != ethhdr->h_source) &&
|
if (((batman_packet->orig != ethhdr->h_source) &&
|
||||||
(batman_packet->ttl > 2)) ||
|
(batman_packet->ttl > 2)) ||
|
||||||
(batman_packet->flags & PRIMARIES_FIRST_HOP))
|
(batman_packet->flags & PRIMARIES_FIRST_HOP))
|
||||||
update_transtable(bat_priv, orig_node, tt_buff,
|
tt_update_orig(bat_priv, orig_node, tt_buff,
|
||||||
batman_packet->tt_num_changes,
|
batman_packet->tt_num_changes,
|
||||||
batman_packet->ttvn,
|
batman_packet->ttvn, batman_packet->tt_crc);
|
||||||
batman_packet->tt_crc);
|
|
||||||
|
|
||||||
if (orig_node->gw_flags != batman_packet->gw_flags)
|
if (orig_node->gw_flags != batman_packet->gw_flags)
|
||||||
gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
|
gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
|
||||||
|
@ -1243,7 +1182,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TT_RESPONSE:
|
case TT_RESPONSE:
|
||||||
/* packet needs to be linearised to access the TT changes */
|
/* packet needs to be linearized to access the TT changes */
|
||||||
if (skb_linearize(skb) < 0)
|
if (skb_linearize(skb) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1300,7 +1239,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
|
||||||
roam_adv_packet->client);
|
roam_adv_packet->client);
|
||||||
|
|
||||||
tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
|
tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
|
||||||
atomic_read(&orig_node->last_ttvn) + 1, true);
|
atomic_read(&orig_node->last_ttvn) + 1, true, false);
|
||||||
|
|
||||||
/* Roaming phase starts: I have new information but the ttvn has not
|
/* Roaming phase starts: I have new information but the ttvn has not
|
||||||
* been incremented yet. This flag will make me check all the incoming
|
* been incremented yet. This flag will make me check all the incoming
|
||||||
|
@ -1536,7 +1475,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
|
||||||
|
|
||||||
ethhdr = (struct ethhdr *)(skb->data +
|
ethhdr = (struct ethhdr *)(skb->data +
|
||||||
sizeof(struct unicast_packet));
|
sizeof(struct unicast_packet));
|
||||||
orig_node = transtable_search(bat_priv, ethhdr->h_dest);
|
orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
|
||||||
|
|
||||||
if (!orig_node) {
|
if (!orig_node) {
|
||||||
if (!is_my_client(bat_priv, ethhdr->h_dest))
|
if (!is_my_client(bat_priv, ethhdr->h_dest))
|
||||||
|
|
|
@ -135,7 +135,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
|
||||||
"Forwarding"));
|
"Forwarding"));
|
||||||
bat_dbg(DBG_BATMAN, bat_priv,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
|
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
|
||||||
" IDF %s, hvn %d) on interface %s [%pM]\n",
|
" IDF %s, ttvn %d) on interface %s [%pM]\n",
|
||||||
fwd_str, (packet_num > 0 ? "aggregated " : ""),
|
fwd_str, (packet_num > 0 ? "aggregated " : ""),
|
||||||
batman_packet->orig, ntohl(batman_packet->seqno),
|
batman_packet->orig, ntohl(batman_packet->seqno),
|
||||||
batman_packet->tq, batman_packet->ttl,
|
batman_packet->tq, batman_packet->ttl,
|
||||||
|
@ -313,7 +313,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
|
||||||
prepare_packet_buffer(bat_priv, hard_iface);
|
prepare_packet_buffer(bat_priv, hard_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the changes have been sent enough times */
|
/* if the changes have been sent often enough */
|
||||||
if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
|
if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
|
||||||
reset_packet_buffer(bat_priv, hard_iface);
|
reset_packet_buffer(bat_priv, hard_iface);
|
||||||
}
|
}
|
||||||
|
@ -454,7 +454,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a broadcast packet to the queue and setup timers. broadcast packets
|
/* add a broadcast packet to the queue and setup timers. broadcast packets
|
||||||
* are sent multiple times to increase probability for beeing received.
|
* are sent multiple times to increase probability for being received.
|
||||||
*
|
*
|
||||||
* This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
|
* This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
|
||||||
* errors.
|
* errors.
|
||||||
|
@ -612,7 +612,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
|
||||||
&bat_priv->forw_bcast_list, list) {
|
&bat_priv->forw_bcast_list, list) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if purge_outstanding_packets() was called with an argmument
|
* if purge_outstanding_packets() was called with an argument
|
||||||
* we delete only packets belonging to the given interface
|
* we delete only packets belonging to the given interface
|
||||||
*/
|
*/
|
||||||
if ((hard_iface) &&
|
if ((hard_iface) &&
|
||||||
|
@ -641,7 +641,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
|
||||||
&bat_priv->forw_bat_list, list) {
|
&bat_priv->forw_bat_list, list) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if purge_outstanding_packets() was called with an argmument
|
* if purge_outstanding_packets() was called with an argument
|
||||||
* we delete only packets belonging to the given interface
|
* we delete only packets belonging to the given interface
|
||||||
*/
|
*/
|
||||||
if ((hard_iface) &&
|
if ((hard_iface) &&
|
||||||
|
|
|
@ -532,11 +532,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
|
||||||
if (!is_valid_ether_addr(addr->sa_data))
|
if (!is_valid_ether_addr(addr->sa_data))
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
|
|
||||||
/* only modify transtable if it has been initialised before */
|
/* only modify transtable if it has been initialized before */
|
||||||
if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
|
if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
|
||||||
tt_local_remove(bat_priv, dev->dev_addr,
|
tt_local_remove(bat_priv, dev->dev_addr,
|
||||||
"mac address changed", false);
|
"mac address changed", false);
|
||||||
tt_local_add(dev, addr->sa_data);
|
tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
|
||||||
|
@ -595,9 +595,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
|
||||||
goto dropped;
|
goto dropped;
|
||||||
|
|
||||||
/* Register the client MAC in the transtable */
|
/* Register the client MAC in the transtable */
|
||||||
tt_local_add(soft_iface, ethhdr->h_source);
|
tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
|
||||||
|
|
||||||
orig_node = transtable_search(bat_priv, ethhdr->h_dest);
|
orig_node = transtable_search(bat_priv, ethhdr->h_source,
|
||||||
|
ethhdr->h_dest);
|
||||||
if (is_multicast_ether_addr(ethhdr->h_dest) ||
|
if (is_multicast_ether_addr(ethhdr->h_dest) ||
|
||||||
(orig_node && orig_node->gw_flags)) {
|
(orig_node && orig_node->gw_flags)) {
|
||||||
ret = gw_is_target(bat_priv, skb, orig_node);
|
ret = gw_is_target(bat_priv, skb, orig_node);
|
||||||
|
@ -739,6 +740,9 @@ void interface_rx(struct net_device *soft_iface,
|
||||||
|
|
||||||
soft_iface->last_rx = jiffies;
|
soft_iface->last_rx = jiffies;
|
||||||
|
|
||||||
|
if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
|
||||||
|
goto dropped;
|
||||||
|
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -812,6 +816,7 @@ struct net_device *softif_create(const char *name)
|
||||||
|
|
||||||
atomic_set(&bat_priv->aggregated_ogms, 1);
|
atomic_set(&bat_priv->aggregated_ogms, 1);
|
||||||
atomic_set(&bat_priv->bonding, 0);
|
atomic_set(&bat_priv->bonding, 0);
|
||||||
|
atomic_set(&bat_priv->ap_isolation, 0);
|
||||||
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
|
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
|
||||||
atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
|
atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
|
||||||
atomic_set(&bat_priv->gw_sel_class, 20);
|
atomic_set(&bat_priv->gw_sel_class, 20);
|
||||||
|
|
|
@ -183,7 +183,8 @@ static int tt_local_init(struct bat_priv *bat_priv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
|
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
||||||
|
int ifindex)
|
||||||
{
|
{
|
||||||
struct bat_priv *bat_priv = netdev_priv(soft_iface);
|
struct bat_priv *bat_priv = netdev_priv(soft_iface);
|
||||||
struct tt_local_entry *tt_local_entry = NULL;
|
struct tt_local_entry *tt_local_entry = NULL;
|
||||||
|
@ -207,6 +208,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
|
||||||
memcpy(tt_local_entry->addr, addr, ETH_ALEN);
|
memcpy(tt_local_entry->addr, addr, ETH_ALEN);
|
||||||
tt_local_entry->last_seen = jiffies;
|
tt_local_entry->last_seen = jiffies;
|
||||||
tt_local_entry->flags = NO_FLAGS;
|
tt_local_entry->flags = NO_FLAGS;
|
||||||
|
if (is_wifi_iface(ifindex))
|
||||||
|
tt_local_entry->flags |= TT_CLIENT_WIFI;
|
||||||
atomic_set(&tt_local_entry->refcount, 2);
|
atomic_set(&tt_local_entry->refcount, 2);
|
||||||
|
|
||||||
/* the batman interface mac address should never be purged */
|
/* the batman interface mac address should never be purged */
|
||||||
|
@ -329,7 +332,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
__hlist_for_each_rcu(node, head)
|
__hlist_for_each_rcu(node, head)
|
||||||
buf_size += 21;
|
buf_size += 29;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,8 +351,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hlist_for_each_entry_rcu(tt_local_entry, node,
|
hlist_for_each_entry_rcu(tt_local_entry, node,
|
||||||
head, hash_entry) {
|
head, hash_entry) {
|
||||||
pos += snprintf(buff + pos, 22, " * %pM\n",
|
pos += snprintf(buff + pos, 30, " * %pM "
|
||||||
tt_local_entry->addr);
|
"[%c%c%c%c%c]\n",
|
||||||
|
tt_local_entry->addr,
|
||||||
|
(tt_local_entry->flags &
|
||||||
|
TT_CLIENT_ROAM ? 'R' : '.'),
|
||||||
|
(tt_local_entry->flags &
|
||||||
|
TT_CLIENT_NOPURGE ? 'P' : '.'),
|
||||||
|
(tt_local_entry->flags &
|
||||||
|
TT_CLIENT_NEW ? 'N' : '.'),
|
||||||
|
(tt_local_entry->flags &
|
||||||
|
TT_CLIENT_PENDING ? 'X' : '.'),
|
||||||
|
(tt_local_entry->flags &
|
||||||
|
TT_CLIENT_WIFI ? 'W' : '.'));
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
@ -369,8 +383,8 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
|
||||||
tt_local_event(bat_priv, tt_local_entry->addr,
|
tt_local_event(bat_priv, tt_local_entry->addr,
|
||||||
tt_local_entry->flags | flags);
|
tt_local_entry->flags | flags);
|
||||||
|
|
||||||
/* The local client has to be merked as "pending to be removed" but has
|
/* The local client has to be marked as "pending to be removed" but has
|
||||||
* to be kept in the table in order to send it in an full tables
|
* to be kept in the table in order to send it in a full table
|
||||||
* response issued before the net ttvn increment (consistency check) */
|
* response issued before the net ttvn increment (consistency check) */
|
||||||
tt_local_entry->flags |= TT_CLIENT_PENDING;
|
tt_local_entry->flags |= TT_CLIENT_PENDING;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +509,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
|
||||||
|
|
||||||
/* caller must hold orig_node refcount */
|
/* caller must hold orig_node refcount */
|
||||||
int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
const unsigned char *tt_addr, uint8_t ttvn, bool roaming)
|
const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
|
||||||
|
bool wifi)
|
||||||
{
|
{
|
||||||
struct tt_global_entry *tt_global_entry;
|
struct tt_global_entry *tt_global_entry;
|
||||||
struct orig_node *orig_node_tmp;
|
struct orig_node *orig_node_tmp;
|
||||||
|
@ -537,6 +552,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
tt_global_entry->roam_at = 0;
|
tt_global_entry->roam_at = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wifi)
|
||||||
|
tt_global_entry->flags |= TT_CLIENT_WIFI;
|
||||||
|
|
||||||
bat_dbg(DBG_TT, bat_priv,
|
bat_dbg(DBG_TT, bat_priv,
|
||||||
"Creating new global tt entry: %pM (via %pM)\n",
|
"Creating new global tt entry: %pM (via %pM)\n",
|
||||||
tt_global_entry->addr, orig_node->orig);
|
tt_global_entry->addr, orig_node->orig);
|
||||||
|
@ -582,8 +600,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
seq_printf(seq,
|
seq_printf(seq,
|
||||||
"Globally announced TT entries received via the mesh %s\n",
|
"Globally announced TT entries received via the mesh %s\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
seq_printf(seq, " %-13s %s %-15s %s\n",
|
seq_printf(seq, " %-13s %s %-15s %s %s\n",
|
||||||
"Client", "(TTVN)", "Originator", "(Curr TTVN)");
|
"Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
|
||||||
|
|
||||||
buf_size = 1;
|
buf_size = 1;
|
||||||
/* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
|
/* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
|
||||||
|
@ -593,7 +611,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
__hlist_for_each_rcu(node, head)
|
__hlist_for_each_rcu(node, head)
|
||||||
buf_size += 59;
|
buf_size += 67;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,14 +630,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hlist_for_each_entry_rcu(tt_global_entry, node,
|
hlist_for_each_entry_rcu(tt_global_entry, node,
|
||||||
head, hash_entry) {
|
head, hash_entry) {
|
||||||
pos += snprintf(buff + pos, 61,
|
pos += snprintf(buff + pos, 69,
|
||||||
" * %pM (%3u) via %pM (%3u)\n",
|
" * %pM (%3u) via %pM (%3u) "
|
||||||
tt_global_entry->addr,
|
"[%c%c%c]\n", tt_global_entry->addr,
|
||||||
tt_global_entry->ttvn,
|
tt_global_entry->ttvn,
|
||||||
tt_global_entry->orig_node->orig,
|
tt_global_entry->orig_node->orig,
|
||||||
(uint8_t) atomic_read(
|
(uint8_t) atomic_read(
|
||||||
&tt_global_entry->orig_node->
|
&tt_global_entry->orig_node->
|
||||||
last_ttvn));
|
last_ttvn),
|
||||||
|
(tt_global_entry->flags &
|
||||||
|
TT_CLIENT_ROAM ? 'R' : '.'),
|
||||||
|
(tt_global_entry->flags &
|
||||||
|
TT_CLIENT_PENDING ? 'X' : '.'),
|
||||||
|
(tt_global_entry->flags &
|
||||||
|
TT_CLIENT_WIFI ? 'W' : '.'));
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
@ -774,30 +798,56 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
|
||||||
bat_priv->tt_global_hash = NULL;
|
bat_priv->tt_global_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct orig_node *transtable_search(struct bat_priv *bat_priv,
|
static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
|
||||||
const uint8_t *addr)
|
struct tt_global_entry *tt_global_entry)
|
||||||
{
|
{
|
||||||
struct tt_global_entry *tt_global_entry;
|
bool ret = false;
|
||||||
|
|
||||||
|
if (tt_local_entry->flags & TT_CLIENT_WIFI &&
|
||||||
|
tt_global_entry->flags & TT_CLIENT_WIFI)
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct orig_node *transtable_search(struct bat_priv *bat_priv,
|
||||||
|
const uint8_t *src, const uint8_t *addr)
|
||||||
|
{
|
||||||
|
struct tt_local_entry *tt_local_entry = NULL;
|
||||||
|
struct tt_global_entry *tt_global_entry = NULL;
|
||||||
struct orig_node *orig_node = NULL;
|
struct orig_node *orig_node = NULL;
|
||||||
|
|
||||||
tt_global_entry = tt_global_hash_find(bat_priv, addr);
|
if (src && atomic_read(&bat_priv->ap_isolation)) {
|
||||||
|
tt_local_entry = tt_local_hash_find(bat_priv, src);
|
||||||
|
if (!tt_local_entry)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt_global_entry = tt_global_hash_find(bat_priv, addr);
|
||||||
if (!tt_global_entry)
|
if (!tt_global_entry)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* check whether the clients should not communicate due to AP
|
||||||
|
* isolation */
|
||||||
|
if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
|
if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
|
||||||
goto free_tt;
|
goto out;
|
||||||
|
|
||||||
/* A global client marked as PENDING has already moved from that
|
/* A global client marked as PENDING has already moved from that
|
||||||
* originator */
|
* originator */
|
||||||
if (tt_global_entry->flags & TT_CLIENT_PENDING)
|
if (tt_global_entry->flags & TT_CLIENT_PENDING)
|
||||||
goto free_tt;
|
goto out;
|
||||||
|
|
||||||
orig_node = tt_global_entry->orig_node;
|
orig_node = tt_global_entry->orig_node;
|
||||||
|
|
||||||
free_tt:
|
|
||||||
tt_global_entry_free_ref(tt_global_entry);
|
|
||||||
out:
|
out:
|
||||||
|
if (tt_global_entry)
|
||||||
|
tt_global_entry_free_ref(tt_global_entry);
|
||||||
|
if (tt_local_entry)
|
||||||
|
tt_local_entry_free_ref(tt_local_entry);
|
||||||
|
|
||||||
return orig_node;
|
return orig_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,8 +1079,9 @@ out:
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node,
|
static int send_tt_request(struct bat_priv *bat_priv,
|
||||||
uint8_t ttvn, uint16_t tt_crc, bool full_table)
|
struct orig_node *dst_orig_node,
|
||||||
|
uint8_t ttvn, uint16_t tt_crc, bool full_table)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
struct tt_query_packet *tt_request;
|
struct tt_query_packet *tt_request;
|
||||||
|
@ -1137,12 +1188,12 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
|
||||||
orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
|
orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
|
||||||
req_ttvn = tt_request->ttvn;
|
req_ttvn = tt_request->ttvn;
|
||||||
|
|
||||||
/* I have not the requested data */
|
/* I don't have the requested data */
|
||||||
if (orig_ttvn != req_ttvn ||
|
if (orig_ttvn != req_ttvn ||
|
||||||
tt_request->tt_data != req_dst_orig_node->tt_crc)
|
tt_request->tt_data != req_dst_orig_node->tt_crc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* If it has explicitly been requested the full table */
|
/* If the full table has been explicitly requested */
|
||||||
if (tt_request->flags & TT_FULL_TABLE ||
|
if (tt_request->flags & TT_FULL_TABLE ||
|
||||||
!req_dst_orig_node->tt_buff)
|
!req_dst_orig_node->tt_buff)
|
||||||
full_table = true;
|
full_table = true;
|
||||||
|
@ -1363,7 +1414,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv,
|
||||||
(tt_change + i)->flags & TT_CLIENT_ROAM);
|
(tt_change + i)->flags & TT_CLIENT_ROAM);
|
||||||
else
|
else
|
||||||
if (!tt_global_add(bat_priv, orig_node,
|
if (!tt_global_add(bat_priv, orig_node,
|
||||||
(tt_change + i)->addr, ttvn, false))
|
(tt_change + i)->addr, ttvn, false,
|
||||||
|
(tt_change + i)->flags &
|
||||||
|
TT_CLIENT_WIFI))
|
||||||
/* In case of problem while storing a
|
/* In case of problem while storing a
|
||||||
* global_entry, we stop the updating
|
* global_entry, we stop the updating
|
||||||
* procedure without committing the
|
* procedure without committing the
|
||||||
|
@ -1403,9 +1456,10 @@ out:
|
||||||
orig_node_free_ref(orig_node);
|
orig_node_free_ref(orig_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
static void tt_update_changes(struct bat_priv *bat_priv,
|
||||||
uint16_t tt_num_changes, uint8_t ttvn,
|
struct orig_node *orig_node,
|
||||||
struct tt_change *tt_change)
|
uint16_t tt_num_changes, uint8_t ttvn,
|
||||||
|
struct tt_change *tt_change)
|
||||||
{
|
{
|
||||||
_tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
|
_tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
|
||||||
ttvn);
|
ttvn);
|
||||||
|
@ -1720,3 +1774,90 @@ void tt_commit_changes(struct bat_priv *bat_priv)
|
||||||
atomic_inc(&bat_priv->ttvn);
|
atomic_inc(&bat_priv->ttvn);
|
||||||
bat_priv->tt_poss_change = false;
|
bat_priv->tt_poss_change = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
|
||||||
|
{
|
||||||
|
struct tt_local_entry *tt_local_entry = NULL;
|
||||||
|
struct tt_global_entry *tt_global_entry = NULL;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
if (!atomic_read(&bat_priv->ap_isolation))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tt_local_entry = tt_local_hash_find(bat_priv, dst);
|
||||||
|
if (!tt_local_entry)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
tt_global_entry = tt_global_hash_find(bat_priv, src);
|
||||||
|
if (!tt_global_entry)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (_is_ap_isolated(tt_local_entry, tt_global_entry))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = false;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (tt_global_entry)
|
||||||
|
tt_global_entry_free_ref(tt_global_entry);
|
||||||
|
if (tt_local_entry)
|
||||||
|
tt_local_entry_free_ref(tt_local_entry);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
|
const unsigned char *tt_buff, uint8_t tt_num_changes,
|
||||||
|
uint8_t ttvn, uint16_t tt_crc)
|
||||||
|
{
|
||||||
|
uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
|
||||||
|
bool full_table = true;
|
||||||
|
|
||||||
|
/* the ttvn increased by one -> we can apply the attached changes */
|
||||||
|
if (ttvn - orig_ttvn == 1) {
|
||||||
|
/* the OGM could not contain the changes due to their size or
|
||||||
|
* because they have already been sent TT_OGM_APPEND_MAX times.
|
||||||
|
* In this case send a tt request */
|
||||||
|
if (!tt_num_changes) {
|
||||||
|
full_table = false;
|
||||||
|
goto request_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
|
||||||
|
(struct tt_change *)tt_buff);
|
||||||
|
|
||||||
|
/* Even if we received the precomputed crc with the OGM, we
|
||||||
|
* prefer to recompute it to spot any possible inconsistency
|
||||||
|
* in the global table */
|
||||||
|
orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
|
||||||
|
|
||||||
|
/* The ttvn alone is not enough to guarantee consistency
|
||||||
|
* because a single value could represent different states
|
||||||
|
* (due to the wrap around). Thus a node has to check whether
|
||||||
|
* the resulting table (after applying the changes) is still
|
||||||
|
* consistent or not. E.g. a node could disconnect while its
|
||||||
|
* ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
|
||||||
|
* checking the CRC value is mandatory to detect the
|
||||||
|
* inconsistency */
|
||||||
|
if (orig_node->tt_crc != tt_crc)
|
||||||
|
goto request_table;
|
||||||
|
|
||||||
|
/* Roaming phase is over: tables are in sync again. I can
|
||||||
|
* unset the flag */
|
||||||
|
orig_node->tt_poss_change = false;
|
||||||
|
} else {
|
||||||
|
/* if we missed more than one change or our tables are not
|
||||||
|
* in sync anymore -> request fresh tt data */
|
||||||
|
if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
|
||||||
|
request_table:
|
||||||
|
bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
|
||||||
|
"Need to retrieve the correct information "
|
||||||
|
"(ttvn: %u last_ttvn: %u crc: %u last_crc: "
|
||||||
|
"%u num_changes: %u)\n", orig_node->orig, ttvn,
|
||||||
|
orig_ttvn, tt_crc, orig_node->tt_crc,
|
||||||
|
tt_num_changes);
|
||||||
|
send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
|
||||||
|
full_table);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,15 +26,16 @@ int tt_len(int changes_num);
|
||||||
int tt_changes_fill_buffer(struct bat_priv *bat_priv,
|
int tt_changes_fill_buffer(struct bat_priv *bat_priv,
|
||||||
unsigned char *buff, int buff_len);
|
unsigned char *buff, int buff_len);
|
||||||
int tt_init(struct bat_priv *bat_priv);
|
int tt_init(struct bat_priv *bat_priv);
|
||||||
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr);
|
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
||||||
|
int ifindex);
|
||||||
void tt_local_remove(struct bat_priv *bat_priv,
|
void tt_local_remove(struct bat_priv *bat_priv,
|
||||||
const uint8_t *addr, const char *message, bool roaming);
|
const uint8_t *addr, const char *message, bool roaming);
|
||||||
int tt_local_seq_print_text(struct seq_file *seq, void *offset);
|
int tt_local_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
const unsigned char *tt_buff, int tt_buff_len);
|
const unsigned char *tt_buff, int tt_buff_len);
|
||||||
int tt_global_add(struct bat_priv *bat_priv,
|
int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
struct orig_node *orig_node, const unsigned char *addr,
|
const unsigned char *addr, uint8_t ttvn, bool roaming,
|
||||||
uint8_t ttvn, bool roaming);
|
bool wifi);
|
||||||
int tt_global_seq_print_text(struct seq_file *seq, void *offset);
|
int tt_global_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
void tt_global_del_orig(struct bat_priv *bat_priv,
|
void tt_global_del_orig(struct bat_priv *bat_priv,
|
||||||
struct orig_node *orig_node, const char *message);
|
struct orig_node *orig_node, const char *message);
|
||||||
|
@ -42,25 +43,23 @@ void tt_global_del(struct bat_priv *bat_priv,
|
||||||
struct orig_node *orig_node, const unsigned char *addr,
|
struct orig_node *orig_node, const unsigned char *addr,
|
||||||
const char *message, bool roaming);
|
const char *message, bool roaming);
|
||||||
struct orig_node *transtable_search(struct bat_priv *bat_priv,
|
struct orig_node *transtable_search(struct bat_priv *bat_priv,
|
||||||
const uint8_t *addr);
|
const uint8_t *src, const uint8_t *addr);
|
||||||
void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
const unsigned char *tt_buff, uint8_t tt_num_changes);
|
const unsigned char *tt_buff, uint8_t tt_num_changes);
|
||||||
uint16_t tt_local_crc(struct bat_priv *bat_priv);
|
uint16_t tt_local_crc(struct bat_priv *bat_priv);
|
||||||
uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
|
uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
|
||||||
void tt_free(struct bat_priv *bat_priv);
|
void tt_free(struct bat_priv *bat_priv);
|
||||||
int send_tt_request(struct bat_priv *bat_priv,
|
|
||||||
struct orig_node *dst_orig_node, uint8_t hvn,
|
|
||||||
uint16_t tt_crc, bool full_table);
|
|
||||||
bool send_tt_response(struct bat_priv *bat_priv,
|
bool send_tt_response(struct bat_priv *bat_priv,
|
||||||
struct tt_query_packet *tt_request);
|
struct tt_query_packet *tt_request);
|
||||||
void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
|
||||||
uint16_t tt_num_changes, uint8_t ttvn,
|
|
||||||
struct tt_change *tt_change);
|
|
||||||
bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
|
bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
|
||||||
void handle_tt_response(struct bat_priv *bat_priv,
|
void handle_tt_response(struct bat_priv *bat_priv,
|
||||||
struct tt_query_packet *tt_response);
|
struct tt_query_packet *tt_response);
|
||||||
void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
|
void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
|
||||||
struct orig_node *orig_node);
|
struct orig_node *orig_node);
|
||||||
void tt_commit_changes(struct bat_priv *bat_priv);
|
void tt_commit_changes(struct bat_priv *bat_priv);
|
||||||
|
bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
|
||||||
|
void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
|
||||||
|
const unsigned char *tt_buff, uint8_t tt_num_changes,
|
||||||
|
uint8_t ttvn, uint16_t tt_crc);
|
||||||
|
|
||||||
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
|
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct hard_iface {
|
||||||
* @batman_seqno_reset: time when the batman seqno window was reset
|
* @batman_seqno_reset: time when the batman seqno window was reset
|
||||||
* @gw_flags: flags related to gateway class
|
* @gw_flags: flags related to gateway class
|
||||||
* @flags: for now only VIS_SERVER flag
|
* @flags: for now only VIS_SERVER flag
|
||||||
* @last_real_seqno: last and best known squence number
|
* @last_real_seqno: last and best known sequence number
|
||||||
* @last_ttl: ttl of last received packet
|
* @last_ttl: ttl of last received packet
|
||||||
* @last_bcast_seqno: last broadcast sequence number received by this host
|
* @last_bcast_seqno: last broadcast sequence number received by this host
|
||||||
*
|
*
|
||||||
|
@ -146,6 +146,7 @@ struct bat_priv {
|
||||||
atomic_t aggregated_ogms; /* boolean */
|
atomic_t aggregated_ogms; /* boolean */
|
||||||
atomic_t bonding; /* boolean */
|
atomic_t bonding; /* boolean */
|
||||||
atomic_t fragmentation; /* boolean */
|
atomic_t fragmentation; /* boolean */
|
||||||
|
atomic_t ap_isolation; /* boolean */
|
||||||
atomic_t vis_mode; /* VIS_TYPE_* */
|
atomic_t vis_mode; /* VIS_TYPE_* */
|
||||||
atomic_t gw_mode; /* GW_MODE_* */
|
atomic_t gw_mode; /* GW_MODE_* */
|
||||||
atomic_t gw_sel_class; /* uint */
|
atomic_t gw_sel_class; /* uint */
|
||||||
|
@ -156,7 +157,7 @@ struct bat_priv {
|
||||||
atomic_t bcast_seqno;
|
atomic_t bcast_seqno;
|
||||||
atomic_t bcast_queue_left;
|
atomic_t bcast_queue_left;
|
||||||
atomic_t batman_queue_left;
|
atomic_t batman_queue_left;
|
||||||
atomic_t ttvn; /* tranlation table version number */
|
atomic_t ttvn; /* translation table version number */
|
||||||
atomic_t tt_ogm_append_cnt;
|
atomic_t tt_ogm_append_cnt;
|
||||||
atomic_t tt_local_changes; /* changes registered in a OGM interval */
|
atomic_t tt_local_changes; /* changes registered in a OGM interval */
|
||||||
/* The tt_poss_change flag is used to detect an ongoing roaming phase.
|
/* The tt_poss_change flag is used to detect an ongoing roaming phase.
|
||||||
|
|
|
@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
|
||||||
goto find_router;
|
goto find_router;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for tt host - increases orig_node refcount */
|
/* check for tt host - increases orig_node refcount.
|
||||||
orig_node = transtable_search(bat_priv, ethhdr->h_dest);
|
* returns NULL in case of AP isolation */
|
||||||
|
orig_node = transtable_search(bat_priv, ethhdr->h_source,
|
||||||
|
ethhdr->h_dest);
|
||||||
|
|
||||||
find_router:
|
find_router:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
|
||||||
#define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */
|
#define FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */
|
||||||
#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
|
#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
|
||||||
|
|
||||||
int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
|
int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
|
||||||
|
|
|
@ -131,7 +131,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* its a new address, add it to the list */
|
/* it's a new address, add it to the list */
|
||||||
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
|
@ -465,7 +465,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
|
||||||
/* try to add it */
|
/* try to add it */
|
||||||
hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
|
hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
|
||||||
info, &info->hash_entry);
|
info, &info->hash_entry);
|
||||||
if (hash_added < 0) {
|
if (hash_added != 0) {
|
||||||
/* did not work (for some reason) */
|
/* did not work (for some reason) */
|
||||||
kref_put(&info->refcount, free_info);
|
kref_put(&info->refcount, free_info);
|
||||||
info = NULL;
|
info = NULL;
|
||||||
|
@ -920,7 +920,7 @@ int vis_init(struct bat_priv *bat_priv)
|
||||||
hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
|
hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
|
||||||
bat_priv->my_vis_info,
|
bat_priv->my_vis_info,
|
||||||
&bat_priv->my_vis_info->hash_entry);
|
&bat_priv->my_vis_info->hash_entry);
|
||||||
if (hash_added < 0) {
|
if (hash_added != 0) {
|
||||||
pr_err("Can't add own vis packet into hash\n");
|
pr_err("Can't add own vis packet into hash\n");
|
||||||
/* not in hash, need to remove it manually. */
|
/* not in hash, need to remove it manually. */
|
||||||
kref_put(&bat_priv->my_vis_info->refcount, free_info);
|
kref_put(&bat_priv->my_vis_info->refcount, free_info);
|
||||||
|
|
Loading…
Reference in New Issue