Loading net/batman-adv/vis.c +81 −143 Original line number Diff line number Diff line Loading @@ -140,193 +140,131 @@ static void batadv_vis_data_insert_interface(const uint8_t *interface, hlist_add_head(&entry->list, if_list); } static ssize_t batadv_vis_prim_sec(char *buff, const struct hlist_head *if_list) static void batadv_vis_data_read_prim_sec(struct seq_file *seq, const struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; size_t len = 0; hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) len += sprintf(buff + len, "PRIMARY, "); seq_printf(seq, "PRIMARY, "); else len += sprintf(buff + len, "SEC %pM, ", entry->addr); seq_printf(seq, "SEC %pM, ", entry->addr); } return len; } static size_t batadv_vis_cnt_prim_sec(struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; size_t count = 0; hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) count += 9; else count += 23; } return count; } /* read an entry */ static ssize_t batadv_vis_data_read_entry(char *buff, static ssize_t batadv_vis_data_read_entry(struct seq_file *seq, const struct vis_info_entry *entry, const uint8_t *src, bool primary) { /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ if (primary && entry->quality == 0) return sprintf(buff, "TT %pM, ", entry->dest); return seq_printf(seq, "TT %pM, ", entry->dest); else if (batadv_compare_eth(entry->src, src)) return sprintf(buff, "TQ %pM %d, ", entry->dest, return seq_printf(seq, "TQ %pM %d, ", entry->dest, entry->quality); return 0; } int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) static void batadv_vis_data_insert_interfaces(struct hlist_head *list, struct vis_packet *packet, struct vis_info_entry *entries) { struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; struct vis_info *info; struct vis_packet *packet; struct vis_info_entry *entries; struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->vis_hash; HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; uint32_t i; int j, ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); size_t buff_pos, buf_size; char *buff; int i; primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; if (vis_server == VIS_TYPE_CLIENT_UPDATE) goto out; for (i = 0; i < packet->entries; i++) { if (entries[i].quality == 0) continue; buf_size = 1; /* Estimate length */ spin_lock_bh(&bat_priv->vis_hash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; if (batadv_compare_eth(entries[i].src, packet->vis_orig)) continue; rcu_read_lock(); hlist_for_each_entry_rcu(info, node, head, hash_entry) { packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) ((char *)packet + sizeof(*packet)); batadv_vis_data_insert_interface(entries[i].src, list, false); } } batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); static void batadv_vis_data_read_entries(struct seq_file *seq, struct hlist_head *list, struct vis_packet *packet, struct vis_info_entry *entries) { int i; struct if_list_entry *entry; struct hlist_node *pos; for (j = 0; j < packet->entries; j++) { if (entries[j].quality == 0) continue; if (batadv_compare_eth(entries[j].src, packet->vis_orig)) continue; batadv_vis_data_insert_interface(entries[j].src, &vis_if_list, false); } hlist_for_each_entry(entry, pos, list, list) { seq_printf(seq, "%pM,", entry->addr); hlist_for_each_entry(entry, pos, &vis_if_list, list) { buf_size += 18 + 26 * packet->entries; for (i = 0; i < packet->entries; i++) batadv_vis_data_read_entry(seq, &entries[i], entry->addr, entry->primary); /* add primary/secondary records */ if (batadv_compare_eth(entry->addr, packet->vis_orig)) buf_size += batadv_vis_cnt_prim_sec(&vis_if_list); buf_size += 1; } if (batadv_compare_eth(entry->addr, packet->vis_orig)) batadv_vis_data_read_prim_sec(seq, list); hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_del(&entry->list); kfree(entry); seq_printf(seq, "\n"); } } rcu_read_unlock(); } buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->vis_hash_lock); ret = -ENOMEM; goto out; } buff[0] = '\0'; buff_pos = 0; static void batadv_vis_seq_print_text_bucket(struct seq_file *seq, const struct hlist_head *head) { struct hlist_node *node; struct vis_info *info; struct vis_packet *packet; uint8_t *entries_pos; struct vis_info_entry *entries; struct if_list_entry *entry; struct hlist_node *pos, *n; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; HLIST_HEAD(vis_if_list); rcu_read_lock(); hlist_for_each_entry_rcu(info, node, head, hash_entry) { packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) ((char *)packet + sizeof(*packet)); batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); entries_pos = (uint8_t *)packet + sizeof(*packet); entries = (struct vis_info_entry *)entries_pos; for (j = 0; j < packet->entries; j++) { if (entries[j].quality == 0) continue; if (batadv_compare_eth(entries[j].src, packet->vis_orig)) continue; batadv_vis_data_insert_interface(entries[j].src, &vis_if_list, false); } hlist_for_each_entry(entry, pos, &vis_if_list, list) { buff_pos += sprintf(buff + buff_pos, "%pM,", entry->addr); for (j = 0; j < packet->entries; j++) buff_pos += batadv_vis_data_read_entry( buff + buff_pos, &entries[j], entry->addr, entry->primary); /* add primary/secondary records */ if (batadv_compare_eth(entry->addr, packet->vis_orig)) buff_pos += batadv_vis_prim_sec(buff + buff_pos, &vis_if_list); batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); batadv_vis_data_insert_interfaces(&vis_if_list, packet, entries); batadv_vis_data_read_entries(seq, &vis_if_list, packet, entries); buff_pos += sprintf(buff + buff_pos, "\n"); } hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_del(&entry->list); kfree(entry); } } rcu_read_unlock(); } spin_unlock_bh(&bat_priv->vis_hash_lock); int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) { struct hard_iface *primary_if; struct hlist_head *head; struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->vis_hash; uint32_t i; int ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); seq_printf(seq, "%s", buff); kfree(buff); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; if (vis_server == VIS_TYPE_CLIENT_UPDATE) goto out; spin_lock_bh(&bat_priv->vis_hash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; batadv_vis_seq_print_text_bucket(seq, head); } spin_unlock_bh(&bat_priv->vis_hash_lock); out: if (primary_if) Loading Loading
net/batman-adv/vis.c +81 −143 Original line number Diff line number Diff line Loading @@ -140,193 +140,131 @@ static void batadv_vis_data_insert_interface(const uint8_t *interface, hlist_add_head(&entry->list, if_list); } static ssize_t batadv_vis_prim_sec(char *buff, const struct hlist_head *if_list) static void batadv_vis_data_read_prim_sec(struct seq_file *seq, const struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; size_t len = 0; hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) len += sprintf(buff + len, "PRIMARY, "); seq_printf(seq, "PRIMARY, "); else len += sprintf(buff + len, "SEC %pM, ", entry->addr); seq_printf(seq, "SEC %pM, ", entry->addr); } return len; } static size_t batadv_vis_cnt_prim_sec(struct hlist_head *if_list) { struct if_list_entry *entry; struct hlist_node *pos; size_t count = 0; hlist_for_each_entry(entry, pos, if_list, list) { if (entry->primary) count += 9; else count += 23; } return count; } /* read an entry */ static ssize_t batadv_vis_data_read_entry(char *buff, static ssize_t batadv_vis_data_read_entry(struct seq_file *seq, const struct vis_info_entry *entry, const uint8_t *src, bool primary) { /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ if (primary && entry->quality == 0) return sprintf(buff, "TT %pM, ", entry->dest); return seq_printf(seq, "TT %pM, ", entry->dest); else if (batadv_compare_eth(entry->src, src)) return sprintf(buff, "TQ %pM %d, ", entry->dest, return seq_printf(seq, "TQ %pM %d, ", entry->dest, entry->quality); return 0; } int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) static void batadv_vis_data_insert_interfaces(struct hlist_head *list, struct vis_packet *packet, struct vis_info_entry *entries) { struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; struct vis_info *info; struct vis_packet *packet; struct vis_info_entry *entries; struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->vis_hash; HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; uint32_t i; int j, ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); size_t buff_pos, buf_size; char *buff; int i; primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; if (vis_server == VIS_TYPE_CLIENT_UPDATE) goto out; for (i = 0; i < packet->entries; i++) { if (entries[i].quality == 0) continue; buf_size = 1; /* Estimate length */ spin_lock_bh(&bat_priv->vis_hash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; if (batadv_compare_eth(entries[i].src, packet->vis_orig)) continue; rcu_read_lock(); hlist_for_each_entry_rcu(info, node, head, hash_entry) { packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) ((char *)packet + sizeof(*packet)); batadv_vis_data_insert_interface(entries[i].src, list, false); } } batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); static void batadv_vis_data_read_entries(struct seq_file *seq, struct hlist_head *list, struct vis_packet *packet, struct vis_info_entry *entries) { int i; struct if_list_entry *entry; struct hlist_node *pos; for (j = 0; j < packet->entries; j++) { if (entries[j].quality == 0) continue; if (batadv_compare_eth(entries[j].src, packet->vis_orig)) continue; batadv_vis_data_insert_interface(entries[j].src, &vis_if_list, false); } hlist_for_each_entry(entry, pos, list, list) { seq_printf(seq, "%pM,", entry->addr); hlist_for_each_entry(entry, pos, &vis_if_list, list) { buf_size += 18 + 26 * packet->entries; for (i = 0; i < packet->entries; i++) batadv_vis_data_read_entry(seq, &entries[i], entry->addr, entry->primary); /* add primary/secondary records */ if (batadv_compare_eth(entry->addr, packet->vis_orig)) buf_size += batadv_vis_cnt_prim_sec(&vis_if_list); buf_size += 1; } if (batadv_compare_eth(entry->addr, packet->vis_orig)) batadv_vis_data_read_prim_sec(seq, list); hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_del(&entry->list); kfree(entry); seq_printf(seq, "\n"); } } rcu_read_unlock(); } buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->vis_hash_lock); ret = -ENOMEM; goto out; } buff[0] = '\0'; buff_pos = 0; static void batadv_vis_seq_print_text_bucket(struct seq_file *seq, const struct hlist_head *head) { struct hlist_node *node; struct vis_info *info; struct vis_packet *packet; uint8_t *entries_pos; struct vis_info_entry *entries; struct if_list_entry *entry; struct hlist_node *pos, *n; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; HLIST_HEAD(vis_if_list); rcu_read_lock(); hlist_for_each_entry_rcu(info, node, head, hash_entry) { packet = (struct vis_packet *)info->skb_packet->data; entries = (struct vis_info_entry *) ((char *)packet + sizeof(*packet)); batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); entries_pos = (uint8_t *)packet + sizeof(*packet); entries = (struct vis_info_entry *)entries_pos; for (j = 0; j < packet->entries; j++) { if (entries[j].quality == 0) continue; if (batadv_compare_eth(entries[j].src, packet->vis_orig)) continue; batadv_vis_data_insert_interface(entries[j].src, &vis_if_list, false); } hlist_for_each_entry(entry, pos, &vis_if_list, list) { buff_pos += sprintf(buff + buff_pos, "%pM,", entry->addr); for (j = 0; j < packet->entries; j++) buff_pos += batadv_vis_data_read_entry( buff + buff_pos, &entries[j], entry->addr, entry->primary); /* add primary/secondary records */ if (batadv_compare_eth(entry->addr, packet->vis_orig)) buff_pos += batadv_vis_prim_sec(buff + buff_pos, &vis_if_list); batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list, true); batadv_vis_data_insert_interfaces(&vis_if_list, packet, entries); batadv_vis_data_read_entries(seq, &vis_if_list, packet, entries); buff_pos += sprintf(buff + buff_pos, "\n"); } hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_del(&entry->list); kfree(entry); } } rcu_read_unlock(); } spin_unlock_bh(&bat_priv->vis_hash_lock); int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) { struct hard_iface *primary_if; struct hlist_head *head; struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->vis_hash; uint32_t i; int ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); seq_printf(seq, "%s", buff); kfree(buff); primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) goto out; if (vis_server == VIS_TYPE_CLIENT_UPDATE) goto out; spin_lock_bh(&bat_priv->vis_hash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; batadv_vis_seq_print_text_bucket(seq, head); } spin_unlock_bh(&bat_priv->vis_hash_lock); out: if (primary_if) Loading