netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning)
@ 2012-08-13 15:47 Pavel Emelyanov
  2012-08-13 15:49 ` [PATCH 1/4] packet: Introduce net/packet/internal.h header Pavel Emelyanov
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Pavel Emelyanov @ 2012-08-13 15:47 UTC (permalink / raw)
  To: Linux Netdev List, David Miller

There's a set of stuff residing on a AF_PACKET socket which is currently
write-only -- rings, copy_thresh and mclist. But we need to know these
while doing the checkpoint-restore.

As a solution for the similar problem with unix sockets, the sock-diag
engine was developed, so here's the basic implementation of the packet
sockets extension. It doesn't report rings, fanout and stats, but it can
be easily added later.

I'd like to mention, that it's not a strict requirement, that the diag is
used for getting info about sockets, it would be perfectly fine just to
fix the packet getsockopt callback to return the desired info. So, if the
diag for packet sockets is for any reason unacceptable, just let me know.

Thanks,
Pavel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/4] packet: Introduce net/packet/internal.h header
  2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
@ 2012-08-13 15:49 ` Pavel Emelyanov
  2012-08-13 15:53 ` [PATCH 2/4] packet: Diag core and basic socket info dumping Pavel Emelyanov
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Emelyanov @ 2012-08-13 15:49 UTC (permalink / raw)
  To: Linux Netdev List, David Miller

The diag module will need to access some private packet_sock data, so
move it to a header in advance. This file will be shared between the
af_packet.c and the diag.c

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 net/packet/af_packet.c |   99 +---------------------------------------------
 net/packet/internal.h  |  103 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 97 deletions(-)
 create mode 100644 net/packet/internal.h

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index ceaca7c..8a1605a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -93,6 +93,8 @@
 #include <net/inet_common.h>
 #endif
 
+#include "internal.h"
+
 /*
    Assumptions:
    - if device has no dev->hard_header routine, it adds and removes ll header
@@ -146,14 +148,6 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it)
 
 /* Private packet socket structures. */
 
-struct packet_mclist {
-	struct packet_mclist	*next;
-	int			ifindex;
-	int			count;
-	unsigned short		type;
-	unsigned short		alen;
-	unsigned char		addr[MAX_ADDR_LEN];
-};
 /* identical to struct packet_mreq except it has
  * a longer address field.
  */
@@ -175,63 +169,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 #define BLK_PLUS_PRIV(sz_of_priv) \
 	(BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT))
 
-/* kbdq - kernel block descriptor queue */
-struct tpacket_kbdq_core {
-	struct pgv	*pkbdq;
-	unsigned int	feature_req_word;
-	unsigned int	hdrlen;
-	unsigned char	reset_pending_on_curr_blk;
-	unsigned char   delete_blk_timer;
-	unsigned short	kactive_blk_num;
-	unsigned short	blk_sizeof_priv;
-
-	/* last_kactive_blk_num:
-	 * trick to see if user-space has caught up
-	 * in order to avoid refreshing timer when every single pkt arrives.
-	 */
-	unsigned short	last_kactive_blk_num;
-
-	char		*pkblk_start;
-	char		*pkblk_end;
-	int		kblk_size;
-	unsigned int	knum_blocks;
-	uint64_t	knxt_seq_num;
-	char		*prev;
-	char		*nxt_offset;
-	struct sk_buff	*skb;
-
-	atomic_t	blk_fill_in_prog;
-
-	/* Default is set to 8ms */
-#define DEFAULT_PRB_RETIRE_TOV	(8)
-
-	unsigned short  retire_blk_tov;
-	unsigned short  version;
-	unsigned long	tov_in_jiffies;
-
-	/* timer to retire an outstanding block */
-	struct timer_list retire_blk_timer;
-};
-
 #define PGV_FROM_VMALLOC 1
-struct pgv {
-	char *buffer;
-};
-
-struct packet_ring_buffer {
-	struct pgv		*pg_vec;
-	unsigned int		head;
-	unsigned int		frames_per_block;
-	unsigned int		frame_size;
-	unsigned int		frame_max;
-
-	unsigned int		pg_vec_order;
-	unsigned int		pg_vec_pages;
-	unsigned int		pg_vec_len;
-
-	struct tpacket_kbdq_core	prb_bdqc;
-	atomic_t		pending;
-};
 
 #define BLOCK_STATUS(x)	((x)->hdr.bh1.block_status)
 #define BLOCK_NUM_PKTS(x)	((x)->hdr.bh1.num_pkts)
@@ -269,34 +207,6 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *,
 		struct tpacket3_hdr *);
 static void packet_flush_mclist(struct sock *sk);
 
-struct packet_fanout;
-struct packet_sock {
-	/* struct sock has to be the first member of packet_sock */
-	struct sock		sk;
-	struct packet_fanout	*fanout;
-	struct tpacket_stats	stats;
-	union  tpacket_stats_u	stats_u;
-	struct packet_ring_buffer	rx_ring;
-	struct packet_ring_buffer	tx_ring;
-	int			copy_thresh;
-	spinlock_t		bind_lock;
-	struct mutex		pg_vec_lock;
-	unsigned int		running:1,	/* prot_hook is attached*/
-				auxdata:1,
-				origdev:1,
-				has_vnet_hdr:1;
-	int			ifindex;	/* bound device		*/
-	__be16			num;
-	struct packet_mclist	*mclist;
-	atomic_t		mapped;
-	enum tpacket_versions	tp_version;
-	unsigned int		tp_hdrlen;
-	unsigned int		tp_reserve;
-	unsigned int		tp_loss:1;
-	unsigned int		tp_tstamp;
-	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
-};
-
 #define PACKET_FANOUT_MAX	256
 
 struct packet_fanout {
@@ -334,11 +244,6 @@ struct packet_skb_cb {
 	(((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \
 	((x)->kactive_blk_num+1) : 0)
 
-static struct packet_sock *pkt_sk(struct sock *sk)
-{
-	return (struct packet_sock *)sk;
-}
-
 static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
 static void __fanout_link(struct sock *sk, struct packet_sock *po);
 
diff --git a/net/packet/internal.h b/net/packet/internal.h
new file mode 100644
index 0000000..2c5fca2
--- /dev/null
+++ b/net/packet/internal.h
@@ -0,0 +1,103 @@
+#ifndef __PACKET_INTERNAL_H__
+#define __PACKET_INTERNAL_H__
+
+struct packet_mclist {
+	struct packet_mclist	*next;
+	int			ifindex;
+	int			count;
+	unsigned short		type;
+	unsigned short		alen;
+	unsigned char		addr[MAX_ADDR_LEN];
+};
+
+/* kbdq - kernel block descriptor queue */
+struct tpacket_kbdq_core {
+	struct pgv	*pkbdq;
+	unsigned int	feature_req_word;
+	unsigned int	hdrlen;
+	unsigned char	reset_pending_on_curr_blk;
+	unsigned char   delete_blk_timer;
+	unsigned short	kactive_blk_num;
+	unsigned short	blk_sizeof_priv;
+
+	/* last_kactive_blk_num:
+	 * trick to see if user-space has caught up
+	 * in order to avoid refreshing timer when every single pkt arrives.
+	 */
+	unsigned short	last_kactive_blk_num;
+
+	char		*pkblk_start;
+	char		*pkblk_end;
+	int		kblk_size;
+	unsigned int	knum_blocks;
+	uint64_t	knxt_seq_num;
+	char		*prev;
+	char		*nxt_offset;
+	struct sk_buff	*skb;
+
+	atomic_t	blk_fill_in_prog;
+
+	/* Default is set to 8ms */
+#define DEFAULT_PRB_RETIRE_TOV	(8)
+
+	unsigned short  retire_blk_tov;
+	unsigned short  version;
+	unsigned long	tov_in_jiffies;
+
+	/* timer to retire an outstanding block */
+	struct timer_list retire_blk_timer;
+};
+
+struct pgv {
+	char *buffer;
+};
+
+struct packet_ring_buffer {
+	struct pgv		*pg_vec;
+	unsigned int		head;
+	unsigned int		frames_per_block;
+	unsigned int		frame_size;
+	unsigned int		frame_max;
+
+	unsigned int		pg_vec_order;
+	unsigned int		pg_vec_pages;
+	unsigned int		pg_vec_len;
+
+	struct tpacket_kbdq_core	prb_bdqc;
+	atomic_t		pending;
+};
+
+struct packet_fanout;
+struct packet_sock {
+	/* struct sock has to be the first member of packet_sock */
+	struct sock		sk;
+	struct packet_fanout	*fanout;
+	struct tpacket_stats	stats;
+	union  tpacket_stats_u	stats_u;
+	struct packet_ring_buffer	rx_ring;
+	struct packet_ring_buffer	tx_ring;
+	int			copy_thresh;
+	spinlock_t		bind_lock;
+	struct mutex		pg_vec_lock;
+	unsigned int		running:1,	/* prot_hook is attached*/
+				auxdata:1,
+				origdev:1,
+				has_vnet_hdr:1;
+	int			ifindex;	/* bound device		*/
+	__be16			num;
+	struct packet_mclist	*mclist;
+	atomic_t		mapped;
+	enum tpacket_versions	tp_version;
+	unsigned int		tp_hdrlen;
+	unsigned int		tp_reserve;
+	unsigned int		tp_loss:1;
+	unsigned int		tp_tstamp;
+	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
+};
+
+static struct packet_sock *pkt_sk(struct sock *sk)
+{
+	return (struct packet_sock *)sk;
+}
+
+#endif
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] packet: Diag core and basic socket info dumping
  2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
  2012-08-13 15:49 ` [PATCH 1/4] packet: Introduce net/packet/internal.h header Pavel Emelyanov
@ 2012-08-13 15:53 ` Pavel Emelyanov
  2012-08-13 15:55 ` [PATCH 2/4] packet: Report more packet sk info via diag module Pavel Emelyanov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Emelyanov @ 2012-08-13 15:53 UTC (permalink / raw)
  To: Linux Netdev List, David Miller

The diag module can be built independently from the af_packet.ko one,
just like it's done in unix sockets.

The core dumping message carries the info available at socket creation
time, i.e. family, type and protocol (in the same byte order as shown in
the proc file).

The socket inode number and cookie is reserved for future per-socket info
retrieving. The per-protocol filtering is also reserved for future by
requiring the sdiag_protocol to be zero.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/Kbuild        |    1 +
 include/linux/packet_diag.h |   24 ++++++++++
 net/packet/Kconfig          |    8 +++
 net/packet/Makefile         |    2 +
 net/packet/diag.c           |  104 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 139 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/packet_diag.h
 create mode 100644 net/packet/diag.c

diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index d9a7544..d823d60 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -195,6 +195,7 @@ header-y += in_route.h
 header-y += sock_diag.h
 header-y += inet_diag.h
 header-y += unix_diag.h
+header-y += packet_diag.h
 header-y += inotify.h
 header-y += input.h
 header-y += ioctl.h
diff --git a/include/linux/packet_diag.h b/include/linux/packet_diag.h
new file mode 100644
index 0000000..fa19300
--- /dev/null
+++ b/include/linux/packet_diag.h
@@ -0,0 +1,24 @@
+#ifndef __PACKET_DIAG_H__
+#define __PACKET_DIAG_H__
+
+#include <linux/types.h>
+
+struct packet_diag_req {
+	__u8	sdiag_family;
+	__u8	sdiag_protocol;
+	__u16	pad;
+	__u32	pdiag_ino;
+	__u32	pdiag_show;
+	__u32	pdiag_cookie[2];
+};
+
+struct packet_diag_msg {
+	__u8	pdiag_family;
+	__u8	pdiag_type;
+	__u16	pdiag_num;
+
+	__u32	pdiag_ino;
+	__u32	pdiag_cookie[2];
+};
+
+#endif
diff --git a/net/packet/Kconfig b/net/packet/Kconfig
index 0060e3b..cc55b35 100644
--- a/net/packet/Kconfig
+++ b/net/packet/Kconfig
@@ -14,3 +14,11 @@ config PACKET
 	  be called af_packet.
 
 	  If unsure, say Y.
+
+config PACKET_DIAG
+	tristate "Packet: sockets monitoring interface"
+	depends on PACKET
+	default n
+	---help---
+	  Support for PF_PACKET sockets monitoring interface used by the ss tool.
+	  If unsure, say Y.
diff --git a/net/packet/Makefile b/net/packet/Makefile
index 81183ea..9df6134 100644
--- a/net/packet/Makefile
+++ b/net/packet/Makefile
@@ -3,3 +3,5 @@
 #
 
 obj-$(CONFIG_PACKET) += af_packet.o
