Index: if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.111 diff -u -p -r1.111 if_trunk.c --- if_trunk.c 10 Sep 2015 16:41:30 -0000 1.111 +++ if_trunk.c 19 Sep 2015 00:38:26 -0000 @@ -343,9 +343,6 @@ trunk_port_create(struct trunk_softc *tr tp->tp_iftype = ifp->if_type; ifp->if_type = IFT_IEEE8023ADLAG; - /* Change input handler of the physical interface. */ - if_ih_insert(ifp, trunk_input, NULL); - ifp->if_tp = (caddr_t)tp; tp->tp_ioctl = ifp->if_ioctl; ifp->if_ioctl = trunk_port_ioctl; @@ -394,6 +391,9 @@ trunk_port_create(struct trunk_softc *tr if (tr->tr_port_create != NULL) error = (*tr->tr_port_create)(tp); + /* Change input handler of the physical interface. */ + if_ih_insert(ifp, trunk_input, NULL); + return (error); } @@ -421,6 +421,9 @@ trunk_port_destroy(struct trunk_port *tp struct trunk_port *tp_ptr; struct ifnet *ifp = tp->tp_if; + /* Restore previous input handler. */ + if_ih_remove(ifp, trunk_input, NULL); + if (tr->tr_port_destroy != NULL) (*tr->tr_port_destroy)(tp); @@ -436,9 +439,6 @@ trunk_port_destroy(struct trunk_port *tp /* Restore interface type. */ ifp->if_type = tp->tp_iftype; - /* Restore previous input handler. */ - if_ih_remove(ifp, trunk_input, NULL); - ifp->if_watchdog = tp->tp_watchdog; ifp->if_ioctl = tp->tp_ioctl; ifp->if_output = tp->tp_output; @@ -684,6 +684,8 @@ trunk_ioctl(struct ifnet *ifp, u_long cm error = EPROTONOSUPPORT; break; } + SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) + if_ih_remove(tp->tp_if, trunk_input, tp); if (tr->tr_proto != TRUNK_PROTO_NONE) error = tr->tr_detach(tr); if (error != 0) @@ -698,6 +700,9 @@ trunk_ioctl(struct ifnet *ifp, u_long cm tr->tr_proto = trunk_protos[i].ti_proto; if (tr->tr_proto != TRUNK_PROTO_NONE) error = trunk_protos[i].ti_attach(tr); + SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) + if_ih_insert(tp->tp_if, + trunk_input, tp); goto out; } } @@ -985,6 +990,9 @@ trunk_hashmbuf(struct mbuf *m, SIPHASH_K #endif SIPHASH_CTX ctx; + if (m->m_pkthdr.flowid & M_FLOWID_VALID) + return (m->m_pkthdr.flowid & M_FLOWID_MASK); + SipHash24_Init(&ctx, key); off = sizeof(*eh); if (m->m_len < off) @@ -1108,7 +1116,6 @@ trunk_input(struct ifnet *ifp, struct mb * We stop here if the packet has been consumed * by the protocol routine. */ - m_freem(m); return (1); } @@ -1378,8 +1385,10 @@ trunk_fail_input(struct trunk_softc *tr, if ((tmp_tp == NULL || tmp_tp == tp)) accept = 1; } - if (!accept) + if (!accept) { + m_freem(m); return (-1); + } return (0); } Index: trunklacp.c =================================================================== RCS file: /cvs/src/sys/net/trunklacp.c,v retrieving revision 1.24 diff -u -p -r1.24 trunklacp.c --- trunklacp.c 30 Jun 2015 13:54:42 -0000 1.24 +++ trunklacp.c 19 Sep 2015 00:38:26 -0000 @@ -108,6 +108,7 @@ u_int16_t lacp_compose_key(struct lacp_p int tlv_check(const void *, size_t, const struct tlvhdr *, const struct tlv_template *, int); void lacp_tick(void *); +void lacp_input_process(void *); void lacp_fill_aggregator_id(struct lacp_aggregator *, const struct lacp_port *); @@ -245,11 +246,10 @@ lacp_input(struct trunk_port *tp, struct m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); switch (subtype) { case SLOWPROTOCOLS_SUBTYPE_LACP: - lacp_pdu_input(lp, m); - return (1); - case SLOWPROTOCOLS_SUBTYPE_MARKER: - lacp_marker_input(lp, m); + mq_enqueue(&lp->lp_q, m); + if (task_add(systq, &lp->lp_input)) + refcnt_take(&lp->lp_refcnt); return (1); } } @@ -260,13 +260,40 @@ lacp_input(struct trunk_port *tp, struct */ /* This port is joined to the active aggregator */ if ((lp->lp_state & LACP_STATE_COLLECTING) == 0 || - la == NULL || la != lsc->lsc_active_aggregator) + la == NULL || la != lsc->lsc_active_aggregator) { + m_freem(m); return (-1); + } /* Not a subtype we are interested in */ return (0); } +void +lacp_input_process(void *port) +{ + struct lacp_port *lp = port; + struct mbuf *m; + u_int8_t subtype; + + while ((m = mq_dequeue(&lp->lp_q)) != NULL) { + m_copydata(m, sizeof(struct ether_header), + sizeof(subtype), &subtype); + + switch (subtype) { + case SLOWPROTOCOLS_SUBTYPE_LACP: + lacp_pdu_input(lp, m); + break; + + case SLOWPROTOCOLS_SUBTYPE_MARKER: + lacp_marker_input(lp, m); + break; + } + } + + refcnt_rele_wake(&lp->lp_refcnt); +} + /* * lacp_pdu_input: process lacpdu */ @@ -520,6 +547,10 @@ lacp_port_create(struct trunk_port *tp) lp->lp_trunk = tp; lp->lp_lsc = lsc; + refcnt_init(&lp->lp_refcnt); + mq_init(&lp->lp_q, 8, IPL_NET); + task_set(&lp->lp_input, lacp_input_process, lp); + LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next); lacp_fill_actorinfo(lp, &lp->lp_actor); @@ -539,6 +570,7 @@ void lacp_port_destroy(struct trunk_port *tp) { struct lacp_port *lp = LACP_PORT(tp); + struct mbuf *m; int i; for (i = 0; i < LACP_NTIMER; i++) @@ -547,6 +579,14 @@ lacp_port_destroy(struct trunk_port *tp) lacp_disable_collecting(lp); lacp_disable_distributing(lp); lacp_unselect(lp); + + if (task_del(systq, &lp->lp_input)) + refcnt_rele_wake(&lp->lp_refcnt); + + while ((m = mq_dequeue(&lp->lp_q)) != NULL) + m_freem(m); + + refcnt_finalize(&lp->lp_refcnt, "lacpdtor"); LIST_REMOVE(lp, lp_next); free(lp, M_DEVBUF, sizeof(*lp)); Index: trunklacp.h =================================================================== RCS file: /cvs/src/sys/net/trunklacp.h,v retrieving revision 1.9 diff -u -p -r1.9 trunklacp.h --- trunklacp.h 11 May 2015 08:41:43 -0000 1.9 +++ trunklacp.h 19 Sep 2015 00:38:26 -0000 @@ -111,6 +111,9 @@ struct lacp_markerinfo { } __packed; #ifdef _KERNEL +#include +#include +#include /* * IEEE802.3ad LACP implementation details. @@ -193,6 +196,11 @@ struct lacp_port { struct lacp_softc *lp_lsc; struct trunk_port *lp_trunk; struct ifnet *lp_ifp; + + struct refcnt lp_refcnt; + struct task lp_input; + struct mbuf_queue lp_q; + struct lacp_peerinfo lp_partner; struct lacp_peerinfo lp_actor; struct lacp_markerinfo lp_marker; @@ -254,13 +262,6 @@ struct lacp_softc { #define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->tp_psc) #define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->tr_psc) - -#define LACP_LOCK_INIT(_lsc) mtx_init(&(_lsc)->lsc_mtx, \ - "lacp mtx", NULL, MTX_DEF) -#define LACP_LOCK_DESTROY(_lsc) mtx_destroy(&(_lsc)->lsc_mtx) -#define LACP_LOCK(_lsc) mtx_lock(&(_lsc)->lsc_mtx) -#define LACP_UNLOCK(_lsc) mtx_unlock(&(_lsc)->lsc_mtx) -#define LACP_LOCK_ASSERT(_lsc) mtx_assert(&(_lsc)->lsc_mtx, MA_OWNED) int lacp_input(struct trunk_port *, struct mbuf *); struct trunk_port *lacp_select_tx_port(struct trunk_softc *, struct mbuf *);