On Mon, Aug 05, 2013 at 10:28:57AM -0400, Lawrence Teo wrote:
> Index: ip_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.244
> diff -U5 -p -r1.244 ip_output.c
> --- ip_output.c 31 Jul 2013 15:41:52 -0000 1.244
> +++ ip_output.c 5 Aug 2013 02:44:20 -0000
> @@ -2058,25 +2058,35 @@ ip_mloopback(struct ifnet *ifp, struct m
> */
> void
> in_delayed_cksum(struct mbuf *m)
> {
> struct ip *ip;
> - u_int16_t csum, offset;
> + u_int16_t csum = 0, offset;
>
> ip = mtod(m, struct ip *);
> offset = ip->ip_hl << 2;
> +
> + if (ip->ip_p == IPPROTO_ICMP)
> + if (m_copyback(m, offset + offsetof(struct icmp, icmp_cksum),
> + sizeof(csum), &csum, M_NOWAIT))
> + return;
The code at the end of this function tries to avoid the m_copyback()
in the common case unless (offset + sizeof(u_int16_t)) > m->m_len).
Do we want this optimization here?
bluhm
> +
> csum = in4_cksum(m, 0, offset, m->m_pkthdr.len - offset);
> - if (csum == 0 && ip->ip_p == IPPROTO_UDP)
> - csum = 0xffff;
>
> switch (ip->ip_p) {
> case IPPROTO_TCP:
> offset += offsetof(struct tcphdr, th_sum);
> break;
>
> case IPPROTO_UDP:
> offset += offsetof(struct udphdr, uh_sum);
> + if (csum == 0)
> + csum = 0xffff;
> + break;
> +
> + case IPPROTO_ICMP:
> + offset += offsetof(struct icmp, icmp_cksum);
> break;
>
> default:
> return;
> }
> @@ -2101,17 +2111,9 @@ in_proto_cksum_out(struct mbuf *m, struc
> ifp->if_bridgeport != NULL) {
> in_delayed_cksum(m);
> m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
> }
> } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
> - struct ip *ip = mtod(m, struct ip *);
> - int hlen;
> - struct icmp *icp;
> -
> - hlen = ip->ip_hl << 2;
> - icp = (struct icmp *)(mtod(m, caddr_t) + hlen);
> - icp->icmp_cksum = 0;
> - icp->icmp_cksum = in4_cksum(m, 0, hlen,
> - ntohs(ip->ip_len) - hlen);
> + in_delayed_cksum(m);
> m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
> }
> }