-/* $OpenBSD: if_ethersubr.c,v 1.195 2015/05/04 10:24:08 mpi Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.196 2015/05/11 08:41:43 mpi Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
int llcfound = 0;
struct llc *l;
struct arpcom *ac;
-#if NTRUNK > 0
- int i = 0;
-#endif
#if NPPPOE > 0
struct ether_header *eh_tmp;
#endif
m_adj(m, ETHER_HDR_LEN);
}
-#if NTRUNK > 0
- /* Handle input from a trunk port */
- while (ifp->if_type == IFT_IEEE8023ADLAG) {
- if (++i > TRUNK_MAX_STACKING) {
- m_freem(m);
- return (1);
- }
- if (trunk_input(ifp, eh, m) != 0)
- return (1);
-
- /* Has been set to the trunk interface */
- ifp = m->m_pkthdr.rcvif;
- }
-#endif
-
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return (1);
else
m->m_flags |= M_MCAST;
ifp->if_imcasts++;
-#if NTRUNK > 0
- if (ifp != ifp0)
- ifp0->if_imcasts++;
-#endif
}
ifp->if_ibytes += m->m_pkthdr.len + sizeof(*eh);
-#if NTRUNK > 0
- if (ifp != ifp0)
- ifp0->if_ibytes += m->m_pkthdr.len + sizeof(*eh);
-#endif
etype = ntohs(eh->ether_type);
-/* $OpenBSD: if_trunk.c,v 1.95 2015/03/14 03:38:51 jsg Exp $ */
+/* $OpenBSD: if_trunk.c,v 1.96 2015/05/11 08:41:43 mpi Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
void trunk_rr_port_destroy(struct trunk_port *);
int trunk_rr_start(struct trunk_softc *, struct mbuf *);
int trunk_rr_input(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
/* Active failover */
int trunk_fail_attach(struct trunk_softc *);
int trunk_fail_detach(struct trunk_softc *);
int trunk_fail_start(struct trunk_softc *, struct mbuf *);
int trunk_fail_input(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
/* Loadbalancing */
int trunk_lb_attach(struct trunk_softc *);
void trunk_lb_port_destroy(struct trunk_port *);
int trunk_lb_start(struct trunk_softc *, struct mbuf *);
int trunk_lb_input(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
int trunk_lb_porttable(struct trunk_softc *, struct trunk_port *);
/* Broadcast mode */
int trunk_bcast_detach(struct trunk_softc *);
int trunk_bcast_start(struct trunk_softc *, struct mbuf *);
int trunk_bcast_input(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
/* 802.3ad LACP */
int trunk_lacp_attach(struct trunk_softc *);
int trunk_lacp_detach(struct trunk_softc *);
int trunk_lacp_start(struct trunk_softc *, struct mbuf *);
int trunk_lacp_input(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
/* Trunk protocol table */
static const struct {
{
struct trunk_softc *tr_ptr;
struct trunk_port *tp;
+ struct ifih *trunk_ifih;
int error = 0;
/* Limit the maximal number of trunk ports */
M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
return (ENOMEM);
+ trunk_ifih = malloc(sizeof(*trunk_ifih), M_DEVBUF, M_NOWAIT);
+ if (trunk_ifih == NULL) {
+ free(tp, M_DEVBUF, 0);
+ return (ENOMEM);
+ }
+
/* Check if port is a stacked trunk */
SLIST_FOREACH(tr_ptr, &trunk_list, tr_entries) {
if (ifp == &tr_ptr->tr_ac.ac_if) {
tp->tp_flags |= TRUNK_PORT_STACK;
if (trunk_port_checkstacking(tr_ptr) >=
TRUNK_MAX_STACKING) {
+ free(trunk_ifih, M_DEVBUF, sizeof(*trunk_ifih));
free(tp, M_DEVBUF, 0);
return (E2BIG);
}
/* Change the interface type */
tp->tp_iftype = ifp->if_type;
ifp->if_type = IFT_IEEE8023ADLAG;
+
+ /* Change input handler of the physical interface. */
+ trunk_ifih->ifih_input = trunk_input;
+ SLIST_INSERT_HEAD(&ifp->if_inputs, trunk_ifih, ifih_next);
+
ifp->if_tp = (caddr_t)tp;
tp->tp_ioctl = ifp->if_ioctl;
ifp->if_ioctl = trunk_port_ioctl;
{
struct trunk_softc *tr = (struct trunk_softc *)tp->tp_trunk;
struct trunk_port *tp_ptr;
+ struct ifih *trunk_ifih;
struct ifnet *ifp = tp->tp_if;
if (tr->tr_port_destroy != NULL)
ifpromisc(ifp, 0);
- /* Restore interface */
+ /* Restore interface type. */
ifp->if_type = tp->tp_iftype;
+
+ /* Restore previous input handler. */
+ trunk_ifih = SLIST_FIRST(&ifp->if_inputs);
+ SLIST_REMOVE_HEAD(&ifp->if_inputs, ifih_next);
+ KASSERT(trunk_ifih->ifih_input == trunk_input);
+ free(trunk_ifih, M_DEVBUF, sizeof(*trunk_ifih));
+
ifp->if_watchdog = tp->tp_watchdog;
ifp->if_ioctl = tp->tp_ioctl;
ifp->if_tp = NULL;
}
int
-trunk_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
+trunk_input(struct mbuf *m, void *hdr)
{
+ struct ifnet *ifp;
struct trunk_softc *tr;
struct trunk_port *tp;
struct ifnet *trifp = NULL;
- int error = 0;
+ struct ether_header *eh = hdr;
+ int error;
+
+ ifp = m->m_pkthdr.rcvif;
+
+ if (eh == NULL)
+ eh = mtod(m, struct ether_header *);
+
+ if (ETHER_IS_MULTICAST(eh->ether_dhost))
+ ifp->if_imcasts++;
+
+ ifp->if_ibytes += m->m_pkthdr.len;
/* Should be checked by the caller */
if (ifp->if_type != IFT_IEEE8023ADLAG) {
#if NBPFILTER > 0
if (trifp->if_bpf && tr->tr_proto != TRUNK_PROTO_FAILOVER)
- bpf_mtap_hdr(trifp->if_bpf, (char *)eh, ETHER_HDR_LEN, m,
- BPF_DIRECTION_IN, NULL);
+ bpf_mtap_ether(trifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
- error = (*tr->tr_input)(tr, tp, eh, m);
- if (error != 0)
- return (error);
+ if ((*tr->tr_input)(tr, tp, m)) {
+ /*
+ * We stop here if the packet has been consumed
+ * by the protocol routine.
+ */
+ m_freem(m);
+ return (1);
+ }
trifp->if_ipackets++;
+ m->m_pkthdr.rcvif = trifp;
return (0);
bad:
- if (error > 0 && trifp != NULL)
+ if (trifp != NULL)
trifp->if_ierrors++;
m_freem(m);
return (error);
}
int
-trunk_rr_input(struct trunk_softc *tr, struct trunk_port *tp,
- struct ether_header *eh, struct mbuf *m)
+trunk_rr_input(struct trunk_softc *tr, struct trunk_port *tp, struct mbuf *m)
{
- struct ifnet *ifp = &tr->tr_ac.ac_if;
-
/* Just pass in the packet to our trunk device */
- m->m_pkthdr.rcvif = ifp;
-
return (0);
}
}
int
-trunk_fail_input(struct trunk_softc *tr, struct trunk_port *tp,
- struct ether_header *eh, struct mbuf *m)
+trunk_fail_input(struct trunk_softc *tr, struct trunk_port *tp, struct mbuf *m)
{
struct ifnet *ifp = &tr->tr_ac.ac_if;
struct trunk_port *tmp_tp;
if ((tmp_tp == NULL || tmp_tp == tp))
accept = 1;
}
- if (!accept) {
- m_freem(m);
+ if (!accept)
return (-1);
- }
#if NBPFILTER > 0
if (ifp->if_bpf)
- bpf_mtap_hdr(ifp->if_bpf, (char *)eh, ETHER_HDR_LEN, m,
- BPF_DIRECTION_IN, NULL);
+ bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
- m->m_pkthdr.rcvif = ifp;
return (0);
}
}
int
-trunk_lb_input(struct trunk_softc *tr, struct trunk_port *tp,
- struct ether_header *eh, struct mbuf *m)
+trunk_lb_input(struct trunk_softc *tr, struct trunk_port *tp, struct mbuf *m)
{
- struct ifnet *ifp = &tr->tr_ac.ac_if;
-
/* Just pass in the packet to our trunk device */
- m->m_pkthdr.rcvif = ifp;
-
return (0);
}
}
int
-trunk_bcast_input(struct trunk_softc *tr, struct trunk_port *tp,
- struct ether_header *eh, struct mbuf *m)
+trunk_bcast_input(struct trunk_softc *tr, struct trunk_port *tp, struct mbuf *m)
{
- struct ifnet *ifp = &tr->tr_ac.ac_if;
-
- m->m_pkthdr.rcvif = ifp;
return (0);
}
}
int
-trunk_lacp_input(struct trunk_softc *tr, struct trunk_port *tp,
- struct ether_header *eh, struct mbuf *m)
+trunk_lacp_input(struct trunk_softc *tr, struct trunk_port *tp, struct mbuf *m)
{
- struct ifnet *ifp = &tr->tr_ac.ac_if;
-
- m = lacp_input(tp, eh, m);
- if (m == NULL)
- return (-1);
-
- m->m_pkthdr.rcvif = ifp;
- return (0);
+ return (lacp_input(tp, m));
}
-/* $OpenBSD: if_trunk.h,v 1.19 2014/12/04 00:01:53 tedu Exp $ */
+/* $OpenBSD: if_trunk.h,v 1.20 2015/05/11 08:41:43 mpi Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
int (*tr_start)(struct trunk_softc *, struct mbuf *);
int (*tr_watchdog)(struct trunk_softc *);
int (*tr_input)(struct trunk_softc *, struct trunk_port *,
- struct ether_header *, struct mbuf *);
+ struct mbuf *);
int (*tr_port_create)(struct trunk_port *);
void (*tr_port_destroy)(struct trunk_port *);
void (*tr_linkstate)(struct trunk_port *);
struct trunk_port *lb_ports[TRUNK_MAX_PORTS];
};
-int trunk_input(struct ifnet *, struct ether_header *,
- struct mbuf *);
+int trunk_input(struct mbuf *, void *);
int trunk_enqueue(struct ifnet *, struct mbuf *);
u_int32_t trunk_hashmbuf(struct mbuf *, SIPHASH_KEY *);
#endif /* _KERNEL */
-/* $OpenBSD: trunklacp.c,v 1.19 2015/03/14 03:38:51 jsg Exp $ */
+/* $OpenBSD: trunklacp.c,v 1.20 2015/05/11 08:41:43 mpi Exp $ */
/* $NetBSD: ieee8023ad_lacp.c,v 1.3 2005/12/11 12:24:54 christos Exp $ */
/* $FreeBSD:ieee8023ad_lacp.c,v 1.15 2008/03/16 19:25:30 thompsa Exp $ */
/* receive machine */
-int lacp_pdu_input(struct lacp_port *,
- struct ether_header *, struct mbuf *);
-int lacp_marker_input(struct lacp_port *,
- struct ether_header *, struct mbuf *);
+int lacp_pdu_input(struct lacp_port *, struct mbuf *);
+int lacp_marker_input(struct lacp_port *, struct mbuf *);
void lacp_sm_rx(struct lacp_port *, const struct lacpdu *);
void lacp_sm_rx_timer(struct lacp_port *);
void lacp_sm_rx_set_expired(struct lacp_port *);
[LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer,
};
-struct mbuf *
-lacp_input(struct trunk_port *tp, struct ether_header *eh, struct mbuf *m)
+int
+lacp_input(struct trunk_port *tp, struct mbuf *m)
{
struct lacp_port *lp = LACP_PORT(tp);
struct lacp_softc *lsc = lp->lp_lsc;
struct lacp_aggregator *la = lp->lp_aggregator;
+ struct ether_header *eh;
u_int8_t subtype;
+ eh = mtod(m, struct ether_header *);
+
if (ntohs(eh->ether_type) == ETHERTYPE_SLOW) {
- if (m->m_pkthdr.len < sizeof(subtype)) {
- m_freem(m);
- return (NULL);
- }
- subtype = *mtod(m, u_int8_t *);
+ if (m->m_pkthdr.len < (sizeof(*eh) + sizeof(subtype)))
+ return (-1);
+ m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype);
switch (subtype) {
case SLOWPROTOCOLS_SUBTYPE_LACP:
- lacp_pdu_input(lp, eh, m);
- return (NULL);
+ lacp_pdu_input(lp, m);
+ return (1);
case SLOWPROTOCOLS_SUBTYPE_MARKER:
- lacp_marker_input(lp, eh, m);
- return (NULL);
+ lacp_marker_input(lp, m);
+ return (1);
}
}
*/
/* This port is joined to the active aggregator */
if ((lp->lp_state & LACP_STATE_COLLECTING) == 0 ||
- la == NULL || la != lsc->lsc_active_aggregator) {
- m_freem(m);
- return (NULL);
- }
+ la == NULL || la != lsc->lsc_active_aggregator)
+ return (-1);
/* Not a subtype we are interested in */
- return (m);
+ return (0);
}
/*
* lacp_pdu_input: process lacpdu
*/
int
-lacp_pdu_input(struct lacp_port *lp, struct ether_header *eh, struct mbuf *m)
+lacp_pdu_input(struct lacp_port *lp, struct mbuf *m)
{
struct lacpdu *du;
int error = 0;
}
du = mtod(m, struct lacpdu *);
- if (memcmp(&eh->ether_dhost,
+ if (memcmp(&du->ldu_eh.ether_dhost,
ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN))
goto bad;
lacp_sm_rx(lp, du);
- m_freem(m);
return (error);
bad:
- m_freem(m);
return (EINVAL);
}
{
struct trunk_port *tp = lp->lp_trunk;
struct mbuf *m;
- struct ether_header *eh;
struct lacpdu *du;
int error, s;
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m == NULL)
return (ENOMEM);
- m->m_len = m->m_pkthdr.len = sizeof(*eh) + sizeof(*du);
+ m->m_len = m->m_pkthdr.len = sizeof(*du);
m->m_pkthdr.pf.prio = LACP_IFQ_PRIO;
- eh = mtod(m, struct ether_header *);
- memcpy(&eh->ether_dhost, ethermulticastaddr_slowprotocols,
- ETHER_ADDR_LEN);
- memcpy(&eh->ether_shost, tp->tp_lladdr, ETHER_ADDR_LEN);
- eh->ether_type = htons(ETHERTYPE_SLOW);
-
- m->m_data += sizeof(*eh);
du = mtod(m, struct lacpdu *);
- m->m_data -= sizeof(*eh);
-
memset(du, 0, sizeof(*du));
+ memcpy(&du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
+ ETHER_ADDR_LEN);
+ memcpy(&du->ldu_eh.ether_shost, tp->tp_lladdr, ETHER_ADDR_LEN);
+ du->ldu_eh.ether_type = htons(ETHERTYPE_SLOW);
+
du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP;
du->ldu_sph.sph_version = 1;
{
struct trunk_port *tp = lp->lp_trunk;
struct mbuf *m;
- struct ether_header *eh;
struct markerdu *mdu;
int error, s;
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m == NULL)
return (ENOMEM);
- m->m_len = m->m_pkthdr.len = sizeof(*eh) + sizeof(*mdu);
+ m->m_len = m->m_pkthdr.len = sizeof(*mdu);
m->m_pkthdr.pf.prio = LACP_IFQ_PRIO;
- eh = mtod(m, struct ether_header *);
- memcpy(&eh->ether_dhost, ethermulticastaddr_slowprotocols,
- ETHER_ADDR_LEN);
- memcpy(&eh->ether_shost, tp->tp_lladdr, ETHER_ADDR_LEN);
- eh->ether_type = htons(ETHERTYPE_SLOW);
-
- m->m_data += sizeof(*eh);
mdu = mtod(m, struct markerdu *);
- m->m_data -= sizeof(*eh);
-
memset(mdu, 0, sizeof(*mdu));
+ memcpy(&mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
+ ETHER_ADDR_LEN);
+ memcpy(&mdu->mdu_eh.ether_shost, tp->tp_lladdr, ETHER_ADDR_LEN);
+ mdu->mdu_eh.ether_type = htons(ETHERTYPE_SLOW);
+
mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER;
mdu->mdu_sph.sph_version = 1;
TLV_SET(&mdu->mdu_tlv, MARKER_TYPE_INFO, sizeof(mdu->mdu_info));
mdu->mdu_info = lp->lp_marker;
- LACP_DPRINTF((lp, "marker transmit, port=%u, sys=%6D, id=%u\n",
- ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system, ":",
+ LACP_DPRINTF((lp, "marker transmit, port=%u, sys=%s, id=%u\n",
+ ntohs(mdu->mdu_info.mi_rq_port),
+ ether_sprintf(mdu->mdu_info.mi_rq_system),
ntohl(mdu->mdu_info.mi_rq_xid)));
m->m_flags |= M_MCAST;
}
int
-lacp_marker_input(struct lacp_port *lp, struct ether_header *eh, struct mbuf *m)
+lacp_marker_input(struct lacp_port *lp, struct mbuf *m)
{
struct lacp_softc *lsc = lp->lp_lsc;
struct trunk_port *tp = lp->lp_trunk;
mdu = mtod(m, struct markerdu *);
- if (memcmp(&eh->ether_dhost,
+ if (memcmp(&mdu->mdu_eh.ether_dhost,
ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN))
goto bad;
goto bad;
mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE;
- memcpy(&eh->ether_dhost,
+ memcpy(&mdu->mdu_eh.ether_dhost,
ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN);
- memcpy(&eh->ether_shost,
+ memcpy(&mdu->mdu_eh.ether_shost,
tp->tp_lladdr, ETHER_ADDR_LEN);
error = trunk_enqueue(lp->lp_ifp, m);
break;
marker_response_tlv_template, 1))
goto bad;
- LACP_DPRINTF((lp, "marker response, port=%u, sys=%6D, id=%u\n",
- ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system,
- ":", ntohl(mdu->mdu_info.mi_rq_xid)));
+ LACP_DPRINTF((lp, "marker response, port=%u, sys=%s, id=%u\n",
+ ntohs(mdu->mdu_info.mi_rq_port),
+ ether_sprintf(mdu->mdu_info.mi_rq_system),
+ ntohl(mdu->mdu_info.mi_rq_xid)));
/* Verify that it is the last marker we sent out */
if (memcmp(&mdu->mdu_info, &lp->lp_marker,
lsc->lsc_suppress_distributing = 0;
}
}
- m_freem(m);
break;
default:
bad:
LACP_DPRINTF((lp, "bad marker frame\n"));
- m_freem(m);
return (EINVAL);
}
-/* $OpenBSD: trunklacp.h,v 1.8 2014/12/04 00:01:53 tedu Exp $ */
+/* $OpenBSD: trunklacp.h,v 1.9 2015/05/11 08:41:43 mpi Exp $ */
/* $NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $ */
/*
} __packed;
struct lacpdu {
+ struct ether_header ldu_eh;
struct slowprothdr ldu_sph;
struct tlvhdr ldu_tlv_actor;
"\010EXPIRED"
struct markerdu {
+ struct ether_header mdu_eh;
struct slowprothdr mdu_sph;
struct tlvhdr mdu_tlv;
#define LACP_UNLOCK(_lsc) mtx_unlock(&(_lsc)->lsc_mtx)
#define LACP_LOCK_ASSERT(_lsc) mtx_assert(&(_lsc)->lsc_mtx, MA_OWNED)
-struct mbuf *lacp_input(struct trunk_port *,
- struct ether_header *, struct mbuf *);
+int lacp_input(struct trunk_port *, struct mbuf *);
struct trunk_port *lacp_select_tx_port(struct trunk_softc *, struct mbuf *);
int lacp_attach(struct trunk_softc *);
int lacp_detach(struct trunk_softc *);