forked from Minki/linux
included changes:
- some code cleanups and minor fixes (3 of them were reported by Coverity) - 'struct hard_iface' re-shaping to improve multi-protocol support - ECTP packets silent drop - transfer the WIFI flag on clients in case of roaming -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iEYEABECAAYFAlCOQzIACgkQpGgxIkP9cwdjVgCgmTSMNhAOvIWG/8dV6iiAvDeP bwIAnjZb5QeF/d4L+lRuqw5hMVTEQnJo =SAxj -----END PGP SIGNATURE----- Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge included changes: - some code cleanups and minor fixes (3 of them were reported by Coverity) - 'struct hard_iface' re-shaping to improve multi-protocol support - ECTP packets silent drop - transfer the WIFI flag on clients in case of roaming
This commit is contained in:
commit
157083811c
@ -57,20 +57,22 @@ out:
|
||||
static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
unsigned char *ogm_buff;
|
||||
uint32_t random_seqno;
|
||||
int res = -ENOMEM;
|
||||
|
||||
/* randomize initial seqno to avoid collision */
|
||||
get_random_bytes(&random_seqno, sizeof(random_seqno));
|
||||
atomic_set(&hard_iface->seqno, random_seqno);
|
||||
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
|
||||
|
||||
hard_iface->packet_len = BATADV_OGM_HLEN;
|
||||
hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
|
||||
|
||||
if (!hard_iface->packet_buff)
|
||||
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
|
||||
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
|
||||
if (!ogm_buff)
|
||||
goto out;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
|
||||
hard_iface->bat_iv.ogm_buff = ogm_buff;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
|
||||
batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
|
||||
batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
|
||||
batadv_ogm_packet->header.ttl = 2;
|
||||
@ -87,15 +89,16 @@ out:
|
||||
|
||||
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
kfree(hard_iface->packet_buff);
|
||||
hard_iface->packet_buff = NULL;
|
||||
kfree(hard_iface->bat_iv.ogm_buff);
|
||||
hard_iface->bat_iv.ogm_buff = NULL;
|
||||
}
|
||||
|
||||
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
|
||||
memcpy(batadv_ogm_packet->orig,
|
||||
hard_iface->net_dev->dev_addr, ETH_ALEN);
|
||||
memcpy(batadv_ogm_packet->prev_sender,
|
||||
@ -106,8 +109,9 @@ static void
|
||||
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
|
||||
batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
|
||||
batadv_ogm_packet->header.ttl = BATADV_TTL;
|
||||
}
|
||||
@ -590,8 +594,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
|
||||
static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
{
|
||||
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
|
||||
unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
|
||||
struct batadv_ogm_packet *batadv_ogm_packet;
|
||||
struct batadv_hard_iface *primary_if;
|
||||
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
|
||||
int vis_server, tt_num_changes = 0;
|
||||
uint32_t seqno;
|
||||
uint8_t bandwidth;
|
||||
@ -600,17 +606,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
|
||||
if (hard_iface == primary_if)
|
||||
tt_num_changes = batadv_tt_append_diff(bat_priv,
|
||||
&hard_iface->packet_buff,
|
||||
&hard_iface->packet_len,
|
||||
tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff,
|
||||
ogm_buff_len,
|
||||
BATADV_OGM_HLEN);
|
||||
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
|
||||
batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
|
||||
|
||||
/* change sequence number to network order */
|
||||
seqno = (uint32_t)atomic_read(&hard_iface->seqno);
|
||||
seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
|
||||
batadv_ogm_packet->seqno = htonl(seqno);
|
||||
atomic_inc(&hard_iface->seqno);
|
||||
atomic_inc(&hard_iface->bat_iv.ogm_seqno);
|
||||
|
||||
batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
|
||||
batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
|
||||
@ -631,8 +636,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
|
||||
}
|
||||
|
||||
batadv_slide_own_bcast_window(hard_iface);
|
||||
batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
|
||||
hard_iface->packet_len, hard_iface, 1,
|
||||
batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
|
||||
hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
|
||||
batadv_iv_ogm_emit_send_time(bat_priv));
|
||||
|
||||
if (primary_if)
|
||||
@ -1015,7 +1020,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
|
||||
return;
|
||||
|
||||
/* could be changed by schedule_own_packet() */
|
||||
if_incoming_seqno = atomic_read(&if_incoming->seqno);
|
||||
if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
|
||||
|
||||
if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
|
||||
has_directlink_flag = 1;
|
||||
|
@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
|
||||
* or the old packet got delayed somewhere in the network. The
|
||||
* packet should be dropped without calling this function if the
|
||||
* seqno window is protected.
|
||||
*
|
||||
* seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
|
||||
* or
|
||||
* seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
|
||||
*/
|
||||
if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
|
||||
seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Other host probably restarted!\n");
|
||||
|
||||
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
|
||||
"Other host probably restarted!\n");
|
||||
bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, 0);
|
||||
|
||||
bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
|
||||
if (set_mark)
|
||||
batadv_set_bit(seq_bits, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -1585,23 +1585,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
|
||||
struct hlist_head *head;
|
||||
uint32_t i;
|
||||
bool is_own;
|
||||
int ret = 0;
|
||||
uint8_t *primary_addr;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
primary_addr = primary_if->net_dev->dev_addr;
|
||||
seq_printf(seq,
|
||||
@ -1628,7 +1616,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
|
||||
@ -1643,23 +1631,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
|
||||
int secs, msecs;
|
||||
uint32_t i;
|
||||
bool is_own;
|
||||
int ret = 0;
|
||||
uint8_t *primary_addr;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
primary_addr = primary_if->net_dev->dev_addr;
|
||||
seq_printf(seq,
|
||||
@ -1693,5 +1669,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
@ -99,15 +99,17 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
|
||||
|
||||
static int batadv_log_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EBUSY;
|
||||
|
||||
nonseekable_open(inode, file);
|
||||
file->private_data = inode->i_private;
|
||||
batadv_inc_module_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int batadv_log_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
batadv_dec_module_count();
|
||||
module_put(THIS_MODULE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
|
||||
struct batadv_hard_iface *primary_if;
|
||||
struct batadv_gw_node *gw_node;
|
||||
struct hlist_node *node;
|
||||
int gw_count = 0, ret = 0;
|
||||
int gw_count = 0;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq,
|
||||
" %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
|
||||
@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
|
||||
|
@ -450,8 +450,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
|
||||
/* This can't be called via a bat_priv callback because
|
||||
* we have no bat_priv yet.
|
||||
*/
|
||||
atomic_set(&hard_iface->seqno, 1);
|
||||
hard_iface->packet_buff = NULL;
|
||||
atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
|
||||
hard_iface->bat_iv.ogm_buff = NULL;
|
||||
|
||||
return hard_iface;
|
||||
|
||||
|
@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
|
||||
unsigned int i;
|
||||
struct batadv_socket_client *socket_client;
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EBUSY;
|
||||
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
|
||||
|
||||
if (!socket_client)
|
||||
if (!socket_client) {
|
||||
module_put(THIS_MODULE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
|
||||
if (!batadv_socket_client_hash[i]) {
|
||||
@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
|
||||
if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
|
||||
pr_err("Error - can't add another packet client: maximum number of clients reached\n");
|
||||
kfree(socket_client);
|
||||
module_put(THIS_MODULE);
|
||||
return -EXFULL;
|
||||
}
|
||||
|
||||
@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
|
||||
|
||||
file->private_data = socket_client;
|
||||
|
||||
batadv_inc_module_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file)
|
||||
spin_unlock_bh(&socket_client->lock);
|
||||
|
||||
kfree(socket_client);
|
||||
batadv_dec_module_count();
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -160,16 +160,6 @@ void batadv_mesh_free(struct net_device *soft_iface)
|
||||
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
|
||||
}
|
||||
|
||||
void batadv_inc_module_count(void)
|
||||
{
|
||||
try_module_get(THIS_MODULE);
|
||||
}
|
||||
|
||||
void batadv_dec_module_count(void)
|
||||
{
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
int batadv_is_my_mac(const uint8_t *addr)
|
||||
{
|
||||
const struct batadv_hard_iface *hard_iface;
|
||||
@ -188,6 +178,42 @@ int batadv_is_my_mac(const uint8_t *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_seq_print_text_primary_if_get - called from debugfs table printing
|
||||
* function that requires the primary interface
|
||||
* @seq: debugfs table seq_file struct
|
||||
*
|
||||
* Returns primary interface if found or NULL otherwise.
|
||||
*/
|
||||
struct batadv_hard_iface *
|
||||
batadv_seq_print_text_primary_if_get(struct seq_file *seq)
|
||||
{
|
||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||
struct batadv_priv *bat_priv = netdev_priv(net_dev);
|
||||
struct batadv_hard_iface *primary_if;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
|
||||
if (!primary_if) {
|
||||
seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status == BATADV_IF_ACTIVE)
|
||||
goto out;
|
||||
|
||||
seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
primary_if = NULL;
|
||||
|
||||
out:
|
||||
return primary_if;
|
||||
}
|
||||
|
||||
static int batadv_recv_unhandled_packet(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *recv_if)
|
||||
{
|
||||
|
@ -150,9 +150,9 @@ extern struct workqueue_struct *batadv_event_workqueue;
|
||||
|
||||
int batadv_mesh_init(struct net_device *soft_iface);
|
||||
void batadv_mesh_free(struct net_device *soft_iface);
|
||||
void batadv_inc_module_count(void);
|
||||
void batadv_dec_module_count(void);
|
||||
int batadv_is_my_mac(const uint8_t *addr);
|
||||
struct batadv_hard_iface *
|
||||
batadv_seq_print_text_primary_if_get(struct seq_file *seq);
|
||||
int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
struct packet_type *ptype,
|
||||
struct net_device *orig_dev);
|
||||
@ -165,12 +165,19 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
|
||||
int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
|
||||
int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
|
||||
|
||||
/* all messages related to routing / flooding / broadcasting / etc */
|
||||
/**
|
||||
* enum batadv_dbg_level - available log levels
|
||||
* @BATADV_DBG_BATMAN: OGM and TQ computations related messages
|
||||
* @BATADV_DBG_ROUTES: route added / changed / deleted
|
||||
* @BATADV_DBG_TT: translation table messages
|
||||
* @BATADV_DBG_BLA: bridge loop avoidance messages
|
||||
* @BATADV_DBG_ALL: the union of all the above log levels
|
||||
*/
|
||||
enum batadv_dbg_level {
|
||||
BATADV_DBG_BATMAN = BIT(0),
|
||||
BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */
|
||||
BATADV_DBG_TT = BIT(2), /* translation table operations */
|
||||
BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */
|
||||
BATADV_DBG_ROUTES = BIT(1),
|
||||
BATADV_DBG_TT = BIT(2),
|
||||
BATADV_DBG_BLA = BIT(3),
|
||||
BATADV_DBG_ALL = 15,
|
||||
};
|
||||
|
||||
|
@ -415,23 +415,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
|
||||
int last_seen_msecs;
|
||||
unsigned long last_seen_jiffies;
|
||||
uint32_t i;
|
||||
int ret = 0;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
|
||||
BATADV_SOURCE_VERSION, primary_if->net_dev->name,
|
||||
@ -485,7 +472,7 @@ next:
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
|
||||
|
@ -549,25 +549,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
|
||||
if (tmp_neigh_node->if_incoming == recv_if)
|
||||
continue;
|
||||
|
||||
if (router && tmp_neigh_node->tq_avg <= router->tq_avg)
|
||||
continue;
|
||||
|
||||
if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
|
||||
continue;
|
||||
|
||||
/* if we don't have a router yet
|
||||
* or this one is better, choose it.
|
||||
*/
|
||||
if ((!router) ||
|
||||
(tmp_neigh_node->tq_avg > router->tq_avg)) {
|
||||
/* decrement refcount of
|
||||
* previously selected router
|
||||
*/
|
||||
if (router)
|
||||
batadv_neigh_node_free_ref(router);
|
||||
/* decrement refcount of previously selected router */
|
||||
if (router)
|
||||
batadv_neigh_node_free_ref(router);
|
||||
|
||||
router = tmp_neigh_node;
|
||||
atomic_inc_not_zero(&router->refcount);
|
||||
}
|
||||
|
||||
batadv_neigh_node_free_ref(tmp_neigh_node);
|
||||
/* we found a better router (or at least one valid router) */
|
||||
router = tmp_neigh_node;
|
||||
}
|
||||
|
||||
/* use the first candidate if nothing was found. */
|
||||
@ -687,21 +680,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
|
||||
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
|
||||
struct batadv_roam_adv_packet *roam_adv_packet;
|
||||
struct batadv_orig_node *orig_node;
|
||||
struct ethhdr *ethhdr;
|
||||
|
||||
/* drop packet if it has not necessary minimum size */
|
||||
if (unlikely(!pskb_may_pull(skb,
|
||||
sizeof(struct batadv_roam_adv_packet))))
|
||||
goto out;
|
||||
|
||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||
|
||||
/* packet with unicast indication but broadcast recipient */
|
||||
if (is_broadcast_ether_addr(ethhdr->h_dest))
|
||||
goto out;
|
||||
|
||||
/* packet with broadcast sender address */
|
||||
if (is_broadcast_ether_addr(ethhdr->h_source))
|
||||
if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
|
||||
goto out;
|
||||
|
||||
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
|
||||
@ -928,8 +908,12 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
bool tt_poss_change;
|
||||
int is_old_ttvn;
|
||||
|
||||
/* I could need to modify it */
|
||||
if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0)
|
||||
/* check if there is enough data before accessing it */
|
||||
if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
|
||||
return 0;
|
||||
|
||||
/* create a copy of the skb (in case of for re-routing) to modify it. */
|
||||
if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
|
||||
return 0;
|
||||
|
||||
unicast_packet = (struct batadv_unicast_packet *)skb->data;
|
||||
@ -985,10 +969,10 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
|
||||
batadv_orig_node_free_ref(orig_node);
|
||||
}
|
||||
|
||||
batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
|
||||
"TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n",
|
||||
unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest,
|
||||
unicast_packet->dest);
|
||||
net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
|
||||
"TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n",
|
||||
unicast_packet->ttvn, curr_ttvn,
|
||||
ethhdr->h_dest, unicast_packet->dest);
|
||||
|
||||
unicast_packet->ttvn = curr_ttvn;
|
||||
}
|
||||
|
@ -146,8 +146,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
struct batadv_bcast_packet *bcast_packet;
|
||||
struct vlan_ethhdr *vhdr;
|
||||
__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
|
||||
static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00,
|
||||
0x00};
|
||||
static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
|
||||
0x00, 0x00};
|
||||
static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00};
|
||||
unsigned int header_len = 0;
|
||||
int data_len = skb->len, ret;
|
||||
short vid __maybe_unused = -1;
|
||||
@ -180,10 +182,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
||||
|
||||
/* don't accept stp packets. STP does not help in meshes.
|
||||
* better use the bridge loop avoidance ...
|
||||
*
|
||||
* The same goes for ECTP sent at least by some Cisco Switches,
|
||||
* it might confuse the mesh when used with bridge loop avoidance.
|
||||
*/
|
||||
if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
|
||||
goto dropped;
|
||||
|
||||
if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
|
||||
goto dropped;
|
||||
|
||||
if (is_multicast_ether_addr(ethhdr->h_dest)) {
|
||||
do_bcast = true;
|
||||
|
||||
@ -347,7 +355,51 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
/* batman-adv network devices have devices nesting below it and are a special
|
||||
* "super class" of normal network devices; split their locks off into a
|
||||
* separate class since they always nest.
|
||||
*/
|
||||
static struct lock_class_key batadv_netdev_xmit_lock_key;
|
||||
static struct lock_class_key batadv_netdev_addr_lock_key;
|
||||
|
||||
/**
|
||||
* batadv_set_lockdep_class_one - Set lockdep class for a single tx queue
|
||||
* @dev: device which owns the tx queue
|
||||
* @txq: tx queue to modify
|
||||
* @_unused: always NULL
|
||||
*/
|
||||
static void batadv_set_lockdep_class_one(struct net_device *dev,
|
||||
struct netdev_queue *txq,
|
||||
void *_unused)
|
||||
{
|
||||
lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_set_lockdep_class - Set txq and addr_list lockdep class
|
||||
* @dev: network device to modify
|
||||
*/
|
||||
static void batadv_set_lockdep_class(struct net_device *dev)
|
||||
{
|
||||
lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
|
||||
netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_softif_init - Late stage initialization of soft interface
|
||||
* @dev: registered network device to modify
|
||||
*
|
||||
* Returns error code on failures
|
||||
*/
|
||||
static int batadv_softif_init(struct net_device *dev)
|
||||
{
|
||||
batadv_set_lockdep_class(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops batadv_netdev_ops = {
|
||||
.ndo_init = batadv_softif_init,
|
||||
.ndo_open = batadv_interface_open,
|
||||
.ndo_stop = batadv_interface_release,
|
||||
.ndo_get_stats = batadv_interface_stats,
|
||||
|
@ -122,55 +122,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \
|
||||
batadv_store_##_name)
|
||||
|
||||
|
||||
#define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func) \
|
||||
ssize_t batadv_store_##_name(struct kobject *kobj, \
|
||||
struct attribute *attr, char *buff, \
|
||||
size_t count) \
|
||||
{ \
|
||||
struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
|
||||
struct batadv_hard_iface *hard_iface; \
|
||||
ssize_t length; \
|
||||
\
|
||||
hard_iface = batadv_hardif_get_by_netdev(net_dev); \
|
||||
if (!hard_iface) \
|
||||
return 0; \
|
||||
\
|
||||
length = __batadv_store_uint_attr(buff, count, _min, _max, \
|
||||
_post_func, attr, \
|
||||
&hard_iface->_name, net_dev); \
|
||||
\
|
||||
batadv_hardif_free_ref(hard_iface); \
|
||||
return length; \
|
||||
}
|
||||
|
||||
#define BATADV_ATTR_HIF_SHOW_UINT(_name) \
|
||||
ssize_t batadv_show_##_name(struct kobject *kobj, \
|
||||
struct attribute *attr, char *buff) \
|
||||
{ \
|
||||
struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
|
||||
struct batadv_hard_iface *hard_iface; \
|
||||
ssize_t length; \
|
||||
\
|
||||
hard_iface = batadv_hardif_get_by_netdev(net_dev); \
|
||||
if (!hard_iface) \
|
||||
return 0; \
|
||||
\
|
||||
length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
|
||||
\
|
||||
batadv_hardif_free_ref(hard_iface); \
|
||||
return length; \
|
||||
}
|
||||
|
||||
/* Use this, if you are going to set [name] in hard_iface to an
|
||||
* unsigned integer value
|
||||
*/
|
||||
#define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func) \
|
||||
static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\
|
||||
static BATADV_ATTR_HIF_SHOW_UINT(_name) \
|
||||
static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
|
||||
batadv_store_##_name)
|
||||
|
||||
|
||||
static int batadv_store_bool_attr(char *buff, size_t count,
|
||||
struct net_device *net_dev,
|
||||
const char *attr_name, atomic_t *attr)
|
||||
|
@ -434,22 +434,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||
struct hlist_node *node;
|
||||
struct hlist_head *head;
|
||||
uint32_t i;
|
||||
int ret = 0;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq,
|
||||
"Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
|
||||
@ -479,7 +467,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -501,24 +489,39 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
|
||||
tt_local_entry->common.addr, message);
|
||||
}
|
||||
|
||||
void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr,
|
||||
const char *message, bool roaming)
|
||||
/**
|
||||
* batadv_tt_local_remove - logically remove an entry from the local table
|
||||
* @bat_priv: the bat priv with all the soft interface information
|
||||
* @addr: the MAC address of the client to remove
|
||||
* @message: message to append to the log on deletion
|
||||
* @roaming: true if the deletion is due to a roaming event
|
||||
*
|
||||
* Returns the flags assigned to the local entry before being deleted
|
||||
*/
|
||||
uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
|
||||
const uint8_t *addr, const char *message,
|
||||
bool roaming)
|
||||
{
|
||||
struct batadv_tt_local_entry *tt_local_entry = NULL;
|
||||
uint16_t flags;
|
||||
uint16_t flags, curr_flags = BATADV_NO_FLAGS;
|
||||
|
||||
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
|
||||
if (!tt_local_entry)
|
||||
goto out;
|
||||
|
||||
curr_flags = tt_local_entry->common.flags;
|
||||
|
||||
flags = BATADV_TT_CLIENT_DEL;
|
||||
if (roaming)
|
||||
flags |= BATADV_TT_CLIENT_ROAM;
|
||||
|
||||
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
|
||||
|
||||
out:
|
||||
if (tt_local_entry)
|
||||
batadv_tt_local_entry_free_ref(tt_local_entry);
|
||||
|
||||
return curr_flags;
|
||||
}
|
||||
|
||||
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
|
||||
@ -725,6 +728,7 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
||||
int ret = 0;
|
||||
int hash_added;
|
||||
struct batadv_tt_common_entry *common;
|
||||
uint16_t local_flags;
|
||||
|
||||
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
|
||||
|
||||
@ -738,6 +742,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
||||
|
||||
common->flags = flags;
|
||||
tt_global_entry->roam_at = 0;
|
||||
/* node must store current time in case of roaming. This is
|
||||
* needed to purge this entry out on timeout (if nobody claims
|
||||
* it)
|
||||
*/
|
||||
if (flags & BATADV_TT_CLIENT_ROAM)
|
||||
tt_global_entry->roam_at = jiffies;
|
||||
atomic_set(&common->refcount, 2);
|
||||
common->added_at = jiffies;
|
||||
|
||||
@ -788,13 +798,16 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
|
||||
batadv_dbg(BATADV_DBG_TT, bat_priv,
|
||||
"Creating new global tt entry: %pM (via %pM)\n",
|
||||
tt_global_entry->common.addr, orig_node->orig);
|
||||
ret = 1;
|
||||
|
||||
out_remove:
|
||||
|
||||
/* remove address from local hash if present */
|
||||
batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr,
|
||||
"global tt received",
|
||||
flags & BATADV_TT_CLIENT_ROAM);
|
||||
ret = 1;
|
||||
local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
|
||||
"global tt received",
|
||||
flags & BATADV_TT_CLIENT_ROAM);
|
||||
tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
|
||||
|
||||
out:
|
||||
if (tt_global_entry)
|
||||
batadv_tt_global_entry_free_ref(tt_global_entry);
|
||||
@ -842,22 +855,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||
struct hlist_node *node;
|
||||
struct hlist_head *head;
|
||||
uint32_t i;
|
||||
int ret = 0;
|
||||
|
||||
primary_if = batadv_primary_if_get_selected(bat_priv);
|
||||
if (!primary_if) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
primary_if = batadv_seq_print_text_primary_if_get(seq);
|
||||
if (!primary_if)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (primary_if->if_status != BATADV_IF_ACTIVE) {
|
||||
ret = seq_printf(seq,
|
||||
"BATMAN mesh %s disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seq_printf(seq,
|
||||
"Globally announced TT entries received via the mesh %s\n",
|
||||
@ -881,7 +882,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||
out:
|
||||
if (primary_if)
|
||||
batadv_hardif_free_ref(primary_if);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deletes the orig list of a tt_global_entry */
|
||||
@ -2438,7 +2439,7 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
|
||||
if (!tt_global_entry)
|
||||
goto out;
|
||||
|
||||
ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
|
||||
ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
|
||||
batadv_tt_global_entry_free_ref(tt_global_entry);
|
||||
out:
|
||||
return ret;
|
||||
|
@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
|
||||
int batadv_tt_init(struct batadv_priv *bat_priv);
|
||||
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
|
||||
int ifindex);
|
||||
void batadv_tt_local_remove(struct batadv_priv *bat_priv,
|
||||
const uint8_t *addr, const char *message,
|
||||
bool roaming);
|
||||
uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
|
||||
const uint8_t *addr, const char *message,
|
||||
bool roaming);
|
||||
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
|
||||
void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
|
||||
struct batadv_orig_node *orig_node,
|
||||
|
@ -28,20 +28,30 @@
|
||||
(ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
|
||||
sizeof(struct batadv_bcast_packet)))
|
||||
|
||||
/**
|
||||
* struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data
|
||||
* @ogm_buff: buffer holding the OGM packet
|
||||
* @ogm_buff_len: length of the OGM packet buffer
|
||||
* @ogm_seqno: OGM sequence number - used to identify each OGM
|
||||
*/
|
||||
struct batadv_hard_iface_bat_iv {
|
||||
unsigned char *ogm_buff;
|
||||
int ogm_buff_len;
|
||||
atomic_t ogm_seqno;
|
||||
};
|
||||
|
||||
struct batadv_hard_iface {
|
||||
struct list_head list;
|
||||
int16_t if_num;
|
||||
char if_status;
|
||||
struct net_device *net_dev;
|
||||
atomic_t seqno;
|
||||
atomic_t frag_seqno;
|
||||
unsigned char *packet_buff;
|
||||
int packet_len;
|
||||
struct kobject *hardif_obj;
|
||||
atomic_t refcount;
|
||||
struct packet_type batman_adv_ptype;
|
||||
struct net_device *soft_iface;
|
||||
struct rcu_head rcu;
|
||||
struct batadv_hard_iface_bat_iv bat_iv;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user