Commit 15708381 authored by David S. Miller's avatar David S. Miller

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
parents 1627801d 0aca86cd
...@@ -57,20 +57,22 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, ...@@ -57,20 +57,22 @@ batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
{ {
struct batadv_ogm_packet *batadv_ogm_packet; struct batadv_ogm_packet *batadv_ogm_packet;
unsigned char *ogm_buff;
uint32_t random_seqno; uint32_t random_seqno;
int res = -ENOMEM; int res = -ENOMEM;
/* randomize initial seqno to avoid collision */ /* randomize initial seqno to avoid collision */
get_random_bytes(&random_seqno, sizeof(random_seqno)); 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->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
if (!ogm_buff)
if (!hard_iface->packet_buff)
goto out; 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.packet_type = BATADV_IV_OGM;
batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
batadv_ogm_packet->header.ttl = 2; batadv_ogm_packet->header.ttl = 2;
...@@ -87,15 +89,16 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) ...@@ -87,15 +89,16 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
{ {
kfree(hard_iface->packet_buff); kfree(hard_iface->bat_iv.ogm_buff);
hard_iface->packet_buff = NULL; hard_iface->bat_iv.ogm_buff = NULL;
} }
static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
{ {
struct batadv_ogm_packet *batadv_ogm_packet; 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, memcpy(batadv_ogm_packet->orig,
hard_iface->net_dev->dev_addr, ETH_ALEN); hard_iface->net_dev->dev_addr, ETH_ALEN);
memcpy(batadv_ogm_packet->prev_sender, memcpy(batadv_ogm_packet->prev_sender,
...@@ -106,8 +109,9 @@ static void ...@@ -106,8 +109,9 @@ static void
batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface) batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
{ {
struct batadv_ogm_packet *batadv_ogm_packet; 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->flags = BATADV_PRIMARIES_FIRST_HOP;
batadv_ogm_packet->header.ttl = BATADV_TTL; batadv_ogm_packet->header.ttl = BATADV_TTL;
} }
...@@ -590,8 +594,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, ...@@ -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) static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
{ {
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_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_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
int vis_server, tt_num_changes = 0; int vis_server, tt_num_changes = 0;
uint32_t seqno; uint32_t seqno;
uint8_t bandwidth; uint8_t bandwidth;
...@@ -600,17 +606,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) ...@@ -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); primary_if = batadv_primary_if_get_selected(bat_priv);
if (hard_iface == primary_if) if (hard_iface == primary_if)
tt_num_changes = batadv_tt_append_diff(bat_priv, tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff,
&hard_iface->packet_buff, ogm_buff_len,
&hard_iface->packet_len,
BATADV_OGM_HLEN); 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 */ /* 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); 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->ttvn = atomic_read(&bat_priv->tt.vn);
batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); 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) ...@@ -631,8 +636,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
} }
batadv_slide_own_bcast_window(hard_iface); batadv_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff, batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
hard_iface->packet_len, hard_iface, 1, hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
batadv_iv_ogm_emit_send_time(bat_priv)); batadv_iv_ogm_emit_send_time(bat_priv));
if (primary_if) if (primary_if)
...@@ -1015,7 +1020,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, ...@@ -1015,7 +1020,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
return; return;
/* could be changed by schedule_own_packet() */ /* 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) if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
has_directlink_flag = 1; has_directlink_flag = 1;
......
...@@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, ...@@ -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 * or the old packet got delayed somewhere in the network. The
* packet should be dropped without calling this function if the * packet should be dropped without calling this function if the
* seqno window is protected. * 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 || batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) { "Other host probably restarted!\n");
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
"Other host probably restarted!\n"); 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 1;
return 0;
} }
...@@ -1585,23 +1585,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) ...@@ -1585,23 +1585,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_head *head; struct hlist_head *head;
uint32_t i; uint32_t i;
bool is_own; bool is_own;
int ret = 0;
uint8_t *primary_addr; uint8_t *primary_addr;
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if) { if (!primary_if)
ret = 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) {
ret = seq_printf(seq,
"BATMAN mesh %s disabled - primary interface not active\n",
net_dev->name);
goto out; goto out;
}
primary_addr = primary_if->net_dev->dev_addr; primary_addr = primary_if->net_dev->dev_addr;
seq_printf(seq, seq_printf(seq,
...@@ -1628,7 +1616,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) ...@@ -1628,7 +1616,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(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) 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) ...@@ -1643,23 +1631,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
int secs, msecs; int secs, msecs;
uint32_t i; uint32_t i;
bool is_own; bool is_own;
int ret = 0;
uint8_t *primary_addr; uint8_t *primary_addr;
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if) { if (!primary_if)
ret = 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) {
ret = seq_printf(seq,
"BATMAN mesh %s disabled - primary interface not active\n",
net_dev->name);
goto out; goto out;
}
primary_addr = primary_if->net_dev->dev_addr; primary_addr = primary_if->net_dev->dev_addr;
seq_printf(seq, seq_printf(seq,
...@@ -1693,5 +1669,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) ...@@ -1693,5 +1669,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(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, ...) ...@@ -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) static int batadv_log_open(struct inode *inode, struct file *file)
{ {
if (!try_module_get(THIS_MODULE))
return -EBUSY;
nonseekable_open(inode, file); nonseekable_open(inode, file);
file->private_data = inode->i_private; file->private_data = inode->i_private;
batadv_inc_module_count();
return 0; return 0;
} }
static int batadv_log_release(struct inode *inode, struct file *file) static int batadv_log_release(struct inode *inode, struct file *file)
{ {
batadv_dec_module_count(); module_put(THIS_MODULE);
return 0; return 0;
} }
......
...@@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) ...@@ -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_hard_iface *primary_if;
struct batadv_gw_node *gw_node; struct batadv_gw_node *gw_node;
struct hlist_node *node; struct hlist_node *node;
int gw_count = 0, ret = 0; int gw_count = 0;
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if) { if (!primary_if)
ret = seq_printf(seq,
"BATMAN mesh %s disabled - please specify interfaces to enable it\n",
net_dev->name);
goto out; 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, seq_printf(seq,
" %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", " %-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) ...@@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(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) 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) ...@@ -450,8 +450,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
/* This can't be called via a bat_priv callback because /* This can't be called via a bat_priv callback because
* we have no bat_priv yet. * we have no bat_priv yet.
*/ */
atomic_set(&hard_iface->seqno, 1); atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
hard_iface->packet_buff = NULL; hard_iface->bat_iv.ogm_buff = NULL;
return hard_iface; return hard_iface;
......
...@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file) ...@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
unsigned int i; unsigned int i;
struct batadv_socket_client *socket_client; struct batadv_socket_client *socket_client;
if (!try_module_get(THIS_MODULE))
return -EBUSY;
nonseekable_open(inode, file); nonseekable_open(inode, file);
socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL); socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
if (!socket_client) {
if (!socket_client) module_put(THIS_MODULE);
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) { for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
if (!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) ...@@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
if (i == ARRAY_SIZE(batadv_socket_client_hash)) { if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
pr_err("Error - can't add another packet client: maximum number of clients reached\n"); pr_err("Error - can't add another packet client: maximum number of clients reached\n");
kfree(socket_client); kfree(socket_client);
module_put(THIS_MODULE);
return -EXFULL; return -EXFULL;
} }
...@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file) ...@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
file->private_data = socket_client; file->private_data = socket_client;
batadv_inc_module_count();
return 0; return 0;
} }
...@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file) ...@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file)
spin_unlock_bh(&socket_client->lock); spin_unlock_bh(&socket_client->lock);
kfree(socket_client); kfree(socket_client);
batadv_dec_module_count(); module_put(THIS_MODULE);
return 0; return 0;
} }
......
...@@ -160,16 +160,6 @@ void batadv_mesh_free(struct net_device *soft_iface) ...@@ -160,16 +160,6 @@ void batadv_mesh_free(struct net_device *soft_iface)
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); 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) int batadv_is_my_mac(const uint8_t *addr)
{ {
const struct batadv_hard_iface *hard_iface; const struct batadv_hard_iface *hard_iface;
...@@ -188,6 +178,42 @@ int batadv_is_my_mac(const uint8_t *addr) ...@@ -188,6 +178,42 @@ int batadv_is_my_mac(const uint8_t *addr)
return 0; 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, static int batadv_recv_unhandled_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if) struct batadv_hard_iface *recv_if)
{ {
......
...@@ -150,9 +150,9 @@ extern struct workqueue_struct *batadv_event_workqueue; ...@@ -150,9 +150,9 @@ extern struct workqueue_struct *batadv_event_workqueue;
int batadv_mesh_init(struct net_device *soft_iface); int batadv_mesh_init(struct net_device *soft_iface);
void batadv_mesh_free(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); 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, int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct packet_type *ptype,
struct net_device *orig_dev); struct net_device *orig_dev);
...@@ -165,12 +165,19 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops); ...@@ -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_select(struct batadv_priv *bat_priv, char *name);
int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); 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 { enum batadv_dbg_level {
BATADV_DBG_BATMAN = BIT(0), BATADV_DBG_BATMAN = BIT(0),
BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */ BATADV_DBG_ROUTES = BIT(1),
BATADV_DBG_TT = BIT(2), /* translation table operations */ BATADV_DBG_TT = BIT(2),
BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */ BATADV_DBG_BLA = BIT(3),
BATADV_DBG_ALL = 15, BATADV_DBG_ALL = 15,
}; };
......
...@@ -415,23 +415,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) ...@@ -415,23 +415,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
int last_seen_msecs; int last_seen_msecs;
unsigned long last_seen_jiffies; unsigned long last_seen_jiffies;
uint32_t i; uint32_t i;
int ret = 0;
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_seq_print_text_primary_if_get(seq);
if (!primary_if)
if (!primary_if) {
ret = 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) {
ret = seq_printf(seq,
"BATMAN mesh %s disabled - primary interface not active\n",
net_dev->name);
goto out; goto out;
}
seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", 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, BATADV_SOURCE_VERSION, primary_if->net_dev->name,
...@@ -485,7 +472,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) ...@@ -485,7 +472,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(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, 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, ...@@ -549,25 +549,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
if (tmp_neigh_node->if_incoming == recv_if) if (tmp_neigh_node->if_incoming == recv_if)
continue; continue;
if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) if (router && tmp_neigh_node->tq_avg <= router->tq_avg)
continue; continue;
/* if we don't have a router yet if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
* or this one is better, choose it. continue;
*/
if ((!router) ||
(tmp_neigh_node->tq_avg > router->tq_avg)) {
/* decrement refcount of
* previously selected router
*/
if (router)
batadv_neigh_node_free_ref(router);
router = tmp_neigh_node; /* decrement refcount of previously selected router */
atomic_inc_not_zero(&router->refcount); if (router)
} batadv_neigh_node_free_ref(router);
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. */ /* 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) ...@@ -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_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_roam_adv_packet *roam_adv_packet; struct batadv_roam_adv_packet *roam_adv_packet;
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
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))
goto out; goto out;
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX); 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, ...@@ -928,8 +908,12 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
bool tt_poss_change; bool tt_poss_change;
int is_old_ttvn; int is_old_ttvn;
/* I could need to modify it */ /* check if there is enough data before accessing it */
if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0) 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; return 0;
unicast_packet = (struct batadv_unicast_packet *)skb->data; unicast_packet = (struct batadv_unicast_packet *)skb->data;
...@@ -985,10 +969,10 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, ...@@ -985,10 +969,10 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
} }
batadv_dbg(BATADV_DBG_ROUTES, bat_priv, 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", "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->ttvn, curr_ttvn,
unicast_packet->dest); ethhdr->h_dest, unicast_packet->dest);
unicast_packet->ttvn = curr_ttvn; unicast_packet->ttvn = curr_ttvn;
} }
......
...@@ -146,8 +146,10 @@ static int batadv_interface_tx(struct sk_buff *skb, ...@@ -146,8 +146,10 @@ static int batadv_interface_tx(struct sk_buff *skb,
struct batadv_bcast_packet *bcast_packet; struct batadv_bcast_packet *bcast_packet;
struct vlan_ethhdr *vhdr; struct vlan_ethhdr *vhdr;
__be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
0x00}; 0x00, 0x00};
static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
0x00, 0x00};
unsigned int header_len = 0; unsigned int header_len = 0;
int data_len = skb->len, ret; int data_len = skb->len, ret;
short vid __maybe_unused = -1; short vid __maybe_unused = -1;
...@@ -180,10 +182,16 @@ static int batadv_interface_tx(struct sk_buff *skb, ...@@ -180,10 +182,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
/* don't accept stp packets. STP does not help in meshes. /* don't accept stp packets. STP does not help in meshes.
* better use the bridge loop avoidance ... * 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)) if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
goto dropped; goto dropped;
if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
goto dropped;
if (is_multicast_ether_addr(ethhdr->h_dest)) { if (is_multicast_ether_addr(ethhdr->h_dest)) {
do_bcast = true; do_bcast = true;
...@@ -347,7 +355,51 @@ void batadv_interface_rx(struct net_device *soft_iface, ...@@ -347,7 +355,51 @@ void batadv_interface_rx(struct net_device *soft_iface,
return; 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 = { static const struct net_device_ops batadv_netdev_ops = {
.ndo_init = batadv_softif_init,
.ndo_open = batadv_interface_open, .ndo_open = batadv_interface_open,
.ndo_stop = batadv_interface_release, .ndo_stop = batadv_interface_release,
.ndo_get_stats = batadv_interface_stats, .ndo_get_stats = batadv_interface_stats,
......
...@@ -122,55 +122,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \ ...@@ -122,55 +122,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \
batadv_store_##_name) 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, static int batadv_store_bool_attr(char *buff, size_t count,
struct net_device *net_dev, struct net_device *net_dev,
const char *attr_name, atomic_t *attr) const char *attr_name, atomic_t *attr)
......
...@@ -434,22 +434,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -434,22 +434,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
uint32_t i; 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);
goto out;
}
if (primary_if->if_status != BATADV_IF_ACTIVE) { primary_if = batadv_seq_print_text_primary_if_get(seq);
ret = seq_printf(seq, if (!primary_if)
"BATMAN mesh %s disabled - primary interface not active\n",
net_dev->name);
goto out; goto out;
}
seq_printf(seq, seq_printf(seq,
"Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", "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) ...@@ -479,7 +467,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
return ret; return 0;
} }
static void static void
...@@ -501,24 +489,39 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv, ...@@ -501,24 +489,39 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
tt_local_entry->common.addr, message); 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; 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); tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
if (!tt_local_entry) if (!tt_local_entry)
goto out; goto out;
curr_flags = tt_local_entry->common.flags;
flags = BATADV_TT_CLIENT_DEL; flags = BATADV_TT_CLIENT_DEL;
if (roaming) if (roaming)
flags |= BATADV_TT_CLIENT_ROAM; flags |= BATADV_TT_CLIENT_ROAM;
batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message); batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
out: out:
if (tt_local_entry) if (tt_local_entry)
batadv_tt_local_entry_free_ref(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, 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, ...@@ -725,6 +728,7 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
int ret = 0; int ret = 0;
int hash_added; int hash_added;
struct batadv_tt_common_entry *common; struct batadv_tt_common_entry *common;
uint16_t local_flags;
tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); 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, ...@@ -738,6 +742,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
common->flags = flags; common->flags = flags;
tt_global_entry->roam_at = 0; 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); atomic_set(&common->refcount, 2);
common->added_at = jiffies; common->added_at = jiffies;
...@@ -788,13 +798,16 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, ...@@ -788,13 +798,16 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
batadv_dbg(BATADV_DBG_TT, bat_priv, batadv_dbg(BATADV_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->common.addr, orig_node->orig); tt_global_entry->common.addr, orig_node->orig);
ret = 1;
out_remove: out_remove:
/* remove address from local hash if present */ /* remove address from local hash if present */
batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr, local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
"global tt received", "global tt received",
flags & BATADV_TT_CLIENT_ROAM); flags & BATADV_TT_CLIENT_ROAM);
ret = 1; tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
out: out:
if (tt_global_entry) if (tt_global_entry)
batadv_tt_global_entry_free_ref(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) ...@@ -842,22 +855,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
struct hlist_node *node; struct hlist_node *node;
struct hlist_head *head; struct hlist_head *head;
uint32_t i; 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);
goto out;
}
if (primary_if->if_status != BATADV_IF_ACTIVE) { primary_if = batadv_seq_print_text_primary_if_get(seq);
ret = seq_printf(seq, if (!primary_if)
"BATMAN mesh %s disabled - primary interface not active\n",
net_dev->name);
goto out; goto out;
}
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",
...@@ -881,7 +882,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -881,7 +882,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
out: out:
if (primary_if) if (primary_if)
batadv_hardif_free_ref(primary_if); batadv_hardif_free_ref(primary_if);
return ret; return 0;
} }
/* deletes the orig list of a tt_global_entry */ /* 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, ...@@ -2438,7 +2439,7 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
if (!tt_global_entry) if (!tt_global_entry)
goto out; 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); batadv_tt_global_entry_free_ref(tt_global_entry);
out: out:
return ret; return ret;
......
...@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num); ...@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
int batadv_tt_init(struct batadv_priv *bat_priv); int batadv_tt_init(struct batadv_priv *bat_priv);
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex); int ifindex);
void batadv_tt_local_remove(struct batadv_priv *bat_priv, uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
const uint8_t *addr, const char *message, const uint8_t *addr, const char *message,
bool roaming); bool roaming);
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_add_orig(struct batadv_priv *bat_priv, void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
......
...@@ -28,20 +28,30 @@ ...@@ -28,20 +28,30 @@
(ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \ (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
sizeof(struct batadv_bcast_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 batadv_hard_iface {
struct list_head list; struct list_head list;
int16_t if_num; int16_t if_num;
char if_status; char if_status;
struct net_device *net_dev; struct net_device *net_dev;
atomic_t seqno;
atomic_t frag_seqno; atomic_t frag_seqno;
unsigned char *packet_buff;
int packet_len;
struct kobject *hardif_obj; struct kobject *hardif_obj;
atomic_t refcount; atomic_t refcount;
struct packet_type batman_adv_ptype; struct packet_type batman_adv_ptype;
struct net_device *soft_iface; struct net_device *soft_iface;
struct rcu_head rcu; struct rcu_head rcu;
struct batadv_hard_iface_bat_iv bat_iv;
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment