mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-17 15:27:36 +00:00
- Previously when broadcasting to N number of interfaces we would run pfil
hooks for each outgoing interface but also run pfil hooks _N times_ on the bridge interface. This is changed so pfil hooks are run once for the bridge interface (bridge0) and then only on the outgoing interfaces in the broadcast loop. - Simplify bridge_enqueue() by moving bridge_pfil() to the callers. - Check (inet6_pfil_hook.ph_busy_count >= 0), it may be possible to have a packet filter hooked for only ipv6 but we were only checking if ipv4 hooks were busy. - Minor optimisation for null mbuf check after bridge_pfil(), move it into the if-block as it couldnt possibly be null outside. Prodded by: mlaier Approved by: re (scottl), mlaier (mentor)
This commit is contained in:
parent
3c308b091f
commit
ea32e73208
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147786
@ -281,7 +281,7 @@ bstp_send_config_bpdu(struct bridge_softc *sc, struct bridge_iflist *bif,
|
||||
|
||||
/* XXX: safe here?!? */
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, ifp, m, 0);
|
||||
bridge_enqueue(sc, ifp, m);
|
||||
BRIDGE_LOCK(sc);
|
||||
}
|
||||
|
||||
@ -397,7 +397,7 @@ bstp_transmit_tcn(struct bridge_softc *sc)
|
||||
|
||||
/* XXX: safe here?!? */
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, ifp, m, 0);
|
||||
bridge_enqueue(sc, ifp, m);
|
||||
BRIDGE_LOCK(sc);
|
||||
}
|
||||
|
||||
|
@ -1239,8 +1239,7 @@ bridge_stop(struct ifnet *ifp, int disable)
|
||||
*
|
||||
*/
|
||||
__inline void
|
||||
bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
|
||||
int runfilt)
|
||||
bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
|
||||
{
|
||||
int len, err;
|
||||
short mflags;
|
||||
@ -1250,13 +1249,6 @@ bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
|
||||
*/
|
||||
m->m_pkthdr.csum_flags = 0;
|
||||
|
||||
if (runfilt && inet_pfil_hook.ph_busy_count >= 0) {
|
||||
if (bridge_pfil(&m, sc->sc_ifp, dst_ifp, PFIL_OUT) != 0)
|
||||
return;
|
||||
}
|
||||
if (m == NULL)
|
||||
return;
|
||||
|
||||
len = m->m_pkthdr.len;
|
||||
mflags = m->m_flags;
|
||||
IFQ_ENQUEUE(&dst_ifp->if_snd, m, err);
|
||||
@ -1302,7 +1294,18 @@ bridge_dummynet(struct mbuf *m, struct ifnet *ifp)
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, ifp, m, 1);
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
if (bridge_pfil(&m, sc->sc_ifp, ifp, PFIL_OUT) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, ifp, m);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1394,7 +1397,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
|
||||
}
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, dst_if, mc, 0);
|
||||
bridge_enqueue(sc, dst_if, mc);
|
||||
}
|
||||
if (used == 0)
|
||||
m_freem(m);
|
||||
@ -1414,7 +1417,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
|
||||
}
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, dst_if, m, 0);
|
||||
bridge_enqueue(sc, dst_if, m);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1453,7 +1456,19 @@ bridge_start(struct ifnet *ifp)
|
||||
bridge_broadcast(sc, ifp, m);
|
||||
else {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, dst_if, m, 1);
|
||||
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
if (bridge_pfil(&m, sc->sc_ifp, dst_if, PFIL_OUT) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, dst_if, m);
|
||||
}
|
||||
}
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
@ -1553,16 +1568,18 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
|
||||
}
|
||||
|
||||
/* run the packet filter */
|
||||
if (inet_pfil_hook.ph_busy_count >= 0) {
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
if (bridge_pfil(&m, ifp, src_if, PFIL_IN) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
BRIDGE_LOCK(sc);
|
||||
}
|
||||
if (m == NULL) {
|
||||
BRIDGE_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst_if == NULL) {
|
||||
/* tap off packets passing the bridge */
|
||||
@ -1603,7 +1620,19 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
|
||||
BPF_MTAP(ifp, m);
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
bridge_enqueue(sc, dst_if, m, 1);
|
||||
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
if (bridge_pfil(&m, sc->sc_ifp, dst_if, PFIL_OUT) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, dst_if, m);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1757,6 +1786,18 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Filter on the bridge interface before broadcasting */
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
|
||||
dst_if = bif->bif_ifp;
|
||||
if (dst_if == src_if)
|
||||
@ -1788,7 +1829,23 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
|
||||
}
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, dst_if, mc, 1);
|
||||
/*
|
||||
* Filter on the output interface. Pass a NULL bridge interface
|
||||
* pointer so we do not redundantly filter on the bridge for
|
||||
* each interface we broadcast on.
|
||||
*/
|
||||
if (inet_pfil_hook.ph_busy_count >= 0
|
||||
#ifdef INET6
|
||||
|| inet6_pfil_hook.ph_busy_count >= 0
|
||||
#endif
|
||||
) {
|
||||
if (bridge_pfil(&m, NULL, dst_if, PFIL_OUT) != 0)
|
||||
return;
|
||||
if (m == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_enqueue(sc, dst_if, mc);
|
||||
}
|
||||
if (used == 0)
|
||||
m_freem(m);
|
||||
@ -2169,7 +2226,8 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
|
||||
/*
|
||||
* Send bridge packets through pfil if they are one of the types pfil can deal
|
||||
* with, or if they are ARP or REVARP. (pfil will pass ARP and REVARP without
|
||||
* question.)
|
||||
* question.) If *bifp or *ifp are NULL then packet filtering is skipped for
|
||||
* that interface.
|
||||
*/
|
||||
static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
|
||||
struct ifnet *ifp, int dir)
|
||||
@ -2269,7 +2327,7 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (IPFW_LOADED && pfil_ipfw != 0 && dir == PFIL_OUT) {
|
||||
if (IPFW_LOADED && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
|
||||
error = -1;
|
||||
args.rule = ip_dn_claim_rule(*mp);
|
||||
if (args.rule != NULL && fw_one_pass)
|
||||
@ -2331,21 +2389,21 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
|
||||
* Keep the order:
|
||||
* in_if -> bridge_if -> out_if
|
||||
*/
|
||||
if (pfil_bridge && dir == PFIL_OUT)
|
||||
if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_member)
|
||||
if (pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&inet_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_bridge && dir == PFIL_IN)
|
||||
if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
@ -2359,21 +2417,21 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
|
||||
break;
|
||||
# ifdef INET6
|
||||
case ETHERTYPE_IPV6 :
|
||||
if (pfil_bridge && dir == PFIL_OUT)
|
||||
if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
|
||||
error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_member)
|
||||
if (pfil_member && ifp != NULL)
|
||||
error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp,
|
||||
dir, NULL);
|
||||
|
||||
if (*mp == NULL || error != 0) /* filter may consume */
|
||||
break;
|
||||
|
||||
if (pfil_bridge && dir == PFIL_IN)
|
||||
if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
|
||||
error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
|
||||
dir, NULL);
|
||||
break;
|
||||
|
@ -352,7 +352,6 @@ void bstp_linkstate(struct ifnet *, int);
|
||||
void bstp_stop(struct bridge_softc *);
|
||||
struct mbuf *bstp_input(struct ifnet *, struct mbuf *);
|
||||
|
||||
void bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *,
|
||||
int);
|
||||
void bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
Loading…
Reference in New Issue
Block a user