+obj-$(CONFIG_PACKET_DIAG) += af_packet_diag.o
+af_packet_diag-y += diag.o
diff --git a/net/packet/diag.c b/net/packet/diag.c
new file mode 100644
index 0000000..ff2f7f5
--- /dev/null
+++ b/net/packet/diag.c
@@ -0,0 +1,104 @@
+#include <linux/module.h>
+#include <linux/sock_diag.h>
+#include <linux/net.h>
+#include <linux/packet_diag.h>
+#include <net/net_namespace.h>
+#include <net/sock.h>
+
+#include "internal.h"
+
+static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req,
+		u32 pid, u32 seq, u32 flags, int sk_ino)
+{
+	struct nlmsghdr *nlh;
+	struct packet_diag_msg *rp;
+	const struct packet_sock *po = pkt_sk(sk);
+
+	nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags);
+	if (!nlh)
+		return -EMSGSIZE;
+
+	rp = nlmsg_data(nlh);
+	rp->pdiag_family = AF_PACKET;
+	rp->pdiag_type = sk->sk_type;
+	rp->pdiag_num = ntohs(po->num);
+	rp->pdiag_ino = sk_ino;
+	sock_diag_save_cookie(sk, rp->pdiag_cookie);
+
+	return nlmsg_end(skb, nlh);
+}
+
+static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int num = 0, s_num = cb->args[0];
+	struct packet_diag_req *req;
+	struct net *net;
+	struct sock *sk;
+	struct hlist_node *node;
+
+	net = sock_net(skb->sk);
+	req = nlmsg_data(cb->nlh);
+
+	rcu_read_lock();
+	sk_for_each_rcu(sk, node, &net->packet.sklist) {
+		if (!net_eq(sock_net(sk), net))
+			continue;
+		if (num < s_num)
+			goto next;
+
+		if (sk_diag_fill(sk, skb, req, NETLINK_CB(cb->skb).pid,
+					cb->nlh->nlmsg_seq, NLM_F_MULTI,
+					sock_i_ino(sk)) < 0)
+			goto done;
+next:
+		num++;
+	}
+done:
+	rcu_read_unlock();
+	cb->args[0] = num;
+
+	return skb->len;
+}
+
+static int packet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
+{
+	int hdrlen = sizeof(struct packet_diag_req);
+	struct net *net = sock_net(skb->sk);
+	struct packet_diag_req *req;
+
+	if (nlmsg_len(h) < hdrlen)
+		return -EINVAL;
+
+	req = nlmsg_data(h);
+	/* Make it possible to support protocol filtering later */
+	if (req->sdiag_protocol)
+		return -EINVAL;
+
+	if (h->nlmsg_flags & NLM_F_DUMP) {
+		struct netlink_dump_control c = {
+			.dump = packet_diag_dump,
+		};
+		return netlink_dump_start(net->diag_nlsk, skb, h, &c);
+	} else
+		return -EOPNOTSUPP;
+}
+
+static const struct sock_diag_handler packet_diag_handler = {
+	.family = AF_PACKET,
+	.dump = packet_diag_handler_dump,
+};
+
+static int __init packet_diag_init(void)
+{
+	return sock_diag_register(&packet_diag_handler);
+}
+
+static void __exit packet_diag_exit(void)
+{
+	sock_diag_unregister(&packet_diag_handler);
+}
+
+module_init(packet_diag_init);
+module_exit(packet_diag_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */);
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] packet: Report more packet sk info via diag module
  2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
  2012-08-13 15:49 ` [PATCH 1/4] packet: Introduce net/packet/internal.h header Pavel Emelyanov
  2012-08-13 15:53 ` [PATCH 2/4] packet: Diag core and basic socket info dumping Pavel Emelyanov
