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

Commit 9f0a6aca authored by Jianguo Wu's avatar Jianguo Wu Committed by Greg Kroah-Hartman
Browse files

net-procfs: show net devices bound packet types



commit 1d10f8a1f40b965d449e8f2d5ed7b96a7c138b77 upstream.

After commit:7866a621 ("dev: add per net_device packet type chains"),
we can not get packet types that are bound to a specified net device by
/proc/net/ptype, this patch fix the regression.

Run "tcpdump -i ens192 udp -nns0" Before and after apply this patch:

Before:
  [root@localhost ~]# cat /proc/net/ptype
  Type Device      Function
  0800          ip_rcv
  0806          arp_rcv
  86dd          ipv6_rcv

After:
  [root@localhost ~]# cat /proc/net/ptype
  Type Device      Function
  ALL  ens192   tpacket_rcv
  0800          ip_rcv
  0806          arp_rcv
  86dd          ipv6_rcv

v1 -> v2:
  - fix the regression rather than adding new /proc API as
    suggested by Stephen Hemminger.

Fixes: 7866a621 ("dev: add per net_device packet type chains")
Signed-off-by: default avatarJianguo Wu <wujianguo@chinatelecom.cn>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4fd45ff2
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -182,12 +182,23 @@ static const struct seq_operations softnet_seq_ops = {
	.show  = softnet_seq_show,
};

static void *ptype_get_idx(loff_t pos)
static void *ptype_get_idx(struct seq_file *seq, loff_t pos)
{
	struct list_head *ptype_list = NULL;
	struct packet_type *pt = NULL;
	struct net_device *dev;
	loff_t i = 0;
	int t;

	for_each_netdev_rcu(seq_file_net(seq), dev) {
		ptype_list = &dev->ptype_all;
		list_for_each_entry_rcu(pt, ptype_list, list) {
			if (i == pos)
				return pt;
			++i;
		}
	}

	list_for_each_entry_rcu(pt, &ptype_all, list) {
		if (i == pos)
			return pt;
@@ -208,22 +219,40 @@ static void *ptype_seq_start(struct seq_file *seq, loff_t *pos)
	__acquires(RCU)
{
	rcu_read_lock();
	return *pos ? ptype_get_idx(*pos - 1) : SEQ_START_TOKEN;
	return *pos ? ptype_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
}

static void *ptype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct net_device *dev;
	struct packet_type *pt;
	struct list_head *nxt;
	int hash;

	++*pos;
	if (v == SEQ_START_TOKEN)
		return ptype_get_idx(0);
		return ptype_get_idx(seq, 0);

	pt = v;
	nxt = pt->list.next;
	if (pt->dev) {
		if (nxt != &pt->dev->ptype_all)
			goto found;

		dev = pt->dev;
		for_each_netdev_continue_rcu(seq_file_net(seq), dev) {
			if (!list_empty(&dev->ptype_all)) {
				nxt = dev->ptype_all.next;
				goto found;
			}
		}

		nxt = ptype_all.next;
		goto ptype_all;
	}

	if (pt->type == htons(ETH_P_ALL)) {
ptype_all:
		if (nxt != &ptype_all)
			goto found;
		hash = 0;