Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+33 -14
+14 -9
include/uapi/linux/if_packet.h
··· 84 84 __u16 tp_mac; 85 85 __u16 tp_net; 86 86 __u16 tp_vlan_tci; 87 - __u16 tp_padding; 87 + __u16 tp_vlan_tpid; 88 88 }; 89 89 90 90 /* 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 */ 98 99 99 100 /* Tx ring - header status */ 100 101 #define TP_STATUS_AVAILABLE 0 ··· 134 133 __u32 tp_sec; 135 134 __u32 tp_nsec; 136 135 __u16 tp_vlan_tci; 137 - __u16 tp_padding; 136 + __u16 tp_vlan_tpid; 137 + __u8 tp_padding[4]; 138 138 }; 139 139 140 140 struct tpacket_hdr_variant1 { 141 141 __u32 tp_rxhash; 142 142 __u32 tp_vlan_tci; 143 + __u16 tp_vlan_tpid; 144 + __u16 tp_padding; 143 145 }; 144 146 145 147 struct tpacket3_hdr { ··· 158 154 union { 159 155 struct tpacket_hdr_variant1 hv1; 160 156 }; 157 + __u8 tp_padding[8]; 161 158 }; 162 159 163 160 struct tpacket_bd_ts {
+19 -5
net/packet/af_packet.c
··· 977 977 { 978 978 if (vlan_tx_tag_present(pkc->skb)) { 979 979 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; 981 982 } else { 982 983 ppd->hv1.tp_vlan_tci = 0; 984 + ppd->hv1.tp_vlan_tpid = 0; 983 985 ppd->tp_status = TP_STATUS_AVAILABLE; 984 986 } 985 987 } ··· 989 987 static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc, 990 988 struct tpacket3_hdr *ppd) 991 989 { 990 + ppd->hv1.tp_padding = 0; 992 991 prb_fill_vlan_info(pkc, ppd); 993 992 994 993 if (pkc->feature_req_word & TP_FT_REQ_FILL_RXHASH) ··· 1815 1812 struct timespec ts; 1816 1813 __u32 ts_status; 1817 1814 1815 + /* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT. 1816 + * We may add members to them until current aligned size without forcing 1817 + * userspace to call getsockopt(..., PACKET_HDRLEN, ...). 1818 + */ 1819 + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h2)) != 32); 1820 + BUILD_BUG_ON(TPACKET_ALIGN(sizeof(*h.h3)) != 48); 1821 + 1818 1822 if (skb->pkt_type == PACKET_LOOPBACK) 1819 1823 goto drop; 1820 1824 ··· 1928 1918 h.h2->tp_nsec = ts.tv_nsec; 1929 1919 if (vlan_tx_tag_present(skb)) { 1930 1920 h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); 1931 - status |= TP_STATUS_VLAN_VALID; 1921 + h.h2->tp_vlan_tpid = ntohs(skb->vlan_proto); 1922 + status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID; 1932 1923 } else { 1933 1924 h.h2->tp_vlan_tci = 0; 1925 + h.h2->tp_vlan_tpid = 0; 1934 1926 } 1935 - h.h2->tp_padding = 0; 1927 + memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding)); 1936 1928 hdrlen = sizeof(*h.h2); 1937 1929 break; 1938 1930 case TPACKET_V3: ··· 1948 1936 h.h3->tp_net = netoff; 1949 1937 h.h3->tp_sec = ts.tv_sec; 1950 1938 h.h3->tp_nsec = ts.tv_nsec; 1939 + memset(h.h3->tp_padding, 0, sizeof(h.h3->tp_padding)); 1951 1940 hdrlen = sizeof(*h.h3); 1952 1941 break; 1953 1942 default: ··· 2880 2867 aux.tp_net = skb_network_offset(skb); 2881 2868 if (vlan_tx_tag_present(skb)) { 2882 2869 aux.tp_vlan_tci = vlan_tx_tag_get(skb); 2883 - aux.tp_status |= TP_STATUS_VLAN_VALID; 2870 + aux.tp_vlan_tpid = ntohs(skb->vlan_proto); 2871 + aux.tp_status |= TP_STATUS_VLAN_VALID | TP_STATUS_VLAN_TPID_VALID; 2884 2872 } else { 2885 2873 aux.tp_vlan_tci = 0; 2874 + aux.tp_vlan_tpid = 0; 2886 2875 } 2887 - aux.tp_padding = 0; 2888 2876 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); 2889 2877 } 2890 2878