o Remove last argument to ip_fragment(), and obtain all needed information

on checksums directly from mbuf flags. This simplifies code.
o Clear CSUM_IP from the mbuf in ip_fragment() if we did checksums in
  hardware. Some driver may not announce CSUM_IP in theur if_hwassist,
  although try to do checksums if CSUM_IP set on mbuf. Example is em(4).
o While here, consistently use CSUM_IP instead of its alias CSUM_DELAY_IP.
  After this change CSUM_DELAY_IP vanishes from the stack.

Submitted by:	Sebastian Kuzminsky <seb lineratesystems.com>
This commit is contained in:
Gleb Smirnoff 2012-10-26 21:06:33 +00:00
parent 5c0adc7db8
commit 078468ede4
6 changed files with 31 additions and 29 deletions

View File

@ -3379,8 +3379,8 @@ bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
goto out; goto out;
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist, m->m_pkthdr.csum_flags |= CSUM_IP;
CSUM_DELAY_IP); error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist);
if (error) if (error)
goto out; goto out;

View File

@ -542,10 +542,8 @@ passout:
* We have to fragment the packet * We have to fragment the packet
*/ */
m->m_pkthdr.csum_flags |= CSUM_IP; m->m_pkthdr.csum_flags |= CSUM_IP;
if (ip_fragment(ip, &m, mtu, ifp->if_hwassist, if (ip_fragment(ip, &m, mtu, ifp->if_hwassist))
(~ifp->if_hwassist & CSUM_DELAY_IP))) {
goto drop; goto drop;
}
KASSERT(m != NULL, ("null mbuf and no error")); KASSERT(m != NULL, ("null mbuf and no error"));
/* /*
* Send off the fragments via outgoing interface * Send off the fragments via outgoing interface

View File

@ -2404,7 +2404,8 @@ pim_register_prepare(struct ip *ip, struct mbuf *m)
ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2); ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
} else { } else {
/* Fragment the packet */ /* Fragment the packet */
if (ip_fragment(ip, &mb_copy, mtu, 0, CSUM_DELAY_IP) != 0) { mb_copy->m_pkthdr.csum_flags |= CSUM_IP;
if (ip_fragment(ip, &mb_copy, mtu, 0) != 0) {
m_freem(mb_copy); m_freem(mb_copy);
return NULL; return NULL;
} }

View File

@ -125,7 +125,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct sockaddr_in *dst; struct sockaddr_in *dst;
struct in_ifaddr *ia; struct in_ifaddr *ia;
int isbroadcast; int isbroadcast;
uint16_t ip_len, ip_off, sw_csum; uint16_t ip_len, ip_off;
struct route iproute; struct route iproute;
struct rtentry *rte; /* cache for ro->ro_rt */ struct rtentry *rte; /* cache for ro->ro_rt */
struct in_addr odst; struct in_addr odst;
@ -583,18 +583,16 @@ passout:
} }
m->m_pkthdr.csum_flags |= CSUM_IP; m->m_pkthdr.csum_flags |= CSUM_IP;
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_hwassist; if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) {
if (sw_csum & CSUM_DELAY_DATA) {
in_delayed_cksum(m); in_delayed_cksum(m);
sw_csum &= ~CSUM_DELAY_DATA; m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
} }
#ifdef SCTP #ifdef SCTP
if (sw_csum & CSUM_SCTP) { if (m->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) {
sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
sw_csum &= ~CSUM_SCTP; m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
} }
#endif #endif
m->m_pkthdr.csum_flags &= ifp->if_hwassist;
/* /*
* If small enough for interface, or the interface will take * If small enough for interface, or the interface will take
@ -604,8 +602,10 @@ passout:
(m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 || (m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) { ((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) {
ip->ip_sum = 0; ip->ip_sum = 0;
if (sw_csum & CSUM_DELAY_IP) if (m->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) {
ip->ip_sum = in_cksum(m, hlen); ip->ip_sum = in_cksum(m, hlen);
m->m_pkthdr.csum_flags &= ~CSUM_IP;
}
/* /*
* Record statistics for this interface address. * Record statistics for this interface address.
@ -646,7 +646,7 @@ passout:
* Too large for interface; fragment if possible. If successful, * Too large for interface; fragment if possible. If successful,
* on return, m will point to a list of packets to be sent. * on return, m will point to a list of packets to be sent.
*/ */
error = ip_fragment(ip, &m, mtu, ifp->if_hwassist, sw_csum); error = ip_fragment(ip, &m, mtu, ifp->if_hwassist);
if (error) if (error)
goto bad; goto bad;
for (; m; m = m0) { for (; m; m = m0) {
@ -691,11 +691,10 @@ bad:
* chain of fragments that should be freed by the caller. * chain of fragments that should be freed by the caller.
* *
* if_hwassist_flags is the hw offload capabilities (see if_data.ifi_hwassist) * if_hwassist_flags is the hw offload capabilities (see if_data.ifi_hwassist)
* sw_csum contains the delayed checksums flags (e.g., CSUM_DELAY_IP).
*/ */
int int
ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
u_long if_hwassist_flags, int sw_csum) u_long if_hwassist_flags)
{ {
int error = 0; int error = 0;
int hlen = ip->ip_hl << 2; int hlen = ip->ip_hl << 2;
@ -833,8 +832,10 @@ smart_frag_failure:
m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags;
mhip->ip_off = htons(mhip->ip_off); mhip->ip_off = htons(mhip->ip_off);
mhip->ip_sum = 0; mhip->ip_sum = 0;
if (sw_csum & CSUM_DELAY_IP) if (m->m_pkthdr.csum_flags & CSUM_IP & ~if_hwassist_flags) {
mhip->ip_sum = in_cksum(m, mhlen); mhip->ip_sum = in_cksum(m, mhlen);
m->m_pkthdr.csum_flags &= ~CSUM_IP;
}
*mnext = m; *mnext = m;
mnext = &m->m_nextpkt; mnext = &m->m_nextpkt;
} }
@ -853,8 +854,10 @@ smart_frag_failure:
ip->ip_len = htons((u_short)m0->m_pkthdr.len); ip->ip_len = htons((u_short)m0->m_pkthdr.len);
ip->ip_off = htons(ip_off | IP_MF); ip->ip_off = htons(ip_off | IP_MF);
ip->ip_sum = 0; ip->ip_sum = 0;
if (sw_csum & CSUM_DELAY_IP) if (m0->m_pkthdr.csum_flags & CSUM_IP & ~if_hwassist_flags) {
ip->ip_sum = in_cksum(m0, hlen); ip->ip_sum = in_cksum(m0, hlen);
m0->m_pkthdr.csum_flags &= ~CSUM_IP;
}
done: done:
*m_frag = m0; *m_frag = m0;