@ 2012-08-13 15:55 ` Pavel Emelyanov
  2012-08-13 15:57 ` [PATCH 4/4] packet: Report socket mclist " Pavel Emelyanov
  2012-08-14 23:56 ` [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Emelyanov @ 2012-08-13 15:55 UTC (permalink / raw)
  To: Linux Netdev List, David Miller

This reports in one rtattr message all the other scalar values, that can be
set on a packet socket with setsockopt.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/packet_diag.h |   23 +++++++++++++++++++++++
 net/packet/diag.c           |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/include/linux/packet_diag.h b/include/linux/packet_diag.h
index fa19300..3781ea4 100644
--- a/include/linux/packet_diag.h
+++ b/include/linux/packet_diag.h
@@ -12,6 +12,8 @@ struct packet_diag_req {
 	__u32	pdiag_cookie[2];
 };
 
+#define PACKET_SHOW_INFO	0x00000001 /* Basic packet_sk information */
+
 struct packet_diag_msg {
 	__u8	pdiag_family;
 	__u8	pdiag_type;
@@ -21,4 +23,25 @@ struct packet_diag_msg {
 	__u32	pdiag_cookie[2];
 };
 
+enum {
+	PACKET_DIAG_INFO,
+
+	PACKET_DIAG_MAX,
+};
+
+struct packet_diag_info {
+	__u32	pdi_index;
+	__u32	pdi_version;
+	__u32	pdi_reserve;
+	__u32	pdi_copy_thresh;
+	__u32	pdi_tstamp;
+	__u32	pdi_flags;
+
+#define PDI_RUNNING	0x1
+#define PDI_AUXDATA	0x2
+#define PDI_ORIGDEV	0x4
+#define PDI_VNETHDR	0x8
+#define PDI_LOSS	0x10
+};
+
 #endif
diff --git a/net/packet/diag.c b/net/packet/diag.c
index ff2f7f5..d5bd037 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -7,6 +7,31 @@
 
 #include "internal.h"
 
+static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb)
+{
+	struct packet_diag_info pinfo;
+
+	pinfo.pdi_index = po->ifindex;
+	pinfo.pdi_version = po->tp_version;
+	pinfo.pdi_reserve = po->tp_reserve;
+	pinfo.pdi_copy_thresh = po->copy_thresh;
+	pinfo.pdi_tstamp = po->tp_tstamp;
+
+	pinfo.pdi_flags = 0;
+	if (po->running)
+		pinfo.pdi_flags |= PDI_RUNNING;
+	if (po->auxdata)
+		pinfo.pdi_flags |= PDI_AUXDATA;
+	if (po->origdev)
+		pinfo.pdi_flags |= PDI_ORIGDEV;
+	if (po->has_vnet_hdr)
+		pinfo.pdi_flags |= PDI_VNETHDR;
+	if (po->tp_loss)
+		pinfo.pdi_flags |= PDI_LOSS;
+
+	return nla_put(nlskb, PACKET_DIAG_INFO, sizeof(pinfo), &pinfo);
+}
+
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req,
 		u32 pid, u32 seq, u32 flags, int sk_ino)
 {
@@ -25,7 +50,15 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag
 	rp->pdiag_ino = sk_ino;
 	sock_diag_save_cookie(sk, rp->pdiag_cookie);
 
+	if ((req->pdiag_show & PACKET_SHOW_INFO) &&
+			pdiag_put_info(po, skb))
+		goto out_nlmsg_trim;
+
 	return nlmsg_end(skb, nlh);
+
+out_nlmsg_trim:
+	nlmsg_cancel(skb, nlh);
+	return -EMSGSIZE;
 }
 
 static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] packet: Report socket mclist info via diag module
  2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
                   ` (2 preceding siblings ...)
  2012-08-13 15:55 ` [PATCH 2/4] packet: Report more packet sk info via diag module Pavel Emelyanov
@ 2012-08-13 15:57 ` Pavel Emelyanov
  2012-08-14 23:56 ` [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Pavel Emelyanov @ 2012-08-13 15:57 UTC (permalink / raw)
  To: Linux Netdev List, David Miller

The info is reported as an array of packet_diag_mclist structures. Each
includes not only the directly configured values (index, type, etc), but
also the "count".

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---
 include/linux/packet_diag.h |   10 ++++++++++
 net/packet/diag.c           |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/include/linux/packet_diag.h b/include/linux/packet_diag.h
index 3781ea4..ea2e8923 100644
--- a/include/linux/packet_diag.h
+++ b/include/linux/packet_diag.h
@@ -13,6 +13,7 @@ struct packet_diag_req {
 };
 
 #define PACKET_SHOW_INFO	0x00000001 /* Basic packet_sk information */
+#define PACKET_SHOW_MCLIST	0x00000002 /* A set of packet_diag_mclist-s */
 
 struct packet_diag_msg {
 	__u8	pdiag_family;
@@ -25,6 +26,7 @@ struct packet_diag_msg {
 
 enum {
 	PACKET_DIAG_INFO,
+	PACKET_DIAG_MCLIST,
 
 	PACKET_DIAG_MAX,
 };
@@ -44,4 +46,12 @@ struct packet_diag_info {
 #define PDI_LOSS	0x10
 };
 
+struct packet_diag_mclist {
+	__u32	pdmc_index;
+	__u32	pdmc_count;
+	__u16	pdmc_type;
+	__u16	pdmc_alen;
+	__u8	pdmc_addr[MAX_ADDR_LEN];
+};
+
 #endif
diff --git a/net/packet/diag.c b/net/packet/diag.c
index d5bd037..3dda4ec 100644
--- a/net/packet/diag.c
+++ b/net/packet/diag.c
@@ -1,6 +1,7 @@
 #include <linux/module.h>
 #include <linux/sock_diag.h>
 #include <linux/net.h>
+#include <linux/netdevice.h>
 #include <linux/packet_diag.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
@@ -32,6 +33,40 @@ static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb)
 	return nla_put(nlskb, PACKET_DIAG_INFO, sizeof(pinfo), &pinfo);
 }
 
+static int pdiag_put_mclist(const struct packet_sock *po, struct sk_buff *nlskb)
+{
+	struct nlattr *mca;
+	struct packet_mclist *ml;
+
+	mca = nla_nest_start(nlskb, PACKET_DIAG_MCLIST);
+	if (!mca)
+		return -EMSGSIZE;
+
+	rtnl_lock();
+	for (ml = po->mclist; ml; ml = ml->next) {
+		struct packet_diag_mclist *dml;
+
+		dml = nla_reserve_nohdr(nlskb, sizeof(*dml));
+		if (!dml) {
+			rtnl_unlock();
+			nla_nest_cancel(nlskb, mca);
+			return -EMSGSIZE;
+		}
+
+		dml->pdmc_index = ml->ifindex;
+		dml->pdmc_type = ml->type;
+		dml->pdmc_alen = ml->alen;
+		dml->pdmc_count = ml->count;
+		BUILD_BUG_ON(sizeof(dml->pdmc_addr) != sizeof(ml->addr));
+		memcpy(dml->pdmc_addr, ml->addr, sizeof(ml->addr));
+	}
+
+	rtnl_unlock();
+	nla_nest_end(nlskb, mca);
+
+	return 0;
+}
+
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req,
 		u32 pid, u32 seq, u32 flags, int sk_ino)
 {
@@ -54,6 +89,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag
 			pdiag_put_info(po, skb))
 		goto out_nlmsg_trim;
 
+	if ((req->pdiag_show & PACKET_SHOW_MCLIST) &&
+			pdiag_put_mclist(po, skb))
+		goto out_nlmsg_trim;
+
 	return nlmsg_end(skb, nlh);
 
 out_nlmsg_trim:
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning)
  2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
                   ` (3 preceding siblings ...)
  2012-08-13 15:57 ` [PATCH 4/4] packet: Report socket mclist " Pavel Emelyanov
@ 2012-08-14 23:56 ` David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2012-08-14 23:56 UTC (permalink / raw)
  To: xemul; +Cc: netdev

