bridge ip chsum handling
so we have to special case the bridge in teh stack because it doesn't behave wrt ip checksums (yes yes, all hail layer violations). so make the bridge behave by always peeking into the ip header, and not just when we have a kernel with pf compiled in (aka no change really) and apply the same cksum treatment as in ip_output. as a bonus this makes us use hardware checksumming where available. there is anoteh rspecial casing in pf that can also be killed by i already have too many pf Ms, thus -> later. needs heavy testing by bridge users. Index: net/if_bridge.c === RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.188 diff -u -p -r1.188 if_bridge.c --- net/if_bridge.c 4 Nov 2010 23:07:15 - 1.188 +++ net/if_bridge.c 3 Apr 2011 16:56:22 - @@ -68,7 +68,6 @@ #ifdef IPSEC #include - #include #endif @@ -148,10 +147,8 @@ intbridge_flushrule(struct bridge_ifli intbridge_brlconf(struct bridge_softc *, struct ifbrlconf *); u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, struct mbuf *); -#if NPF > 0 -struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, +struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *, struct ether_header *, struct mbuf *m); -#endif intbridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *); void bridge_fragment(struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *); @@ -1065,9 +1062,8 @@ bridge_output(struct ifnet *ifp, struct } #endif /* IPSEC */ - /* Catch packets that need TCP/UDP/IP hardware checksumming */ - if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT || - m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT || + /* Catch packets that need TCP/UDP hardware checksumming */ + if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT || m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) { m_freem(m); splx(s); @@ -1308,11 +1304,9 @@ bridgeintr_frame(struct bridge_softc *sc m_freem(m); return; } -#if NPF > 0 - m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); + m = bridge_ip(sc, BRIDGE_IN, src_if, &eh, m); if (m == NULL) return; -#endif /* * If the packet is a multicast or broadcast OR if we don't * know any better, forward it to all interfaces. @@ -1350,11 +1344,9 @@ bridgeintr_frame(struct bridge_softc *sc m_freem(m); return; } -#if NPF > 0 - m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); + m = bridge_ip(sc, BRIDGE_OUT, dst_if, &eh, m); if (m == NULL) return; -#endif len = m->m_pkthdr.len; #if NVLAN > 0 @@ -1656,11 +1648,9 @@ bridge_broadcast(struct bridge_softc *sc mc = m1; } -#if NPF > 0 - mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); + mc = bridge_ip(sc, BRIDGE_OUT, dst_if, eh, mc); if (mc == NULL) continue; -#endif len = mc->m_pkthdr.len; #if NVLAN > 0 @@ -2506,7 +2496,6 @@ bridge_ipsec(struct bridge_softc *sc, st } #endif /* IPSEC */ -#if NPF > 0 /* * Filter IP packets by peeking into the ethernet frame. This violates * the ISO model, but allows us to act as a IP filter at the data link @@ -2514,7 +2503,7 @@ bridge_ipsec(struct bridge_softc *sc, st * who've read net/if_ethersubr.c and netinet/ip_input.c */ struct mbuf * -bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp, +bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) { struct llc llc; @@ -2590,9 +2579,20 @@ bridge_filter(struct bridge_softc *sc, i ip = mtod(m, struct ip *); } - if ((ip->ip_sum = in_cksum(m, hlen)) != 0) { - ipstat.ips_badsum++; - goto dropit; + if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) { + if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) { + ipstat.ips_inhwcsum++; + ipstat.ips_badsum++; + goto dropit; + } + + if (in_cksum(m, hlen) != 0) { + ipstat.ips_badsum++; + goto dropit; + } + } else { + m->m_pkthdr.csum_flags &= ~M_IPV4_CSUM_IN_OK; + ipstat.ips_inhwcsum++; } if (ntohs(ip->ip_len) < hlen) @@ -2614,12 +2614,13 @@ bridge_filter(struct bridge_softc *sc, i dir, A
Re: bridge ip chsum handling
On 3 April 2011 14:22, Henning Brauer wrote: > so we have to special case the bridge in teh stack because it doesn't > behave wrt ip checksums (yes yes, all hail layer violations). > so make the bridge behave by always peeking into the ip header, and > not just when we have a kernel with pf compiled in (aka no change > really) and apply the same cksum treatment as in ip_output. as a bonus > this makes us use hardware checksumming where available. > > there is anoteh rspecial casing in pf that can also be killed by i > already have too many pf Ms, thus -> later. > > needs heavy testing by bridge users. > > Index: net/if_bridge.c > === > RCS file: /cvs/src/sys/net/if_bridge.c,v > retrieving revision 1.188 > diff -u -p -r1.188 if_bridge.c > --- net/if_bridge.c 4 Nov 2010 23:07:15 - 1.188 > +++ net/if_bridge.c 3 Apr 2011 16:56:22 - > @@ -68,7 +68,6 @@ > > #ifdef IPSEC > #include > - > #include > #endif > > @@ -148,10 +147,8 @@ intbridge_flushrule(struct bridge_ifli > intbridge_brlconf(struct bridge_softc *, struct ifbrlconf *); > u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *, > struct mbuf *); > -#if NPF > 0 > -struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *, > +struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *, > struct ether_header *, struct mbuf *m); > -#endif > intbridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *); > void bridge_fragment(struct bridge_softc *, struct ifnet *, > struct ether_header *, struct mbuf *); > @@ -1065,9 +1062,8 @@ bridge_output(struct ifnet *ifp, struct >} > #endif /* IPSEC */ > > - /* Catch packets that need TCP/UDP/IP hardware checksumming */ > - if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT || > - m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT || > + /* Catch packets that need TCP/UDP hardware checksumming */ > + if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT || >m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) { >m_freem(m); >splx(s); > @@ -1308,11 +1304,9 @@ bridgeintr_frame(struct bridge_softc *sc >m_freem(m); >return; >} > -#if NPF > 0 > - m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m); > + m = bridge_ip(sc, BRIDGE_IN, src_if, &eh, m); >if (m == NULL) >return; > -#endif >/* > * If the packet is a multicast or broadcast OR if we don't > * know any better, forward it to all interfaces. > @@ -1350,11 +1344,9 @@ bridgeintr_frame(struct bridge_softc *sc >m_freem(m); >return; >} > -#if NPF > 0 > - m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m); > + m = bridge_ip(sc, BRIDGE_OUT, dst_if, &eh, m); >if (m == NULL) >return; > -#endif > >len = m->m_pkthdr.len; > #if NVLAN > 0 > @@ -1656,11 +1648,9 @@ bridge_broadcast(struct bridge_softc *sc >mc = m1; >} > > -#if NPF > 0 > - mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc); > + mc = bridge_ip(sc, BRIDGE_OUT, dst_if, eh, mc); >if (mc == NULL) >continue; > -#endif > >len = mc->m_pkthdr.len; > #if NVLAN > 0 > @@ -2506,7 +2496,6 @@ bridge_ipsec(struct bridge_softc *sc, st > } > #endif /* IPSEC */ > > -#if NPF > 0 > /* > * Filter IP packets by peeking into the ethernet frame. This violates > * the ISO model, but allows us to act as a IP filter at the data link > @@ -2514,7 +2503,7 @@ bridge_ipsec(struct bridge_softc *sc, st > * who've read net/if_ethersubr.c and netinet/ip_input.c > */ > struct mbuf * > -bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp, > +bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp, > struct ether_header *eh, struct mbuf *m) > { >struct llc llc; > @@ -2590,9 +2579,20 @@ bridge_filter(struct bridge_softc *sc, i >ip = mtod(m, struct ip *); >} > > - if ((ip->ip_sum = in_cksum(m, hlen)) != 0) { > - ipstat.ips_badsum++; > - goto dropit; > + if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) { > + if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) { > + ipstat.ips_inhwcsum++; > + ipstat.ips_badsum++; > + goto dropit; > + } > + > + if (in_cksum(m, hlen) != 0) { > + ipstat.ips_badsum++; > + goto dropit; > + } > + } else { > + m->m
Re: bridge ip chsum handling
* Christiano F. Haesbaert [2011-04-07 19:37]: > Not sure if I got this, but couldn't this be applied to TCP/UDP > checksumming as well ? one thing after the other. i have a big big big big diff rototoilling the csum handling, needs a bit mroe work before it goes out -- Henning Brauer, h...@bsws.de, henn...@openbsd.org BS Web Services, http://bsws.de Full-Service ISP - Secure Hosting, Mail and DNS Services Dedicated Servers, Rootservers, Application Hosting