View File

@ -210,7 +210,7 @@ int inp_setmoptions(struct inpcb *, struct sockopt *);
int ip_ctloutput(struct socket *, struct sockopt *sopt); int ip_ctloutput(struct socket *, struct sockopt *sopt);
void ip_drain(void); void ip_drain(void);
int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
u_long if_hwassist_flags, int sw_csum); u_long if_hwassist_flags);
void ip_forward(struct mbuf *m, int srcrt); void ip_forward(struct mbuf *m, int srcrt);
void ip_init(void); void ip_init(void);
#ifdef VIMAGE #ifdef VIMAGE

View File

@ -5140,7 +5140,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
struct pf_addr naddr; struct pf_addr naddr;
struct pf_src_node *sn = NULL; struct pf_src_node *sn = NULL;
int error = 0; int error = 0;
uint16_t ip_len, ip_off, sw_csum; uint16_t ip_len, ip_off;
KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__));
KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction",
@ -5240,18 +5240,16 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
/* Copied from FreeBSD 10.0-CURRENT ip_output. */ /* Copied from FreeBSD 10.0-CURRENT ip_output. */
m0->m_pkthdr.csum_flags |= CSUM_IP; m0->m_pkthdr.csum_flags |= CSUM_IP;
sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist; if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) {
if (sw_csum & CSUM_DELAY_DATA) {
in_delayed_cksum(m0); in_delayed_cksum(m0);
sw_csum &= ~CSUM_DELAY_DATA; m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
} }
#ifdef SCTP #ifdef SCTP
if (sw_csum & CSUM_SCTP) { if (m0->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) {
sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
sw_csum &= ~CSUM_SCTP; m0->m_pkthdr.csum_flags &= ~CSUM_SCTP;
} }
#endif #endif
m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
/* /*
* If small enough for interface, or the interface will take * If small enough for interface, or the interface will take
@ -5261,8 +5259,10 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
(m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 || (m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) { ((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) {
ip->ip_sum = 0; ip->ip_sum = 0;
if (sw_csum & CSUM_DELAY_IP) if (m0->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) {
ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
m0->m_pkthdr.csum_flags &= ~CSUM_IP;
}
m0->m_flags &= ~(M_PROTOFLAGS); m0->m_flags &= ~(M_PROTOFLAGS);
error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL); error = (*ifp->if_output)(ifp, m0, sintosa(&dst), NULL);
goto done; goto done;
@ -5280,7 +5280,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
goto bad; goto bad;
} }
error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum); error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist);
if (error) if (error)
goto bad; goto bad;