From: Pavel Emelyanov <xemul@parallels.com>
Date: Mon, 13 Aug 2012 19:47:40 +0400

> There's a set of stuff residing on a AF_PACKET socket which is currently
> write-only -- rings, copy_thresh and mclist. But we need to know these
> while doing the checkpoint-restore.
> 
> As a solution for the similar problem with unix sockets, the sock-diag
> engine was developed, so here's the basic implementation of the packet
> sockets extension. It doesn't report rings, fanout and stats, but it can
> be easily added later.
> 
> I'd like to mention, that it's not a strict requirement, that the diag is
> used for getting info about sockets, it would be perfectly fine just to
> fix the packet getsockopt callback to return the desired info. So, if the
> diag for packet sockets is for any reason unacceptable, just let me know.

All applied, looks fine.

Please number your patches properly next time, patch #3 was listed as 2/4

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-08-14 23:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-13 15:47 [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) Pavel Emelyanov
2012-08-13 15:49 ` [PATCH 1/4] packet: Introduce net/packet/internal.h header Pavel Emelyanov
2012-08-13 15:53 ` [PATCH 2/4] packet: Diag core and basic socket info dumping Pavel Emelyanov
2012-08-13 15:55 ` [PATCH 2/4] packet: Report more packet sk info via diag module Pavel Emelyanov
2012-08-13 15:57 ` [PATCH 4/4] packet: Report socket mclist " Pavel Emelyanov
2012-08-14 23:56 ` [PATCH net-next 0/4] packet: Sock-diag extension for packet sockets (beginning) David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).