summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_bridge.c86
1 files changed, 31 insertions, 55 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index b484191..3b723c1 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -333,7 +333,7 @@ static int bridge_ip_checkbasic(struct mbuf **mp);
#ifdef INET6
static int bridge_ip6_checkbasic(struct mbuf **mp);
#endif /* INET6 */
-static int bridge_fragment(struct ifnet *, struct mbuf **mp,
+static int bridge_fragment(struct ifnet *, struct mbuf *,
struct ether_header *, int, struct llc *);
static void bridge_linkstate(struct ifnet *ifp);
static void bridge_linkcheck(struct bridge_softc *sc);
@@ -1921,7 +1921,6 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
m->m_flags &= ~M_VLANTAG;
}
- M_ASSERTPKTHDR(m); /* We shouldn't transmit mbuf without pkthdr */
if ((err = dst_ifp->if_transmit(dst_ifp, m))) {
m_freem(m0);
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
@@ -3239,12 +3238,10 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
break;
/* check if we need to fragment the packet */
- /* bridge_fragment generates a mbuf chain of packets */
- /* that already include eth headers */
if (V_pfil_member && ifp != NULL && dir == PFIL_OUT) {
i = (*mp)->m_pkthdr.len;
if (i > ifp->if_mtu) {
- error = bridge_fragment(ifp, mp, &eh2, snap,
+ error = bridge_fragment(ifp, *mp, &eh2, snap,
&llc1);
return (error);
}
@@ -3483,77 +3480,56 @@ bad:
/*
* bridge_fragment:
*
- * Fragment mbuf chain in multiple packets and prepend ethernet header.
+ * Return a fragmented mbuf chain.
*/
static int
-bridge_fragment(struct ifnet *ifp, struct mbuf **mp, struct ether_header *eh,
+bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
int snap, struct llc *llc)
{
- struct mbuf *m = *mp, *nextpkt = NULL, *mprev = NULL, *mcur = NULL;
+ struct mbuf *m0;
struct ip *ip;
int error = -1;
if (m->m_len < sizeof(struct ip) &&
(m = m_pullup(m, sizeof(struct ip))) == NULL)
- goto dropit;
+ goto out;
ip = mtod(m, struct ip *);
m->m_pkthdr.csum_flags |= CSUM_IP;
error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist);
if (error)
- goto dropit;
+ goto out;
- /*
- * Walk the chain and re-add the Ethernet header for
- * each mbuf packet.
- */
- for (mcur = m; mcur; mcur = mcur->m_nextpkt) {
- nextpkt = mcur->m_nextpkt;
- mcur->m_nextpkt = NULL;
- if (snap) {
- M_PREPEND(mcur, sizeof(struct llc), M_NOWAIT);
- if (mcur == NULL) {
+ /* walk the chain and re-add the Ethernet header */
+ for (m0 = m; m0; m0 = m0->m_nextpkt) {
+ if (error == 0) {
+ if (snap) {
+ M_PREPEND(m0, sizeof(struct llc), M_NOWAIT);
+ if (m0 == NULL) {
+ error = ENOBUFS;
+ continue;
+ }
+ bcopy(llc, mtod(m0, caddr_t),
+ sizeof(struct llc));
+ }
+ M_PREPEND(m0, ETHER_HDR_LEN, M_NOWAIT);
+ if (m0 == NULL) {
error = ENOBUFS;
- if (mprev != NULL)
- mprev->m_nextpkt = nextpkt;
- goto dropit;
+ continue;
}
- bcopy(llc, mtod(mcur, caddr_t),sizeof(struct llc));
- }
-
- M_PREPEND(mcur, ETHER_HDR_LEN, M_NOWAIT);
- if (mcur == NULL) {
- error = ENOBUFS;
- if (mprev != NULL)
- mprev->m_nextpkt = nextpkt;
- goto dropit;
- }
- bcopy(eh, mtod(mcur, caddr_t), ETHER_HDR_LEN);
-
- /*
- * The previous two M_PREPEND could have inserted one or two
- * mbufs in front so we have to update the previous packet's
- * m_nextpkt.
- */
- mcur->m_nextpkt = nextpkt;
- if (mprev != NULL)
- mprev->m_nextpkt = mcur;
- else {
- /* The first mbuf in the original chain needs to be
- * updated. */
- *mp = mcur;
- }
- mprev = mcur;
+ bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN);
+ } else
+ m_freem(m);
}
- KMOD_IPSTAT_INC(ips_fragmented);
+ if (error == 0)
+ KMOD_IPSTAT_INC(ips_fragmented);
+
return (error);
-dropit:
- for (mcur = *mp; mcur; mcur = m) { /* droping the full packet chain */
- m = mcur->m_nextpkt;
- m_freem(mcur);
- }
+out:
+ if (m != NULL)
+ m_freem(m);
return (error);
}
OpenPOWER on IntegriCloud