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 ?

Reply via email to