This diff is a first step towards removing all pseudo-driver #ifdef in ether_output(). As for ether_input() the goal of this work is to provide an elegant design to make it easier to turn pseudo-drivers MP-safe.
So instead of including some bridge(4), vlan(4) and carp(4) specific code in ether_output(), I'd like to split this function and call the interesting chunks in bridge_output(), vlan_output() and carp_output(). The first step is to take the generic code enqueuing packets in its own function: if_output(). Sadly if_start() is still required for hfsc_deferred(). Comments, ok? Index: net/bridgestp.c =================================================================== RCS file: /cvs/src/sys/net/bridgestp.c,v retrieving revision 1.52 diff -u -p -r1.52 bridgestp.c --- net/bridgestp.c 14 Mar 2015 03:38:51 -0000 1.52 +++ net/bridgestp.c 28 Apr 2015 12:22:59 -0000 @@ -357,7 +357,6 @@ bstp_transmit_tcn(struct bstp_state *bs, struct ifnet *ifp = bp->bp_ifp; struct ether_header *eh; struct mbuf *m; - int s, len, error; if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) return; @@ -382,16 +381,8 @@ bstp_transmit_tcn(struct bstp_state *bs, bpdu.tbu_bpdutype = BSTP_MSGTYPE_TCN; bcopy(&bpdu, mtod(m, caddr_t) + sizeof(*eh), sizeof(bpdu)); - s = splnet(); bp->bp_txcount++; - len = m->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error == 0) { - ifp->if_obytes += len; - ifp->if_omcasts++; - if_start(ifp); - } - splx(s); + if_output(ifp, m); } void @@ -473,7 +464,7 @@ bstp_send_bpdu(struct bstp_state *bs, st struct ifnet *ifp = bp->bp_ifp; struct mbuf *m; struct ether_header *eh; - int s, len, error; + int s; s = splnet(); if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) @@ -521,13 +512,7 @@ bstp_send_bpdu(struct bstp_state *bs, st m->m_pkthdr.pf.prio = BSTP_IFQ_PRIO; bp->bp_txcount++; - len = m->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error == 0) { - ifp->if_obytes += len; - ifp->if_omcasts++; - if_start(ifp); - } + if_output(ifp, m); done: splx(s); } Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.330 diff -u -p -r1.330 if.c --- net/if.c 23 Apr 2015 09:45:24 -0000 1.330 +++ net/if.c 28 Apr 2015 12:22:59 -0000 @@ -421,7 +421,6 @@ if_attach_common(struct ifnet *ifp) void if_start(struct ifnet *ifp) { - splassert(IPL_NET); if (ifp->if_snd.ifq_len >= min(8, ifp->if_snd.ifq_maxlen) && @@ -439,6 +438,35 @@ if_start(struct ifnet *ifp) TAILQ_INSERT_TAIL(&iftxlist, ifp, if_txlist); schednetisr(NETISR_TX); } +} + +int +if_output(struct ifnet *ifp, struct mbuf *m) +{ + int s, error = 0; + + s = splnet(); + + /* + * Queue message on interface, and start output if interface + * not yet active. + */ + IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); + if (error) { + splx(s); + return (error); + } + + ifp->if_obytes += m->m_pkthdr.len; + if (m->m_flags & M_MCAST) + ifp->if_omcasts++; + + ifp->if_opackets++; + if_start(ifp); + + splx(s); + + return (0); } struct mbuf_queue if_input_queue = MBUF_QUEUE_INITIALIZER(8192, IPL_NET); Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.235 diff -u -p -r1.235 if_bridge.c --- net/if_bridge.c 17 Apr 2015 11:04:01 -0000 1.235 +++ net/if_bridge.c 28 Apr 2015 12:22:59 -0000 @@ -2683,7 +2683,6 @@ int bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m) { int error, len; - short mflags; #if NGIF > 0 /* Packet needs etherip encapsulation. */ @@ -2735,18 +2734,15 @@ bridge_ifenqueue(struct bridge_softc *sc } #endif len = m->m_pkthdr.len; - mflags = m->m_flags; - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); + + error = if_output(ifp, m); if (error) { sc->sc_if.if_oerrors++; return (error); } + sc->sc_if.if_opackets++; sc->sc_if.if_obytes += len; - ifp->if_obytes += len; - if (mflags & M_MCAST) - ifp->if_omcasts++; - if_start(ifp); return (0); } Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.194 diff -u -p -r1.194 if_ethersubr.c --- net/if_ethersubr.c 13 Apr 2015 08:52:51 -0000 1.194 +++ net/if_ethersubr.c 28 Apr 2015 12:22:59 -0000 @@ -256,14 +256,13 @@ ether_output(struct ifnet *ifp0, struct struct rtentry *rt) { u_int16_t etype; - int s, len, error = 0; + int len, error = 0; u_char edst[ETHER_ADDR_LEN]; u_char *esrc; struct mbuf *m = m0; struct mbuf *mcopy = NULL; struct ether_header *eh; struct arpcom *ac = (struct arpcom *)ifp0; - short mflags; struct ifnet *ifp = ifp0; #ifdef DIAGNOSTIC @@ -418,30 +417,15 @@ ether_output(struct ifnet *ifp0, struct } } #endif - mflags = m->m_flags; + len = m->m_pkthdr.len; - s = splnet(); - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) { - /* mbuf is already freed */ - splx(s); - return (error); - } - ifp->if_obytes += len; + + error = if_output(ifp, m); #if NCARP > 0 - if (ifp != ifp0) + if (!error && ifp != ifp0) ifp0->if_obytes += len; #endif /* NCARP > 0 */ - if (mflags & M_MCAST) - ifp->if_omcasts++; - if_start(ifp); - splx(s); return (error); - bad: if (m) m_freem(m); Index: net/if_gif.c =================================================================== RCS file: /cvs/src/sys/net/if_gif.c,v retrieving revision 1.73 diff -u -p -r1.73 if_gif.c --- net/if_gif.c 14 Mar 2015 03:38:51 -0000 1.73 +++ net/if_gif.c 28 Apr 2015 12:22:59 -0000 @@ -276,7 +276,6 @@ gif_output(struct ifnet *ifp, struct mbu { struct gif_softc *sc = (struct gif_softc*)ifp; int error = 0; - int s; if (!(ifp->if_flags & IFF_UP) || sc->gif_psrc == NULL || sc->gif_pdst == NULL || @@ -316,19 +315,7 @@ gif_output(struct ifnet *ifp, struct mbu if ((error = gif_checkloop(ifp, m))) goto end; - /* - * Queue message on interface, and start output. - */ - s = splnet(); - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) { - /* mbuf is already freed */ - splx(s); - goto end; - } - ifp->if_obytes += m->m_pkthdr.len; - if_start(ifp); - splx(s); + error = if_output(ifp, m); end: if (error) Index: net/if_mpe.c =================================================================== RCS file: /cvs/src/sys/net/if_mpe.c,v retrieving revision 1.43 diff -u -p -r1.43 if_mpe.c --- net/if_mpe.c 10 Apr 2015 13:58:20 -0000 1.43 +++ net/if_mpe.c 28 Apr 2015 12:22:59 -0000 @@ -203,7 +203,6 @@ mpeoutput(struct ifnet *ifp, struct mbuf struct rtentry *rt) { struct shim_hdr shim; - int s; int error; int off; u_int8_t op = 0; @@ -257,16 +256,7 @@ mpeoutput(struct ifnet *ifp, struct mbuf m_copyback(m, off, sizeof(shim), (caddr_t)&shim, M_NOWAIT); - s = splnet(); - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) { - /* mbuf is already freed */ - splx(s); - goto out; - } - if_start(ifp); - splx(s); - + error = if_output(ifp, m); out: if (error) ifp->if_oerrors++; Index: net/if_pppx.c =================================================================== RCS file: /cvs/src/sys/net/if_pppx.c,v retrieving revision 1.37 diff -u -p -r1.37 if_pppx.c --- net/if_pppx.c 10 Apr 2015 13:58:20 -0000 1.37 +++ net/if_pppx.c 28 Apr 2015 12:22:59 -0000 @@ -1034,7 +1034,7 @@ pppx_if_output(struct ifnet *ifp, struct struct rtentry *rt) { int error = 0; - int proto, s; + int proto; if (!ISSET(ifp->if_flags, IFF_UP)) { m_freem(m); @@ -1059,15 +1059,7 @@ pppx_if_output(struct ifnet *ifp, struct } *mtod(m, int *) = proto; - s = splnet(); - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) { - splx(s); - goto out; - } - if_start(ifp); - splx(s); - + error = if_output(ifp, m); out: if (error) ifp->if_oerrors++; Index: net/if_spppsubr.c =================================================================== RCS file: /cvs/src/sys/net/if_spppsubr.c,v retrieving revision 1.132 diff -u -p -r1.132 if_spppsubr.c --- net/if_spppsubr.c 10 Apr 2015 13:58:20 -0000 1.132 +++ net/if_spppsubr.c 28 Apr 2015 12:32:35 -0000 @@ -620,7 +620,7 @@ sppp_output(struct ifnet *ifp, struct mb struct sppp *sp = (struct sppp*) ifp; struct ppp_header *h; struct timeval tv; - int s, len, rv = 0; + int s, rv = 0; u_int16_t protocol; #ifdef DIAGNOSTIC @@ -788,25 +788,19 @@ sppp_output(struct ifnet *ifp, struct mb * Queue message on interface, and start output if interface * not yet active. */ - len = m->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, rv); - + rv = if_output(ifp, m); if (rv != 0) { - ++ifp->if_oerrors; - splx (s); + ifp->if_oerrors++; return (rv); } - if (!(ifp->if_flags & IFF_OACTIVE)) - (*ifp->if_start) (ifp); - /* * Count output packets and bytes. * The packet length includes header, FCS and 1 flag, * according to RFC 1333. */ - ifp->if_obytes += len + sp->pp_framebytes; - splx (s); + ifp->if_obytes += sp->pp_framebytes; + return (0); } Index: net/if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.95 diff -u -p -r1.95 if_trunk.c --- net/if_trunk.c 14 Mar 2015 03:38:51 -0000 1.95 +++ net/if_trunk.c 28 Apr 2015 12:22:59 -0000 @@ -941,29 +941,6 @@ trunk_start(struct ifnet *ifp) } } -int -trunk_enqueue(struct ifnet *ifp, struct mbuf *m) -{ - int len, error = 0; - u_short mflags; - - splassert(IPL_NET); - - /* Send mbuf */ - mflags = m->m_flags; - len = m->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) - return (error); - if_start(ifp); - - ifp->if_obytes += len; - if (mflags & M_MCAST) - ifp->if_omcasts++; - - return (error); -} - u_int32_t trunk_hashmbuf(struct mbuf *m, SIPHASH_KEY *key) { @@ -1279,7 +1256,7 @@ trunk_rr_start(struct trunk_softc *tr, s } /* Send mbuf */ - if ((error = trunk_enqueue(tp->tp_if, m)) != 0) + if ((error = if_output(tp->tp_if, m)) != 0) return (error); /* Get next active port */ @@ -1340,7 +1317,7 @@ trunk_fail_start(struct trunk_softc *tr, } /* Send mbuf */ - return (trunk_enqueue(tp->tp_if, m)); + return (if_output(tp->tp_if, m)); } int @@ -1472,7 +1449,7 @@ trunk_lb_start(struct trunk_softc *tr, s } /* Send mbuf */ - return (trunk_enqueue(tp->tp_if, m)); + return (if_output(tp->tp_if, m)); } int @@ -1537,7 +1514,7 @@ trunk_bcast_start(struct trunk_softc *tr break; } - ret = trunk_enqueue(last->tp_if, m); + ret = if_output(last->tp_if, m); if (ret != 0) errors++; } @@ -1548,7 +1525,7 @@ trunk_bcast_start(struct trunk_softc *tr return (ENOENT); } - ret = trunk_enqueue(last->tp_if, m0); + ret = if_output(last->tp_if, m0); if (ret != 0) errors++; @@ -1626,7 +1603,7 @@ trunk_lacp_start(struct trunk_softc *tr, } /* Send mbuf */ - return (trunk_enqueue(tp->tp_if, m)); + return (if_output(tp->tp_if, m)); } int Index: net/if_trunk.h =================================================================== RCS file: /cvs/src/sys/net/if_trunk.h,v retrieving revision 1.19 diff -u -p -r1.19 if_trunk.h --- net/if_trunk.h 4 Dec 2014 00:01:53 -0000 1.19 +++ net/if_trunk.h 28 Apr 2015 12:22:59 -0000 @@ -221,7 +221,6 @@ struct trunk_lb { int trunk_input(struct ifnet *, struct ether_header *, struct mbuf *); -int trunk_enqueue(struct ifnet *, struct mbuf *); u_int32_t trunk_hashmbuf(struct mbuf *, SIPHASH_KEY *); #endif /* _KERNEL */ Index: net/if_tun.c =================================================================== RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.137 diff -u -p -r1.137 if_tun.c --- net/if_tun.c 15 Apr 2015 10:11:29 -0000 1.137 +++ net/if_tun.c 28 Apr 2015 12:33:01 -0000 @@ -519,7 +519,7 @@ tun_output(struct ifnet *ifp, struct mbu struct rtentry *rt) { struct tun_softc *tp = ifp->if_softc; - int s, len, error; + int s, error; u_int32_t *af; if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { @@ -560,16 +560,13 @@ tun_output(struct ifnet *ifp, struct mbu } #endif - len = m0->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m0, NULL, error); + error = if_output(ifp, m0); if (error) { - splx(s); ifp->if_collisions++; return (error); } + splx(s); - ifp->if_opackets++; - ifp->if_obytes += len; tun_wakeup(tp); return (0); Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.25 diff -u -p -r1.25 if_var.h --- net/if_var.h 23 Apr 2015 09:45:24 -0000 1.25 +++ net/if_var.h 28 Apr 2015 12:22:59 -0000 @@ -418,6 +418,7 @@ extern struct ifnet_head ifnet; extern struct ifnet *lo0ifp; void if_start(struct ifnet *); +int if_output(struct ifnet *, struct mbuf *); void if_input(struct ifnet *, struct mbuf_list *); void ether_input_mbuf(struct ifnet *, struct mbuf *); Index: net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.118 diff -u -p -r1.118 if_vlan.c --- net/if_vlan.c 22 Apr 2015 06:42:11 -0000 1.118 +++ net/if_vlan.c 28 Apr 2015 12:22:59 -0000 @@ -192,7 +192,6 @@ vlan_start(struct ifnet *ifp) struct ifvlan *ifv; struct ifnet *p; struct mbuf *m; - int error; ifv = ifp->if_softc; p = ifv->ifv_p; @@ -248,22 +247,12 @@ vlan_start(struct ifnet *ifp) } #endif /* NBPFILTER > 0 */ - /* - * Send it, precisely as ether_output() would have. - * We are already running at splnet. - */ - IFQ_ENQUEUE(&p->if_snd, m, NULL, error); - if (error) { - /* mbuf is already freed */ + if (if_output(p, m)) { ifp->if_oerrors++; continue; } - p->if_obytes += m->m_pkthdr.len; - if (m->m_flags & M_MCAST) - p->if_omcasts++; ifp->if_opackets++; - if_start(p); } } Index: net/trunklacp.c =================================================================== RCS file: /cvs/src/sys/net/trunklacp.c,v retrieving revision 1.19 diff -u -p -r1.19 trunklacp.c --- net/trunklacp.c 14 Mar 2015 03:38:51 -0000 1.19 +++ net/trunklacp.c 28 Apr 2015 12:22:59 -0000 @@ -348,7 +348,7 @@ lacp_xmit_lacpdu(struct lacp_port *lp) struct mbuf *m; struct ether_header *eh; struct lacpdu *du; - int error, s; + int error; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) @@ -393,9 +393,7 @@ lacp_xmit_lacpdu(struct lacp_port *lp) * XXX should use higher priority queue. * otherwise network congestion can break aggregation. */ - s = splnet(); - error = trunk_enqueue(lp->lp_ifp, m); - splx(s); + error = if_output(lp->lp_ifp, m); return (error); } @@ -406,7 +404,7 @@ lacp_xmit_marker(struct lacp_port *lp) struct mbuf *m; struct ether_header *eh; struct markerdu *mdu; - int error, s; + int error; m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) @@ -439,9 +437,7 @@ lacp_xmit_marker(struct lacp_port *lp) ntohl(mdu->mdu_info.mi_rq_xid))); m->m_flags |= M_MCAST; - s = splnet(); - error = trunk_enqueue(lp->lp_ifp, m); - splx(s); + error = if_output(lp->lp_ifp, m); return (error); } @@ -1667,7 +1663,7 @@ lacp_marker_input(struct lacp_port *lp, ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); memcpy(&eh->ether_shost, tp->tp_lladdr, ETHER_ADDR_LEN); - error = trunk_enqueue(lp->lp_ifp, m); + error = if_output(lp->lp_ifp, m); break; case MARKER_TYPE_RESPONSE: Index: net80211/ieee80211_input.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v retrieving revision 1.133 diff -u -p -r1.133 ieee80211_input.c --- net80211/ieee80211_input.c 14 Mar 2015 03:38:51 -0000 1.133 +++ net80211/ieee80211_input.c 28 Apr 2015 12:34:11 -0000 @@ -827,7 +827,7 @@ ieee80211_deliver_data(struct ieee80211c !(ic->ic_flags & IEEE80211_F_NOBRIDGE) && eh->ether_type != htons(ETHERTYPE_PAE)) { struct ieee80211_node *ni1; - int error, len; + int error; if (ETHER_IS_MULTICAST(eh->ether_dhost)) { m1 = m_copym2(m, 0, M_COPYALL, M_DONTWAIT); @@ -844,16 +844,9 @@ ieee80211_deliver_data(struct ieee80211c } } if (m1 != NULL) { - len = m1->m_pkthdr.len; - IFQ_ENQUEUE(&ifp->if_snd, m1, NULL, error); + error = if_output(ifp, m1); if (error) ifp->if_oerrors++; - else { - if (m != NULL) - ifp->if_omcasts++; - ifp->if_obytes += len; - if_start(ifp); - } } } #endif Index: net80211/ieee80211_output.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_output.c,v retrieving revision 1.94 diff -u -p -r1.94 ieee80211_output.c --- net80211/ieee80211_output.c 14 Mar 2015 03:38:51 -0000 1.94 +++ net80211/ieee80211_output.c 28 Apr 2015 12:35:26 -0000 @@ -113,8 +113,7 @@ ieee80211_output(struct ifnet *ifp, stru { struct ieee80211_frame *wh; struct m_tag *mtag; - int s, len, error = 0; - u_short mflags; + int error = 0; /* Interface has to be up and running */ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != @@ -143,30 +142,7 @@ ieee80211_output(struct ifnet *ifp, stru IEEE80211_FC0_TYPE_CTL) return (EINVAL); - /* - * Queue message on interface without adding any - * further headers, and start output if interface not - * yet active. - */ - mflags = m->m_flags; - len = m->m_pkthdr.len; - s = splnet(); - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error) { - /* mbuf is already freed */ - splx(s); - printf("%s: failed to queue raw tx frame\n", - ifp->if_xname); - return (error); - } - ifp->if_obytes += len; - if (mflags & M_MCAST) - ifp->if_omcasts++; - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - splx(s); - - return (error); + return (if_output(ifp, m)); } fallback: Index: net80211/ieee80211_pae_output.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_pae_output.c,v retrieving revision 1.20 diff -u -p -r1.20 ieee80211_pae_output.c --- net80211/ieee80211_pae_output.c 14 Mar 2015 03:38:51 -0000 1.20 +++ net80211/ieee80211_pae_output.c 28 Apr 2015 12:34:32 -0000 @@ -67,7 +67,7 @@ ieee80211_send_eapol_key(struct ieee8021 struct ether_header *eh; struct ieee80211_eapol_key *key; u_int16_t info; - int s, len, error; + int len; M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT); if (m == NULL) @@ -119,22 +119,12 @@ ieee80211_send_eapol_key(struct ieee8021 if (info & EAPOL_KEY_KEYMIC) ieee80211_eapol_key_mic(key, ptk->kck); - len = m->m_pkthdr.len; - s = splnet(); #ifndef IEEE80211_STA_ONLY /* start a 100ms timeout if an answer is expected from supplicant */ if (info & EAPOL_KEY_KEYACK) timeout_add_msec(&ni->ni_eapol_to, 100); #endif - IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); - if (error == 0) { - ifp->if_obytes += len; - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - } - splx(s); - - return error; + return (if_output(ifp, m)); } #ifndef IEEE80211_STA_ONLY