diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2019-08-05 10:42:52 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2019-08-05 10:42:52 +0000 |
commit | 338fa2e2ad0a7b139b2b9c87f3efe951d91904a5 (patch) | |
tree | 71ce978f8825dc8ca11406bd23d2705dc4001d13 | |
parent | 9e7a3389b7ffa16f27b2eb2f10c654156db0d0ce (diff) |
try to be more compliant with the spec by implementing marker responses.
i hope, i didn't test this that hard.
-rw-r--r-- | sys/net/if_aggr.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/sys/net/if_aggr.c b/sys/net/if_aggr.c index 247be1e7099..45aa1588d2e 100644 --- a/sys/net/if_aggr.c +++ b/sys/net/if_aggr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_aggr.c,v 1.18 2019/07/20 04:54:22 dlg Exp $ */ +/* $OpenBSD: if_aggr.c,v 1.19 2019/08/05 10:42:51 dlg Exp $ */ /* * Copyright (c) 2019 The University of Queensland @@ -178,6 +178,28 @@ struct lacp_du { uint8_t lacp_pad[50]; } __packed __aligned(2); +/* Marker TLV types */ + +#define MARKER_T_INFORMATION 0x01 +#define MARKER_T_RESPONSE 0x02 + +struct marker_info { + uint16_t marker_requester_port; + uint8_t marker_requester_system[ETHER_ADDR_LEN]; + uint8_t marker_requester_txid[4]; + uint8_t marker_pad[2]; +} __packed __aligned(2); + +struct marker_pdu { + struct ether_slowproto_hdr + marker_sph; + + struct lacp_tlv_hdr marker_info_tlv; + struct marker_info marker_info; + struct lacp_tlv_hdr marker_terminator; + uint8_t marker_pad[90]; +} __packed __aligned(2); + enum lacp_rxm_state { LACP_RXM_S_BEGIN = 0, LACP_RXM_S_INITIALIZE, @@ -1684,9 +1706,49 @@ aggr_recordpdu(struct aggr_port *p, const struct lacp_du *lacpdu, int sync) } static void +aggr_marker_response(struct aggr_port *p, struct mbuf *m) +{ + struct aggr_softc *sc = p->p_aggr; + struct arpcom *ac = &sc->sc_ac; + struct ifnet *ifp0 = p->p_ifp0; + struct marker_pdu *mpdu; + struct ether_header *eh; + + mpdu = mtod(m, struct marker_pdu *); + mpdu->marker_info_tlv.lacp_tlv_type = MARKER_T_RESPONSE; + + m = m_prepend(m, sizeof(*eh), M_DONTWAIT); + if (m == NULL) + return; + + eh = mtod(m, struct ether_header *); + memcpy(eh->ether_dhost, lacp_address_slow, sizeof(eh->ether_dhost)); + memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(eh->ether_shost)); + eh->ether_type = htons(ETHERTYPE_SLOW); + + (void)if_enqueue(ifp0, m); +} + +static void aggr_input_marker(struct aggr_port *p, struct mbuf *m) { - m_freem(m); + struct marker_pdu *mpdu; + + if (m->m_len < sizeof(*mpdu)) { + m = m_pullup(m, sizeof(*mpdu)); + if (m == NULL) + return; + } + + mpdu = mtod(m, struct marker_pdu *); + switch (mpdu->marker_info_tlv.lacp_tlv_type) { + case MARKER_T_INFORMATION: + aggr_marker_response(p, m); + break; + default: + m_freem(m); + break; + } } static void |