Restructure ether_input and bridge_input

The network stack of NetBSD is well organized and
layered. A packet reception is processed from a
lower layer to an upper layer one by one. However,
ether_input and bridge_input are not structured so.
bridge_input is called inside ether_input.

The new structure replaces ifnet#if_input of a bridge
member with bridge_input when the member is attached.
So a packet goes straight on a packet reception via
a bridge, bridge_input => ether_input => ip_input.

The change is part of a patch of Lloyd Parkes submitted
in PR 48104. Unlike the patch, the change doesn't
intend to change the behavior of the packet processing.
Another patch will fix PR 48104.
This commit is contained in:
ozaki-r 2014-06-17 10:39:46 +00:00
parent 9dd44a1195
commit cb4cb63151
4 changed files with 68 additions and 76 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: bridgestp.c,v 1.14 2009/01/18 10:28:55 mrg Exp $ */
/* $NetBSD: bridgestp.c,v 1.15 2014/06/17 10:39:46 ozaki-r Exp $ */
/*
* Copyright (c) 2000 Jason L. Wright (jason@thought.net)
@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bridgestp.c,v 1.14 2009/01/18 10:28:55 mrg Exp $");
__KERNEL_RCSID(0, "$NetBSD: bridgestp.c,v 1.15 2014/06/17 10:39:46 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -579,7 +579,7 @@ bstp_acknowledge_topology_change(struct bridge_softc *sc,
bstp_transmit_config(sc, bif);
}
struct mbuf *
void
bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
{
struct ether_header *eh;
@ -592,7 +592,7 @@ bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
eh = mtod(m, struct ether_header *);
if ((bif->bif_flags & IFBIF_STP) == 0)
return (m);
goto out;
len = ntohs(eh->ether_type);
if (len < sizeof(tpdu))
@ -664,7 +664,7 @@ bstp_input(struct bridge_softc *sc, struct bridge_iflist *bif, struct mbuf *m)
out:
if (m)
m_freem(m);
return (NULL);
return;
}
void

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bridge.c,v 1.80 2014/06/16 01:05:25 ozaki-r Exp $ */
/* $NetBSD: if_bridge.c,v 1.81 2014/06/17 10:39:46 ozaki-r Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -80,7 +80,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.80 2014/06/16 01:05:25 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.81 2014/06/17 10:39:46 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_bridge_ipf.h"
@ -188,6 +188,7 @@ static int bridge_init(struct ifnet *);
static void bridge_stop(struct ifnet *, int);
static void bridge_start(struct ifnet *);
static void bridge_input(struct ifnet *, struct mbuf *);
static void bridge_forward(void *);
static void bridge_timer(void *);
@ -707,6 +708,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
break;
}
ifs->if_input = ether_input;
ifs->if_bridge = NULL;
LIST_REMOVE(bif, bif_next);
@ -739,6 +741,9 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
if (ifs->if_bridge != NULL)
return (EBUSY);
if (ifs->if_input != ether_input)
return EINVAL;
bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT);
if (bif == NULL)
return (ENOMEM);
@ -764,6 +769,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
ifs->if_bridge = sc;
LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
ifs->if_input = bridge_input;
if (sc->sc_if.if_flags & IFF_RUNNING)
bstp_initialization(sc);
@ -1570,7 +1576,7 @@ bridge_forward(void *v)
* bridging if it is not for us.
* should be called at splnet()
*/
struct mbuf *
static void
bridge_input(struct ifnet *ifp, struct mbuf *m)
{
struct bridge_softc *sc = ifp->if_bridge;
@ -1578,30 +1584,42 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
struct ether_header *eh;
struct mbuf *mc;
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
return (m);
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
ether_input(ifp, m);
return;
}
bif = bridge_lookup_member_if(sc, ifp);
if (bif == NULL)
return (m);
if (bif == NULL) {
ether_input(ifp, m);
return;
}
eh = mtod(m, struct ether_header *);
if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
if (memcmp(etherbroadcastaddr,
eh->ether_dhost, ETHER_ADDR_LEN) == 0)
m->m_flags |= M_BCAST;
else
m->m_flags |= M_MCAST;
}
if (m->m_flags & (M_BCAST|M_MCAST)) {
if (bif->bif_flags & IFBIF_STP) {
/* Tap off 802.1D packets; they do not get forwarded. */
if (memcmp(eh->ether_dhost, bstp_etheraddr,
ETHER_ADDR_LEN) == 0) {
m = bstp_input(sc, bif, m);
if (m == NULL)
return (NULL);
bstp_input(sc, bif, m);
return;
}
switch (bif->bif_state) {
case BSTP_IFSTATE_BLOCKING:
case BSTP_IFSTATE_LISTENING:
case BSTP_IFSTATE_DISABLED:
return (m);
ether_input(ifp, m);
return;
}
}
@ -1611,17 +1629,18 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
* local processing.
*/
mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
if (mc == NULL)
return m;
/* Perform the bridge forwarding function with the copy. */
if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, mc, 0))) {
m_freem(mc);
return m;
if (mc == NULL) {
ether_input(ifp, m);
return;
}
/* Return the original packet for local processing. */
return (m);
/* Perform the bridge forwarding function with the copy. */
if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, mc, 0)))
m_freem(mc);
/* For local processing. */
ether_input(ifp, m);
return;
}
if (bif->bif_flags & IFBIF_STP) {
@ -1629,7 +1648,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
case BSTP_IFSTATE_BLOCKING:
case BSTP_IFSTATE_LISTENING:
case BSTP_IFSTATE_DISABLED:
return (m);
ether_input(ifp, m);
return;
}
}
@ -1649,7 +1669,8 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
(void) bridge_rtupdate(sc,
eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
m->m_pkthdr.rcvif = bif->bif_ifp;
return (m);
ether_input(bif->bif_ifp, m);
return;
}
/* We just received a packet that we sent out. */
@ -1661,15 +1682,13 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
#endif /* NCARP > 0 */
) {
m_freem(m);
return (NULL);
return;
}
}
/* Perform the bridge forwarding function. */
if (__predict_false(!pktq_enqueue(sc->sc_fwd_pktq, m, 0)))
m_freem(m);
return (NULL);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bridgevar.h,v 1.17 2014/06/16 03:43:10 ozaki-r Exp $ */
/* $NetBSD: if_bridgevar.h,v 1.18 2014/06/17 10:39:46 ozaki-r Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@ -313,11 +313,10 @@ void bridge_ifdetach(struct ifnet *);
int bridge_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
struct rtentry *);
struct mbuf *bridge_input(struct ifnet *, struct mbuf *);
void bstp_initialization(struct bridge_softc *);
void bstp_stop(struct bridge_softc *);
struct mbuf *bstp_input(struct bridge_softc *, struct bridge_iflist *, struct mbuf *);
void bstp_input(struct bridge_softc *, struct bridge_iflist *, struct mbuf *);
void bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *,
int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ethersubr.c,v 1.200 2014/06/10 09:38:30 joerg Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.201 2014/06/17 10:39:46 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.200 2014/06/10 09:38:30 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.201 2014/06/17 10:39:46 ozaki-r Exp $");
#include "opt_inet.h"
#include "opt_atalk.h"
@ -640,49 +640,23 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
ifp->if_ibytes += m->m_pkthdr.len;
#if NBRIDGE > 0
/*
* Tap the packet off here for a bridge. bridge_input()
* will return NULL if it has consumed the packet, otherwise
* it gets processed as normal. Note that bridge_input()
* will always return the original packet if we need to
* process it locally.
*/
if (ifp->if_bridge) {
/* clear M_PROMISC, in case the packets comes from a vlan */
m->m_flags &= ~M_PROMISC;
m = bridge_input(ifp, m);
if (m == NULL)
return;
/*
* Bridge has determined that the packet is for us.
* Update our interface pointer -- we may have had
* to "bridge" the packet locally.
*/
ifp = m->m_pkthdr.rcvif;
} else
#endif /* NBRIDGE > 0 */
{
#if NCARP > 0
if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) {
/*
* clear M_PROMISC, in case the packets comes from a
* vlan
*/
m->m_flags &= ~M_PROMISC;
if (carp_input(m, (uint8_t *)&eh->ether_shost,
(uint8_t *)&eh->ether_dhost, eh->ether_type) == 0)
return;
}
if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) {
/*
* clear M_PROMISC, in case the packets comes from a
* vlan
*/
m->m_flags &= ~M_PROMISC;
if (carp_input(m, (uint8_t *)&eh->ether_shost,
(uint8_t *)&eh->ether_dhost, eh->ether_type) == 0)
return;
}
#endif /* NCARP > 0 */
if ((m->m_flags & (M_BCAST|M_MCAST|M_PROMISC)) == 0 &&
(ifp->if_flags & IFF_PROMISC) != 0 &&
memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
ETHER_ADDR_LEN) != 0) {
m->m_flags |= M_PROMISC;
}
if ((m->m_flags & (M_BCAST|M_MCAST|M_PROMISC)) == 0 &&
(ifp->if_flags & IFF_PROMISC) != 0 &&
memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
ETHER_ADDR_LEN) != 0) {
m->m_flags |= M_PROMISC;
}
if ((m->m_flags & M_PROMISC) == 0) {