Skip to content

Commit

Permalink
Merge branch 'vlan_tpid'
Browse files Browse the repository at this point in the history
Atzm Watanabe says:

====================
packet: deliver VLAN TPID to userspace

This patchset enables userspace to get VLAN TPID as well as the VLAN TCI.

After the 802.1AD support, userspace packet receivers (packet dumper,
software switch, and the like) need how to know VLAN TPID in order to
reconstruct original tagged frame.

v4: Simply use sizeof(tp_padding) for zeroing the padding bytes,
    commented by David Laight.
    Use __u16 for tp_vlan_tpid in tpacket_hdr_variant1,
    commented by Daniel Borkmann.

v3: Add a definition which indicates whether tp_vlan_tpid is valid.
    Explicitly define pad bytes for tpacket{2,3}_hdr and pick the area
    for tp_vlan_tpid from the definition.  Commented by David Laight.

v2: Add BUILD_BUG_ON() to make current aligned size of
    struct tpacket{2,3}_hdr clear.  Commented by Ben Hutchings.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 18, 2013
2 parents 9f605ac + a0cdfcf commit a58f7f8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
23 changes: 14 additions & 9 deletions include/uapi/linux/if_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,18 @@ struct tpacket_auxdata {
__u16 tp_mac;
__u16 tp_net;
__u16 tp_vlan_tci;
__u16 tp_padding;
__u16 tp_vlan_tpid;
};

/* Rx ring - header status */
#define TP_STATUS_KERNEL 0
#define TP_STATUS_USER (1 << 0)
#define TP_STATUS_COPY (1 << 1)
#define TP_STATUS_LOSING (1 << 2)
#define TP_STATUS_CSUMNOTREADY (1 << 3)
#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */
#define TP_STATUS_BLK_TMO (1 << 5)
#define TP_STATUS_KERNEL 0
#define TP_STATUS_USER (1 << 0)
#define TP_STATUS_COPY (1 << 1)
#define TP_STATUS_LOSING (1 << 2)
#define TP_STATUS_CSUMNOTREADY (1 << 3)
#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */
#define TP_STATUS_BLK_TMO (1 << 5)
#define TP_STATUS_VLAN_TPID_VALID (1 << 6) /* auxdata has valid tp_vlan_tpid */

/* Tx ring - header status */
#define TP_STATUS_AVAILABLE 0
Expand Down Expand Up @@ -133,12 +134,15 @@ struct tpacket2_hdr {
__u32 tp_sec;
__u32 tp_nsec;
__u16 tp_vlan_tci;
__u16 tp_padding;
__u16 tp_vlan_tpid;
__u8 tp_padding[4];
};

struct tpacket_hdr_variant1 {
__u32 tp_rxhash;
__u32 tp_vlan_tci;
__u16 tp_vlan_tpid;
__u16 tp_padding;
};

struct tpacket3_hdr {
Expand All @@ -154,6 +158,7 @@ struct tpacket3_hdr {
union {
struct tpacket_hdr_variant1 hv1;
};
__u8 tp_padding[8];
};

struct tpacket_bd_ts {
Expand Down
24 changes: 19 additions & 5 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,16 +977,19 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
{
if (vlan_tx_tag_present(pkc->skb)) {
ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb);
ppd->tp_status = TP_STATUS_VLAN_VALID;
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->vlan_proto);
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
ppd->hv1.tp_vlan_tci = 0;
ppd->hv1.tp_vlan_tpid = 0;
ppd->tp_status = TP_STATUS_AVAILABLE;
}
}

static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc,
struct tpacket3_hdr *ppd)
{
ppd->hv1.tp_padding = 0;
prb_fill_vlan_info(pkc, ppd);

if (pkc->feature_req_word & TP_FT_REQ_FILL_RXHASH)
Expand Down Expand Up @@ -1812,6 +1815,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
struct timespec ts;
__u32 ts_status;

/* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT.
* We may add members to them until current aligned size without forcing
* userspace to call getsockopt(..., PACKET_HDRLEN, ...).
*/
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);

if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;

Expand Down Expand Up @@ -1918,11 +1928,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
h.h2->tp_nsec = ts.tv_nsec;
if (vlan_tx_tag_present(skb)) {
h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
status |= TP_STATUS_VLAN_VALID;
h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto);
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
h.h2->tp_vlan_tci = 0;
h.h2->tp_vlan_tpid = 0;
}
h.h2->tp_padding = 0;
memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding));
hdrlen = sizeof(*h.h2);
break;
case TPACKET_V3:
Expand All @@ -1936,6 +1948,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
h.h3->tp_net = netoff;
h.h3->tp_sec = ts.tv_sec;
h.h3->tp_nsec = ts.tv_nsec;
memset(h.h3->tp_padding, 0, sizeof(h.h3->tp_padding));
hdrlen = sizeof(*h.h3);
break;
default:
Expand Down Expand Up @@ -2867,11 +2880,12 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
aux.tp_net = skb_network_offset(skb);
if (vlan_tx_tag_present(skb)) {
aux.tp_vlan_tci = vlan_tx_tag_get(skb);
aux.tp_status |= TP_STATUS_VLAN_VALID;
aux.tp_vlan_tpid = ntohs(skb->vlan_proto);
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
} else {
aux.tp_vlan_tci = 0;
aux.tp_vlan_tpid = 0;
}
aux.tp_padding = 0;
put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
}

Expand Down

0 comments on commit a58f7f8

Please sign in to comment.