1168561Sthompsa/* $NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $ */ 2168561Sthompsa 3168561Sthompsa/*- 4168561Sthompsa * Copyright (c)2005 YAMAMOTO Takashi, 5168561Sthompsa * All rights reserved. 6168561Sthompsa * 7168561Sthompsa * Redistribution and use in source and binary forms, with or without 8168561Sthompsa * modification, are permitted provided that the following conditions 9168561Sthompsa * are met: 10168561Sthompsa * 1. Redistributions of source code must retain the above copyright 11168561Sthompsa * notice, this list of conditions and the following disclaimer. 12168561Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 13168561Sthompsa * notice, this list of conditions and the following disclaimer in the 14168561Sthompsa * documentation and/or other materials provided with the distribution. 15168561Sthompsa * 16168561Sthompsa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17168561Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18168561Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19168561Sthompsa * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20168561Sthompsa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21168561Sthompsa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22168561Sthompsa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23168561Sthompsa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24168561Sthompsa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25168561Sthompsa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26168561Sthompsa * SUCH DAMAGE. 27168561Sthompsa * 28168561Sthompsa * $FreeBSD$ 29168561Sthompsa */ 30168561Sthompsa 31168561Sthompsa/* 32168561Sthompsa * IEEE802.3ad LACP 33168561Sthompsa * 34168561Sthompsa * implementation details. 35168561Sthompsa */ 36168561Sthompsa 37168561Sthompsa#define LACP_TIMER_CURRENT_WHILE 0 38168561Sthompsa#define LACP_TIMER_PERIODIC 1 39168561Sthompsa#define LACP_TIMER_WAIT_WHILE 2 40168561Sthompsa#define LACP_NTIMER 3 41168561Sthompsa 42168561Sthompsa#define LACP_TIMER_ARM(port, timer, val) \ 43168561Sthompsa (port)->lp_timer[(timer)] = (val) 44168561Sthompsa#define LACP_TIMER_DISARM(port, timer) \ 45168561Sthompsa (port)->lp_timer[(timer)] = 0 46168561Sthompsa#define LACP_TIMER_ISARMED(port, timer) \ 47168561Sthompsa ((port)->lp_timer[(timer)] > 0) 48168561Sthompsa 49168561Sthompsa/* 50168561Sthompsa * IEEE802.3ad LACP 51168561Sthompsa * 52168561Sthompsa * protocol definitions. 53168561Sthompsa */ 54168561Sthompsa 55168561Sthompsa#define LACP_STATE_ACTIVITY (1<<0) 56168561Sthompsa#define LACP_STATE_TIMEOUT (1<<1) 57168561Sthompsa#define LACP_STATE_AGGREGATION (1<<2) 58168561Sthompsa#define LACP_STATE_SYNC (1<<3) 59168561Sthompsa#define LACP_STATE_COLLECTING (1<<4) 60168561Sthompsa#define LACP_STATE_DISTRIBUTING (1<<5) 61168561Sthompsa#define LACP_STATE_DEFAULTED (1<<6) 62168561Sthompsa#define LACP_STATE_EXPIRED (1<<7) 63168561Sthompsa 64170599Sthompsa#define LACP_PORT_NTT 0x00000001 65170599Sthompsa#define LACP_PORT_MARK 0x00000002 66168561Sthompsa 67168561Sthompsa#define LACP_STATE_BITS \ 68168561Sthompsa "\020" \ 69168561Sthompsa "\001ACTIVITY" \ 70168561Sthompsa "\002TIMEOUT" \ 71168561Sthompsa "\003AGGREGATION" \ 72168561Sthompsa "\004SYNC" \ 73168561Sthompsa "\005COLLECTING" \ 74168561Sthompsa "\006DISTRIBUTING" \ 75168561Sthompsa "\007DEFAULTED" \ 76168561Sthompsa "\010EXPIRED" 77168561Sthompsa 78287723Shrs#ifdef _KERNEL 79168561Sthompsa/* 80168561Sthompsa * IEEE802.3 slow protocols 81168561Sthompsa * 82168561Sthompsa * protocol (on-wire) definitions. 83168561Sthompsa * 84168561Sthompsa * XXX should be elsewhere. 85168561Sthompsa */ 86168561Sthompsa 87168561Sthompsa#define SLOWPROTOCOLS_SUBTYPE_LACP 1 88168561Sthompsa#define SLOWPROTOCOLS_SUBTYPE_MARKER 2 89168561Sthompsa 90168561Sthompsastruct slowprothdr { 91168561Sthompsa uint8_t sph_subtype; 92168561Sthompsa uint8_t sph_version; 93168561Sthompsa} __packed; 94168561Sthompsa 95168561Sthompsa/* 96168561Sthompsa * TLV on-wire structure. 97168561Sthompsa */ 98168561Sthompsa 99168561Sthompsastruct tlvhdr { 100168561Sthompsa uint8_t tlv_type; 101168561Sthompsa uint8_t tlv_length; 102168561Sthompsa /* uint8_t tlv_value[]; */ 103168561Sthompsa} __packed; 104168561Sthompsa 105168561Sthompsa/* 106168561Sthompsa * ... and our implementation. 107168561Sthompsa */ 108168561Sthompsa 109168561Sthompsa#define TLV_SET(tlv, type, length) \ 110168561Sthompsa do { \ 111168561Sthompsa (tlv)->tlv_type = (type); \ 112168561Sthompsa (tlv)->tlv_length = sizeof(*tlv) + (length); \ 113168561Sthompsa } while (/*CONSTCOND*/0) 114168561Sthompsa 115168561Sthompsastruct tlv_template { 116168561Sthompsa uint8_t tmpl_type; 117168561Sthompsa uint8_t tmpl_length; 118168561Sthompsa}; 119168561Sthompsa 120168561Sthompsastruct lacp_systemid { 121168561Sthompsa uint16_t lsi_prio; 122168561Sthompsa uint8_t lsi_mac[6]; 123168561Sthompsa} __packed; 124168561Sthompsa 125168561Sthompsastruct lacp_portid { 126168561Sthompsa uint16_t lpi_prio; 127168561Sthompsa uint16_t lpi_portno; 128168561Sthompsa} __packed; 129168561Sthompsa 130168561Sthompsastruct lacp_peerinfo { 131170599Sthompsa struct lacp_systemid lip_systemid; 132168561Sthompsa uint16_t lip_key; 133170599Sthompsa struct lacp_portid lip_portid; 134168561Sthompsa uint8_t lip_state; 135168561Sthompsa uint8_t lip_resv[3]; 136168561Sthompsa} __packed; 137168561Sthompsa 138168561Sthompsastruct lacp_collectorinfo { 139168561Sthompsa uint16_t lci_maxdelay; 140168561Sthompsa uint8_t lci_resv[12]; 141168561Sthompsa} __packed; 142168561Sthompsa 143168561Sthompsastruct lacpdu { 144168561Sthompsa struct ether_header ldu_eh; 145168561Sthompsa struct slowprothdr ldu_sph; 146168561Sthompsa 147168561Sthompsa struct tlvhdr ldu_tlv_actor; 148168561Sthompsa struct lacp_peerinfo ldu_actor; 149168561Sthompsa struct tlvhdr ldu_tlv_partner; 150168561Sthompsa struct lacp_peerinfo ldu_partner; 151168561Sthompsa struct tlvhdr ldu_tlv_collector; 152168561Sthompsa struct lacp_collectorinfo ldu_collector; 153168561Sthompsa struct tlvhdr ldu_tlv_term; 154168561Sthompsa uint8_t ldu_resv[50]; 155168561Sthompsa} __packed; 156168561Sthompsa 157169739Sthompsa/* 158169739Sthompsa * IEEE802.3ad marker protocol 159169739Sthompsa * 160169739Sthompsa * protocol (on-wire) definitions. 161169739Sthompsa */ 162169739Sthompsastruct lacp_markerinfo { 163169739Sthompsa uint16_t mi_rq_port; 164169739Sthompsa uint8_t mi_rq_system[ETHER_ADDR_LEN]; 165169739Sthompsa uint32_t mi_rq_xid; 166169739Sthompsa uint8_t mi_pad[2]; 167169739Sthompsa} __packed; 168168561Sthompsa 169169739Sthompsastruct markerdu { 170169739Sthompsa struct ether_header mdu_eh; 171169739Sthompsa struct slowprothdr mdu_sph; 172169739Sthompsa 173169739Sthompsa struct tlvhdr mdu_tlv; 174169739Sthompsa struct lacp_markerinfo mdu_info; 175169739Sthompsa struct tlvhdr mdu_tlv_term; 176169739Sthompsa uint8_t mdu_resv[90]; 177169739Sthompsa} __packed; 178169739Sthompsa 179169739Sthompsa#define MARKER_TYPE_INFO 0x01 180169739Sthompsa#define MARKER_TYPE_RESPONSE 0x02 181169739Sthompsa 182168561Sthompsaenum lacp_selected { 183168561Sthompsa LACP_UNSELECTED, 184168561Sthompsa LACP_STANDBY, /* not used in this implementation */ 185168561Sthompsa LACP_SELECTED, 186168561Sthompsa}; 187168561Sthompsa 188168561Sthompsaenum lacp_mux_state { 189168561Sthompsa LACP_MUX_DETACHED, 190168561Sthompsa LACP_MUX_WAITING, 191168561Sthompsa LACP_MUX_ATTACHED, 192168561Sthompsa LACP_MUX_COLLECTING, 193168561Sthompsa LACP_MUX_DISTRIBUTING, 194168561Sthompsa}; 195168561Sthompsa 196177274Sthompsa#define LACP_MAX_PORTS 32 197177274Sthompsa 198177274Sthompsastruct lacp_portmap { 199177274Sthompsa int pm_count; 200177274Sthompsa struct lacp_port *pm_map[LACP_MAX_PORTS]; 201177274Sthompsa}; 202177274Sthompsa 203168561Sthompsastruct lacp_port { 204168561Sthompsa TAILQ_ENTRY(lacp_port) lp_dist_q; 205168561Sthompsa LIST_ENTRY(lacp_port) lp_next; 206168561Sthompsa struct lacp_softc *lp_lsc; 207168793Sthompsa struct lagg_port *lp_lagg; 208168561Sthompsa struct ifnet *lp_ifp; 209168561Sthompsa struct lacp_peerinfo lp_partner; 210168561Sthompsa struct lacp_peerinfo lp_actor; 211169739Sthompsa struct lacp_markerinfo lp_marker; 212168561Sthompsa#define lp_state lp_actor.lip_state 213168561Sthompsa#define lp_key lp_actor.lip_key 214169739Sthompsa#define lp_systemid lp_actor.lip_systemid 215168561Sthompsa struct timeval lp_last_lacpdu; 216168561Sthompsa int lp_lacpdu_sent; 217168561Sthompsa enum lacp_mux_state lp_mux_state; 218168561Sthompsa enum lacp_selected lp_selected; 219168561Sthompsa int lp_flags; 220168561Sthompsa u_int lp_media; /* XXX redundant */ 221168561Sthompsa int lp_timer[LACP_NTIMER]; 222169327Sthompsa struct ifmultiaddr *lp_ifma; 223168561Sthompsa 224168561Sthompsa struct lacp_aggregator *lp_aggregator; 225168561Sthompsa}; 226168561Sthompsa 227168561Sthompsastruct lacp_aggregator { 228168561Sthompsa TAILQ_ENTRY(lacp_aggregator) la_q; 229168561Sthompsa int la_refcnt; /* num of ports which selected us */ 230168561Sthompsa int la_nports; /* num of distributing ports */ 231168561Sthompsa TAILQ_HEAD(, lacp_port) la_ports; /* distributing ports */ 232168561Sthompsa struct lacp_peerinfo la_partner; 233168561Sthompsa struct lacp_peerinfo la_actor; 234170599Sthompsa int la_pending; /* number of ports in wait_while */ 235168561Sthompsa}; 236168561Sthompsa 237168561Sthompsastruct lacp_softc { 238170599Sthompsa struct lagg_softc *lsc_softc; 239177274Sthompsa struct mtx lsc_mtx; 240168561Sthompsa struct lacp_aggregator *lsc_active_aggregator; 241168561Sthompsa TAILQ_HEAD(, lacp_aggregator) lsc_aggregators; 242168561Sthompsa boolean_t lsc_suppress_distributing; 243168561Sthompsa struct callout lsc_transit_callout; 244168561Sthompsa struct callout lsc_callout; 245168561Sthompsa LIST_HEAD(, lacp_port) lsc_ports; 246177274Sthompsa struct lacp_portmap lsc_pmap[2]; 247177274Sthompsa volatile u_int lsc_activemap; 248168561Sthompsa u_int32_t lsc_hashkey; 249253687Sadrian struct { 250253687Sadrian u_int32_t lsc_rx_test; 251253687Sadrian u_int32_t lsc_tx_test; 252253687Sadrian } lsc_debug; 253253687Sadrian u_int32_t lsc_strict_mode; 254287808Shiren boolean_t lsc_fast_timeout; /* if set, fast timeout */ 255168561Sthompsa}; 256168561Sthompsa 257168561Sthompsa#define LACP_TYPE_ACTORINFO 1 258168561Sthompsa#define LACP_TYPE_PARTNERINFO 2 259168561Sthompsa#define LACP_TYPE_COLLECTORINFO 3 260168561Sthompsa 261168561Sthompsa/* timeout values (in sec) */ 262168561Sthompsa#define LACP_FAST_PERIODIC_TIME (1) 263168561Sthompsa#define LACP_SLOW_PERIODIC_TIME (30) 264168561Sthompsa#define LACP_SHORT_TIMEOUT_TIME (3 * LACP_FAST_PERIODIC_TIME) 265168561Sthompsa#define LACP_LONG_TIMEOUT_TIME (3 * LACP_SLOW_PERIODIC_TIME) 266168561Sthompsa#define LACP_CHURN_DETECTION_TIME (60) 267168561Sthompsa#define LACP_AGGREGATE_WAIT_TIME (2) 268169739Sthompsa#define LACP_TRANSIT_DELAY 3000 /* in msec */ 269168561Sthompsa 270168561Sthompsa#define LACP_STATE_EQ(s1, s2, mask) \ 271168561Sthompsa ((((s1) ^ (s2)) & (mask)) == 0) 272168561Sthompsa 273169741Sthompsa#define LACP_SYS_PRI(peer) (peer).lip_systemid.lsi_prio 274169741Sthompsa 275168793Sthompsa#define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->lp_psc) 276168793Sthompsa#define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->sc_psc) 277168561Sthompsa 278177274Sthompsa#define LACP_LOCK_INIT(_lsc) mtx_init(&(_lsc)->lsc_mtx, \ 279177289Sthompsa "lacp mtx", NULL, MTX_DEF) 280177289Sthompsa#define LACP_LOCK_DESTROY(_lsc) mtx_destroy(&(_lsc)->lsc_mtx) 281177274Sthompsa#define LACP_LOCK(_lsc) mtx_lock(&(_lsc)->lsc_mtx) 282177274Sthompsa#define LACP_UNLOCK(_lsc) mtx_unlock(&(_lsc)->lsc_mtx) 283177274Sthompsa#define LACP_LOCK_ASSERT(_lsc) mtx_assert(&(_lsc)->lsc_mtx, MA_OWNED) 284177274Sthompsa 285175005Sthompsastruct mbuf *lacp_input(struct lagg_port *, struct mbuf *); 286168793Sthompsastruct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *); 287287723Shrsvoid lacp_attach(struct lagg_softc *); 288287723Shrsint lacp_detach(void *); 289168793Sthompsavoid lacp_init(struct lagg_softc *); 290168793Sthompsavoid lacp_stop(struct lagg_softc *); 291168793Sthompsaint lacp_port_create(struct lagg_port *); 292168793Sthompsavoid lacp_port_destroy(struct lagg_port *); 293168793Sthompsavoid lacp_linkstate(struct lagg_port *); 294171247Sthompsavoid lacp_req(struct lagg_softc *, caddr_t); 295171247Sthompsavoid lacp_portreq(struct lagg_port *, caddr_t); 296168561Sthompsa 297177274Sthompsastatic __inline int 298177274Sthompsalacp_isactive(struct lagg_port *lgp) 299177274Sthompsa{ 300177274Sthompsa struct lacp_port *lp = LACP_PORT(lgp); 301177274Sthompsa struct lacp_softc *lsc = lp->lp_lsc; 302177274Sthompsa struct lacp_aggregator *la = lp->lp_aggregator; 303177274Sthompsa 304177274Sthompsa /* This port is joined to the active aggregator */ 305177274Sthompsa if (la != NULL && la == lsc->lsc_active_aggregator) 306177274Sthompsa return (1); 307177274Sthompsa 308177274Sthompsa return (0); 309177274Sthompsa} 310177274Sthompsa 311177274Sthompsastatic __inline int 312177274Sthompsalacp_iscollecting(struct lagg_port *lgp) 313177274Sthompsa{ 314177274Sthompsa struct lacp_port *lp = LACP_PORT(lgp); 315177274Sthompsa 316177274Sthompsa return ((lp->lp_state & LACP_STATE_COLLECTING) != 0); 317177274Sthompsa} 318177274Sthompsa 319177274Sthompsastatic __inline int 320177274Sthompsalacp_isdistributing(struct lagg_port *lgp) 321177274Sthompsa{ 322177274Sthompsa struct lacp_port *lp = LACP_PORT(lgp); 323177274Sthompsa 324177274Sthompsa return ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0); 325177274Sthompsa} 326177274Sthompsa 327168561Sthompsa/* following constants don't include terminating NUL */ 328168561Sthompsa#define LACP_MACSTR_MAX (2*6 + 5) 329168561Sthompsa#define LACP_SYSTEMPRIOSTR_MAX (4) 330168561Sthompsa#define LACP_SYSTEMIDSTR_MAX (LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX) 331168561Sthompsa#define LACP_PORTPRIOSTR_MAX (4) 332168561Sthompsa#define LACP_PORTNOSTR_MAX (4) 333168561Sthompsa#define LACP_PORTIDSTR_MAX (LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX) 334168561Sthompsa#define LACP_KEYSTR_MAX (4) 335168561Sthompsa#define LACP_PARTNERSTR_MAX \ 336168561Sthompsa (1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \ 337168561Sthompsa + LACP_PORTIDSTR_MAX + 1) 338168561Sthompsa#define LACP_LAGIDSTR_MAX \ 339168561Sthompsa (1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1) 340168561Sthompsa#define LACP_STATESTR_MAX (255) /* XXX */ 341287723Shrs#endif /* _KERNEL */ 342