1b47888ceSAndrew Thompson /* $NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $ */ 2b47888ceSAndrew Thompson 3b47888ceSAndrew Thompson /*- 4b47888ceSAndrew Thompson * Copyright (c)2005 YAMAMOTO Takashi, 5b47888ceSAndrew Thompson * All rights reserved. 6b47888ceSAndrew Thompson * 7b47888ceSAndrew Thompson * Redistribution and use in source and binary forms, with or without 8b47888ceSAndrew Thompson * modification, are permitted provided that the following conditions 9b47888ceSAndrew Thompson * are met: 10b47888ceSAndrew Thompson * 1. Redistributions of source code must retain the above copyright 11b47888ceSAndrew Thompson * notice, this list of conditions and the following disclaimer. 12b47888ceSAndrew Thompson * 2. Redistributions in binary form must reproduce the above copyright 13b47888ceSAndrew Thompson * notice, this list of conditions and the following disclaimer in the 14b47888ceSAndrew Thompson * documentation and/or other materials provided with the distribution. 15b47888ceSAndrew Thompson * 16b47888ceSAndrew Thompson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17b47888ceSAndrew Thompson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18b47888ceSAndrew Thompson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19b47888ceSAndrew Thompson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20b47888ceSAndrew Thompson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b47888ceSAndrew Thompson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22b47888ceSAndrew Thompson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23b47888ceSAndrew Thompson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24b47888ceSAndrew Thompson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25b47888ceSAndrew Thompson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26b47888ceSAndrew Thompson * SUCH DAMAGE. 27b47888ceSAndrew Thompson * 28b47888ceSAndrew Thompson * $FreeBSD$ 29b47888ceSAndrew Thompson */ 30b47888ceSAndrew Thompson 31b47888ceSAndrew Thompson /* 32b47888ceSAndrew Thompson * IEEE802.3ad LACP 33b47888ceSAndrew Thompson * 34b47888ceSAndrew Thompson * implementation details. 35b47888ceSAndrew Thompson */ 36b47888ceSAndrew Thompson 37b47888ceSAndrew Thompson #define LACP_TIMER_CURRENT_WHILE 0 38b47888ceSAndrew Thompson #define LACP_TIMER_PERIODIC 1 39b47888ceSAndrew Thompson #define LACP_TIMER_WAIT_WHILE 2 40b47888ceSAndrew Thompson #define LACP_NTIMER 3 41b47888ceSAndrew Thompson 42b47888ceSAndrew Thompson #define LACP_TIMER_ARM(port, timer, val) \ 43b47888ceSAndrew Thompson (port)->lp_timer[(timer)] = (val) 44b47888ceSAndrew Thompson #define LACP_TIMER_DISARM(port, timer) \ 45b47888ceSAndrew Thompson (port)->lp_timer[(timer)] = 0 46b47888ceSAndrew Thompson #define LACP_TIMER_ISARMED(port, timer) \ 47b47888ceSAndrew Thompson ((port)->lp_timer[(timer)] > 0) 48b47888ceSAndrew Thompson 49b47888ceSAndrew Thompson /* 50b47888ceSAndrew Thompson * IEEE802.3ad LACP 51b47888ceSAndrew Thompson * 52b47888ceSAndrew Thompson * protocol definitions. 53b47888ceSAndrew Thompson */ 54b47888ceSAndrew Thompson 55b47888ceSAndrew Thompson #define LACP_STATE_ACTIVITY (1<<0) 56b47888ceSAndrew Thompson #define LACP_STATE_TIMEOUT (1<<1) 57b47888ceSAndrew Thompson #define LACP_STATE_AGGREGATION (1<<2) 58b47888ceSAndrew Thompson #define LACP_STATE_SYNC (1<<3) 59b47888ceSAndrew Thompson #define LACP_STATE_COLLECTING (1<<4) 60b47888ceSAndrew Thompson #define LACP_STATE_DISTRIBUTING (1<<5) 61b47888ceSAndrew Thompson #define LACP_STATE_DEFAULTED (1<<6) 62b47888ceSAndrew Thompson #define LACP_STATE_EXPIRED (1<<7) 63b47888ceSAndrew Thompson 64b47888ceSAndrew Thompson #define LACP_PORT_NTT 0x00000001 65998971a7SAndrew Thompson #define LACP_PORT_MARK 0x00000002 66b47888ceSAndrew Thompson #define LACP_PORT_PROMISC 0x00000004 67b47888ceSAndrew Thompson #define LACP_PORT_LADDRCHANGED 0x00000008 68b47888ceSAndrew Thompson #define LACP_PORT_ATTACHED 0x00000010 69b47888ceSAndrew Thompson #define LACP_PORT_LARVAL 0x00000020 70b47888ceSAndrew Thompson #define LACP_PORT_DETACHING 0x00000040 71b47888ceSAndrew Thompson 72b47888ceSAndrew Thompson #define LACP_STATE_BITS \ 73b47888ceSAndrew Thompson "\020" \ 74b47888ceSAndrew Thompson "\001ACTIVITY" \ 75b47888ceSAndrew Thompson "\002TIMEOUT" \ 76b47888ceSAndrew Thompson "\003AGGREGATION" \ 77b47888ceSAndrew Thompson "\004SYNC" \ 78b47888ceSAndrew Thompson "\005COLLECTING" \ 79b47888ceSAndrew Thompson "\006DISTRIBUTING" \ 80b47888ceSAndrew Thompson "\007DEFAULTED" \ 81b47888ceSAndrew Thompson "\010EXPIRED" 82b47888ceSAndrew Thompson 83b47888ceSAndrew Thompson /* 84b47888ceSAndrew Thompson * IEEE802.3 slow protocols 85b47888ceSAndrew Thompson * 86b47888ceSAndrew Thompson * protocol (on-wire) definitions. 87b47888ceSAndrew Thompson * 88b47888ceSAndrew Thompson * XXX should be elsewhere. 89b47888ceSAndrew Thompson */ 90b47888ceSAndrew Thompson 91b47888ceSAndrew Thompson #define SLOWPROTOCOLS_SUBTYPE_LACP 1 92b47888ceSAndrew Thompson #define SLOWPROTOCOLS_SUBTYPE_MARKER 2 93b47888ceSAndrew Thompson 94b47888ceSAndrew Thompson struct slowprothdr { 95b47888ceSAndrew Thompson uint8_t sph_subtype; 96b47888ceSAndrew Thompson uint8_t sph_version; 97b47888ceSAndrew Thompson } __packed; 98b47888ceSAndrew Thompson 99b47888ceSAndrew Thompson /* 100b47888ceSAndrew Thompson * TLV on-wire structure. 101b47888ceSAndrew Thompson */ 102b47888ceSAndrew Thompson 103b47888ceSAndrew Thompson struct tlvhdr { 104b47888ceSAndrew Thompson uint8_t tlv_type; 105b47888ceSAndrew Thompson uint8_t tlv_length; 106b47888ceSAndrew Thompson /* uint8_t tlv_value[]; */ 107b47888ceSAndrew Thompson } __packed; 108b47888ceSAndrew Thompson 109b47888ceSAndrew Thompson /* 110b47888ceSAndrew Thompson * ... and our implementation. 111b47888ceSAndrew Thompson */ 112b47888ceSAndrew Thompson 113b47888ceSAndrew Thompson #define TLV_SET(tlv, type, length) \ 114b47888ceSAndrew Thompson do { \ 115b47888ceSAndrew Thompson (tlv)->tlv_type = (type); \ 116b47888ceSAndrew Thompson (tlv)->tlv_length = sizeof(*tlv) + (length); \ 117b47888ceSAndrew Thompson } while (/*CONSTCOND*/0) 118b47888ceSAndrew Thompson 119b47888ceSAndrew Thompson struct tlv_template { 120b47888ceSAndrew Thompson uint8_t tmpl_type; 121b47888ceSAndrew Thompson uint8_t tmpl_length; 122b47888ceSAndrew Thompson }; 123b47888ceSAndrew Thompson 124b47888ceSAndrew Thompson struct lacp_systemid { 125b47888ceSAndrew Thompson uint16_t lsi_prio; 126b47888ceSAndrew Thompson uint8_t lsi_mac[6]; 127b47888ceSAndrew Thompson } __packed; 128b47888ceSAndrew Thompson 129b47888ceSAndrew Thompson struct lacp_portid { 130b47888ceSAndrew Thompson uint16_t lpi_prio; 131b47888ceSAndrew Thompson uint16_t lpi_portno; 132b47888ceSAndrew Thompson } __packed; 133b47888ceSAndrew Thompson 134b47888ceSAndrew Thompson struct lacp_peerinfo { 135b47888ceSAndrew Thompson struct lacp_systemid lip_systemid; 136b47888ceSAndrew Thompson uint16_t lip_key; 137b47888ceSAndrew Thompson struct lacp_portid lip_portid; 138b47888ceSAndrew Thompson uint8_t lip_state; 139b47888ceSAndrew Thompson uint8_t lip_resv[3]; 140b47888ceSAndrew Thompson } __packed; 141b47888ceSAndrew Thompson 142b47888ceSAndrew Thompson struct lacp_collectorinfo { 143b47888ceSAndrew Thompson uint16_t lci_maxdelay; 144b47888ceSAndrew Thompson uint8_t lci_resv[12]; 145b47888ceSAndrew Thompson } __packed; 146b47888ceSAndrew Thompson 147b47888ceSAndrew Thompson struct lacpdu { 148b47888ceSAndrew Thompson struct ether_header ldu_eh; 149b47888ceSAndrew Thompson struct slowprothdr ldu_sph; 150b47888ceSAndrew Thompson 151b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_actor; 152b47888ceSAndrew Thompson struct lacp_peerinfo ldu_actor; 153b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_partner; 154b47888ceSAndrew Thompson struct lacp_peerinfo ldu_partner; 155b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_collector; 156b47888ceSAndrew Thompson struct lacp_collectorinfo ldu_collector; 157b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_term; 158b47888ceSAndrew Thompson uint8_t ldu_resv[50]; 159b47888ceSAndrew Thompson } __packed; 160b47888ceSAndrew Thompson 161998971a7SAndrew Thompson /* 162998971a7SAndrew Thompson * IEEE802.3ad marker protocol 163998971a7SAndrew Thompson * 164998971a7SAndrew Thompson * protocol (on-wire) definitions. 165998971a7SAndrew Thompson */ 166998971a7SAndrew Thompson struct lacp_markerinfo { 167998971a7SAndrew Thompson uint16_t mi_rq_port; 168998971a7SAndrew Thompson uint8_t mi_rq_system[ETHER_ADDR_LEN]; 169998971a7SAndrew Thompson uint32_t mi_rq_xid; 170998971a7SAndrew Thompson uint8_t mi_pad[2]; 171998971a7SAndrew Thompson } __packed; 172998971a7SAndrew Thompson 173998971a7SAndrew Thompson struct markerdu { 174998971a7SAndrew Thompson struct ether_header mdu_eh; 175998971a7SAndrew Thompson struct slowprothdr mdu_sph; 176998971a7SAndrew Thompson 177998971a7SAndrew Thompson struct tlvhdr mdu_tlv; 178998971a7SAndrew Thompson struct lacp_markerinfo mdu_info; 179998971a7SAndrew Thompson struct tlvhdr mdu_tlv_term; 180998971a7SAndrew Thompson uint8_t mdu_resv[90]; 181998971a7SAndrew Thompson } __packed; 182998971a7SAndrew Thompson 183998971a7SAndrew Thompson #define MARKER_TYPE_INFO 0x01 184998971a7SAndrew Thompson #define MARKER_TYPE_RESPONSE 0x02 185b47888ceSAndrew Thompson 186b47888ceSAndrew Thompson enum lacp_selected { 187b47888ceSAndrew Thompson LACP_UNSELECTED, 188b47888ceSAndrew Thompson LACP_STANDBY, /* not used in this implementation */ 189b47888ceSAndrew Thompson LACP_SELECTED, 190b47888ceSAndrew Thompson }; 191b47888ceSAndrew Thompson 192b47888ceSAndrew Thompson enum lacp_mux_state { 193b47888ceSAndrew Thompson LACP_MUX_DETACHED, 194b47888ceSAndrew Thompson LACP_MUX_WAITING, 195b47888ceSAndrew Thompson LACP_MUX_ATTACHED, 196b47888ceSAndrew Thompson LACP_MUX_COLLECTING, 197b47888ceSAndrew Thompson LACP_MUX_DISTRIBUTING, 198b47888ceSAndrew Thompson }; 199b47888ceSAndrew Thompson 200b47888ceSAndrew Thompson struct lacp_port { 201b47888ceSAndrew Thompson TAILQ_ENTRY(lacp_port) lp_dist_q; 202b47888ceSAndrew Thompson LIST_ENTRY(lacp_port) lp_next; 203b47888ceSAndrew Thompson struct lacp_softc *lp_lsc; 20418242d3bSAndrew Thompson struct lagg_port *lp_lagg; 205b47888ceSAndrew Thompson struct ifnet *lp_ifp; 206b47888ceSAndrew Thompson struct lacp_peerinfo lp_partner; 207b47888ceSAndrew Thompson struct lacp_peerinfo lp_actor; 208998971a7SAndrew Thompson struct lacp_markerinfo lp_marker; 209b47888ceSAndrew Thompson #define lp_state lp_actor.lip_state 210b47888ceSAndrew Thompson #define lp_key lp_actor.lip_key 211998971a7SAndrew Thompson #define lp_systemid lp_actor.lip_systemid 212b47888ceSAndrew Thompson struct timeval lp_last_lacpdu; 213b47888ceSAndrew Thompson int lp_lacpdu_sent; 214b47888ceSAndrew Thompson enum lacp_mux_state lp_mux_state; 215b47888ceSAndrew Thompson enum lacp_selected lp_selected; 216b47888ceSAndrew Thompson int lp_flags; 217b47888ceSAndrew Thompson u_int lp_media; /* XXX redundant */ 218b47888ceSAndrew Thompson int lp_timer[LACP_NTIMER]; 219d74fd345SAndrew Thompson struct ifmultiaddr *lp_ifma; 220b47888ceSAndrew Thompson 221b47888ceSAndrew Thompson struct lacp_aggregator *lp_aggregator; 222b47888ceSAndrew Thompson }; 223b47888ceSAndrew Thompson 224b47888ceSAndrew Thompson struct lacp_aggregator { 225b47888ceSAndrew Thompson TAILQ_ENTRY(lacp_aggregator) la_q; 226b47888ceSAndrew Thompson int la_refcnt; /* num of ports which selected us */ 227b47888ceSAndrew Thompson int la_nports; /* num of distributing ports */ 228b47888ceSAndrew Thompson TAILQ_HEAD(, lacp_port) la_ports; /* distributing ports */ 229b47888ceSAndrew Thompson struct lacp_peerinfo la_partner; 230b47888ceSAndrew Thompson struct lacp_peerinfo la_actor; 231b47888ceSAndrew Thompson int la_pending; /* number of ports which is waiting wait_while */ 232b47888ceSAndrew Thompson }; 233b47888ceSAndrew Thompson 234b47888ceSAndrew Thompson struct lacp_softc { 23518242d3bSAndrew Thompson struct lagg_softc *lsc_lagg; 236b47888ceSAndrew Thompson struct lacp_aggregator *lsc_active_aggregator; 237b47888ceSAndrew Thompson TAILQ_HEAD(, lacp_aggregator) lsc_aggregators; 238b47888ceSAndrew Thompson boolean_t lsc_suppress_distributing; 239b47888ceSAndrew Thompson struct callout lsc_transit_callout; 240b47888ceSAndrew Thompson struct callout lsc_callout; 241b47888ceSAndrew Thompson LIST_HEAD(, lacp_port) lsc_ports; 242b47888ceSAndrew Thompson u_int32_t lsc_hashkey; 2433bf517e3SAndrew Thompson struct task lsc_qtask; 2443bf517e3SAndrew Thompson struct ifqueue lsc_queue; /* pdu input queue */ 245b47888ceSAndrew Thompson }; 246b47888ceSAndrew Thompson 247b47888ceSAndrew Thompson #define LACP_TYPE_ACTORINFO 1 248b47888ceSAndrew Thompson #define LACP_TYPE_PARTNERINFO 2 249b47888ceSAndrew Thompson #define LACP_TYPE_COLLECTORINFO 3 250b47888ceSAndrew Thompson 251b47888ceSAndrew Thompson /* timeout values (in sec) */ 252b47888ceSAndrew Thompson #define LACP_FAST_PERIODIC_TIME (1) 253b47888ceSAndrew Thompson #define LACP_SLOW_PERIODIC_TIME (30) 254b47888ceSAndrew Thompson #define LACP_SHORT_TIMEOUT_TIME (3 * LACP_FAST_PERIODIC_TIME) 255b47888ceSAndrew Thompson #define LACP_LONG_TIMEOUT_TIME (3 * LACP_SLOW_PERIODIC_TIME) 256b47888ceSAndrew Thompson #define LACP_CHURN_DETECTION_TIME (60) 257b47888ceSAndrew Thompson #define LACP_AGGREGATE_WAIT_TIME (2) 258998971a7SAndrew Thompson #define LACP_TRANSIT_DELAY 3000 /* in msec */ 259b47888ceSAndrew Thompson 260b47888ceSAndrew Thompson /* 261b47888ceSAndrew Thompson int tlv_check(const void *, size_t, const struct tlvhdr *, 262b47888ceSAndrew Thompson const struct tlv_template *, boolean_t); 263b47888ceSAndrew Thompson */ 264b47888ceSAndrew Thompson 265b47888ceSAndrew Thompson #define LACP_STATE_EQ(s1, s2, mask) \ 266b47888ceSAndrew Thompson ((((s1) ^ (s2)) & (mask)) == 0) 267b47888ceSAndrew Thompson 268fe45e65fSAndrew Thompson #define LACP_SYS_PRI(peer) (peer).lip_systemid.lsi_prio 269fe45e65fSAndrew Thompson 27018242d3bSAndrew Thompson #define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->lp_psc) 27118242d3bSAndrew Thompson #define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->sc_psc) 272b47888ceSAndrew Thompson 2733bf517e3SAndrew Thompson void lacp_input(struct lagg_port *, struct mbuf *); 27418242d3bSAndrew Thompson struct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *); 27518242d3bSAndrew Thompson int lacp_attach(struct lagg_softc *); 27618242d3bSAndrew Thompson int lacp_detach(struct lagg_softc *); 27718242d3bSAndrew Thompson void lacp_init(struct lagg_softc *); 27818242d3bSAndrew Thompson void lacp_stop(struct lagg_softc *); 27918242d3bSAndrew Thompson int lacp_port_create(struct lagg_port *); 28018242d3bSAndrew Thompson void lacp_port_destroy(struct lagg_port *); 28118242d3bSAndrew Thompson void lacp_linkstate(struct lagg_port *); 28218242d3bSAndrew Thompson int lacp_port_isactive(struct lagg_port *); 283b47888ceSAndrew Thompson 284b47888ceSAndrew Thompson /* following constants don't include terminating NUL */ 285b47888ceSAndrew Thompson #define LACP_MACSTR_MAX (2*6 + 5) 286b47888ceSAndrew Thompson #define LACP_SYSTEMPRIOSTR_MAX (4) 287b47888ceSAndrew Thompson #define LACP_SYSTEMIDSTR_MAX (LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX) 288b47888ceSAndrew Thompson #define LACP_PORTPRIOSTR_MAX (4) 289b47888ceSAndrew Thompson #define LACP_PORTNOSTR_MAX (4) 290b47888ceSAndrew Thompson #define LACP_PORTIDSTR_MAX (LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX) 291b47888ceSAndrew Thompson #define LACP_KEYSTR_MAX (4) 292b47888ceSAndrew Thompson #define LACP_PARTNERSTR_MAX \ 293b47888ceSAndrew Thompson (1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \ 294b47888ceSAndrew Thompson + LACP_PORTIDSTR_MAX + 1) 295b47888ceSAndrew Thompson #define LACP_LAGIDSTR_MAX \ 296b47888ceSAndrew Thompson (1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1) 297b47888ceSAndrew Thompson #define LACP_STATESTR_MAX (255) /* XXX */ 298