aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAtzm Watanabe <atzm@stratosphere.co.jp>2013-12-17 08:53:40 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-18 00:36:16 -0500
commita0cdfcf39362410d5ea983f4daf67b38de129408 (patch)
tree31de8d8010bafd58bade0701fb3f501bd6e4c0a7
parente4d26f4b080f55e9577b45e6b51a04971eb459e9 (diff)
packet: deliver VLAN TPID to userspace
This enables userspace to get VLAN TPID as well as the VLAN TCI. Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp> Acked-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/if_packet.h24
-rw-r--r--net/packet/af_packet.c14
2 files changed, 24 insertions, 14 deletions
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index 9185dc9a4485..e9d844c80c11 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -84,17 +84,18 @@ struct tpacket_auxdata {
84 __u16 tp_mac; 84 __u16 tp_mac;
85 __u16 tp_net; 85 __u16 tp_net;
86 __u16 tp_vlan_tci; 86 __u16 tp_vlan_tci;
87 __u16 tp_padding; 87 __u16 tp_vlan_tpid;
88}; 88};
89 89
90/* Rx ring - header status */ 90/* Rx ring - header status */
91#define TP_STATUS_KERNEL 0 91#define TP_STATUS_KERNEL 0
92#define TP_STATUS_USER (1 << 0) 92#define TP_STATUS_USER (1 << 0)
93#define TP_STATUS_COPY (1 << 1) 93#define TP_STATUS_COPY (1 << 1)
94#define TP_STATUS_LOSING (1 << 2) 94#define TP_STATUS_LOSING (1 << 2)
95#define TP_STATUS_CSUMNOTREADY (1 << 3) 95#define TP_STATUS_CSUMNOTREADY (1 << 3)
96#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */ 96#define TP_STATUS_VLAN_VALID (1 << 4) /* auxdata has valid tp_vlan_tci */
97#define TP_STATUS_BLK_TMO (1 << 5) 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/* Tx ring - header status */ 100/* Tx ring - header status */
100#define TP_STATUS_AVAILABLE 0 101#define TP_STATUS_AVAILABLE 0
@@ -133,12 +134,15 @@ struct tpacket2_hdr {
133 __u32 tp_sec; 134 __u32 tp_sec;
134 __u32 tp_nsec; 135 __u32 tp_nsec;
135 __u16 tp_vlan_tci; 136 __u16 tp_vlan_tci;
136 __u8 tp_padding[6]; 137 __u16 tp_vlan_tpid;
138 __u8 tp_padding[4];
137}; 139};
138 140
139struct tpacket_hdr_variant1 { 141struct tpacket_hdr_variant1 {
140 __u32 tp_rxhash; 142 __u32 tp_rxhash;
141 __u32 tp_vlan_tci; 143 __u32 tp_vlan_tci;
144 __u16 tp_vlan_tpid;
145 __u16 tp_padding;
142}; 146};
143 147
144struct tpacket3_hdr { 148struct tpacket3_hdr {
@@ -154,7 +158,7 @@ struct tpacket3_hdr {
154 union { 158 union {
155 struct tpacket_hdr_variant1 hv1; 159 struct tpacket_hdr_variant1 hv1;
156 }; 160 };
157 __u8 tp_padding[12]; 161 __u8 tp_padding[8];
158}; 162};
159 163
160struct tpacket_bd_ts { 164struct tpacket_bd_ts {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f281999ba92e..dd3840846ce2 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -977,9 +977,11 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
977{ 977{
978 if (vlan_tx_tag_present(pkc->skb)) { 978 if (vlan_tx_tag_present(pkc->skb)) {
979 ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb); 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 } else { 982 } else {
982 ppd->hv1.tp_vlan_tci = 0; 983 ppd->hv1.tp_vlan_tci = 0;
984 ppd->hv1.tp_vlan_tpid = 0;
983 ppd->tp_status = TP_STATUS_AVAILABLE; 985 ppd->tp_status = TP_STATUS_AVAILABLE;
984 } 986 }
985} 987}
@@ -987,6 +989,7 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc,
987static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc, 989static void prb_run_all_ft_ops(struct tpacket_kbdq_core *pkc,
988 struct tpacket3_hdr *ppd) 990 struct tpacket3_hdr *ppd)
989{ 991{
992 ppd->hv1.tp_padding = 0;
990 prb_fill_vlan_info(pkc, ppd); 993 prb_fill_vlan_info(pkc, ppd);
991 994
992 if (pkc->feature_req_word & TP_FT_REQ_FILL_RXHASH) 995 if (pkc->feature_req_word & TP_FT_REQ_FILL_RXHASH)
@@ -1925,9 +1928,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
1925 h.h2->tp_nsec = ts.tv_nsec; 1928 h.h2->tp_nsec = ts.tv_nsec;
1926 if (vlan_tx_tag_present(skb)) { 1929 if (vlan_tx_tag_present(skb)) {
1927 h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); 1930 h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
1928 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;
1929 } else { 1933 } else {
1930 h.h2->tp_vlan_tci = 0; 1934 h.h2->tp_vlan_tci = 0;
1935 h.h2->tp_vlan_tpid = 0;
1931 } 1936 }
1932 memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding)); 1937 memset(h.h2->tp_padding, 0, sizeof(h.h2->tp_padding));
1933 hdrlen = sizeof(*h.h2); 1938 hdrlen = sizeof(*h.h2);
@@ -2875,11 +2880,12 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2875 aux.tp_net = skb_network_offset(skb); 2880 aux.tp_net = skb_network_offset(skb);
2876 if (vlan_tx_tag_present(skb)) { 2881 if (vlan_tx_tag_present(skb)) {
2877 aux.tp_vlan_tci = vlan_tx_tag_get(skb); 2882 aux.tp_vlan_tci = vlan_tx_tag_get(skb);
2878 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;
2879 } else { 2885 } else {
2880 aux.tp_vlan_tci = 0; 2886 aux.tp_vlan_tci = 0;
2887 aux.tp_vlan_tpid = 0;
2881 } 2888 }
2882 aux.tp_padding = 0;
2883 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); 2889 put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
2884 } 2890 }
2885 2891