diff options
author | David S. Miller <davem@davemloft.net> | 2012-10-31 21:52:52 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-31 21:52:52 +0400 |
commit | 157083811c933fc223a3193d319c7ac805f30bb7 (patch) | |
tree | 5ff8ebd0cd890b4949777199e44b05ff5d5cb807 /net | |
parent | 1627801def0e1cef948f9d593e6757eab295803f (diff) | |
parent | 0aca86cd92282359d2f7202804bd92e7d092c04e (diff) | |
download | linux-157083811c933fc223a3193d319c7ac805f30bb7.tar.xz |
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
Diffstat (limited to 'net')
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 43 | ||||
-rw-r--r-- | net/batman-adv/bitarray.c | 23 | ||||
-rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 36 | ||||
-rw-r--r-- | net/batman-adv/debugfs.c | 6 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 19 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 4 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 12 | ||||
-rw-r--r-- | net/batman-adv/main.c | 46 | ||||
-rw-r--r-- | net/batman-adv/main.h | 19 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 19 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 54 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 56 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 49 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 77 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 6 | ||||
-rw-r--r-- | net/batman-adv/types.h | 16 |
16 files changed, 238 insertions, 247 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index b02b75dae3a8..75403a491892 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -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; diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index aea174cdbfbd..5453b17d8df2 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -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); - - return 1; - } + bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); + if (set_mark) + batadv_set_bit(seq_bits, 0); - /* never reached */ - return 0; + return 1; } diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index fd8d5afec0dd..29a5542aac75 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -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); - 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); + primary_if = batadv_seq_print_text_primary_if_get(seq); + if (!primary_if) 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); - 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); + primary_if = batadv_seq_print_text_primary_if_get(seq); + if (!primary_if) 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; } diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 391d4fb2026f..bd032bc4e262 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -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; } diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 15d67abc10a4..dd07c7e3654f 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -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) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index d112fd6750b0..fab9e4158dc2 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -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; diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index bde3cf747507..5874c0e84846 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -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; } diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index b4aa470bc4a6..f9bcfa17f50f 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -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) { diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index d57b746219de..897ba6a8f8f2 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -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, }; diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ac9bdf8f80a6..d9c14b8fca0e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -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); - 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); + primary_if = batadv_seq_print_text_primary_if_get(seq); + if (!primary_if) 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, diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 376b4cc6ca82..46dd5b47ed29 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -549,25 +549,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig, if (tmp_neigh_node->if_incoming == recv_if) continue; - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + if (router && tmp_neigh_node->tq_avg <= router->tq_avg) 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); + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; - router = tmp_neigh_node; - atomic_inc_not_zero(&router->refcount); - } + /* decrement refcount of previously selected router */ + 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. */ @@ -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; } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index b9a28d2dd3e8..22bc65102370 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -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, diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 66518c75c217..42cd09e24c5f 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -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) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 112edd371b2f..a570d957a5a0 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -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); - 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); + primary_if = batadv_seq_print_text_primary_if_get(seq); + if (!primary_if) 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); - 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); + primary_if = batadv_seq_print_text_primary_if_get(seq); + if (!primary_if) 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; diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 811fffd4760c..9fa4fe41c868 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -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, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ac1e07a80454..faaebd6c8140 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -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; }; /** |