Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28afd3c0 authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Antonio Quartulli
Browse files

batman-adv: Directly print to seq_file in vis



The vis output doesn't need to be buffered in an character buffer before it can
be send to the userspace program that reads from the vis debug file.

Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
parent 3e34819e
Loading
Loading
Loading
Loading
+81 −143
Original line number Original line Diff line number Diff line
@@ -140,193 +140,131 @@ static void batadv_vis_data_insert_interface(const uint8_t *interface,
	hlist_add_head(&entry->list, if_list);
	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 if_list_entry *entry;
	struct hlist_node *pos;
	struct hlist_node *pos;
	size_t len = 0;


	hlist_for_each_entry(entry, pos, if_list, list) {
	hlist_for_each_entry(entry, pos, if_list, list) {
		if (entry->primary)
		if (entry->primary)
			len += sprintf(buff + len, "PRIMARY, ");
			seq_printf(seq, "PRIMARY, ");
		else
		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  */
/* 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 struct vis_info_entry *entry,
					  const uint8_t *src, bool primary)
					  const uint8_t *src, bool primary)
{
{
	/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
	if (primary && entry->quality == 0)
	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))
	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);
				  entry->quality);


	return 0;
	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;
	int i;
	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;


	primary_if = batadv_primary_if_get_selected(bat_priv);
	for (i = 0; i < packet->entries; i++) {
	if (!primary_if)
		if (entries[i].quality == 0)
		goto out;
			continue;

	if (vis_server == VIS_TYPE_CLIENT_UPDATE)
		goto out;


	buf_size = 1;
		if (batadv_compare_eth(entries[i].src, packet->vis_orig))
	/* Estimate length */
			continue;
	spin_lock_bh(&bat_priv->vis_hash_lock);
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];


		rcu_read_lock();
		batadv_vis_data_insert_interface(entries[i].src, list, false);
		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,
static void batadv_vis_data_read_entries(struct seq_file *seq,
							 &vis_if_list, true);
					 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++) {
	hlist_for_each_entry(entry, pos, list, list) {
				if (entries[j].quality == 0)
		seq_printf(seq, "%pM,", entry->addr);
					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) {
		for (i = 0; i < packet->entries; i++)
				buf_size += 18 + 26 * packet->entries;
			batadv_vis_data_read_entry(seq, &entries[i],
						   entry->addr, entry->primary);


		/* add primary/secondary records */
		/* add primary/secondary records */
				if (batadv_compare_eth(entry->addr,
		if (batadv_compare_eth(entry->addr, packet->vis_orig))
						       packet->vis_orig))
			batadv_vis_data_read_prim_sec(seq, list);
					buf_size +=
					  batadv_vis_cnt_prim_sec(&vis_if_list);

				buf_size += 1;
			}


			hlist_for_each_entry_safe(entry, pos, n, &vis_if_list,
		seq_printf(seq, "\n");
						  list) {
				hlist_del(&entry->list);
				kfree(entry);
	}
	}
}
}
		rcu_read_unlock();
	}


	buff = kmalloc(buf_size, GFP_ATOMIC);
static void batadv_vis_seq_print_text_bucket(struct seq_file *seq,
	if (!buff) {
					     const struct hlist_head *head)
		spin_unlock_bh(&bat_priv->vis_hash_lock);
{
		ret = -ENOMEM;
	struct hlist_node *node;
		goto out;
	struct vis_info *info;
	}
	struct vis_packet *packet;
	buff[0] = '\0';
	uint8_t *entries_pos;
	buff_pos = 0;
	struct vis_info_entry *entries;
	struct if_list_entry *entry;
	struct hlist_node *pos, *n;


	for (i = 0; i < hash->size; i++) {
	HLIST_HEAD(vis_if_list);
		head = &hash->table[i];


		rcu_read_lock();
	hlist_for_each_entry_rcu(info, node, head, hash_entry) {
	hlist_for_each_entry_rcu(info, node, head, hash_entry) {
		packet = (struct vis_packet *)info->skb_packet->data;
		packet = (struct vis_packet *)info->skb_packet->data;
			entries = (struct vis_info_entry *)
		entries_pos = (uint8_t *)packet + sizeof(*packet);
				((char *)packet + sizeof(*packet));
		entries = (struct vis_info_entry *)entries_pos;

			batadv_vis_data_insert_interface(packet->vis_orig,
							 &vis_if_list, true);


			for (j = 0; j < packet->entries; j++) {
		batadv_vis_data_insert_interface(packet->vis_orig, &vis_if_list,
				if (entries[j].quality == 0)
						 true);
					continue;
		batadv_vis_data_insert_interfaces(&vis_if_list, packet,
				if (batadv_compare_eth(entries[j].src,
						  entries);
						       packet->vis_orig))
		batadv_vis_data_read_entries(seq, &vis_if_list, packet,
					continue;
					     entries);
				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);


				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);
			hlist_del(&entry->list);
			kfree(entry);
			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);
	primary_if = batadv_primary_if_get_selected(bat_priv);
	kfree(buff);
	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:
out:
	if (primary_if)
	if (primary_if)