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 65b47888ceSAndrew Thompson #define LACP_PORT_PROMISC 0x00000004 66b47888ceSAndrew Thompson #define LACP_PORT_LADDRCHANGED 0x00000008 67b47888ceSAndrew Thompson #define LACP_PORT_ATTACHED 0x00000010 68b47888ceSAndrew Thompson #define LACP_PORT_LARVAL 0x00000020 69b47888ceSAndrew Thompson #define LACP_PORT_DETACHING 0x00000040 70b47888ceSAndrew Thompson 71b47888ceSAndrew Thompson #define LACP_STATE_BITS \ 72b47888ceSAndrew Thompson "\020" \ 73b47888ceSAndrew Thompson "\001ACTIVITY" \ 74b47888ceSAndrew Thompson "\002TIMEOUT" \ 75b47888ceSAndrew Thompson "\003AGGREGATION" \ 76b47888ceSAndrew Thompson "\004SYNC" \ 77b47888ceSAndrew Thompson "\005COLLECTING" \ 78b47888ceSAndrew Thompson "\006DISTRIBUTING" \ 79b47888ceSAndrew Thompson "\007DEFAULTED" \ 80b47888ceSAndrew Thompson "\010EXPIRED" 81b47888ceSAndrew Thompson 82b47888ceSAndrew Thompson /* 83b47888ceSAndrew Thompson * IEEE802.3 slow protocols 84b47888ceSAndrew Thompson * 85b47888ceSAndrew Thompson * protocol (on-wire) definitions. 86b47888ceSAndrew Thompson * 87b47888ceSAndrew Thompson * XXX should be elsewhere. 88b47888ceSAndrew Thompson */ 89b47888ceSAndrew Thompson 90b47888ceSAndrew Thompson #define SLOWPROTOCOLS_SUBTYPE_LACP 1 91b47888ceSAndrew Thompson #define SLOWPROTOCOLS_SUBTYPE_MARKER 2 92b47888ceSAndrew Thompson 93b47888ceSAndrew Thompson struct slowprothdr { 94b47888ceSAndrew Thompson uint8_t sph_subtype; 95b47888ceSAndrew Thompson uint8_t sph_version; 96b47888ceSAndrew Thompson } __packed; 97b47888ceSAndrew Thompson 98b47888ceSAndrew Thompson /* 99b47888ceSAndrew Thompson * TLV on-wire structure. 100b47888ceSAndrew Thompson */ 101b47888ceSAndrew Thompson 102b47888ceSAndrew Thompson struct tlvhdr { 103b47888ceSAndrew Thompson uint8_t tlv_type; 104b47888ceSAndrew Thompson uint8_t tlv_length; 105b47888ceSAndrew Thompson /* uint8_t tlv_value[]; */ 106b47888ceSAndrew Thompson } __packed; 107b47888ceSAndrew Thompson 108b47888ceSAndrew Thompson /* 109b47888ceSAndrew Thompson * ... and our implementation. 110b47888ceSAndrew Thompson */ 111b47888ceSAndrew Thompson 112b47888ceSAndrew Thompson #define TLV_SET(tlv, type, length) \ 113b47888ceSAndrew Thompson do { \ 114b47888ceSAndrew Thompson (tlv)->tlv_type = (type); \ 115b47888ceSAndrew Thompson (tlv)->tlv_length = sizeof(*tlv) + (length); \ 116b47888ceSAndrew Thompson } while (/*CONSTCOND*/0) 117b47888ceSAndrew Thompson 118b47888ceSAndrew Thompson struct tlv_template { 119b47888ceSAndrew Thompson uint8_t tmpl_type; 120b47888ceSAndrew Thompson uint8_t tmpl_length; 121b47888ceSAndrew Thompson }; 122b47888ceSAndrew Thompson 123b47888ceSAndrew Thompson struct lacp_systemid { 124b47888ceSAndrew Thompson uint16_t lsi_prio; 125b47888ceSAndrew Thompson uint8_t lsi_mac[6]; 126b47888ceSAndrew Thompson } __packed; 127b47888ceSAndrew Thompson 128b47888ceSAndrew Thompson struct lacp_portid { 129b47888ceSAndrew Thompson uint16_t lpi_prio; 130b47888ceSAndrew Thompson uint16_t lpi_portno; 131b47888ceSAndrew Thompson } __packed; 132b47888ceSAndrew Thompson 133b47888ceSAndrew Thompson struct lacp_peerinfo { 134b47888ceSAndrew Thompson struct lacp_systemid lip_systemid; 135b47888ceSAndrew Thompson uint16_t lip_key; 136b47888ceSAndrew Thompson struct lacp_portid lip_portid; 137b47888ceSAndrew Thompson uint8_t lip_state; 138b47888ceSAndrew Thompson uint8_t lip_resv[3]; 139b47888ceSAndrew Thompson } __packed; 140b47888ceSAndrew Thompson 141b47888ceSAndrew Thompson struct lacp_collectorinfo { 142b47888ceSAndrew Thompson uint16_t lci_maxdelay; 143b47888ceSAndrew Thompson uint8_t lci_resv[12]; 144b47888ceSAndrew Thompson } __packed; 145b47888ceSAndrew Thompson 146b47888ceSAndrew Thompson struct lacpdu { 147b47888ceSAndrew Thompson struct ether_header ldu_eh; 148b47888ceSAndrew Thompson struct slowprothdr ldu_sph; 149b47888ceSAndrew Thompson 150b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_actor; 151b47888ceSAndrew Thompson struct lacp_peerinfo ldu_actor; 152b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_partner; 153b47888ceSAndrew Thompson struct lacp_peerinfo ldu_partner; 154b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_collector; 155b47888ceSAndrew Thompson struct lacp_collectorinfo ldu_collector; 156b47888ceSAndrew Thompson struct tlvhdr ldu_tlv_term; 157b47888ceSAndrew Thompson uint8_t ldu_resv[50]; 158b47888ceSAndrew Thompson } __packed; 159b47888ceSAndrew Thompson 160b47888ceSAndrew Thompson #define LACP_TRANSIT_DELAY 1000 /* in msec */ 161b47888ceSAndrew Thompson 162b47888ceSAndrew Thompson enum lacp_selected { 163b47888ceSAndrew Thompson LACP_UNSELECTED, 164b47888ceSAndrew Thompson LACP_STANDBY, /* not used in this implementation */ 165b47888ceSAndrew Thompson LACP_SELECTED, 166b47888ceSAndrew Thompson }; 167b47888ceSAndrew Thompson 168b47888ceSAndrew Thompson enum lacp_mux_state { 169b47888ceSAndrew Thompson LACP_MUX_DETACHED, 170b47888ceSAndrew Thompson LACP_MUX_WAITING, 171b47888ceSAndrew Thompson LACP_MUX_ATTACHED, 172b47888ceSAndrew Thompson LACP_MUX_COLLECTING, 173b47888ceSAndrew Thompson LACP_MUX_DISTRIBUTING, 174b47888ceSAndrew Thompson }; 175b47888ceSAndrew Thompson 176b47888ceSAndrew Thompson struct lacp_port { 177b47888ceSAndrew Thompson TAILQ_ENTRY(lacp_port) lp_dist_q; 178b47888ceSAndrew Thompson LIST_ENTRY(lacp_port) lp_next; 179b47888ceSAndrew Thompson struct lacp_softc *lp_lsc; 18018242d3bSAndrew Thompson struct lagg_port *lp_lagg; 181b47888ceSAndrew Thompson struct ifnet *lp_ifp; 182b47888ceSAndrew Thompson struct lacp_peerinfo lp_partner; 183b47888ceSAndrew Thompson struct lacp_peerinfo lp_actor; 184b47888ceSAndrew Thompson #define lp_state lp_actor.lip_state 185b47888ceSAndrew Thompson #define lp_key lp_actor.lip_key 186b47888ceSAndrew Thompson struct timeval lp_last_lacpdu; 187b47888ceSAndrew Thompson int lp_lacpdu_sent; 188b47888ceSAndrew Thompson enum lacp_mux_state lp_mux_state; 189b47888ceSAndrew Thompson enum lacp_selected lp_selected; 190b47888ceSAndrew Thompson int lp_flags; 191b47888ceSAndrew Thompson u_int lp_media; /* XXX redundant */ 192b47888ceSAndrew Thompson int lp_timer[LACP_NTIMER]; 193d74fd345SAndrew Thompson struct ifmultiaddr *lp_ifma; 194b47888ceSAndrew Thompson 195b47888ceSAndrew Thompson struct lacp_aggregator *lp_aggregator; 196b47888ceSAndrew Thompson }; 197b47888ceSAndrew Thompson 198b47888ceSAndrew Thompson struct lacp_aggregator { 199b47888ceSAndrew Thompson TAILQ_ENTRY(lacp_aggregator) la_q; 200b47888ceSAndrew Thompson int la_refcnt; /* num of ports which selected us */ 201b47888ceSAndrew Thompson int la_nports; /* num of distributing ports */ 202b47888ceSAndrew Thompson TAILQ_HEAD(, lacp_port) la_ports; /* distributing ports */ 203b47888ceSAndrew Thompson struct lacp_peerinfo la_partner; 204b47888ceSAndrew Thompson struct lacp_peerinfo la_actor; 205b47888ceSAndrew Thompson int la_pending; /* number of ports which is waiting wait_while */ 206b47888ceSAndrew Thompson }; 207b47888ceSAndrew Thompson 208b47888ceSAndrew Thompson struct lacp_softc { 20918242d3bSAndrew Thompson struct lagg_softc *lsc_lagg; 210b47888ceSAndrew Thompson struct lacp_aggregator *lsc_active_aggregator; 211b47888ceSAndrew Thompson TAILQ_HEAD(, lacp_aggregator) lsc_aggregators; 212b47888ceSAndrew Thompson boolean_t lsc_suppress_distributing; 213b47888ceSAndrew Thompson struct callout lsc_transit_callout; 214b47888ceSAndrew Thompson struct callout lsc_callout; 215b47888ceSAndrew Thompson LIST_HEAD(, lacp_port) lsc_ports; 216b47888ceSAndrew Thompson u_int32_t lsc_hashkey; 217b47888ceSAndrew Thompson }; 218b47888ceSAndrew Thompson 219b47888ceSAndrew Thompson #define LACP_TYPE_ACTORINFO 1 220b47888ceSAndrew Thompson #define LACP_TYPE_PARTNERINFO 2 221b47888ceSAndrew Thompson #define LACP_TYPE_COLLECTORINFO 3 222b47888ceSAndrew Thompson 223b47888ceSAndrew Thompson /* timeout values (in sec) */ 224b47888ceSAndrew Thompson #define LACP_FAST_PERIODIC_TIME (1) 225b47888ceSAndrew Thompson #define LACP_SLOW_PERIODIC_TIME (30) 226b47888ceSAndrew Thompson #define LACP_SHORT_TIMEOUT_TIME (3 * LACP_FAST_PERIODIC_TIME) 227b47888ceSAndrew Thompson #define LACP_LONG_TIMEOUT_TIME (3 * LACP_SLOW_PERIODIC_TIME) 228b47888ceSAndrew Thompson #define LACP_CHURN_DETECTION_TIME (60) 229b47888ceSAndrew Thompson #define LACP_AGGREGATE_WAIT_TIME (2) 230b47888ceSAndrew Thompson 231b47888ceSAndrew Thompson /* 232b47888ceSAndrew Thompson int tlv_check(const void *, size_t, const struct tlvhdr *, 233b47888ceSAndrew Thompson const struct tlv_template *, boolean_t); 234b47888ceSAndrew Thompson */ 235b47888ceSAndrew Thompson 236b47888ceSAndrew Thompson /* 237b47888ceSAndrew Thompson * IEEE802.3ad marker protocol 238b47888ceSAndrew Thompson * 239b47888ceSAndrew Thompson * protocol (on-wire) definitions. 240b47888ceSAndrew Thompson */ 241b47888ceSAndrew Thompson 242b47888ceSAndrew Thompson struct markerdu { 243b47888ceSAndrew Thompson struct ether_header mdu_eh; 244b47888ceSAndrew Thompson struct slowprothdr mdu_sph; 245b47888ceSAndrew Thompson 246b47888ceSAndrew Thompson struct tlvhdr mdu_tlv; 247b47888ceSAndrew Thompson uint16_t mdu_rq_port; 248b47888ceSAndrew Thompson uint8_t mdu_rq_system[6]; 249b47888ceSAndrew Thompson uint8_t mdu_rq_xid[4]; 250b47888ceSAndrew Thompson uint8_t mdu_pad[2]; 251b47888ceSAndrew Thompson 252b47888ceSAndrew Thompson struct tlvhdr mdu_tlv_term; 253b47888ceSAndrew Thompson uint8_t mdu_resv[90]; 254b47888ceSAndrew Thompson } __packed; 255b47888ceSAndrew Thompson 256b47888ceSAndrew Thompson #define MARKER_TYPE_INFO 1 257b47888ceSAndrew Thompson #define MARKER_TYPE_RESPONSE 2 258b47888ceSAndrew Thompson 259b47888ceSAndrew Thompson #define LACP_STATE_EQ(s1, s2, mask) \ 260b47888ceSAndrew Thompson ((((s1) ^ (s2)) & (mask)) == 0) 261b47888ceSAndrew Thompson 26218242d3bSAndrew Thompson #define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->lp_psc) 26318242d3bSAndrew Thompson #define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->sc_psc) 264b47888ceSAndrew Thompson 26518242d3bSAndrew Thompson int lacp_input(struct lagg_port *, struct mbuf *); 26618242d3bSAndrew Thompson int lacp_marker_input(struct lagg_port *, struct mbuf *); 26718242d3bSAndrew Thompson struct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *); 26818242d3bSAndrew Thompson int lacp_attach(struct lagg_softc *); 26918242d3bSAndrew Thompson int lacp_detach(struct lagg_softc *); 27018242d3bSAndrew Thompson void lacp_init(struct lagg_softc *); 27118242d3bSAndrew Thompson void lacp_stop(struct lagg_softc *); 27218242d3bSAndrew Thompson int lacp_port_create(struct lagg_port *); 27318242d3bSAndrew Thompson void lacp_port_destroy(struct lagg_port *); 27418242d3bSAndrew Thompson void lacp_linkstate(struct lagg_port *); 27518242d3bSAndrew Thompson int lacp_port_isactive(struct lagg_port *); 276b47888ceSAndrew Thompson 277b47888ceSAndrew Thompson /* following constants don't include terminating NUL */ 278b47888ceSAndrew Thompson #define LACP_MACSTR_MAX (2*6 + 5) 279b47888ceSAndrew Thompson #define LACP_SYSTEMPRIOSTR_MAX (4) 280b47888ceSAndrew Thompson #define LACP_SYSTEMIDSTR_MAX (LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX) 281b47888ceSAndrew Thompson #define LACP_PORTPRIOSTR_MAX (4) 282b47888ceSAndrew Thompson #define LACP_PORTNOSTR_MAX (4) 283b47888ceSAndrew Thompson #define LACP_PORTIDSTR_MAX (LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX) 284b47888ceSAndrew Thompson #define LACP_KEYSTR_MAX (4) 285b47888ceSAndrew Thompson #define LACP_PARTNERSTR_MAX \ 286b47888ceSAndrew Thompson (1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \ 287b47888ceSAndrew Thompson + LACP_PORTIDSTR_MAX + 1) 288b47888ceSAndrew Thompson #define LACP_LAGIDSTR_MAX \ 289b47888ceSAndrew Thompson (1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1) 290b47888ceSAndrew Thompson #define LACP_STATESTR_MAX (255) /* XXX */ 291