On 3 April 2011 14:22, Henning Brauer <henn...@openbsd.org> 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 -0000 1.188 > +++ net/if_bridge.c 3 Apr 2011 16:56:22 -0000 > @@ -68,7 +68,6 @@ > > #ifdef IPSEC > #include <netinet/ip_ipsp.h> > - > #include <net/if_enc.h> > #endif > > @@ -148,10 +147,8 @@ int bridge_flushrule(struct bridge_ifli > int bridge_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 > int bridge_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, AF_INET, hlen, m)) > return (NULL); > #endif /* IPSEC */ > - > +#if NPF > 0 > /* Finally, we get to filter the packet! */ > if (pf_test(dir, ifp, &m, eh) != PF_PASS) > goto dropit; > if (m == NULL) > goto dropit; > +#endif /* NPF > 0 */ > > /* Rebuild the IP header */ > if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL)) > @@ -2628,7 +2629,11 @@ bridge_filter(struct bridge_softc *sc, i > goto dropit; > ip = mtod(m, struct ip *); > ip->ip_sum = 0; > - ip->ip_sum = in_cksum(m, hlen); > + if ((ifp->if_capabilities & IFCAP_CSUM_IPv4)) { > + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > + ipstat.ips_outhwcsum++; > + } else > + ip->ip_sum = in_cksum(m, hlen); > > break; > > @@ -2661,10 +2666,12 @@ bridge_filter(struct bridge_softc *sc, i > return (NULL); > #endif /* IPSEC */ > > +#if NPF > 0 > if (pf_test6(dir, ifp, &m, eh) != PF_PASS) > goto dropit; > if (m == NULL) > return (NULL); > +#endif /* NPF > 0 */ > > break; > } > @@ -2696,7 +2703,6 @@ dropit: > m_freem(m); > return (NULL); > } > -#endif /* NPF > 0 */ > > void > bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp, > Index: netinet/ip_output.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_output.c,v > retrieving revision 1.214 > diff -u -p -r1.214 ip_output.c > --- netinet/ip_output.c 30 Sep 2010 09:18:18 -0000 1.214 > +++ netinet/ip_output.c 3 Apr 2011 16:56:23 -0000 > @@ -760,8 +760,7 @@ sendit: > */ > if (ntohs(ip->ip_len) <= mtu) { > ip->ip_sum = 0; > - if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) && > - ifp->if_bridge == NULL) { > + if ((ifp->if_capabilities & IFCAP_CSUM_IPv4)) { > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > ipstat.ips_outhwcsum++; > } else > @@ -911,8 +910,7 @@ ip_fragment(struct mbuf *m, struct ifnet > mhip->ip_off = htons((u_int16_t)mhip->ip_off); > mhip->ip_sum = 0; > if ((ifp != NULL) && > - (ifp->if_capabilities & IFCAP_CSUM_IPv4) && > - ifp->if_bridge == NULL) { > + (ifp->if_capabilities & IFCAP_CSUM_IPv4)) { > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > ipstat.ips_outhwcsum++; > } else > @@ -931,8 +929,7 @@ ip_fragment(struct mbuf *m, struct ifnet > ip->ip_off |= htons(IP_MF); > ip->ip_sum = 0; > if ((ifp != NULL) && > - (ifp->if_capabilities & IFCAP_CSUM_IPv4) && > - ifp->if_bridge == NULL) { > + (ifp->if_capabilities & IFCAP_CSUM_IPv4)) { > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > ipstat.ips_outhwcsum++; > } else > > > -- > 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 > >
Not sure if I got this, but couldn't this be applied to TCP/UDP checksumming as well ?