netlink: add RX/TX-ring support to netlink diag
authorPatrick McHardy <kaber@trash.net>
Wed, 17 Apr 2013 06:47:06 +0000 (06:47 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Apr 2013 18:57:58 +0000 (14:57 -0400)
Based on AF_PACKET.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/netlink_diag.h
net/netlink/diag.c

index 88009a3..4e31db4 100644 (file)
@@ -25,9 +25,18 @@ struct netlink_diag_msg {
        __u32   ndiag_cookie[2];
 };
 
+struct netlink_diag_ring {
+       __u32   ndr_block_size;
+       __u32   ndr_block_nr;
+       __u32   ndr_frame_size;
+       __u32   ndr_frame_nr;
+};
+
 enum {
        NETLINK_DIAG_MEMINFO,
        NETLINK_DIAG_GROUPS,
+       NETLINK_DIAG_RX_RING,
+       NETLINK_DIAG_TX_RING,
 
        __NETLINK_DIAG_MAX,
 };
@@ -38,5 +47,6 @@ enum {
 
 #define NDIAG_SHOW_MEMINFO     0x00000001 /* show memory info of a socket */
 #define NDIAG_SHOW_GROUPS      0x00000002 /* show groups of a netlink socket */
+#define NDIAG_SHOW_RING_CFG    0x00000004 /* show ring configuration */
 
 #endif
index 5ffb1d1..4e4aa47 100644 (file)
@@ -7,6 +7,34 @@
 
 #include "af_netlink.h"
 
+static int sk_diag_put_ring(struct netlink_ring *ring, int nl_type,
+                           struct sk_buff *nlskb)
+{
+       struct netlink_diag_ring ndr;
+
+       ndr.ndr_block_size = ring->pg_vec_pages << PAGE_SHIFT;
+       ndr.ndr_block_nr   = ring->pg_vec_len;
+       ndr.ndr_frame_size = ring->frame_size;
+       ndr.ndr_frame_nr   = ring->frame_max + 1;
+
+       return nla_put(nlskb, nl_type, sizeof(ndr), &ndr);
+}
+
+static int sk_diag_put_rings_cfg(struct sock *sk, struct sk_buff *nlskb)
+{
+       struct netlink_sock *nlk = nlk_sk(sk);
+       int ret;
+
+       mutex_lock(&nlk->pg_vec_lock);
+       ret = sk_diag_put_ring(&nlk->rx_ring, NETLINK_DIAG_RX_RING, nlskb);
+       if (!ret)
+               ret = sk_diag_put_ring(&nlk->tx_ring, NETLINK_DIAG_TX_RING,
+                                      nlskb);
+       mutex_unlock(&nlk->pg_vec_lock);
+
+       return ret;
+}
+
 static int sk_diag_dump_groups(struct sock *sk, struct sk_buff *nlskb)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
@@ -51,6 +79,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
            sock_diag_put_meminfo(sk, skb, NETLINK_DIAG_MEMINFO))
                goto out_nlmsg_trim;
 
+       if ((req->ndiag_show & NDIAG_SHOW_RING_CFG) &&
+           sk_diag_put_rings_cfg(sk, skb))
+               goto out_nlmsg_trim;
+
        return nlmsg_end(skb, nlh);
 
 out_nlmsg_trim: