summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2011-04-04 13:55:55 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2011-04-04 13:55:55 +0000
commitb0031333e275192956102354558f8cdfb2587a1b (patch)
tree39f47427861b01d98285ea857222c4a6aecaf59a
parent9cbcb698eff9cf43b38421f923ed231e5f30da74 (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
-rw-r--r--sys/net/if_bridge.c56
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,