Under IPv4, when I send a UDP packet with invalid checksum, kernel used udp_rcv() to up packet to UDP layer, application used udp_recvmsg to receive message. So if one UDP packet with invalid checksum is arrived to host, UDP_MIB_INDATAGRAMS will be increased 1, UDP_MIB_INERRORS should be increased 1. int udp_rcv(struct sk_buff *skb) { ... udp_queue_rcv_skb(); ... }
static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { ... if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { if (__udp_checksum_complete(skb)) { UDP_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); return -1; } skb->ip_summed = CHECKSUM_UNNECESSARY; } .... UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); ... } static int udp_recvmsg(...) { ... csum_copy_err: UDP_INC_STATS_BH(UDP_MIB_INERRORS); ... } In my test, I send a to a IPv4 UDP packet with invalid checksum to echo- udp, I can find the following message in file /var/log/messages: xinetd[4468]: service echo-dgram, recvfrom: Resource temporarily unavailable (errno = 11) and UDP_MIB_INDATAGRAMS increased 1, UDP_MIB_INERRORS increased 0. xinetd used other fucntion to receive message, not udp_recvmsg()? The other question is why discard the packet with invalid checksum only when sk->sk_filter is set? By the way, under IPv6, packet with invalid checksum be discard in udpv6_rcv(), so So if one UDP packet with invalid checksum is arrived to IPv6 host, UDP_MIB_INDATAGRAMS will be increased 0, UDP_MIB_INERRORS should be increased 1. static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) { ... udpv6_queue_rcv_skb(); ... } static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { ... if (skb->ip_summed != CHECKSUM_UNNECESSARY) { if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { UDP6_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); return 0; } skb->ip_summed = CHECKSUM_UNNECESSARY; } ... UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS); ... } One packet with invalid checksum arrived to IPv4 and IPv6 host, the count of UDP_MIB_INDATAGRAMS and UDP_MIB_INERRORS get different increase. There definition of the two count are some difference between IPv4 and IPv6? > > IPv4 UDP does not discard the datagram with invalid checksum. UDP can > > validate UDP checksums correctly only when socket filtering > instructions > > is set. If socket filtering instructions is not set, datagram with > > invalid checksum will be passed to the application. > > We check the checksum later, in parallel with the copy of > the packet data into userspace. > > See udp_recvmsg(), where we do this: > > if (skb->ip_summed==CHECKSUM_UNNECESSARY) { > err = skb_copy_datagram_iovec(skb, sizeof(struct > udphdr), msg->msg_iov, > copied); > } else if (msg->msg_flags&MSG_TRUNC) { > if (__udp_checksum_complete(skb)) > goto csum_copy_err; > err = skb_copy_datagram_iovec(skb, sizeof(struct > udphdr), msg->msg_iov, > copied); > } else { > err = skb_copy_and_csum_datagram_iovec(skb, sizeof > (struct udphdr), msg->msg_iov); > > if (err == -EINVAL) > goto csum_copy_err; > } - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html