diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2011-04-04 13:55:55 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2011-04-04 13:55:55 +0000 |
commit | b0031333e275192956102354558f8cdfb2587a1b (patch) | |
tree | 39f47427861b01d98285ea857222c4a6aecaf59a /sys | |
parent | 9cbcb698eff9cf43b38421f923ed231e5f30da74 (diff) |
all I wanted is to make the bridge behave like the real stack wrt the ip
chekcsum. turned out is always recalculates it as long as your kernel does
have pf compiled in, as in, always, since compilation of GENERIC without
pf explodes in about a hundred ways.
so rename bridge_filter -> bridge_ip and always compile it, pf or not,
just make the pf_test calls #if NPF, and sync the ip fuckery code with
ip_output. as a bonus this lets us use the checksum offloading to the NIC
if it is capable of that.
ok claudio dlg sthen
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_bridge.c | 56 |
1 files changed, 31 insertions, 25 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index b8b0b652e70..e94f7402c3f 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.188 2010/11/04 23:07:15 weerd Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.189 2011/04/04 13:55:54 henning Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -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_iflist *); 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 mbuf *m, struct sockaddr *sa, } #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, struct mbuf *m) 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, struct mbuf *m) 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, struct ifnet *ifp, 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, struct ifnet *ifp, } #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, struct ifnet *ifp, * 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, int dir, struct ifnet *ifp, 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, int dir, struct ifnet *ifp, 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, int dir, struct ifnet *ifp, 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, int dir, struct ifnet *ifp, 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, |