浏览代码

af_packet: pass checksum validation status to the user

Introduce TP_STATUS_CSUM_VALID tp_status flag to tell the
af_packet user that at least the transport header checksum
has been already validated.

For now, the flag may be set for incoming packets only.

Signed-off-by: Alexander Drozdov <al.drozdov@gmail.com>
Cc: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Alexander Drozdov 10 年之前
父节点
当前提交
682f048bd4
共有 3 个文件被更改,包括 20 次插入3 次删除
  1. 10 3
      Documentation/networking/packet_mmap.txt
  2. 1 0
      include/uapi/linux/if_packet.h
  3. 9 0
      net/packet/af_packet.c

+ 10 - 3
Documentation/networking/packet_mmap.txt

@@ -440,9 +440,10 @@ and the following flags apply:
 +++ Capture process:
 +++ Capture process:
      from include/linux/if_packet.h
      from include/linux/if_packet.h
 
 
-     #define TP_STATUS_COPY          2 
-     #define TP_STATUS_LOSING        4 
-     #define TP_STATUS_CSUMNOTREADY  8 
+     #define TP_STATUS_COPY          (1 << 1)
+     #define TP_STATUS_LOSING        (1 << 2)
+     #define TP_STATUS_CSUMNOTREADY  (1 << 3)
+     #define TP_STATUS_CSUM_VALID    (1 << 7)
 
 
 TP_STATUS_COPY        : This flag indicates that the frame (and associated
 TP_STATUS_COPY        : This flag indicates that the frame (and associated
                         meta information) has been truncated because it's 
                         meta information) has been truncated because it's 
@@ -466,6 +467,12 @@ TP_STATUS_CSUMNOTREADY: currently it's used for outgoing IP packets which
                         reading the packet we should not try to check the 
                         reading the packet we should not try to check the 
                         checksum. 
                         checksum. 
 
 
+TP_STATUS_CSUM_VALID  : This flag indicates that at least the transport
+                        header checksum of the packet has been already
+                        validated on the kernel side. If the flag is not set
+                        then we are free to check the checksum by ourselves
+                        provided that TP_STATUS_CSUMNOTREADY is also not set.
+
 for convenience there are also the following defines:
 for convenience there are also the following defines:
 
 
      #define TP_STATUS_KERNEL        0
      #define TP_STATUS_KERNEL        0

+ 1 - 0
include/uapi/linux/if_packet.h

@@ -99,6 +99,7 @@ struct tpacket_auxdata {
 #define TP_STATUS_VLAN_VALID		(1 << 4) /* auxdata has valid tp_vlan_tci */
 #define TP_STATUS_VLAN_VALID		(1 << 4) /* auxdata has valid tp_vlan_tci */
 #define TP_STATUS_BLK_TMO		(1 << 5)
 #define TP_STATUS_BLK_TMO		(1 << 5)
 #define TP_STATUS_VLAN_TPID_VALID	(1 << 6) /* auxdata has valid tp_vlan_tpid */
 #define TP_STATUS_VLAN_TPID_VALID	(1 << 6) /* auxdata has valid tp_vlan_tpid */
+#define TP_STATUS_CSUM_VALID		(1 << 7)
 
 
 /* Tx ring - header status */
 /* Tx ring - header status */
 #define TP_STATUS_AVAILABLE	      0
 #define TP_STATUS_AVAILABLE	      0

+ 9 - 0
net/packet/af_packet.c

@@ -1924,6 +1924,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		status |= TP_STATUS_CSUMNOTREADY;
 		status |= TP_STATUS_CSUMNOTREADY;
+	else if (skb->pkt_type != PACKET_OUTGOING &&
+		 (skb->ip_summed == CHECKSUM_COMPLETE ||
+		  skb_csum_unnecessary(skb)))
+		status |= TP_STATUS_CSUM_VALID;
 
 
 	if (snaplen > res)
 	if (snaplen > res)
 		snaplen = res;
 		snaplen = res;
@@ -3031,6 +3035,11 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 		aux.tp_status = TP_STATUS_USER;
 		aux.tp_status = TP_STATUS_USER;
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 		if (skb->ip_summed == CHECKSUM_PARTIAL)
 			aux.tp_status |= TP_STATUS_CSUMNOTREADY;
 			aux.tp_status |= TP_STATUS_CSUMNOTREADY;
+		else if (skb->pkt_type != PACKET_OUTGOING &&
+			 (skb->ip_summed == CHECKSUM_COMPLETE ||
+			  skb_csum_unnecessary(skb)))
+			aux.tp_status |= TP_STATUS_CSUM_VALID;
+
 		aux.tp_len = origlen;
 		aux.tp_len = origlen;
 		aux.tp_snaplen = skb->len;
 		aux.tp_snaplen = skb->len;
 		aux.tp_mac = 0;
 		aux.tp_mac = 0;