Skip to content

Commit a58f7f8

Browse files
committed
Merge branch 'vlan_tpid'
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>
2 parents 9f605ac + a0cdfcf commit a58f7f8

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

include/uapi/linux/if_packet.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,18 @@ struct tpacket_auxdata {
8484
__u16 tp_mac;
8585
__u16 tp_net;
8686
__u16 tp_vlan_tci;
87-
__u16 tp_padding;
87+
__u16 tp_vlan_tpid;
8888
};
8989

9090
/* Rx ring - header status */
91-
#define TP_STATUS_KERNEL 0
92-
#define TP_STATUS_USER (1 << 0)
93-
#define TP_STATUS_COPY (1 << 1)
94-
#define TP_STATUS_LOSING (1 << 2)
95-
#define TP_STATUS_CSUMNOTREADY (1 << 3)
96-
#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */
97-
#define TP_STATUS_BLK_TMO (1 << 5)
91+
#define TP_STATUS_KERNEL 0
92+
#define TP_STATUS_USER (1 << 0)
93+
#define TP_STATUS_COPY (1 << 1)
94+
#define TP_STATUS_LOSING (1 << 2)
95+
#define TP_STATUS_CSUMNOTREADY (1 << 3)
96+
#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */
97+
#define TP_STATUS_BLK_TMO (1 << 5)
98+
#define TP_STATUS_VLAN_TPID_VALID (1 << 6) /* auxdata has valid tp_vlan_tpid */
9899

99100
/* Tx ring - header status */
100101
#define TP_STATUS_AVAILABLE 0
@@ -133,12 +134,15 @@ struct tpacket2_hdr {
133134
__u32 tp_sec;
134135
__u32 tp_nsec;
135136
__u16 tp_vlan_tci;
136-
__u16 tp_padding;
137+
__u16 tp_vlan_tpid;
138+
__u8 tp_padding[4];
137139
};
138140

139141
struct tpacket_hdr_variant1 {
140142
__u32 tp_rxhash;
141143
__u32 tp_vlan_tci;
144+
__u16 tp_vlan_tpid;
145+
__u16 tp_padding;
142146
};
143147

144148
struct tpacket3_hdr {
@@ -154,6 +158,7 @@ struct tpacket3_hdr {
154158
union {
155159
struct tpacket_hdr_variant1 hv1;
156160
};
161+
__u8 tp_padding[8];
157162
};
158163

159164
struct tpacket_bd_ts {

net/packet/af_packet.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,16 +977,19 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
977977
{
978978
if (vlan_tx_tag_present(pkc->skb)) {
979979
ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb);
980-
ppd->tp_status = TP_STATUS_VLAN_VALID;
980+
ppd->hv1.tp_vlan_tpid = ntohs(pkc->skb->vlan_proto);
981+
ppd->tp_status = TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
981982
} else {
982983
ppd->hv1.tp_vlan_tci = 0;
984+
ppd->hv1.tp_vlan_tpid = 0;
983985
ppd->tp_status = TP_STATUS_AVAILABLE;
984986
}
985987
}
986988

987989
static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc,
988990
struct tpacket3_hdr *ppd)
989991
{
992+
ppd->hv1.tp_padding = 0;
990993
prb_fill_vlan_info(pkc, ppd);
991994

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

1818+
/* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT.
1819+
* We may add members to them until current aligned size without forcing
1820+
* userspace to call getsockopt(..., PACKET_HDRLEN, ...).
1821+
*/
1822+
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32);
1823+
BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48);
1824+
18151825
if (skb->pkt_type == PACKET_LOOPBACK)
18161826
goto drop;
18171827

@@ -1918,11 +1928,13 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
19181928
h.h2->tp_nsec = ts.tv_nsec;
19191929
if (vlan_tx_tag_present(skb)) {
19201930
h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
1921-
status |= TP_STATUS_VLAN_VALID;
1931+
h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto);
1932+
status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
19221933
} else {
19231934
h.h2->tp_vlan_tci = 0;
1935+
h.h2->tp_vlan_tpid = 0;
19241936
}
1925-
h.h2->tp_padding = 0;
1937+
memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding));
19261938
hdrlen = sizeof(*h.h2);
19271939
break;
19281940
case TPACKET_V3:
@@ -1936,6 +1948,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
19361948
h.h3->tp_net = netoff;
19371949
h.h3->tp_sec = ts.tv_sec;
19381950
h.h3->tp_nsec = ts.tv_nsec;
1951+
memset(h.h3->tp_padding, 0, sizeof(h.h3->tp_padding));
19391952
hdrlen = sizeof(*h.h3);
19401953
break;
19411954
default:
@@ -2867,11 +2880,12 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
28672880
aux.tp_net = skb_network_offset(skb);
28682881
if (vlan_tx_tag_present(skb)) {
28692882
aux.tp_vlan_tci = vlan_tx_tag_get(skb);
2870-
aux.tp_status |= TP_STATUS_VLAN_VALID;
2883+
aux.tp_vlan_tpid = ntohs(skb->vlan_proto);
2884+
aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID;
28712885
} else {
28722886
aux.tp_vlan_tci = 0;
2887+
aux.tp_vlan_tpid = 0;
28732888
}
2874-
aux.tp_padding = 0;
28752889
put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
28762890
}
28772891

0 commit comments

Comments
 (0)