packet: Sock-diag extension for packet sockets (beginning)
Subsystems (3)
cover packet: Sock-diag extension for packet sockets (beginning)
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
PATCH 1/4 packet: Introduce net/packet/internal.h header
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
--- 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
net/packet/af_packet.c +2 -97
@@ -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 256struct 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);
net/packet/internal.h new file +103 -0
103 lines not on this page · raw message
Signature · 1 line
1.7.6.5
PATCH 2/4 packet: Diag core and basic socket info dumping
In reply to Pavel EmelyanovThe 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.
--- 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
include/linux/Kbuild +1 -0
@@ -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
include/linux/packet_diag.h new file +24 -0
@@ -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
net/packet/Kconfig +8 -0
@@ -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.
net/packet/Makefile +2 -0
@@ -3,3 +3,5 @@ # obj-$(CONFIG_PACKET) += af_packet.o +obj-$(CONFIG_PACKET_DIAG) += af_packet_diag.o +af_packet_diag-y += diag.o
net/packet/diag.c new file +104 -0
104 lines not on this page · raw message
Signature · 1 line
1.7.6.5
PATCH 2/4 packet: Report more packet sk info via diag module
In reply to Pavel EmelyanovThis reports in one rtattr message all the other scalar values, that can be set on a packet socket with setsockopt.
--- include/linux/packet_diag.h | 23 +++++++++++++++++++++++ net/packet/diag.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 0 deletions(-)
include/linux/packet_diag.h +23 -0
@@ -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
net/packet/diag.c +33 -0
@@ -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)
Signature · 1 line
1.7.6.5
PATCH 4/4 packet: Report socket mclist info via diag module
In reply to Pavel EmelyanovThe 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".
--- include/linux/packet_diag.h | 10 ++++++++++ net/packet/diag.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 0 deletions(-)
include/linux/packet_diag.h +10 -0
@@ -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
net/packet/diag.c +39 -0
@@ -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:
Signature · 1 line
1.7.6.5
David Miller
maintainerFrom: Pavel Emelyanov <[email protected]>
Date: Mon, 13 Aug 2012 19:47:40 +0400
Quoted 9 lines
There's a set of stuff residing on a
AF_PACKETsocket which is currently write-only -- rings,copy_threshand 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.
Quoted 4 lines
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