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