1*a14b8f16Smpf /* $OpenBSD: trunklacp.h,v 1.1 2008/06/15 06:56:09 mpf Exp $ */ 2*a14b8f16Smpf /* $NetBSD: ieee8023ad_impl.h,v 1.2 2005/12/10 23:21:39 elad Exp $ */ 3*a14b8f16Smpf 4*a14b8f16Smpf /* 5*a14b8f16Smpf * Copyright (c)2005 YAMAMOTO Takashi, 6*a14b8f16Smpf * All rights reserved. 7*a14b8f16Smpf * 8*a14b8f16Smpf * Redistribution and use in source and binary forms, with or without 9*a14b8f16Smpf * modification, are permitted provided that the following conditions 10*a14b8f16Smpf * are met: 11*a14b8f16Smpf * 1. Redistributions of source code must retain the above copyright 12*a14b8f16Smpf * notice, this list of conditions and the following disclaimer. 13*a14b8f16Smpf * 2. Redistributions in binary form must reproduce the above copyright 14*a14b8f16Smpf * notice, this list of conditions and the following disclaimer in the 15*a14b8f16Smpf * documentation and/or other materials provided with the distribution. 16*a14b8f16Smpf * 17*a14b8f16Smpf * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*a14b8f16Smpf * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*a14b8f16Smpf * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*a14b8f16Smpf * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*a14b8f16Smpf * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*a14b8f16Smpf * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*a14b8f16Smpf * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*a14b8f16Smpf * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*a14b8f16Smpf * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*a14b8f16Smpf * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*a14b8f16Smpf * SUCH DAMAGE. 28*a14b8f16Smpf * 29*a14b8f16Smpf * $FreeBSD: src/sys/net/ieee8023ad_lacp.h,v 1.11 2008/03/17 01:26:44 thompsa Exp $ 30*a14b8f16Smpf */ 31*a14b8f16Smpf 32*a14b8f16Smpf /* 33*a14b8f16Smpf * IEEE802.3ad LACP 34*a14b8f16Smpf * 35*a14b8f16Smpf * implementation details. 36*a14b8f16Smpf */ 37*a14b8f16Smpf 38*a14b8f16Smpf #define LACP_TIMER_CURRENT_WHILE 0 39*a14b8f16Smpf #define LACP_TIMER_PERIODIC 1 40*a14b8f16Smpf #define LACP_TIMER_WAIT_WHILE 2 41*a14b8f16Smpf #define LACP_NTIMER 3 42*a14b8f16Smpf 43*a14b8f16Smpf #define LACP_TIMER_ARM(port, timer, val) \ 44*a14b8f16Smpf (port)->lp_timer[(timer)] = (val) 45*a14b8f16Smpf #define LACP_TIMER_DISARM(port, timer) \ 46*a14b8f16Smpf (port)->lp_timer[(timer)] = 0 47*a14b8f16Smpf #define LACP_TIMER_ISARMED(port, timer) \ 48*a14b8f16Smpf ((port)->lp_timer[(timer)] > 0) 49*a14b8f16Smpf 50*a14b8f16Smpf /* 51*a14b8f16Smpf * IEEE802.3ad LACP 52*a14b8f16Smpf * 53*a14b8f16Smpf * protocol definitions. 54*a14b8f16Smpf */ 55*a14b8f16Smpf 56*a14b8f16Smpf #define LACP_STATE_ACTIVITY (1<<0) 57*a14b8f16Smpf #define LACP_STATE_TIMEOUT (1<<1) 58*a14b8f16Smpf #define LACP_STATE_AGGREGATION (1<<2) 59*a14b8f16Smpf #define LACP_STATE_SYNC (1<<3) 60*a14b8f16Smpf #define LACP_STATE_COLLECTING (1<<4) 61*a14b8f16Smpf #define LACP_STATE_DISTRIBUTING (1<<5) 62*a14b8f16Smpf #define LACP_STATE_DEFAULTED (1<<6) 63*a14b8f16Smpf #define LACP_STATE_EXPIRED (1<<7) 64*a14b8f16Smpf 65*a14b8f16Smpf #define LACP_PORT_NTT 0x00000001 66*a14b8f16Smpf #define LACP_PORT_MARK 0x00000002 67*a14b8f16Smpf 68*a14b8f16Smpf #define LACP_STATE_BITS \ 69*a14b8f16Smpf "\020" \ 70*a14b8f16Smpf "\001ACTIVITY" \ 71*a14b8f16Smpf "\002TIMEOUT" \ 72*a14b8f16Smpf "\003AGGREGATION" \ 73*a14b8f16Smpf "\004SYNC" \ 74*a14b8f16Smpf "\005COLLECTING" \ 75*a14b8f16Smpf "\006DISTRIBUTING" \ 76*a14b8f16Smpf "\007DEFAULTED" \ 77*a14b8f16Smpf "\010EXPIRED" 78*a14b8f16Smpf 79*a14b8f16Smpf /* 80*a14b8f16Smpf * IEEE802.3 slow protocols 81*a14b8f16Smpf * 82*a14b8f16Smpf * protocol (on-wire) definitions. 83*a14b8f16Smpf * 84*a14b8f16Smpf * XXX should be elsewhere. 85*a14b8f16Smpf */ 86*a14b8f16Smpf 87*a14b8f16Smpf #define SLOWPROTOCOLS_SUBTYPE_LACP 1 88*a14b8f16Smpf #define SLOWPROTOCOLS_SUBTYPE_MARKER 2 89*a14b8f16Smpf 90*a14b8f16Smpf struct slowprothdr { 91*a14b8f16Smpf uint8_t sph_subtype; 92*a14b8f16Smpf uint8_t sph_version; 93*a14b8f16Smpf } __packed; 94*a14b8f16Smpf 95*a14b8f16Smpf /* 96*a14b8f16Smpf * TLV on-wire structure. 97*a14b8f16Smpf */ 98*a14b8f16Smpf 99*a14b8f16Smpf struct tlvhdr { 100*a14b8f16Smpf uint8_t tlv_type; 101*a14b8f16Smpf uint8_t tlv_length; 102*a14b8f16Smpf /* uint8_t tlv_value[]; */ 103*a14b8f16Smpf } __packed; 104*a14b8f16Smpf 105*a14b8f16Smpf /* 106*a14b8f16Smpf * ... and our implementation. 107*a14b8f16Smpf */ 108*a14b8f16Smpf 109*a14b8f16Smpf #define TLV_SET(tlv, type, length) \ 110*a14b8f16Smpf do { \ 111*a14b8f16Smpf (tlv)->tlv_type = (type); \ 112*a14b8f16Smpf (tlv)->tlv_length = sizeof(*tlv) + (length); \ 113*a14b8f16Smpf } while (/*CONSTCOND*/0) 114*a14b8f16Smpf 115*a14b8f16Smpf struct tlv_template { 116*a14b8f16Smpf uint8_t tmpl_type; 117*a14b8f16Smpf uint8_t tmpl_length; 118*a14b8f16Smpf }; 119*a14b8f16Smpf 120*a14b8f16Smpf struct lacp_systemid { 121*a14b8f16Smpf uint16_t lsi_prio; 122*a14b8f16Smpf uint8_t lsi_mac[6]; 123*a14b8f16Smpf } __packed; 124*a14b8f16Smpf 125*a14b8f16Smpf struct lacp_portid { 126*a14b8f16Smpf uint16_t lpi_prio; 127*a14b8f16Smpf uint16_t lpi_portno; 128*a14b8f16Smpf } __packed; 129*a14b8f16Smpf 130*a14b8f16Smpf struct lacp_peerinfo { 131*a14b8f16Smpf struct lacp_systemid lip_systemid; 132*a14b8f16Smpf uint16_t lip_key; 133*a14b8f16Smpf struct lacp_portid lip_portid; 134*a14b8f16Smpf uint8_t lip_state; 135*a14b8f16Smpf uint8_t lip_resv[3]; 136*a14b8f16Smpf } __packed; 137*a14b8f16Smpf 138*a14b8f16Smpf struct lacp_collectorinfo { 139*a14b8f16Smpf uint16_t lci_maxdelay; 140*a14b8f16Smpf uint8_t lci_resv[12]; 141*a14b8f16Smpf } __packed; 142*a14b8f16Smpf 143*a14b8f16Smpf struct lacpdu { 144*a14b8f16Smpf struct ether_header ldu_eh; 145*a14b8f16Smpf struct slowprothdr ldu_sph; 146*a14b8f16Smpf 147*a14b8f16Smpf struct tlvhdr ldu_tlv_actor; 148*a14b8f16Smpf struct lacp_peerinfo ldu_actor; 149*a14b8f16Smpf struct tlvhdr ldu_tlv_partner; 150*a14b8f16Smpf struct lacp_peerinfo ldu_partner; 151*a14b8f16Smpf struct tlvhdr ldu_tlv_collector; 152*a14b8f16Smpf struct lacp_collectorinfo ldu_collector; 153*a14b8f16Smpf struct tlvhdr ldu_tlv_term; 154*a14b8f16Smpf uint8_t ldu_resv[50]; 155*a14b8f16Smpf } __packed; 156*a14b8f16Smpf 157*a14b8f16Smpf /* 158*a14b8f16Smpf * IEEE802.3ad marker protocol 159*a14b8f16Smpf * 160*a14b8f16Smpf * protocol (on-wire) definitions. 161*a14b8f16Smpf */ 162*a14b8f16Smpf struct lacp_markerinfo { 163*a14b8f16Smpf uint16_t mi_rq_port; 164*a14b8f16Smpf uint8_t mi_rq_system[ETHER_ADDR_LEN]; 165*a14b8f16Smpf uint32_t mi_rq_xid; 166*a14b8f16Smpf uint8_t mi_pad[2]; 167*a14b8f16Smpf } __packed; 168*a14b8f16Smpf 169*a14b8f16Smpf struct markerdu { 170*a14b8f16Smpf struct ether_header mdu_eh; 171*a14b8f16Smpf struct slowprothdr mdu_sph; 172*a14b8f16Smpf 173*a14b8f16Smpf struct tlvhdr mdu_tlv; 174*a14b8f16Smpf struct lacp_markerinfo mdu_info; 175*a14b8f16Smpf struct tlvhdr mdu_tlv_term; 176*a14b8f16Smpf uint8_t mdu_resv[90]; 177*a14b8f16Smpf } __packed; 178*a14b8f16Smpf 179*a14b8f16Smpf #define MARKER_TYPE_INFO 0x01 180*a14b8f16Smpf #define MARKER_TYPE_RESPONSE 0x02 181*a14b8f16Smpf 182*a14b8f16Smpf enum lacp_selected { 183*a14b8f16Smpf LACP_UNSELECTED, 184*a14b8f16Smpf LACP_STANDBY, /* not used in this implementation */ 185*a14b8f16Smpf LACP_SELECTED, 186*a14b8f16Smpf }; 187*a14b8f16Smpf 188*a14b8f16Smpf enum lacp_mux_state { 189*a14b8f16Smpf LACP_MUX_DETACHED, 190*a14b8f16Smpf LACP_MUX_WAITING, 191*a14b8f16Smpf LACP_MUX_ATTACHED, 192*a14b8f16Smpf LACP_MUX_COLLECTING, 193*a14b8f16Smpf LACP_MUX_DISTRIBUTING, 194*a14b8f16Smpf }; 195*a14b8f16Smpf 196*a14b8f16Smpf #define LACP_MAX_PORTS 32 197*a14b8f16Smpf 198*a14b8f16Smpf struct lacp_portmap { 199*a14b8f16Smpf int pm_count; 200*a14b8f16Smpf struct lacp_port *pm_map[LACP_MAX_PORTS]; 201*a14b8f16Smpf }; 202*a14b8f16Smpf 203*a14b8f16Smpf struct lacp_port { 204*a14b8f16Smpf TAILQ_ENTRY(lacp_port) lp_dist_q; 205*a14b8f16Smpf LIST_ENTRY(lacp_port) lp_next; 206*a14b8f16Smpf struct lacp_softc *lp_lsc; 207*a14b8f16Smpf struct trunk_port *lp_trunk; 208*a14b8f16Smpf struct ifnet *lp_ifp; 209*a14b8f16Smpf struct lacp_peerinfo lp_partner; 210*a14b8f16Smpf struct lacp_peerinfo lp_actor; 211*a14b8f16Smpf struct lacp_markerinfo lp_marker; 212*a14b8f16Smpf #define lp_state lp_actor.lip_state 213*a14b8f16Smpf #define lp_key lp_actor.lip_key 214*a14b8f16Smpf #define lp_systemid lp_actor.lip_systemid 215*a14b8f16Smpf struct timeval lp_last_lacpdu; 216*a14b8f16Smpf int lp_lacpdu_sent; 217*a14b8f16Smpf enum lacp_mux_state lp_mux_state; 218*a14b8f16Smpf enum lacp_selected lp_selected; 219*a14b8f16Smpf int lp_flags; 220*a14b8f16Smpf u_int lp_media; /* XXX redundant */ 221*a14b8f16Smpf int lp_timer[LACP_NTIMER]; 222*a14b8f16Smpf struct ifmultiaddr *lp_ifma; 223*a14b8f16Smpf 224*a14b8f16Smpf struct lacp_aggregator *lp_aggregator; 225*a14b8f16Smpf }; 226*a14b8f16Smpf 227*a14b8f16Smpf struct lacp_aggregator { 228*a14b8f16Smpf TAILQ_ENTRY(lacp_aggregator) la_q; 229*a14b8f16Smpf int la_refcnt; /* num of ports which selected us */ 230*a14b8f16Smpf int la_nports; /* num of distributing ports */ 231*a14b8f16Smpf TAILQ_HEAD(, lacp_port) la_ports; /* distributing ports */ 232*a14b8f16Smpf struct lacp_peerinfo la_partner; 233*a14b8f16Smpf struct lacp_peerinfo la_actor; 234*a14b8f16Smpf int la_pending; /* number of ports in wait_while */ 235*a14b8f16Smpf }; 236*a14b8f16Smpf 237*a14b8f16Smpf struct lacp_softc { 238*a14b8f16Smpf struct trunk_softc *lsc_softc; 239*a14b8f16Smpf struct lacp_aggregator *lsc_active_aggregator; 240*a14b8f16Smpf TAILQ_HEAD(, lacp_aggregator) lsc_aggregators; 241*a14b8f16Smpf int lsc_suppress_distributing; 242*a14b8f16Smpf struct timeout lsc_transit_callout; 243*a14b8f16Smpf struct timeout lsc_callout; 244*a14b8f16Smpf LIST_HEAD(, lacp_port) lsc_ports; 245*a14b8f16Smpf struct lacp_portmap lsc_pmap[2]; 246*a14b8f16Smpf volatile u_int lsc_activemap; 247*a14b8f16Smpf u_int32_t lsc_hashkey; 248*a14b8f16Smpf }; 249*a14b8f16Smpf 250*a14b8f16Smpf #define LACP_TYPE_ACTORINFO 1 251*a14b8f16Smpf #define LACP_TYPE_PARTNERINFO 2 252*a14b8f16Smpf #define LACP_TYPE_COLLECTORINFO 3 253*a14b8f16Smpf 254*a14b8f16Smpf /* timeout values (in sec) */ 255*a14b8f16Smpf #define LACP_FAST_PERIODIC_TIME (1) 256*a14b8f16Smpf #define LACP_SLOW_PERIODIC_TIME (30) 257*a14b8f16Smpf #define LACP_SHORT_TIMEOUT_TIME (3 * LACP_FAST_PERIODIC_TIME) 258*a14b8f16Smpf #define LACP_LONG_TIMEOUT_TIME (3 * LACP_SLOW_PERIODIC_TIME) 259*a14b8f16Smpf #define LACP_CHURN_DETECTION_TIME (60) 260*a14b8f16Smpf #define LACP_AGGREGATE_WAIT_TIME (2) 261*a14b8f16Smpf #define LACP_TRANSIT_DELAY 3000 /* in msec */ 262*a14b8f16Smpf 263*a14b8f16Smpf #define LACP_STATE_EQ(s1, s2, mask) \ 264*a14b8f16Smpf ((((s1) ^ (s2)) & (mask)) == 0) 265*a14b8f16Smpf 266*a14b8f16Smpf #define LACP_SYS_PRI(peer) (peer).lip_systemid.lsi_prio 267*a14b8f16Smpf 268*a14b8f16Smpf #define LACP_PORT(_lp) ((struct lacp_port *)(_lp)->tp_psc) 269*a14b8f16Smpf #define LACP_SOFTC(_sc) ((struct lacp_softc *)(_sc)->tr_psc) 270*a14b8f16Smpf 271*a14b8f16Smpf #define LACP_LOCK_INIT(_lsc) mtx_init(&(_lsc)->lsc_mtx, \ 272*a14b8f16Smpf "lacp mtx", NULL, MTX_DEF) 273*a14b8f16Smpf #define LACP_LOCK_DESTROY(_lsc) mtx_destroy(&(_lsc)->lsc_mtx) 274*a14b8f16Smpf #define LACP_LOCK(_lsc) mtx_lock(&(_lsc)->lsc_mtx) 275*a14b8f16Smpf #define LACP_UNLOCK(_lsc) mtx_unlock(&(_lsc)->lsc_mtx) 276*a14b8f16Smpf #define LACP_LOCK_ASSERT(_lsc) mtx_assert(&(_lsc)->lsc_mtx, MA_OWNED) 277*a14b8f16Smpf 278*a14b8f16Smpf struct mbuf *lacp_input(struct trunk_port *, struct mbuf *); 279*a14b8f16Smpf struct trunk_port *lacp_select_tx_port(struct trunk_softc *, struct mbuf *); 280*a14b8f16Smpf int lacp_attach(struct trunk_softc *); 281*a14b8f16Smpf int lacp_detach(struct trunk_softc *); 282*a14b8f16Smpf void lacp_init(struct trunk_softc *); 283*a14b8f16Smpf void lacp_stop(struct trunk_softc *); 284*a14b8f16Smpf int lacp_port_create(struct trunk_port *); 285*a14b8f16Smpf void lacp_port_destroy(struct trunk_port *); 286*a14b8f16Smpf void lacp_linkstate(struct trunk_port *); 287*a14b8f16Smpf void lacp_req(struct trunk_softc *, caddr_t); 288*a14b8f16Smpf void lacp_portreq(struct trunk_port *, caddr_t); 289*a14b8f16Smpf 290*a14b8f16Smpf static __inline int 291*a14b8f16Smpf lacp_isactive(struct trunk_port *lgp) 292*a14b8f16Smpf { 293*a14b8f16Smpf struct lacp_port *lp = LACP_PORT(lgp); 294*a14b8f16Smpf struct lacp_softc *lsc = lp->lp_lsc; 295*a14b8f16Smpf struct lacp_aggregator *la = lp->lp_aggregator; 296*a14b8f16Smpf 297*a14b8f16Smpf /* This port is joined to the active aggregator */ 298*a14b8f16Smpf if (la != NULL && la == lsc->lsc_active_aggregator) 299*a14b8f16Smpf return (1); 300*a14b8f16Smpf 301*a14b8f16Smpf return (0); 302*a14b8f16Smpf } 303*a14b8f16Smpf 304*a14b8f16Smpf static __inline int 305*a14b8f16Smpf lacp_iscollecting(struct trunk_port *lgp) 306*a14b8f16Smpf { 307*a14b8f16Smpf struct lacp_port *lp = LACP_PORT(lgp); 308*a14b8f16Smpf 309*a14b8f16Smpf return ((lp->lp_state & LACP_STATE_COLLECTING) != 0); 310*a14b8f16Smpf } 311*a14b8f16Smpf 312*a14b8f16Smpf static __inline int 313*a14b8f16Smpf lacp_isdistributing(struct trunk_port *lgp) 314*a14b8f16Smpf { 315*a14b8f16Smpf struct lacp_port *lp = LACP_PORT(lgp); 316*a14b8f16Smpf 317*a14b8f16Smpf return ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0); 318*a14b8f16Smpf } 319*a14b8f16Smpf 320*a14b8f16Smpf /* following constants don't include terminating NUL */ 321*a14b8f16Smpf #define LACP_MACSTR_MAX (2*6 + 5) 322*a14b8f16Smpf #define LACP_SYSTEMPRIOSTR_MAX (4) 323*a14b8f16Smpf #define LACP_SYSTEMIDSTR_MAX (LACP_SYSTEMPRIOSTR_MAX + 1 + LACP_MACSTR_MAX) 324*a14b8f16Smpf #define LACP_PORTPRIOSTR_MAX (4) 325*a14b8f16Smpf #define LACP_PORTNOSTR_MAX (4) 326*a14b8f16Smpf #define LACP_PORTIDSTR_MAX (LACP_PORTPRIOSTR_MAX + 1 + LACP_PORTNOSTR_MAX) 327*a14b8f16Smpf #define LACP_KEYSTR_MAX (4) 328*a14b8f16Smpf #define LACP_PARTNERSTR_MAX \ 329*a14b8f16Smpf (1 + LACP_SYSTEMIDSTR_MAX + 1 + LACP_KEYSTR_MAX + 1 \ 330*a14b8f16Smpf + LACP_PORTIDSTR_MAX + 1) 331*a14b8f16Smpf #define LACP_LAGIDSTR_MAX \ 332*a14b8f16Smpf (1 + LACP_PARTNERSTR_MAX + 1 + LACP_PARTNERSTR_MAX + 1) 333*a14b8f16Smpf #define LACP_STATESTR_MAX (255) /* XXX */ 334