31 32#include <sys/param.h> 33#include <sys/callout.h> 34#include <sys/mbuf.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/kernel.h> /* hz */ 38#include <sys/socket.h> /* for net/if.h */ 39#include <sys/sockio.h> 40#include <machine/stdarg.h> 41 42#include <net/if.h> 43#include <net/if_dl.h> 44#include <net/ethernet.h> 45#include <net/if_media.h> 46#include <net/if_types.h> 47 48#include <net/if_lagg.h> 49#include <net/ieee8023ad_lacp.h> 50 51/* 52 * actor system priority and port priority. 53 * XXX should be configurable. 54 */ 55 56#define LACP_SYSTEM_PRIO 0x8000 57#define LACP_PORT_PRIO 0x8000 58 59const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] = 60 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; 61 62static const struct tlv_template lacp_info_tlv_template[] = { 63 { LACP_TYPE_ACTORINFO, 64 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 65 { LACP_TYPE_PARTNERINFO, 66 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 67 { LACP_TYPE_COLLECTORINFO, 68 sizeof(struct tlvhdr) + sizeof(struct lacp_collectorinfo) }, 69 { 0, 0 }, 70}; 71 72typedef void (*lacp_timer_func_t)(struct lacp_port *); 73 74static const struct tlv_template marker_info_tlv_template[] = { 75 { MARKER_TYPE_INFO, 16 }, 76 { 0, 0 }, 77}; 78 79static const struct tlv_template marker_response_tlv_template[] = { 80 { MARKER_TYPE_RESPONSE, 16 }, 81 { 0, 0 }, 82}; 83 84static void lacp_fill_actorinfo(struct lacp_port *, struct lacp_peerinfo *); 85 86static uint64_t lacp_aggregator_bandwidth(struct lacp_aggregator *); 87static void lacp_suppress_distributing(struct lacp_softc *, 88 struct lacp_aggregator *); 89static void lacp_transit_expire(void *); 90static void lacp_select_active_aggregator(struct lacp_softc *); 91static uint16_t lacp_compose_key(struct lacp_port *); 92static int tlv_check(const void *, size_t, const struct tlvhdr *, 93 const struct tlv_template *, boolean_t); 94static void lacp_tick(void *); 95 96static void lacp_fill_aggregator_id(struct lacp_aggregator *, 97 const struct lacp_port *); 98static void lacp_fill_aggregator_id_peer(struct lacp_peerinfo *, 99 const struct lacp_peerinfo *); 100static int lacp_aggregator_is_compatible(const struct lacp_aggregator *, 101 const struct lacp_port *); 102static int lacp_peerinfo_is_compatible(const struct lacp_peerinfo *, 103 const struct lacp_peerinfo *); 104 105static struct lacp_aggregator *lacp_aggregator_get(struct lacp_softc *, 106 struct lacp_port *); 107static void lacp_aggregator_addref(struct lacp_softc *, 108 struct lacp_aggregator *); 109static void lacp_aggregator_delref(struct lacp_softc *, 110 struct lacp_aggregator *); 111 112/* receive machine */ 113 114static void lacp_sm_rx(struct lacp_port *, const struct lacpdu *); 115static void lacp_sm_rx_timer(struct lacp_port *); 116static void lacp_sm_rx_set_expired(struct lacp_port *); 117static void lacp_sm_rx_update_ntt(struct lacp_port *, 118 const struct lacpdu *); 119static void lacp_sm_rx_record_pdu(struct lacp_port *, 120 const struct lacpdu *); 121static void lacp_sm_rx_update_selected(struct lacp_port *, 122 const struct lacpdu *); 123static void lacp_sm_rx_record_default(struct lacp_port *); 124static void lacp_sm_rx_update_default_selected(struct lacp_port *); 125static void lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *, 126 const struct lacp_peerinfo *); 127 128/* mux machine */ 129 130static void lacp_sm_mux(struct lacp_port *); 131static void lacp_set_mux(struct lacp_port *, enum lacp_mux_state); 132static void lacp_sm_mux_timer(struct lacp_port *); 133 134/* periodic transmit machine */ 135 136static void lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t); 137static void lacp_sm_ptx_tx_schedule(struct lacp_port *); 138static void lacp_sm_ptx_timer(struct lacp_port *); 139 140/* transmit machine */ 141 142static void lacp_sm_tx(struct lacp_port *); 143static void lacp_sm_assert_ntt(struct lacp_port *); 144 145static void lacp_run_timers(struct lacp_port *); 146static int lacp_compare_peerinfo(const struct lacp_peerinfo *, 147 const struct lacp_peerinfo *); 148static int lacp_compare_systemid(const struct lacp_systemid *, 149 const struct lacp_systemid *); 150static void lacp_port_enable(struct lacp_port *); 151static void lacp_port_disable(struct lacp_port *); 152static void lacp_select(struct lacp_port *); 153static void lacp_unselect(struct lacp_port *); 154static void lacp_disable_collecting(struct lacp_port *); 155static void lacp_enable_collecting(struct lacp_port *); 156static void lacp_disable_distributing(struct lacp_port *); 157static void lacp_enable_distributing(struct lacp_port *); 158static int lacp_xmit_lacpdu(struct lacp_port *); 159 160#if defined(LACP_DEBUG) 161static void lacp_dump_lacpdu(const struct lacpdu *); 162static const char *lacp_format_partner(const struct lacp_peerinfo *, char *, 163 size_t); 164static const char *lacp_format_lagid(const struct lacp_peerinfo *, 165 const struct lacp_peerinfo *, char *, size_t); 166static const char *lacp_format_lagid_aggregator(const struct lacp_aggregator *, 167 char *, size_t); 168static const char *lacp_format_state(uint8_t, char *, size_t); 169static const char *lacp_format_mac(const uint8_t *, char *, size_t); 170static const char *lacp_format_systemid(const struct lacp_systemid *, char *, 171 size_t); 172static const char *lacp_format_portid(const struct lacp_portid *, char *, 173 size_t); 174static void lacp_dprintf(const struct lacp_port *, const char *, ...) 175 __attribute__((__format__(__printf__, 2, 3))); 176#define LACP_DPRINTF(a) lacp_dprintf a 177#else 178#define LACP_DPRINTF(a) /* nothing */ 179#endif 180 181/* 182 * partner administration variables. 183 * XXX should be configurable. 184 */ 185 186static const struct lacp_peerinfo lacp_partner_admin = { 187 .lip_systemid = { .lsi_prio = 0xffff }, 188 .lip_portid = { .lpi_prio = 0xffff }, 189#if 1 190 /* optimistic */ 191 .lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION | 192 LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING, 193#else 194 /* pessimistic */ 195 .lip_state = 0, 196#endif 197}; 198 199static const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = { 200 [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer, 201 [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer, 202 [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer, 203}; 204 205/* 206 * lacp_input: process lacpdu 207 */ 208int 209lacp_input(struct lagg_port *lgp, struct mbuf *m) 210{ 211 struct lacp_port *lp = LACP_PORT(lgp); 212 struct lacpdu *du; 213 int error = 0; 214 215 LAGG_LOCK_ASSERT(lgp->lp_lagg); 216 217 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 218 goto bad; 219 } 220 221 if (m->m_pkthdr.len != sizeof(*du)) { 222 goto bad; 223 } 224 225 if ((m->m_flags & M_MCAST) == 0) { 226 goto bad; 227 } 228 229 if (m->m_len < sizeof(*du)) { 230 m = m_pullup(m, sizeof(*du)); 231 if (m == NULL) { 232 return (ENOMEM); 233 } 234 } 235 236 du = mtod(m, struct lacpdu *); 237 238 if (memcmp(&du->ldu_eh.ether_dhost, 239 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 240 goto bad; 241 } 242 243 /* XXX 244 KASSERT(du->ldu_sph.sph_subtype == SLOWPROTOCOLS_SUBTYPE_LACP, 245 ("a very bad kassert!")); 246 */ 247 248 /* 249 * ignore the version for compatibility with 250 * the future protocol revisions. 251 */ 252 253#if 0 254 if (du->ldu_sph.sph_version != 1) { 255 goto bad; 256 } 257#endif 258 259 /* 260 * ignore tlv types for compatibility with 261 * the future protocol revisions. 262 */ 263 264 if (tlv_check(du, sizeof(*du), &du->ldu_tlv_actor, 265 lacp_info_tlv_template, FALSE)) { 266 goto bad; 267 } 268 269#if defined(LACP_DEBUG) 270 LACP_DPRINTF((lp, "lacpdu receive\n")); 271 lacp_dump_lacpdu(du); 272#endif /* defined(LACP_DEBUG) */ 273 lacp_sm_rx(lp, du); 274 275 m_freem(m); 276 277 return (error); 278 279bad: 280 m_freem(m); 281 return (EINVAL); 282} 283 284static void 285lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info) 286{ 287 struct lagg_port *lgp = lp->lp_lagg; 288 struct lagg_softc *lgs = lgp->lp_lagg; 289 290 info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO); 291 memcpy(&info->lip_systemid.lsi_mac, 292 IF_LLADDR(lgs->sc_ifp), ETHER_ADDR_LEN); 293 info->lip_portid.lpi_prio = htons(LACP_PORT_PRIO); 294 info->lip_portid.lpi_portno = htons(lp->lp_ifp->if_index); 295 info->lip_state = lp->lp_state; 296} 297 298static int 299lacp_xmit_lacpdu(struct lacp_port *lp) 300{ 301 struct lagg_port *lgp = lp->lp_lagg; 302 struct mbuf *m; 303 struct lacpdu *du; 304 int error; 305 306 LAGG_LOCK_ASSERT(lgp->lp_lagg); 307 308 m = m_gethdr(M_DONTWAIT, MT_DATA); 309 if (m == NULL) { 310 return (ENOMEM); 311 } 312 m->m_len = m->m_pkthdr.len = sizeof(*du); 313 314 du = mtod(m, struct lacpdu *); 315 memset(du, 0, sizeof(*du)); 316 317 memcpy(&du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 318 ETHER_ADDR_LEN); 319 memcpy(&du->ldu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN); 320 du->ldu_eh.ether_type = htons(ETHERTYPE_SLOW); 321 322 du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP; 323 du->ldu_sph.sph_version = 1; 324 325 TLV_SET(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO, sizeof(du->ldu_actor)); 326 du->ldu_actor = lp->lp_actor; 327 328 TLV_SET(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO, 329 sizeof(du->ldu_partner)); 330 du->ldu_partner = lp->lp_partner; 331 332 TLV_SET(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO, 333 sizeof(du->ldu_collector)); 334 du->ldu_collector.lci_maxdelay = 0; 335 336#if defined(LACP_DEBUG) 337 LACP_DPRINTF((lp, "lacpdu transmit\n")); 338 lacp_dump_lacpdu(du); 339#endif /* defined(LACP_DEBUG) */ 340 341 m->m_flags |= M_MCAST; 342 343 /* 344 * XXX should use higher priority queue. 345 * otherwise network congestion can break aggregation. 346 */ 347 348 error = lagg_enqueue(lp->lp_ifp, m); 349 return (error); 350} 351 352void 353lacp_linkstate(struct lagg_port *lgp) 354{ 355 struct lacp_port *lp = LACP_PORT(lgp); 356 struct ifnet *ifp = lgp->lp_ifp; 357 struct ifmediareq ifmr; 358 int error = 0; 359 u_int media; 360 uint8_t old_state; 361 uint16_t old_key; 362 363 LAGG_LOCK_ASSERT(lgp->lp_lagg); 364 365 bzero((char *)&ifmr, sizeof(ifmr)); 366 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 367 if (error != 0) 368 return; 369 370 media = ifmr.ifm_active; 371 LACP_DPRINTF((lp, "media changed 0x%x -> 0x%x, ether = %d, fdx = %d, " 372 "link = %d\n", lp->lp_media, media, IFM_TYPE(media) == IFM_ETHER, 373 (media & IFM_FDX) != 0, ifp->if_link_state == LINK_STATE_UP)); 374 old_state = lp->lp_state; 375 old_key = lp->lp_key; 376 377 lp->lp_media = media; 378 /* 379 * If the port is not an active full duplex Ethernet link then it can 380 * not be aggregated. 381 */ 382 if (IFM_TYPE(media) != IFM_ETHER || (media & IFM_FDX) == 0 || 383 ifp->if_link_state != LINK_STATE_UP) { 384 lacp_port_disable(lp); 385 } else { 386 lacp_port_enable(lp); 387 } 388 lp->lp_key = lacp_compose_key(lp); 389 390 if (old_state != lp->lp_state || old_key != lp->lp_key) { 391 LACP_DPRINTF((lp, "-> UNSELECTED\n")); 392 lp->lp_selected = LACP_UNSELECTED; 393 } 394} 395 396static void 397lacp_tick(void *arg) 398{ 399 struct lacp_softc *lsc = arg; 400 struct lacp_port *lp; 401 402 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 403 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) 404 continue; 405 406 lacp_run_timers(lp); 407 408 lacp_select(lp); 409 lacp_sm_mux(lp); 410 lacp_sm_tx(lp); 411 lacp_sm_ptx_tx_schedule(lp); 412 } 413 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 414} 415 416int 417lacp_port_create(struct lagg_port *lgp) 418{ 419 struct lagg_softc *lgs = lgp->lp_lagg; 420 struct lacp_softc *lsc = LACP_SOFTC(lgs); 421 struct lacp_port *lp; 422 struct ifnet *ifp = lgp->lp_ifp; 423 struct sockaddr_dl sdl; 424 struct ifmultiaddr *rifma = NULL; 425 int error; 426 427 boolean_t active = TRUE; /* XXX should be configurable */ 428 boolean_t fast = FALSE; /* XXX should be configurable */ 429 430 LAGG_LOCK_ASSERT(lgs); 431 432 bzero((char *)&sdl, sizeof(sdl)); 433 sdl.sdl_len = sizeof(sdl); 434 sdl.sdl_family = AF_LINK; 435 sdl.sdl_index = ifp->if_index; 436 sdl.sdl_type = IFT_ETHER; 437 sdl.sdl_alen = ETHER_ADDR_LEN; 438 439 bcopy(ðermulticastaddr_slowprotocols, 440 LLADDR(&sdl), ETHER_ADDR_LEN); 441 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 442 if (error) { 443 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname); 444 return (error); 445 } 446 447 lp = malloc(sizeof(struct lacp_port), 448 M_DEVBUF, M_NOWAIT|M_ZERO); 449 if (lp == NULL) 450 return (ENOMEM); 451 452 lgp->lp_psc = (caddr_t)lp; 453 lp->lp_ifp = ifp; 454 lp->lp_lagg = lgp; 455 lp->lp_lsc = lsc;
| 31 32#include <sys/param.h> 33#include <sys/callout.h> 34#include <sys/mbuf.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/kernel.h> /* hz */ 38#include <sys/socket.h> /* for net/if.h */ 39#include <sys/sockio.h> 40#include <machine/stdarg.h> 41 42#include <net/if.h> 43#include <net/if_dl.h> 44#include <net/ethernet.h> 45#include <net/if_media.h> 46#include <net/if_types.h> 47 48#include <net/if_lagg.h> 49#include <net/ieee8023ad_lacp.h> 50 51/* 52 * actor system priority and port priority. 53 * XXX should be configurable. 54 */ 55 56#define LACP_SYSTEM_PRIO 0x8000 57#define LACP_PORT_PRIO 0x8000 58 59const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] = 60 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; 61 62static const struct tlv_template lacp_info_tlv_template[] = { 63 { LACP_TYPE_ACTORINFO, 64 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 65 { LACP_TYPE_PARTNERINFO, 66 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 67 { LACP_TYPE_COLLECTORINFO, 68 sizeof(struct tlvhdr) + sizeof(struct lacp_collectorinfo) }, 69 { 0, 0 }, 70}; 71 72typedef void (*lacp_timer_func_t)(struct lacp_port *); 73 74static const struct tlv_template marker_info_tlv_template[] = { 75 { MARKER_TYPE_INFO, 16 }, 76 { 0, 0 }, 77}; 78 79static const struct tlv_template marker_response_tlv_template[] = { 80 { MARKER_TYPE_RESPONSE, 16 }, 81 { 0, 0 }, 82}; 83 84static void lacp_fill_actorinfo(struct lacp_port *, struct lacp_peerinfo *); 85 86static uint64_t lacp_aggregator_bandwidth(struct lacp_aggregator *); 87static void lacp_suppress_distributing(struct lacp_softc *, 88 struct lacp_aggregator *); 89static void lacp_transit_expire(void *); 90static void lacp_select_active_aggregator(struct lacp_softc *); 91static uint16_t lacp_compose_key(struct lacp_port *); 92static int tlv_check(const void *, size_t, const struct tlvhdr *, 93 const struct tlv_template *, boolean_t); 94static void lacp_tick(void *); 95 96static void lacp_fill_aggregator_id(struct lacp_aggregator *, 97 const struct lacp_port *); 98static void lacp_fill_aggregator_id_peer(struct lacp_peerinfo *, 99 const struct lacp_peerinfo *); 100static int lacp_aggregator_is_compatible(const struct lacp_aggregator *, 101 const struct lacp_port *); 102static int lacp_peerinfo_is_compatible(const struct lacp_peerinfo *, 103 const struct lacp_peerinfo *); 104 105static struct lacp_aggregator *lacp_aggregator_get(struct lacp_softc *, 106 struct lacp_port *); 107static void lacp_aggregator_addref(struct lacp_softc *, 108 struct lacp_aggregator *); 109static void lacp_aggregator_delref(struct lacp_softc *, 110 struct lacp_aggregator *); 111 112/* receive machine */ 113 114static void lacp_sm_rx(struct lacp_port *, const struct lacpdu *); 115static void lacp_sm_rx_timer(struct lacp_port *); 116static void lacp_sm_rx_set_expired(struct lacp_port *); 117static void lacp_sm_rx_update_ntt(struct lacp_port *, 118 const struct lacpdu *); 119static void lacp_sm_rx_record_pdu(struct lacp_port *, 120 const struct lacpdu *); 121static void lacp_sm_rx_update_selected(struct lacp_port *, 122 const struct lacpdu *); 123static void lacp_sm_rx_record_default(struct lacp_port *); 124static void lacp_sm_rx_update_default_selected(struct lacp_port *); 125static void lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *, 126 const struct lacp_peerinfo *); 127 128/* mux machine */ 129 130static void lacp_sm_mux(struct lacp_port *); 131static void lacp_set_mux(struct lacp_port *, enum lacp_mux_state); 132static void lacp_sm_mux_timer(struct lacp_port *); 133 134/* periodic transmit machine */ 135 136static void lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t); 137static void lacp_sm_ptx_tx_schedule(struct lacp_port *); 138static void lacp_sm_ptx_timer(struct lacp_port *); 139 140/* transmit machine */ 141 142static void lacp_sm_tx(struct lacp_port *); 143static void lacp_sm_assert_ntt(struct lacp_port *); 144 145static void lacp_run_timers(struct lacp_port *); 146static int lacp_compare_peerinfo(const struct lacp_peerinfo *, 147 const struct lacp_peerinfo *); 148static int lacp_compare_systemid(const struct lacp_systemid *, 149 const struct lacp_systemid *); 150static void lacp_port_enable(struct lacp_port *); 151static void lacp_port_disable(struct lacp_port *); 152static void lacp_select(struct lacp_port *); 153static void lacp_unselect(struct lacp_port *); 154static void lacp_disable_collecting(struct lacp_port *); 155static void lacp_enable_collecting(struct lacp_port *); 156static void lacp_disable_distributing(struct lacp_port *); 157static void lacp_enable_distributing(struct lacp_port *); 158static int lacp_xmit_lacpdu(struct lacp_port *); 159 160#if defined(LACP_DEBUG) 161static void lacp_dump_lacpdu(const struct lacpdu *); 162static const char *lacp_format_partner(const struct lacp_peerinfo *, char *, 163 size_t); 164static const char *lacp_format_lagid(const struct lacp_peerinfo *, 165 const struct lacp_peerinfo *, char *, size_t); 166static const char *lacp_format_lagid_aggregator(const struct lacp_aggregator *, 167 char *, size_t); 168static const char *lacp_format_state(uint8_t, char *, size_t); 169static const char *lacp_format_mac(const uint8_t *, char *, size_t); 170static const char *lacp_format_systemid(const struct lacp_systemid *, char *, 171 size_t); 172static const char *lacp_format_portid(const struct lacp_portid *, char *, 173 size_t); 174static void lacp_dprintf(const struct lacp_port *, const char *, ...) 175 __attribute__((__format__(__printf__, 2, 3))); 176#define LACP_DPRINTF(a) lacp_dprintf a 177#else 178#define LACP_DPRINTF(a) /* nothing */ 179#endif 180 181/* 182 * partner administration variables. 183 * XXX should be configurable. 184 */ 185 186static const struct lacp_peerinfo lacp_partner_admin = { 187 .lip_systemid = { .lsi_prio = 0xffff }, 188 .lip_portid = { .lpi_prio = 0xffff }, 189#if 1 190 /* optimistic */ 191 .lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION | 192 LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING, 193#else 194 /* pessimistic */ 195 .lip_state = 0, 196#endif 197}; 198 199static const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = { 200 [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer, 201 [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer, 202 [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer, 203}; 204 205/* 206 * lacp_input: process lacpdu 207 */ 208int 209lacp_input(struct lagg_port *lgp, struct mbuf *m) 210{ 211 struct lacp_port *lp = LACP_PORT(lgp); 212 struct lacpdu *du; 213 int error = 0; 214 215 LAGG_LOCK_ASSERT(lgp->lp_lagg); 216 217 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 218 goto bad; 219 } 220 221 if (m->m_pkthdr.len != sizeof(*du)) { 222 goto bad; 223 } 224 225 if ((m->m_flags & M_MCAST) == 0) { 226 goto bad; 227 } 228 229 if (m->m_len < sizeof(*du)) { 230 m = m_pullup(m, sizeof(*du)); 231 if (m == NULL) { 232 return (ENOMEM); 233 } 234 } 235 236 du = mtod(m, struct lacpdu *); 237 238 if (memcmp(&du->ldu_eh.ether_dhost, 239 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 240 goto bad; 241 } 242 243 /* XXX 244 KASSERT(du->ldu_sph.sph_subtype == SLOWPROTOCOLS_SUBTYPE_LACP, 245 ("a very bad kassert!")); 246 */ 247 248 /* 249 * ignore the version for compatibility with 250 * the future protocol revisions. 251 */ 252 253#if 0 254 if (du->ldu_sph.sph_version != 1) { 255 goto bad; 256 } 257#endif 258 259 /* 260 * ignore tlv types for compatibility with 261 * the future protocol revisions. 262 */ 263 264 if (tlv_check(du, sizeof(*du), &du->ldu_tlv_actor, 265 lacp_info_tlv_template, FALSE)) { 266 goto bad; 267 } 268 269#if defined(LACP_DEBUG) 270 LACP_DPRINTF((lp, "lacpdu receive\n")); 271 lacp_dump_lacpdu(du); 272#endif /* defined(LACP_DEBUG) */ 273 lacp_sm_rx(lp, du); 274 275 m_freem(m); 276 277 return (error); 278 279bad: 280 m_freem(m); 281 return (EINVAL); 282} 283 284static void 285lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info) 286{ 287 struct lagg_port *lgp = lp->lp_lagg; 288 struct lagg_softc *lgs = lgp->lp_lagg; 289 290 info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO); 291 memcpy(&info->lip_systemid.lsi_mac, 292 IF_LLADDR(lgs->sc_ifp), ETHER_ADDR_LEN); 293 info->lip_portid.lpi_prio = htons(LACP_PORT_PRIO); 294 info->lip_portid.lpi_portno = htons(lp->lp_ifp->if_index); 295 info->lip_state = lp->lp_state; 296} 297 298static int 299lacp_xmit_lacpdu(struct lacp_port *lp) 300{ 301 struct lagg_port *lgp = lp->lp_lagg; 302 struct mbuf *m; 303 struct lacpdu *du; 304 int error; 305 306 LAGG_LOCK_ASSERT(lgp->lp_lagg); 307 308 m = m_gethdr(M_DONTWAIT, MT_DATA); 309 if (m == NULL) { 310 return (ENOMEM); 311 } 312 m->m_len = m->m_pkthdr.len = sizeof(*du); 313 314 du = mtod(m, struct lacpdu *); 315 memset(du, 0, sizeof(*du)); 316 317 memcpy(&du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 318 ETHER_ADDR_LEN); 319 memcpy(&du->ldu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN); 320 du->ldu_eh.ether_type = htons(ETHERTYPE_SLOW); 321 322 du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP; 323 du->ldu_sph.sph_version = 1; 324 325 TLV_SET(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO, sizeof(du->ldu_actor)); 326 du->ldu_actor = lp->lp_actor; 327 328 TLV_SET(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO, 329 sizeof(du->ldu_partner)); 330 du->ldu_partner = lp->lp_partner; 331 332 TLV_SET(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO, 333 sizeof(du->ldu_collector)); 334 du->ldu_collector.lci_maxdelay = 0; 335 336#if defined(LACP_DEBUG) 337 LACP_DPRINTF((lp, "lacpdu transmit\n")); 338 lacp_dump_lacpdu(du); 339#endif /* defined(LACP_DEBUG) */ 340 341 m->m_flags |= M_MCAST; 342 343 /* 344 * XXX should use higher priority queue. 345 * otherwise network congestion can break aggregation. 346 */ 347 348 error = lagg_enqueue(lp->lp_ifp, m); 349 return (error); 350} 351 352void 353lacp_linkstate(struct lagg_port *lgp) 354{ 355 struct lacp_port *lp = LACP_PORT(lgp); 356 struct ifnet *ifp = lgp->lp_ifp; 357 struct ifmediareq ifmr; 358 int error = 0; 359 u_int media; 360 uint8_t old_state; 361 uint16_t old_key; 362 363 LAGG_LOCK_ASSERT(lgp->lp_lagg); 364 365 bzero((char *)&ifmr, sizeof(ifmr)); 366 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 367 if (error != 0) 368 return; 369 370 media = ifmr.ifm_active; 371 LACP_DPRINTF((lp, "media changed 0x%x -> 0x%x, ether = %d, fdx = %d, " 372 "link = %d\n", lp->lp_media, media, IFM_TYPE(media) == IFM_ETHER, 373 (media & IFM_FDX) != 0, ifp->if_link_state == LINK_STATE_UP)); 374 old_state = lp->lp_state; 375 old_key = lp->lp_key; 376 377 lp->lp_media = media; 378 /* 379 * If the port is not an active full duplex Ethernet link then it can 380 * not be aggregated. 381 */ 382 if (IFM_TYPE(media) != IFM_ETHER || (media & IFM_FDX) == 0 || 383 ifp->if_link_state != LINK_STATE_UP) { 384 lacp_port_disable(lp); 385 } else { 386 lacp_port_enable(lp); 387 } 388 lp->lp_key = lacp_compose_key(lp); 389 390 if (old_state != lp->lp_state || old_key != lp->lp_key) { 391 LACP_DPRINTF((lp, "-> UNSELECTED\n")); 392 lp->lp_selected = LACP_UNSELECTED; 393 } 394} 395 396static void 397lacp_tick(void *arg) 398{ 399 struct lacp_softc *lsc = arg; 400 struct lacp_port *lp; 401 402 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 403 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) 404 continue; 405 406 lacp_run_timers(lp); 407 408 lacp_select(lp); 409 lacp_sm_mux(lp); 410 lacp_sm_tx(lp); 411 lacp_sm_ptx_tx_schedule(lp); 412 } 413 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 414} 415 416int 417lacp_port_create(struct lagg_port *lgp) 418{ 419 struct lagg_softc *lgs = lgp->lp_lagg; 420 struct lacp_softc *lsc = LACP_SOFTC(lgs); 421 struct lacp_port *lp; 422 struct ifnet *ifp = lgp->lp_ifp; 423 struct sockaddr_dl sdl; 424 struct ifmultiaddr *rifma = NULL; 425 int error; 426 427 boolean_t active = TRUE; /* XXX should be configurable */ 428 boolean_t fast = FALSE; /* XXX should be configurable */ 429 430 LAGG_LOCK_ASSERT(lgs); 431 432 bzero((char *)&sdl, sizeof(sdl)); 433 sdl.sdl_len = sizeof(sdl); 434 sdl.sdl_family = AF_LINK; 435 sdl.sdl_index = ifp->if_index; 436 sdl.sdl_type = IFT_ETHER; 437 sdl.sdl_alen = ETHER_ADDR_LEN; 438 439 bcopy(ðermulticastaddr_slowprotocols, 440 LLADDR(&sdl), ETHER_ADDR_LEN); 441 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 442 if (error) { 443 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname); 444 return (error); 445 } 446 447 lp = malloc(sizeof(struct lacp_port), 448 M_DEVBUF, M_NOWAIT|M_ZERO); 449 if (lp == NULL) 450 return (ENOMEM); 451 452 lgp->lp_psc = (caddr_t)lp; 453 lp->lp_ifp = ifp; 454 lp->lp_lagg = lgp; 455 lp->lp_lsc = lsc;
|
502 LIST_REMOVE(lp, lp_next); 503 free(lp, M_DEVBUF); 504} 505 506int 507lacp_port_isactive(struct lagg_port *lgp) 508{ 509 struct lacp_port *lp = LACP_PORT(lgp); 510 struct lacp_softc *lsc = lp->lp_lsc; 511 struct lacp_aggregator *la = lp->lp_aggregator; 512 513 /* This port is joined to the active aggregator */ 514 if (la != NULL && la == lsc->lsc_active_aggregator) 515 return (1); 516 517 return (0); 518} 519 520static void 521lacp_disable_collecting(struct lacp_port *lp) 522{ 523 struct lagg_port *lgp = lp->lp_lagg; 524 525 LACP_DPRINTF((lp, "collecting disabled\n")); 526 527 lp->lp_state &= ~LACP_STATE_COLLECTING; 528 lgp->lp_flags &= ~LAGG_PORT_COLLECTING; 529} 530 531static void 532lacp_enable_collecting(struct lacp_port *lp) 533{ 534 struct lagg_port *lgp = lp->lp_lagg; 535 536 LACP_DPRINTF((lp, "collecting enabled\n")); 537 538 lp->lp_state |= LACP_STATE_COLLECTING; 539 lgp->lp_flags |= LAGG_PORT_COLLECTING; 540} 541 542static void 543lacp_disable_distributing(struct lacp_port *lp) 544{ 545 struct lacp_aggregator *la = lp->lp_aggregator; 546 struct lacp_softc *lsc = lp->lp_lsc; 547 struct lagg_port *lgp = lp->lp_lagg; 548#if defined(LACP_DEBUG) 549 char buf[LACP_LAGIDSTR_MAX+1]; 550#endif /* defined(LACP_DEBUG) */ 551 552 LAGG_LOCK_ASSERT(lgp->lp_lagg); 553 554 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 555 return; 556 } 557 558 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 559 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 560 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); 561 562 LACP_DPRINTF((lp, "disable distributing on aggregator %s, " 563 "nports %d -> %d\n", 564 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 565 la->la_nports, la->la_nports - 1)); 566 567 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 568 la->la_nports--; 569 570 lacp_suppress_distributing(lsc, la); 571 572 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; 573 lgp->lp_flags &= ~LAGG_PORT_DISTRIBUTING; 574 575 if (lsc->lsc_active_aggregator == la) { 576 lacp_select_active_aggregator(lsc); 577 } 578} 579 580static void 581lacp_enable_distributing(struct lacp_port *lp) 582{ 583 struct lacp_aggregator *la = lp->lp_aggregator; 584 struct lacp_softc *lsc = lp->lp_lsc; 585 struct lagg_port *lgp = lp->lp_lagg; 586#if defined(LACP_DEBUG) 587 char buf[LACP_LAGIDSTR_MAX+1]; 588#endif /* defined(LACP_DEBUG) */ 589 590 LAGG_LOCK_ASSERT(lgp->lp_lagg); 591 592 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 593 return; 594 } 595 596 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 597 "nports %d -> %d\n", 598 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 599 la->la_nports, la->la_nports + 1)); 600 601 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 602 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 603 la->la_nports++; 604 605 lacp_suppress_distributing(lsc, la); 606 607 lp->lp_state |= LACP_STATE_DISTRIBUTING; 608 lgp->lp_flags |= LAGG_PORT_DISTRIBUTING; 609 610 if (lsc->lsc_active_aggregator != la) { 611 lacp_select_active_aggregator(lsc); 612 } 613} 614 615static void 616lacp_transit_expire(void *vp) 617{ 618 struct lacp_softc *lsc = vp; 619 620 LACP_DPRINTF((NULL, "%s\n", __func__)); 621 lsc->lsc_suppress_distributing = FALSE; 622} 623 624int 625lacp_attach(struct lagg_softc *lgs) 626{ 627 struct lacp_softc *lsc; 628 629 LAGG_LOCK_ASSERT(lgs); 630 631 lsc = malloc(sizeof(struct lacp_softc), 632 M_DEVBUF, M_NOWAIT|M_ZERO); 633 if (lsc == NULL) 634 return (ENOMEM); 635 636 lgs->sc_psc = (caddr_t)lsc; 637 lsc->lsc_lagg = lgs; 638 639 lsc->lsc_hashkey = arc4random(); 640 lsc->lsc_active_aggregator = NULL; 641 TAILQ_INIT(&lsc->lsc_aggregators); 642 LIST_INIT(&lsc->lsc_ports); 643 644 callout_init_mtx(&lsc->lsc_transit_callout, &lgs->sc_mtx, 0); 645 callout_init_mtx(&lsc->lsc_callout, &lgs->sc_mtx, 0); 646 647 /* if the lagg is already up then do the same */ 648 if (lgs->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) 649 lacp_init(lgs); 650 651 return (0); 652} 653 654int 655lacp_detach(struct lagg_softc *lgs) 656{ 657 struct lacp_softc *lsc = LACP_SOFTC(lgs); 658 659 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 660 ("aggregators still active")); 661 KASSERT(lsc->lsc_active_aggregator == NULL, 662 ("aggregator still attached")); 663 664 lgs->sc_psc = NULL; 665 callout_drain(&lsc->lsc_transit_callout); 666 callout_drain(&lsc->lsc_callout); 667 668 free(lsc, M_DEVBUF); 669 return (0); 670} 671 672void 673lacp_init(struct lagg_softc *lgs) 674{ 675 struct lacp_softc *lsc = LACP_SOFTC(lgs); 676 677 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 678} 679 680void 681lacp_stop(struct lagg_softc *lgs) 682{ 683 struct lacp_softc *lsc = LACP_SOFTC(lgs); 684 685 callout_stop(&lsc->lsc_transit_callout); 686 callout_stop(&lsc->lsc_callout); 687} 688 689struct lagg_port * 690lacp_select_tx_port(struct lagg_softc *lgs, struct mbuf *m) 691{ 692 struct lacp_softc *lsc = LACP_SOFTC(lgs); 693 struct lacp_aggregator *la; 694 struct lacp_port *lp; 695 uint32_t hash; 696 int nports; 697 698 LAGG_LOCK_ASSERT(lgs); 699 700 if (__predict_false(lsc->lsc_suppress_distributing)) { 701 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 702 return (NULL); 703 } 704 705 la = lsc->lsc_active_aggregator; 706 if (__predict_false(la == NULL)) { 707 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 708 return (NULL); 709 } 710 711 nports = la->la_nports; 712 KASSERT(nports > 0, ("no ports available")); 713 714 hash = lagg_hashmbuf(m, lsc->lsc_hashkey); 715 hash %= nports; 716 lp = TAILQ_FIRST(&la->la_ports); 717 while (hash--) { 718 lp = TAILQ_NEXT(lp, lp_dist_q); 719 } 720 721 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 722 ("aggregated port is not distributing")); 723 724 return (lp->lp_lagg); 725} 726/* 727 * lacp_suppress_distributing: drop transmit packets for a while 728 * to preserve packet ordering. 729 */ 730 731static void 732lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) 733{ 734 if (lsc->lsc_active_aggregator != la) { 735 return; 736 } 737 738 LACP_DPRINTF((NULL, "%s\n", __func__)); 739 lsc->lsc_suppress_distributing = TRUE; 740 /* XXX should consider collector max delay */ 741 callout_reset(&lsc->lsc_transit_callout, 742 LACP_TRANSIT_DELAY * hz / 1000, lacp_transit_expire, lsc); 743} 744 745static int 746lacp_compare_peerinfo(const struct lacp_peerinfo *a, 747 const struct lacp_peerinfo *b) 748{ 749 return (memcmp(a, b, offsetof(struct lacp_peerinfo, lip_state))); 750} 751 752static int 753lacp_compare_systemid(const struct lacp_systemid *a, 754 const struct lacp_systemid *b) 755{ 756 return (memcmp(a, b, sizeof(*a))); 757} 758 759#if 0 /* unused */ 760static int 761lacp_compare_portid(const struct lacp_portid *a, 762 const struct lacp_portid *b) 763{ 764 return (memcmp(a, b, sizeof(*a))); 765} 766#endif 767 768static uint64_t 769lacp_aggregator_bandwidth(struct lacp_aggregator *la) 770{ 771 struct lacp_port *lp; 772 uint64_t speed; 773 774 lp = TAILQ_FIRST(&la->la_ports); 775 if (lp == NULL) { 776 return (0); 777 } 778 779 speed = ifmedia_baudrate(lp->lp_media); 780 speed *= la->la_nports; 781 if (speed == 0) { 782 LACP_DPRINTF((lp, "speed 0? media=0x%x nports=%d\n", 783 lp->lp_media, la->la_nports)); 784 } 785 786 return (speed); 787} 788 789/* 790 * lacp_select_active_aggregator: select an aggregator to be used to transmit 791 * packets from lagg(4) interface. 792 */ 793 794static void 795lacp_select_active_aggregator(struct lacp_softc *lsc) 796{ 797 struct lacp_aggregator *la; 798 struct lacp_aggregator *best_la = NULL; 799 uint64_t best_speed = 0; 800#if defined(LACP_DEBUG) 801 char buf[LACP_LAGIDSTR_MAX+1]; 802#endif /* defined(LACP_DEBUG) */ 803 804 LACP_DPRINTF((NULL, "%s:\n", __func__)); 805 806 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 807 uint64_t speed; 808 809 if (la->la_nports == 0) { 810 continue; 811 } 812 813 speed = lacp_aggregator_bandwidth(la); 814 LACP_DPRINTF((NULL, "%s, speed=%jd, nports=%d\n", 815 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 816 speed, la->la_nports)); 817 if (speed > best_speed || 818 (speed == best_speed && 819 la == lsc->lsc_active_aggregator)) { 820 best_la = la; 821 best_speed = speed; 822 } 823 } 824 825 KASSERT(best_la == NULL || best_la->la_nports > 0, 826 ("invalid aggregator refcnt")); 827 KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports), 828 ("invalid aggregator list")); 829 830#if defined(LACP_DEBUG) 831 if (lsc->lsc_active_aggregator != best_la) { 832 LACP_DPRINTF((NULL, "active aggregator changed\n")); 833 LACP_DPRINTF((NULL, "old %s\n", 834 lacp_format_lagid_aggregator(lsc->lsc_active_aggregator, 835 buf, sizeof(buf)))); 836 } else { 837 LACP_DPRINTF((NULL, "active aggregator not changed\n")); 838 } 839 LACP_DPRINTF((NULL, "new %s\n", 840 lacp_format_lagid_aggregator(best_la, buf, sizeof(buf)))); 841#endif /* defined(LACP_DEBUG) */ 842 843 if (lsc->lsc_active_aggregator != best_la) { 844 lsc->lsc_active_aggregator = best_la; 845 if (best_la) { 846 lacp_suppress_distributing(lsc, best_la); 847 } 848 } 849} 850 851static uint16_t 852lacp_compose_key(struct lacp_port *lp) 853{ 854 struct lagg_port *lgp = lp->lp_lagg; 855 struct lagg_softc *lgs = lgp->lp_lagg; 856 u_int media = lp->lp_media; 857 uint16_t key; 858 859 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 860 861 /* 862 * non-aggregatable links should have unique keys. 863 * 864 * XXX this isn't really unique as if_index is 16 bit. 865 */ 866 867 /* bit 0..14: (some bits of) if_index of this port */ 868 key = lp->lp_ifp->if_index; 869 /* bit 15: 1 */ 870 key |= 0x8000; 871 } else { 872 u_int subtype = IFM_SUBTYPE(media); 873 874 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type")); 875 KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface")); 876 877 /* bit 0..4: IFM_SUBTYPE */ 878 key = subtype; 879 /* bit 5..14: (some bits of) if_index of lagg device */ 880 key |= 0x7fe0 & ((lgs->sc_ifp->if_index) << 5); 881 /* bit 15: 0 */ 882 } 883 return (htons(key)); 884} 885 886static void 887lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 888{ 889#if defined(LACP_DEBUG) 890 char buf[LACP_LAGIDSTR_MAX+1]; 891#endif 892 893 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 894 __func__, 895 lacp_format_lagid(&la->la_actor, &la->la_partner, 896 buf, sizeof(buf)), 897 la->la_refcnt, la->la_refcnt + 1)); 898 899 KASSERT(la->la_refcnt > 0, ("refcount <= 0")); 900 la->la_refcnt++; 901 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcount")); 902} 903 904static void 905lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la) 906{ 907#if defined(LACP_DEBUG) 908 char buf[LACP_LAGIDSTR_MAX+1]; 909#endif 910 911 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 912 __func__, 913 lacp_format_lagid(&la->la_actor, &la->la_partner, 914 buf, sizeof(buf)), 915 la->la_refcnt, la->la_refcnt - 1)); 916 917 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcnt")); 918 la->la_refcnt--; 919 if (la->la_refcnt > 0) { 920 return; 921 } 922 923 KASSERT(la->la_refcnt == 0, ("refcount not zero")); 924 KASSERT(lsc->lsc_active_aggregator != la, ("aggregator active")); 925 926 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q); 927 928 free(la, M_DEVBUF); 929} 930 931/* 932 * lacp_aggregator_get: allocate an aggregator. 933 */ 934 935static struct lacp_aggregator * 936lacp_aggregator_get(struct lacp_softc *lsc, struct lacp_port *lp) 937{ 938 struct lacp_aggregator *la; 939 940 la = malloc(sizeof(*la), M_DEVBUF, M_NOWAIT); 941 if (la) { 942 la->la_refcnt = 1; 943 la->la_nports = 0; 944 TAILQ_INIT(&la->la_ports); 945 la->la_pending = 0; 946 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q); 947 } 948 949 return (la); 950} 951 952/* 953 * lacp_fill_aggregator_id: setup a newly allocated aggregator from a port. 954 */ 955 956static void 957lacp_fill_aggregator_id(struct lacp_aggregator *la, const struct lacp_port *lp) 958{ 959 lacp_fill_aggregator_id_peer(&la->la_partner, &lp->lp_partner); 960 lacp_fill_aggregator_id_peer(&la->la_actor, &lp->lp_actor); 961 962 la->la_actor.lip_state = lp->lp_state & LACP_STATE_AGGREGATION; 963} 964 965static void 966lacp_fill_aggregator_id_peer(struct lacp_peerinfo *lpi_aggr, 967 const struct lacp_peerinfo *lpi_port) 968{ 969 memset(lpi_aggr, 0, sizeof(*lpi_aggr)); 970 lpi_aggr->lip_systemid = lpi_port->lip_systemid; 971 lpi_aggr->lip_key = lpi_port->lip_key; 972} 973 974/* 975 * lacp_aggregator_is_compatible: check if a port can join to an aggregator. 976 */ 977 978static int 979lacp_aggregator_is_compatible(const struct lacp_aggregator *la, 980 const struct lacp_port *lp) 981{ 982 if (!(lp->lp_state & LACP_STATE_AGGREGATION) || 983 !(lp->lp_partner.lip_state & LACP_STATE_AGGREGATION)) { 984 return (0); 985 } 986 987 if (!(la->la_actor.lip_state & LACP_STATE_AGGREGATION)) { 988 return (0); 989 } 990 991 if (!lacp_peerinfo_is_compatible(&la->la_partner, &lp->lp_partner)) { 992 return (0); 993 } 994 995 if (!lacp_peerinfo_is_compatible(&la->la_actor, &lp->lp_actor)) { 996 return (0); 997 } 998 999 return (1); 1000} 1001 1002static int 1003lacp_peerinfo_is_compatible(const struct lacp_peerinfo *a, 1004 const struct lacp_peerinfo *b) 1005{ 1006 if (memcmp(&a->lip_systemid, &b->lip_systemid, 1007 sizeof(a->lip_systemid))) { 1008 return (0); 1009 } 1010 1011 if (memcmp(&a->lip_key, &b->lip_key, sizeof(a->lip_key))) { 1012 return (0); 1013 } 1014 1015 return (1); 1016} 1017 1018static void 1019lacp_port_enable(struct lacp_port *lp) 1020{ 1021 struct lagg_port *lgp = lp->lp_lagg; 1022 1023 lp->lp_state |= LACP_STATE_AGGREGATION; 1024 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 1025} 1026 1027static void 1028lacp_port_disable(struct lacp_port *lp) 1029{ 1030 struct lagg_port *lgp = lp->lp_lagg; 1031 1032 lacp_set_mux(lp, LACP_MUX_DETACHED); 1033 1034 lp->lp_state &= ~LACP_STATE_AGGREGATION; 1035 lp->lp_selected = LACP_UNSELECTED; 1036 lacp_sm_rx_record_default(lp); 1037 lp->lp_partner.lip_state &= ~LACP_STATE_AGGREGATION; 1038 lp->lp_state &= ~LACP_STATE_EXPIRED; 1039 lgp->lp_flags |= LAGG_PORT_DISABLED; 1040} 1041 1042/* 1043 * lacp_select: select an aggregator. create one if necessary. 1044 */ 1045static void 1046lacp_select(struct lacp_port *lp) 1047{ 1048 struct lacp_softc *lsc = lp->lp_lsc; 1049 struct lacp_aggregator *la; 1050#if defined(LACP_DEBUG) 1051 char buf[LACP_LAGIDSTR_MAX+1]; 1052#endif 1053 1054 if (lp->lp_aggregator) { 1055 return; 1056 } 1057 1058 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1059 ("timer_wait_while still active")); 1060 1061 LACP_DPRINTF((lp, "port lagid=%s\n", 1062 lacp_format_lagid(&lp->lp_actor, &lp->lp_partner, 1063 buf, sizeof(buf)))); 1064 1065 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 1066 if (lacp_aggregator_is_compatible(la, lp)) { 1067 break; 1068 } 1069 } 1070 1071 if (la == NULL) { 1072 la = lacp_aggregator_get(lsc, lp); 1073 if (la == NULL) { 1074 LACP_DPRINTF((lp, "aggregator creation failed\n")); 1075 1076 /* 1077 * will retry on the next tick. 1078 */ 1079 1080 return; 1081 } 1082 lacp_fill_aggregator_id(la, lp); 1083 LACP_DPRINTF((lp, "aggregator created\n")); 1084 } else { 1085 LACP_DPRINTF((lp, "compatible aggregator found\n")); 1086 lacp_aggregator_addref(lsc, la); 1087 } 1088 1089 LACP_DPRINTF((lp, "aggregator lagid=%s\n", 1090 lacp_format_lagid(&la->la_actor, &la->la_partner, 1091 buf, sizeof(buf)))); 1092 1093 lp->lp_aggregator = la; 1094 lp->lp_selected = LACP_SELECTED; 1095} 1096 1097/* 1098 * lacp_unselect: finish unselect/detach process. 1099 */ 1100 1101static void 1102lacp_unselect(struct lacp_port *lp) 1103{ 1104 struct lacp_softc *lsc = lp->lp_lsc; 1105 struct lacp_aggregator *la = lp->lp_aggregator; 1106 1107 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1108 ("timer_wait_while still active")); 1109 1110 if (la == NULL) { 1111 return; 1112 } 1113 1114 lp->lp_aggregator = NULL; 1115 lacp_aggregator_delref(lsc, la); 1116} 1117 1118/* mux machine */ 1119 1120static void 1121lacp_sm_mux(struct lacp_port *lp) 1122{ 1123 enum lacp_mux_state new_state; 1124 boolean_t p_sync = 1125 (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0; 1126 boolean_t p_collecting = 1127 (lp->lp_partner.lip_state & LACP_STATE_COLLECTING) != 0; 1128 enum lacp_selected selected = lp->lp_selected; 1129 struct lacp_aggregator *la; 1130 1131 /* LACP_DPRINTF((lp, "%s: state %d\n", __func__, lp->lp_mux_state)); */ 1132 1133re_eval: 1134 la = lp->lp_aggregator; 1135 KASSERT(lp->lp_mux_state == LACP_MUX_DETACHED || la != NULL, 1136 ("MUX not detached")); 1137 new_state = lp->lp_mux_state; 1138 switch (lp->lp_mux_state) { 1139 case LACP_MUX_DETACHED: 1140 if (selected != LACP_UNSELECTED) { 1141 new_state = LACP_MUX_WAITING; 1142 } 1143 break; 1144 case LACP_MUX_WAITING: 1145 KASSERT(la->la_pending > 0 || 1146 !LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1147 ("timer_wait_while still active")); 1148 if (selected == LACP_SELECTED && la->la_pending == 0) { 1149 new_state = LACP_MUX_ATTACHED; 1150 } else if (selected == LACP_UNSELECTED) { 1151 new_state = LACP_MUX_DETACHED; 1152 } 1153 break; 1154 case LACP_MUX_ATTACHED: 1155 if (selected == LACP_SELECTED && p_sync) { 1156 new_state = LACP_MUX_COLLECTING; 1157 } else if (selected != LACP_SELECTED) { 1158 new_state = LACP_MUX_DETACHED; 1159 } 1160 break; 1161 case LACP_MUX_COLLECTING: 1162 if (selected == LACP_SELECTED && p_sync && p_collecting) { 1163 new_state = LACP_MUX_DISTRIBUTING; 1164 } else if (selected != LACP_SELECTED || !p_sync) { 1165 new_state = LACP_MUX_ATTACHED; 1166 } 1167 break; 1168 case LACP_MUX_DISTRIBUTING: 1169 if (selected != LACP_SELECTED || !p_sync || !p_collecting) { 1170 new_state = LACP_MUX_COLLECTING; 1171 } 1172 break; 1173 default: 1174 panic("%s: unknown state", __func__); 1175 } 1176 1177 if (lp->lp_mux_state == new_state) { 1178 return; 1179 } 1180 1181 lacp_set_mux(lp, new_state); 1182 goto re_eval; 1183} 1184 1185static void 1186lacp_set_mux(struct lacp_port *lp, enum lacp_mux_state new_state) 1187{ 1188 struct lacp_aggregator *la = lp->lp_aggregator; 1189 1190 if (lp->lp_mux_state == new_state) { 1191 return; 1192 } 1193 1194 switch (new_state) { 1195 case LACP_MUX_DETACHED: 1196 lp->lp_state &= ~LACP_STATE_SYNC; 1197 lacp_disable_distributing(lp); 1198 lacp_disable_collecting(lp); 1199 lacp_sm_assert_ntt(lp); 1200 /* cancel timer */ 1201 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE)) { 1202 KASSERT(la->la_pending > 0, 1203 ("timer_wait_while not active")); 1204 la->la_pending--; 1205 } 1206 LACP_TIMER_DISARM(lp, LACP_TIMER_WAIT_WHILE); 1207 lacp_unselect(lp); 1208 break; 1209 case LACP_MUX_WAITING: 1210 LACP_TIMER_ARM(lp, LACP_TIMER_WAIT_WHILE, 1211 LACP_AGGREGATE_WAIT_TIME); 1212 la->la_pending++; 1213 break; 1214 case LACP_MUX_ATTACHED: 1215 lp->lp_state |= LACP_STATE_SYNC; 1216 lacp_disable_collecting(lp); 1217 lacp_sm_assert_ntt(lp); 1218 break; 1219 case LACP_MUX_COLLECTING: 1220 lacp_enable_collecting(lp); 1221 lacp_disable_distributing(lp); 1222 lacp_sm_assert_ntt(lp); 1223 break; 1224 case LACP_MUX_DISTRIBUTING: 1225 lacp_enable_distributing(lp); 1226 break; 1227 default: 1228 panic("%s: unknown state", __func__); 1229 } 1230 1231 LACP_DPRINTF((lp, "mux_state %d -> %d\n", lp->lp_mux_state, new_state)); 1232 1233 lp->lp_mux_state = new_state; 1234} 1235 1236static void 1237lacp_sm_mux_timer(struct lacp_port *lp) 1238{ 1239 struct lacp_aggregator *la = lp->lp_aggregator; 1240#if defined(LACP_DEBUG) 1241 char buf[LACP_LAGIDSTR_MAX+1]; 1242#endif 1243 1244 KASSERT(la->la_pending > 0, ("no pending event")); 1245 1246 LACP_DPRINTF((lp, "%s: aggregator %s, pending %d -> %d\n", __func__, 1247 lacp_format_lagid(&la->la_actor, &la->la_partner, 1248 buf, sizeof(buf)), 1249 la->la_pending, la->la_pending - 1)); 1250 1251 la->la_pending--; 1252} 1253 1254/* periodic transmit machine */ 1255 1256static void 1257lacp_sm_ptx_update_timeout(struct lacp_port *lp, uint8_t oldpstate) 1258{ 1259 if (LACP_STATE_EQ(oldpstate, lp->lp_partner.lip_state, 1260 LACP_STATE_TIMEOUT)) { 1261 return; 1262 } 1263 1264 LACP_DPRINTF((lp, "partner timeout changed\n")); 1265 1266 /* 1267 * FAST_PERIODIC -> SLOW_PERIODIC 1268 * or 1269 * SLOW_PERIODIC (-> PERIODIC_TX) -> FAST_PERIODIC 1270 * 1271 * let lacp_sm_ptx_tx_schedule to update timeout. 1272 */ 1273 1274 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1275 1276 /* 1277 * if timeout has been shortened, assert NTT. 1278 */ 1279 1280 if ((lp->lp_partner.lip_state & LACP_STATE_TIMEOUT)) { 1281 lacp_sm_assert_ntt(lp); 1282 } 1283} 1284 1285static void 1286lacp_sm_ptx_tx_schedule(struct lacp_port *lp) 1287{ 1288 int timeout; 1289 1290 if (!(lp->lp_state & LACP_STATE_ACTIVITY) && 1291 !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) { 1292 1293 /* 1294 * NO_PERIODIC 1295 */ 1296 1297 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1298 return; 1299 } 1300 1301 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_PERIODIC)) { 1302 return; 1303 } 1304 1305 timeout = (lp->lp_partner.lip_state & LACP_STATE_TIMEOUT) ? 1306 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME; 1307 1308 LACP_TIMER_ARM(lp, LACP_TIMER_PERIODIC, timeout); 1309} 1310 1311static void 1312lacp_sm_ptx_timer(struct lacp_port *lp) 1313{ 1314 lacp_sm_assert_ntt(lp); 1315} 1316 1317static void 1318lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du) 1319{ 1320 int timeout; 1321 1322 /* 1323 * check LACP_DISABLED first 1324 */ 1325 1326 if (!(lp->lp_state & LACP_STATE_AGGREGATION)) { 1327 return; 1328 } 1329 1330 /* 1331 * check loopback condition. 1332 */ 1333 1334 if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid, 1335 &lp->lp_actor.lip_systemid)) { 1336 return; 1337 } 1338 1339 /* 1340 * EXPIRED, DEFAULTED, CURRENT -> CURRENT 1341 */ 1342 1343 lacp_sm_rx_update_selected(lp, du); 1344 lacp_sm_rx_update_ntt(lp, du); 1345 lacp_sm_rx_record_pdu(lp, du); 1346 1347 timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ? 1348 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME; 1349 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout); 1350 1351 lp->lp_state &= ~LACP_STATE_EXPIRED; 1352 1353 /* 1354 * kick transmit machine without waiting the next tick. 1355 */ 1356 1357 lacp_sm_tx(lp); 1358} 1359 1360static void 1361lacp_sm_rx_set_expired(struct lacp_port *lp) 1362{ 1363 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1364 lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT; 1365 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME); 1366 lp->lp_state |= LACP_STATE_EXPIRED; 1367} 1368 1369static void 1370lacp_sm_rx_timer(struct lacp_port *lp) 1371{ 1372 if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) { 1373 /* CURRENT -> EXPIRED */ 1374 LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__)); 1375 lacp_sm_rx_set_expired(lp); 1376 } else { 1377 /* EXPIRED -> DEFAULTED */ 1378 LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__)); 1379 lacp_sm_rx_update_default_selected(lp); 1380 lacp_sm_rx_record_default(lp); 1381 lp->lp_state &= ~LACP_STATE_EXPIRED; 1382 } 1383} 1384 1385static void 1386lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du) 1387{ 1388 boolean_t active; 1389 uint8_t oldpstate; 1390#if defined(LACP_DEBUG) 1391 char buf[LACP_STATESTR_MAX+1]; 1392#endif 1393 1394 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1395 1396 oldpstate = lp->lp_partner.lip_state; 1397 1398 active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY) 1399 || ((lp->lp_state & LACP_STATE_ACTIVITY) && 1400 (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY)); 1401 1402 lp->lp_partner = du->ldu_actor; 1403 if (active && 1404 ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1405 LACP_STATE_AGGREGATION) && 1406 !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner)) 1407 || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) { 1408 /* XXX nothing? */ 1409 } else { 1410 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1411 } 1412 1413 lp->lp_state &= ~LACP_STATE_DEFAULTED; 1414 1415 if (oldpstate != lp->lp_partner.lip_state) { 1416 LACP_DPRINTF((lp, "old pstate %s\n", 1417 lacp_format_state(oldpstate, buf, sizeof(buf)))); 1418 LACP_DPRINTF((lp, "new pstate %s\n", 1419 lacp_format_state(lp->lp_partner.lip_state, buf, 1420 sizeof(buf)))); 1421 } 1422 1423 lacp_sm_ptx_update_timeout(lp, oldpstate); 1424} 1425 1426static void 1427lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du) 1428{ 1429 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1430 1431 if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) || 1432 !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1433 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) { 1434 LACP_DPRINTF((lp, "%s: assert ntt\n", __func__)); 1435 lacp_sm_assert_ntt(lp); 1436 } 1437} 1438 1439static void 1440lacp_sm_rx_record_default(struct lacp_port *lp) 1441{ 1442 uint8_t oldpstate; 1443 1444 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1445 1446 oldpstate = lp->lp_partner.lip_state; 1447 lp->lp_partner = lacp_partner_admin; 1448 lp->lp_state |= LACP_STATE_DEFAULTED; 1449 lacp_sm_ptx_update_timeout(lp, oldpstate); 1450} 1451 1452static void 1453lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp, 1454 const struct lacp_peerinfo *info) 1455{ 1456 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1457 1458 if (lacp_compare_peerinfo(&lp->lp_partner, info) || 1459 !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state, 1460 LACP_STATE_AGGREGATION)) { 1461 lp->lp_selected = LACP_UNSELECTED; 1462 /* mux machine will clean up lp->lp_aggregator */ 1463 } 1464} 1465 1466static void 1467lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du) 1468{ 1469 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1470 1471 lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor); 1472} 1473 1474static void 1475lacp_sm_rx_update_default_selected(struct lacp_port *lp) 1476{ 1477 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1478 1479 lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin); 1480} 1481 1482/* transmit machine */ 1483 1484static void 1485lacp_sm_tx(struct lacp_port *lp) 1486{ 1487 int error; 1488 1489 if (!(lp->lp_state & LACP_STATE_AGGREGATION) 1490#if 1 1491 || (!(lp->lp_state & LACP_STATE_ACTIVITY) 1492 && !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) 1493#endif 1494 ) { 1495 lp->lp_flags &= ~LACP_PORT_NTT; 1496 } 1497 1498 if (!(lp->lp_flags & LACP_PORT_NTT)) { 1499 return; 1500 } 1501 1502 /* Rate limit to 3 PDUs per LACP_FAST_PERIODIC_TIME */ 1503 if (ppsratecheck(&lp->lp_last_lacpdu, &lp->lp_lacpdu_sent, 1504 (3 / LACP_FAST_PERIODIC_TIME)) == 0) { 1505 LACP_DPRINTF((lp, "rate limited pdu\n")); 1506 return; 1507 } 1508 1509 error = lacp_xmit_lacpdu(lp); 1510 1511 if (error == 0) { 1512 lp->lp_flags &= ~LACP_PORT_NTT; 1513 } else { 1514 LACP_DPRINTF((lp, "lacpdu transmit failure, error %d\n", 1515 error)); 1516 } 1517} 1518 1519static void 1520lacp_sm_assert_ntt(struct lacp_port *lp) 1521{ 1522 1523 lp->lp_flags |= LACP_PORT_NTT; 1524} 1525 1526static void 1527lacp_run_timers(struct lacp_port *lp) 1528{ 1529 int i; 1530 1531 for (i = 0; i < LACP_NTIMER; i++) { 1532 KASSERT(lp->lp_timer[i] >= 0, 1533 ("invalid timer value %d", lp->lp_timer[i])); 1534 if (lp->lp_timer[i] == 0) { 1535 continue; 1536 } else if (--lp->lp_timer[i] <= 0) { 1537 if (lacp_timer_funcs[i]) { 1538 (*lacp_timer_funcs[i])(lp); 1539 } 1540 } 1541 } 1542} 1543 1544int 1545lacp_marker_input(struct lagg_port *lgp, struct mbuf *m) 1546{ 1547 struct lacp_port *lp = LACP_PORT(lgp); 1548 struct markerdu *mdu; 1549 int error = 0; 1550 1551 LAGG_LOCK_ASSERT(lgp->lp_lagg); 1552 1553 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 1554 goto bad; 1555 } 1556 1557 if (m->m_pkthdr.len != sizeof(*mdu)) { 1558 goto bad; 1559 } 1560 1561 if ((m->m_flags & M_MCAST) == 0) { 1562 goto bad; 1563 } 1564 1565 if (m->m_len < sizeof(*mdu)) { 1566 m = m_pullup(m, sizeof(*mdu)); 1567 if (m == NULL) { 1568 return (ENOMEM); 1569 } 1570 } 1571 1572 mdu = mtod(m, struct markerdu *); 1573 1574 if (memcmp(&mdu->mdu_eh.ether_dhost, 1575 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 1576 goto bad; 1577 } 1578 1579 /* XXX 1580 KASSERT(mdu->mdu_sph.sph_subtype == SLOWPROTOCOLS_SUBTYPE_MARKER, 1581 ("a very bad kassert!")); 1582 */ 1583 1584 if (mdu->mdu_sph.sph_version != 1) { 1585 goto bad; 1586 } 1587 1588 switch (mdu->mdu_tlv.tlv_type) { 1589 case MARKER_TYPE_INFO: 1590 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1591 marker_info_tlv_template, TRUE)) { 1592 goto bad; 1593 } 1594 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1595 memcpy(&mdu->mdu_eh.ether_dhost, 1596 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1597 memcpy(&mdu->mdu_eh.ether_shost, 1598 lgp->lp_lladdr, ETHER_ADDR_LEN); 1599 error = lagg_enqueue(lp->lp_ifp, m); 1600 break; 1601 1602 case MARKER_TYPE_RESPONSE: 1603 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1604 marker_response_tlv_template, TRUE)) { 1605 goto bad; 1606 } 1607 /* 1608 * we are not interested in responses as 1609 * we don't have a marker sender. 1610 */ 1611 /* FALLTHROUGH */ 1612 default: 1613 goto bad; 1614 } 1615 1616 return (error); 1617 1618bad: 1619 m_freem(m); 1620 return (EINVAL); 1621} 1622 1623static int 1624tlv_check(const void *p, size_t size, const struct tlvhdr *tlv, 1625 const struct tlv_template *tmpl, boolean_t check_type) 1626{ 1627 while (/* CONSTCOND */ 1) { 1628 if ((const char *)tlv - (const char *)p + sizeof(*tlv) > size) { 1629 return (EINVAL); 1630 } 1631 if ((check_type && tlv->tlv_type != tmpl->tmpl_type) || 1632 tlv->tlv_length != tmpl->tmpl_length) { 1633 return (EINVAL); 1634 } 1635 if (tmpl->tmpl_type == 0) { 1636 break; 1637 } 1638 tlv = (const struct tlvhdr *) 1639 ((const char *)tlv + tlv->tlv_length); 1640 tmpl++; 1641 } 1642 1643 return (0); 1644} 1645 1646#if defined(LACP_DEBUG) 1647const char * 1648lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) 1649{ 1650 snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", 1651 (int)mac[0], 1652 (int)mac[1], 1653 (int)mac[2], 1654 (int)mac[3], 1655 (int)mac[4], 1656 (int)mac[5]); 1657 1658 return (buf); 1659} 1660 1661const char * 1662lacp_format_systemid(const struct lacp_systemid *sysid, 1663 char *buf, size_t buflen) 1664{ 1665 char macbuf[LACP_MACSTR_MAX+1]; 1666 1667 snprintf(buf, buflen, "%04X,%s", 1668 ntohs(sysid->lsi_prio), 1669 lacp_format_mac(sysid->lsi_mac, macbuf, sizeof(macbuf))); 1670 1671 return (buf); 1672} 1673 1674const char * 1675lacp_format_portid(const struct lacp_portid *portid, char *buf, size_t buflen) 1676{ 1677 snprintf(buf, buflen, "%04X,%04X", 1678 ntohs(portid->lpi_prio), 1679 ntohs(portid->lpi_portno)); 1680 1681 return (buf); 1682} 1683 1684const char * 1685lacp_format_partner(const struct lacp_peerinfo *peer, char *buf, size_t buflen) 1686{ 1687 char sysid[LACP_SYSTEMIDSTR_MAX+1]; 1688 char portid[LACP_PORTIDSTR_MAX+1]; 1689 1690 snprintf(buf, buflen, "(%s,%04X,%s)", 1691 lacp_format_systemid(&peer->lip_systemid, sysid, sizeof(sysid)), 1692 ntohs(peer->lip_key), 1693 lacp_format_portid(&peer->lip_portid, portid, sizeof(portid))); 1694 1695 return (buf); 1696} 1697 1698const char * 1699lacp_format_lagid(const struct lacp_peerinfo *a, 1700 const struct lacp_peerinfo *b, char *buf, size_t buflen) 1701{ 1702 char astr[LACP_PARTNERSTR_MAX+1]; 1703 char bstr[LACP_PARTNERSTR_MAX+1]; 1704 1705#if 0 1706 /* 1707 * there's a convention to display small numbered peer 1708 * in the left. 1709 */ 1710 1711 if (lacp_compare_peerinfo(a, b) > 0) { 1712 const struct lacp_peerinfo *t; 1713 1714 t = a; 1715 a = b; 1716 b = t; 1717 } 1718#endif 1719 1720 snprintf(buf, buflen, "[%s,%s]", 1721 lacp_format_partner(a, astr, sizeof(astr)), 1722 lacp_format_partner(b, bstr, sizeof(bstr))); 1723 1724 return (buf); 1725} 1726 1727const char * 1728lacp_format_lagid_aggregator(const struct lacp_aggregator *la, 1729 char *buf, size_t buflen) 1730{ 1731 if (la == NULL) { 1732 return ("(none)"); 1733 } 1734 1735 return (lacp_format_lagid(&la->la_actor, &la->la_partner, buf, buflen)); 1736} 1737 1738const char * 1739lacp_format_state(uint8_t state, char *buf, size_t buflen) 1740{ 1741 snprintf(buf, buflen, "%b", state, LACP_STATE_BITS); 1742 return (buf); 1743} 1744 1745static void 1746lacp_dump_lacpdu(const struct lacpdu *du) 1747{ 1748 char buf[LACP_PARTNERSTR_MAX+1]; 1749 char buf2[LACP_STATESTR_MAX+1]; 1750 1751 printf("actor=%s\n", 1752 lacp_format_partner(&du->ldu_actor, buf, sizeof(buf))); 1753 printf("actor.state=%s\n", 1754 lacp_format_state(du->ldu_actor.lip_state, buf2, sizeof(buf2))); 1755 printf("partner=%s\n", 1756 lacp_format_partner(&du->ldu_partner, buf, sizeof(buf))); 1757 printf("partner.state=%s\n", 1758 lacp_format_state(du->ldu_partner.lip_state, buf2, sizeof(buf2))); 1759 1760 printf("maxdelay=%d\n", ntohs(du->ldu_collector.lci_maxdelay)); 1761} 1762 1763static void 1764lacp_dprintf(const struct lacp_port *lp, const char *fmt, ...) 1765{ 1766 va_list va; 1767 1768 if (lp) { 1769 printf("%s: ", lp->lp_ifp->if_xname); 1770 } 1771 1772 va_start(va, fmt); 1773 vprintf(fmt, va); 1774 va_end(va); 1775} 1776#endif
| 490 LIST_REMOVE(lp, lp_next); 491 free(lp, M_DEVBUF); 492} 493 494int 495lacp_port_isactive(struct lagg_port *lgp) 496{ 497 struct lacp_port *lp = LACP_PORT(lgp); 498 struct lacp_softc *lsc = lp->lp_lsc; 499 struct lacp_aggregator *la = lp->lp_aggregator; 500 501 /* This port is joined to the active aggregator */ 502 if (la != NULL && la == lsc->lsc_active_aggregator) 503 return (1); 504 505 return (0); 506} 507 508static void 509lacp_disable_collecting(struct lacp_port *lp) 510{ 511 struct lagg_port *lgp = lp->lp_lagg; 512 513 LACP_DPRINTF((lp, "collecting disabled\n")); 514 515 lp->lp_state &= ~LACP_STATE_COLLECTING; 516 lgp->lp_flags &= ~LAGG_PORT_COLLECTING; 517} 518 519static void 520lacp_enable_collecting(struct lacp_port *lp) 521{ 522 struct lagg_port *lgp = lp->lp_lagg; 523 524 LACP_DPRINTF((lp, "collecting enabled\n")); 525 526 lp->lp_state |= LACP_STATE_COLLECTING; 527 lgp->lp_flags |= LAGG_PORT_COLLECTING; 528} 529 530static void 531lacp_disable_distributing(struct lacp_port *lp) 532{ 533 struct lacp_aggregator *la = lp->lp_aggregator; 534 struct lacp_softc *lsc = lp->lp_lsc; 535 struct lagg_port *lgp = lp->lp_lagg; 536#if defined(LACP_DEBUG) 537 char buf[LACP_LAGIDSTR_MAX+1]; 538#endif /* defined(LACP_DEBUG) */ 539 540 LAGG_LOCK_ASSERT(lgp->lp_lagg); 541 542 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 543 return; 544 } 545 546 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 547 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 548 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); 549 550 LACP_DPRINTF((lp, "disable distributing on aggregator %s, " 551 "nports %d -> %d\n", 552 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 553 la->la_nports, la->la_nports - 1)); 554 555 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 556 la->la_nports--; 557 558 lacp_suppress_distributing(lsc, la); 559 560 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; 561 lgp->lp_flags &= ~LAGG_PORT_DISTRIBUTING; 562 563 if (lsc->lsc_active_aggregator == la) { 564 lacp_select_active_aggregator(lsc); 565 } 566} 567 568static void 569lacp_enable_distributing(struct lacp_port *lp) 570{ 571 struct lacp_aggregator *la = lp->lp_aggregator; 572 struct lacp_softc *lsc = lp->lp_lsc; 573 struct lagg_port *lgp = lp->lp_lagg; 574#if defined(LACP_DEBUG) 575 char buf[LACP_LAGIDSTR_MAX+1]; 576#endif /* defined(LACP_DEBUG) */ 577 578 LAGG_LOCK_ASSERT(lgp->lp_lagg); 579 580 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 581 return; 582 } 583 584 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 585 "nports %d -> %d\n", 586 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 587 la->la_nports, la->la_nports + 1)); 588 589 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 590 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 591 la->la_nports++; 592 593 lacp_suppress_distributing(lsc, la); 594 595 lp->lp_state |= LACP_STATE_DISTRIBUTING; 596 lgp->lp_flags |= LAGG_PORT_DISTRIBUTING; 597 598 if (lsc->lsc_active_aggregator != la) { 599 lacp_select_active_aggregator(lsc); 600 } 601} 602 603static void 604lacp_transit_expire(void *vp) 605{ 606 struct lacp_softc *lsc = vp; 607 608 LACP_DPRINTF((NULL, "%s\n", __func__)); 609 lsc->lsc_suppress_distributing = FALSE; 610} 611 612int 613lacp_attach(struct lagg_softc *lgs) 614{ 615 struct lacp_softc *lsc; 616 617 LAGG_LOCK_ASSERT(lgs); 618 619 lsc = malloc(sizeof(struct lacp_softc), 620 M_DEVBUF, M_NOWAIT|M_ZERO); 621 if (lsc == NULL) 622 return (ENOMEM); 623 624 lgs->sc_psc = (caddr_t)lsc; 625 lsc->lsc_lagg = lgs; 626 627 lsc->lsc_hashkey = arc4random(); 628 lsc->lsc_active_aggregator = NULL; 629 TAILQ_INIT(&lsc->lsc_aggregators); 630 LIST_INIT(&lsc->lsc_ports); 631 632 callout_init_mtx(&lsc->lsc_transit_callout, &lgs->sc_mtx, 0); 633 callout_init_mtx(&lsc->lsc_callout, &lgs->sc_mtx, 0); 634 635 /* if the lagg is already up then do the same */ 636 if (lgs->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) 637 lacp_init(lgs); 638 639 return (0); 640} 641 642int 643lacp_detach(struct lagg_softc *lgs) 644{ 645 struct lacp_softc *lsc = LACP_SOFTC(lgs); 646 647 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 648 ("aggregators still active")); 649 KASSERT(lsc->lsc_active_aggregator == NULL, 650 ("aggregator still attached")); 651 652 lgs->sc_psc = NULL; 653 callout_drain(&lsc->lsc_transit_callout); 654 callout_drain(&lsc->lsc_callout); 655 656 free(lsc, M_DEVBUF); 657 return (0); 658} 659 660void 661lacp_init(struct lagg_softc *lgs) 662{ 663 struct lacp_softc *lsc = LACP_SOFTC(lgs); 664 665 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 666} 667 668void 669lacp_stop(struct lagg_softc *lgs) 670{ 671 struct lacp_softc *lsc = LACP_SOFTC(lgs); 672 673 callout_stop(&lsc->lsc_transit_callout); 674 callout_stop(&lsc->lsc_callout); 675} 676 677struct lagg_port * 678lacp_select_tx_port(struct lagg_softc *lgs, struct mbuf *m) 679{ 680 struct lacp_softc *lsc = LACP_SOFTC(lgs); 681 struct lacp_aggregator *la; 682 struct lacp_port *lp; 683 uint32_t hash; 684 int nports; 685 686 LAGG_LOCK_ASSERT(lgs); 687 688 if (__predict_false(lsc->lsc_suppress_distributing)) { 689 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 690 return (NULL); 691 } 692 693 la = lsc->lsc_active_aggregator; 694 if (__predict_false(la == NULL)) { 695 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 696 return (NULL); 697 } 698 699 nports = la->la_nports; 700 KASSERT(nports > 0, ("no ports available")); 701 702 hash = lagg_hashmbuf(m, lsc->lsc_hashkey); 703 hash %= nports; 704 lp = TAILQ_FIRST(&la->la_ports); 705 while (hash--) { 706 lp = TAILQ_NEXT(lp, lp_dist_q); 707 } 708 709 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 710 ("aggregated port is not distributing")); 711 712 return (lp->lp_lagg); 713} 714/* 715 * lacp_suppress_distributing: drop transmit packets for a while 716 * to preserve packet ordering. 717 */ 718 719static void 720lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) 721{ 722 if (lsc->lsc_active_aggregator != la) { 723 return; 724 } 725 726 LACP_DPRINTF((NULL, "%s\n", __func__)); 727 lsc->lsc_suppress_distributing = TRUE; 728 /* XXX should consider collector max delay */ 729 callout_reset(&lsc->lsc_transit_callout, 730 LACP_TRANSIT_DELAY * hz / 1000, lacp_transit_expire, lsc); 731} 732 733static int 734lacp_compare_peerinfo(const struct lacp_peerinfo *a, 735 const struct lacp_peerinfo *b) 736{ 737 return (memcmp(a, b, offsetof(struct lacp_peerinfo, lip_state))); 738} 739 740static int 741lacp_compare_systemid(const struct lacp_systemid *a, 742 const struct lacp_systemid *b) 743{ 744 return (memcmp(a, b, sizeof(*a))); 745} 746 747#if 0 /* unused */ 748static int 749lacp_compare_portid(const struct lacp_portid *a, 750 const struct lacp_portid *b) 751{ 752 return (memcmp(a, b, sizeof(*a))); 753} 754#endif 755 756static uint64_t 757lacp_aggregator_bandwidth(struct lacp_aggregator *la) 758{ 759 struct lacp_port *lp; 760 uint64_t speed; 761 762 lp = TAILQ_FIRST(&la->la_ports); 763 if (lp == NULL) { 764 return (0); 765 } 766 767 speed = ifmedia_baudrate(lp->lp_media); 768 speed *= la->la_nports; 769 if (speed == 0) { 770 LACP_DPRINTF((lp, "speed 0? media=0x%x nports=%d\n", 771 lp->lp_media, la->la_nports)); 772 } 773 774 return (speed); 775} 776 777/* 778 * lacp_select_active_aggregator: select an aggregator to be used to transmit 779 * packets from lagg(4) interface. 780 */ 781 782static void 783lacp_select_active_aggregator(struct lacp_softc *lsc) 784{ 785 struct lacp_aggregator *la; 786 struct lacp_aggregator *best_la = NULL; 787 uint64_t best_speed = 0; 788#if defined(LACP_DEBUG) 789 char buf[LACP_LAGIDSTR_MAX+1]; 790#endif /* defined(LACP_DEBUG) */ 791 792 LACP_DPRINTF((NULL, "%s:\n", __func__)); 793 794 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 795 uint64_t speed; 796 797 if (la->la_nports == 0) { 798 continue; 799 } 800 801 speed = lacp_aggregator_bandwidth(la); 802 LACP_DPRINTF((NULL, "%s, speed=%jd, nports=%d\n", 803 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 804 speed, la->la_nports)); 805 if (speed > best_speed || 806 (speed == best_speed && 807 la == lsc->lsc_active_aggregator)) { 808 best_la = la; 809 best_speed = speed; 810 } 811 } 812 813 KASSERT(best_la == NULL || best_la->la_nports > 0, 814 ("invalid aggregator refcnt")); 815 KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports), 816 ("invalid aggregator list")); 817 818#if defined(LACP_DEBUG) 819 if (lsc->lsc_active_aggregator != best_la) { 820 LACP_DPRINTF((NULL, "active aggregator changed\n")); 821 LACP_DPRINTF((NULL, "old %s\n", 822 lacp_format_lagid_aggregator(lsc->lsc_active_aggregator, 823 buf, sizeof(buf)))); 824 } else { 825 LACP_DPRINTF((NULL, "active aggregator not changed\n")); 826 } 827 LACP_DPRINTF((NULL, "new %s\n", 828 lacp_format_lagid_aggregator(best_la, buf, sizeof(buf)))); 829#endif /* defined(LACP_DEBUG) */ 830 831 if (lsc->lsc_active_aggregator != best_la) { 832 lsc->lsc_active_aggregator = best_la; 833 if (best_la) { 834 lacp_suppress_distributing(lsc, best_la); 835 } 836 } 837} 838 839static uint16_t 840lacp_compose_key(struct lacp_port *lp) 841{ 842 struct lagg_port *lgp = lp->lp_lagg; 843 struct lagg_softc *lgs = lgp->lp_lagg; 844 u_int media = lp->lp_media; 845 uint16_t key; 846 847 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 848 849 /* 850 * non-aggregatable links should have unique keys. 851 * 852 * XXX this isn't really unique as if_index is 16 bit. 853 */ 854 855 /* bit 0..14: (some bits of) if_index of this port */ 856 key = lp->lp_ifp->if_index; 857 /* bit 15: 1 */ 858 key |= 0x8000; 859 } else { 860 u_int subtype = IFM_SUBTYPE(media); 861 862 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type")); 863 KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface")); 864 865 /* bit 0..4: IFM_SUBTYPE */ 866 key = subtype; 867 /* bit 5..14: (some bits of) if_index of lagg device */ 868 key |= 0x7fe0 & ((lgs->sc_ifp->if_index) << 5); 869 /* bit 15: 0 */ 870 } 871 return (htons(key)); 872} 873 874static void 875lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 876{ 877#if defined(LACP_DEBUG) 878 char buf[LACP_LAGIDSTR_MAX+1]; 879#endif 880 881 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 882 __func__, 883 lacp_format_lagid(&la->la_actor, &la->la_partner, 884 buf, sizeof(buf)), 885 la->la_refcnt, la->la_refcnt + 1)); 886 887 KASSERT(la->la_refcnt > 0, ("refcount <= 0")); 888 la->la_refcnt++; 889 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcount")); 890} 891 892static void 893lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la) 894{ 895#if defined(LACP_DEBUG) 896 char buf[LACP_LAGIDSTR_MAX+1]; 897#endif 898 899 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 900 __func__, 901 lacp_format_lagid(&la->la_actor, &la->la_partner, 902 buf, sizeof(buf)), 903 la->la_refcnt, la->la_refcnt - 1)); 904 905 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcnt")); 906 la->la_refcnt--; 907 if (la->la_refcnt > 0) { 908 return; 909 } 910 911 KASSERT(la->la_refcnt == 0, ("refcount not zero")); 912 KASSERT(lsc->lsc_active_aggregator != la, ("aggregator active")); 913 914 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q); 915 916 free(la, M_DEVBUF); 917} 918 919/* 920 * lacp_aggregator_get: allocate an aggregator. 921 */ 922 923static struct lacp_aggregator * 924lacp_aggregator_get(struct lacp_softc *lsc, struct lacp_port *lp) 925{ 926 struct lacp_aggregator *la; 927 928 la = malloc(sizeof(*la), M_DEVBUF, M_NOWAIT); 929 if (la) { 930 la->la_refcnt = 1; 931 la->la_nports = 0; 932 TAILQ_INIT(&la->la_ports); 933 la->la_pending = 0; 934 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q); 935 } 936 937 return (la); 938} 939 940/* 941 * lacp_fill_aggregator_id: setup a newly allocated aggregator from a port. 942 */ 943 944static void 945lacp_fill_aggregator_id(struct lacp_aggregator *la, const struct lacp_port *lp) 946{ 947 lacp_fill_aggregator_id_peer(&la->la_partner, &lp->lp_partner); 948 lacp_fill_aggregator_id_peer(&la->la_actor, &lp->lp_actor); 949 950 la->la_actor.lip_state = lp->lp_state & LACP_STATE_AGGREGATION; 951} 952 953static void 954lacp_fill_aggregator_id_peer(struct lacp_peerinfo *lpi_aggr, 955 const struct lacp_peerinfo *lpi_port) 956{ 957 memset(lpi_aggr, 0, sizeof(*lpi_aggr)); 958 lpi_aggr->lip_systemid = lpi_port->lip_systemid; 959 lpi_aggr->lip_key = lpi_port->lip_key; 960} 961 962/* 963 * lacp_aggregator_is_compatible: check if a port can join to an aggregator. 964 */ 965 966static int 967lacp_aggregator_is_compatible(const struct lacp_aggregator *la, 968 const struct lacp_port *lp) 969{ 970 if (!(lp->lp_state & LACP_STATE_AGGREGATION) || 971 !(lp->lp_partner.lip_state & LACP_STATE_AGGREGATION)) { 972 return (0); 973 } 974 975 if (!(la->la_actor.lip_state & LACP_STATE_AGGREGATION)) { 976 return (0); 977 } 978 979 if (!lacp_peerinfo_is_compatible(&la->la_partner, &lp->lp_partner)) { 980 return (0); 981 } 982 983 if (!lacp_peerinfo_is_compatible(&la->la_actor, &lp->lp_actor)) { 984 return (0); 985 } 986 987 return (1); 988} 989 990static int 991lacp_peerinfo_is_compatible(const struct lacp_peerinfo *a, 992 const struct lacp_peerinfo *b) 993{ 994 if (memcmp(&a->lip_systemid, &b->lip_systemid, 995 sizeof(a->lip_systemid))) { 996 return (0); 997 } 998 999 if (memcmp(&a->lip_key, &b->lip_key, sizeof(a->lip_key))) { 1000 return (0); 1001 } 1002 1003 return (1); 1004} 1005 1006static void 1007lacp_port_enable(struct lacp_port *lp) 1008{ 1009 struct lagg_port *lgp = lp->lp_lagg; 1010 1011 lp->lp_state |= LACP_STATE_AGGREGATION; 1012 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 1013} 1014 1015static void 1016lacp_port_disable(struct lacp_port *lp) 1017{ 1018 struct lagg_port *lgp = lp->lp_lagg; 1019 1020 lacp_set_mux(lp, LACP_MUX_DETACHED); 1021 1022 lp->lp_state &= ~LACP_STATE_AGGREGATION; 1023 lp->lp_selected = LACP_UNSELECTED; 1024 lacp_sm_rx_record_default(lp); 1025 lp->lp_partner.lip_state &= ~LACP_STATE_AGGREGATION; 1026 lp->lp_state &= ~LACP_STATE_EXPIRED; 1027 lgp->lp_flags |= LAGG_PORT_DISABLED; 1028} 1029 1030/* 1031 * lacp_select: select an aggregator. create one if necessary. 1032 */ 1033static void 1034lacp_select(struct lacp_port *lp) 1035{ 1036 struct lacp_softc *lsc = lp->lp_lsc; 1037 struct lacp_aggregator *la; 1038#if defined(LACP_DEBUG) 1039 char buf[LACP_LAGIDSTR_MAX+1]; 1040#endif 1041 1042 if (lp->lp_aggregator) { 1043 return; 1044 } 1045 1046 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1047 ("timer_wait_while still active")); 1048 1049 LACP_DPRINTF((lp, "port lagid=%s\n", 1050 lacp_format_lagid(&lp->lp_actor, &lp->lp_partner, 1051 buf, sizeof(buf)))); 1052 1053 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 1054 if (lacp_aggregator_is_compatible(la, lp)) { 1055 break; 1056 } 1057 } 1058 1059 if (la == NULL) { 1060 la = lacp_aggregator_get(lsc, lp); 1061 if (la == NULL) { 1062 LACP_DPRINTF((lp, "aggregator creation failed\n")); 1063 1064 /* 1065 * will retry on the next tick. 1066 */ 1067 1068 return; 1069 } 1070 lacp_fill_aggregator_id(la, lp); 1071 LACP_DPRINTF((lp, "aggregator created\n")); 1072 } else { 1073 LACP_DPRINTF((lp, "compatible aggregator found\n")); 1074 lacp_aggregator_addref(lsc, la); 1075 } 1076 1077 LACP_DPRINTF((lp, "aggregator lagid=%s\n", 1078 lacp_format_lagid(&la->la_actor, &la->la_partner, 1079 buf, sizeof(buf)))); 1080 1081 lp->lp_aggregator = la; 1082 lp->lp_selected = LACP_SELECTED; 1083} 1084 1085/* 1086 * lacp_unselect: finish unselect/detach process. 1087 */ 1088 1089static void 1090lacp_unselect(struct lacp_port *lp) 1091{ 1092 struct lacp_softc *lsc = lp->lp_lsc; 1093 struct lacp_aggregator *la = lp->lp_aggregator; 1094 1095 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1096 ("timer_wait_while still active")); 1097 1098 if (la == NULL) { 1099 return; 1100 } 1101 1102 lp->lp_aggregator = NULL; 1103 lacp_aggregator_delref(lsc, la); 1104} 1105 1106/* mux machine */ 1107 1108static void 1109lacp_sm_mux(struct lacp_port *lp) 1110{ 1111 enum lacp_mux_state new_state; 1112 boolean_t p_sync = 1113 (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0; 1114 boolean_t p_collecting = 1115 (lp->lp_partner.lip_state & LACP_STATE_COLLECTING) != 0; 1116 enum lacp_selected selected = lp->lp_selected; 1117 struct lacp_aggregator *la; 1118 1119 /* LACP_DPRINTF((lp, "%s: state %d\n", __func__, lp->lp_mux_state)); */ 1120 1121re_eval: 1122 la = lp->lp_aggregator; 1123 KASSERT(lp->lp_mux_state == LACP_MUX_DETACHED || la != NULL, 1124 ("MUX not detached")); 1125 new_state = lp->lp_mux_state; 1126 switch (lp->lp_mux_state) { 1127 case LACP_MUX_DETACHED: 1128 if (selected != LACP_UNSELECTED) { 1129 new_state = LACP_MUX_WAITING; 1130 } 1131 break; 1132 case LACP_MUX_WAITING: 1133 KASSERT(la->la_pending > 0 || 1134 !LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1135 ("timer_wait_while still active")); 1136 if (selected == LACP_SELECTED && la->la_pending == 0) { 1137 new_state = LACP_MUX_ATTACHED; 1138 } else if (selected == LACP_UNSELECTED) { 1139 new_state = LACP_MUX_DETACHED; 1140 } 1141 break; 1142 case LACP_MUX_ATTACHED: 1143 if (selected == LACP_SELECTED && p_sync) { 1144 new_state = LACP_MUX_COLLECTING; 1145 } else if (selected != LACP_SELECTED) { 1146 new_state = LACP_MUX_DETACHED; 1147 } 1148 break; 1149 case LACP_MUX_COLLECTING: 1150 if (selected == LACP_SELECTED && p_sync && p_collecting) { 1151 new_state = LACP_MUX_DISTRIBUTING; 1152 } else if (selected != LACP_SELECTED || !p_sync) { 1153 new_state = LACP_MUX_ATTACHED; 1154 } 1155 break; 1156 case LACP_MUX_DISTRIBUTING: 1157 if (selected != LACP_SELECTED || !p_sync || !p_collecting) { 1158 new_state = LACP_MUX_COLLECTING; 1159 } 1160 break; 1161 default: 1162 panic("%s: unknown state", __func__); 1163 } 1164 1165 if (lp->lp_mux_state == new_state) { 1166 return; 1167 } 1168 1169 lacp_set_mux(lp, new_state); 1170 goto re_eval; 1171} 1172 1173static void 1174lacp_set_mux(struct lacp_port *lp, enum lacp_mux_state new_state) 1175{ 1176 struct lacp_aggregator *la = lp->lp_aggregator; 1177 1178 if (lp->lp_mux_state == new_state) { 1179 return; 1180 } 1181 1182 switch (new_state) { 1183 case LACP_MUX_DETACHED: 1184 lp->lp_state &= ~LACP_STATE_SYNC; 1185 lacp_disable_distributing(lp); 1186 lacp_disable_collecting(lp); 1187 lacp_sm_assert_ntt(lp); 1188 /* cancel timer */ 1189 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE)) { 1190 KASSERT(la->la_pending > 0, 1191 ("timer_wait_while not active")); 1192 la->la_pending--; 1193 } 1194 LACP_TIMER_DISARM(lp, LACP_TIMER_WAIT_WHILE); 1195 lacp_unselect(lp); 1196 break; 1197 case LACP_MUX_WAITING: 1198 LACP_TIMER_ARM(lp, LACP_TIMER_WAIT_WHILE, 1199 LACP_AGGREGATE_WAIT_TIME); 1200 la->la_pending++; 1201 break; 1202 case LACP_MUX_ATTACHED: 1203 lp->lp_state |= LACP_STATE_SYNC; 1204 lacp_disable_collecting(lp); 1205 lacp_sm_assert_ntt(lp); 1206 break; 1207 case LACP_MUX_COLLECTING: 1208 lacp_enable_collecting(lp); 1209 lacp_disable_distributing(lp); 1210 lacp_sm_assert_ntt(lp); 1211 break; 1212 case LACP_MUX_DISTRIBUTING: 1213 lacp_enable_distributing(lp); 1214 break; 1215 default: 1216 panic("%s: unknown state", __func__); 1217 } 1218 1219 LACP_DPRINTF((lp, "mux_state %d -> %d\n", lp->lp_mux_state, new_state)); 1220 1221 lp->lp_mux_state = new_state; 1222} 1223 1224static void 1225lacp_sm_mux_timer(struct lacp_port *lp) 1226{ 1227 struct lacp_aggregator *la = lp->lp_aggregator; 1228#if defined(LACP_DEBUG) 1229 char buf[LACP_LAGIDSTR_MAX+1]; 1230#endif 1231 1232 KASSERT(la->la_pending > 0, ("no pending event")); 1233 1234 LACP_DPRINTF((lp, "%s: aggregator %s, pending %d -> %d\n", __func__, 1235 lacp_format_lagid(&la->la_actor, &la->la_partner, 1236 buf, sizeof(buf)), 1237 la->la_pending, la->la_pending - 1)); 1238 1239 la->la_pending--; 1240} 1241 1242/* periodic transmit machine */ 1243 1244static void 1245lacp_sm_ptx_update_timeout(struct lacp_port *lp, uint8_t oldpstate) 1246{ 1247 if (LACP_STATE_EQ(oldpstate, lp->lp_partner.lip_state, 1248 LACP_STATE_TIMEOUT)) { 1249 return; 1250 } 1251 1252 LACP_DPRINTF((lp, "partner timeout changed\n")); 1253 1254 /* 1255 * FAST_PERIODIC -> SLOW_PERIODIC 1256 * or 1257 * SLOW_PERIODIC (-> PERIODIC_TX) -> FAST_PERIODIC 1258 * 1259 * let lacp_sm_ptx_tx_schedule to update timeout. 1260 */ 1261 1262 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1263 1264 /* 1265 * if timeout has been shortened, assert NTT. 1266 */ 1267 1268 if ((lp->lp_partner.lip_state & LACP_STATE_TIMEOUT)) { 1269 lacp_sm_assert_ntt(lp); 1270 } 1271} 1272 1273static void 1274lacp_sm_ptx_tx_schedule(struct lacp_port *lp) 1275{ 1276 int timeout; 1277 1278 if (!(lp->lp_state & LACP_STATE_ACTIVITY) && 1279 !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) { 1280 1281 /* 1282 * NO_PERIODIC 1283 */ 1284 1285 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1286 return; 1287 } 1288 1289 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_PERIODIC)) { 1290 return; 1291 } 1292 1293 timeout = (lp->lp_partner.lip_state & LACP_STATE_TIMEOUT) ? 1294 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME; 1295 1296 LACP_TIMER_ARM(lp, LACP_TIMER_PERIODIC, timeout); 1297} 1298 1299static void 1300lacp_sm_ptx_timer(struct lacp_port *lp) 1301{ 1302 lacp_sm_assert_ntt(lp); 1303} 1304 1305static void 1306lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du) 1307{ 1308 int timeout; 1309 1310 /* 1311 * check LACP_DISABLED first 1312 */ 1313 1314 if (!(lp->lp_state & LACP_STATE_AGGREGATION)) { 1315 return; 1316 } 1317 1318 /* 1319 * check loopback condition. 1320 */ 1321 1322 if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid, 1323 &lp->lp_actor.lip_systemid)) { 1324 return; 1325 } 1326 1327 /* 1328 * EXPIRED, DEFAULTED, CURRENT -> CURRENT 1329 */ 1330 1331 lacp_sm_rx_update_selected(lp, du); 1332 lacp_sm_rx_update_ntt(lp, du); 1333 lacp_sm_rx_record_pdu(lp, du); 1334 1335 timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ? 1336 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME; 1337 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout); 1338 1339 lp->lp_state &= ~LACP_STATE_EXPIRED; 1340 1341 /* 1342 * kick transmit machine without waiting the next tick. 1343 */ 1344 1345 lacp_sm_tx(lp); 1346} 1347 1348static void 1349lacp_sm_rx_set_expired(struct lacp_port *lp) 1350{ 1351 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1352 lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT; 1353 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME); 1354 lp->lp_state |= LACP_STATE_EXPIRED; 1355} 1356 1357static void 1358lacp_sm_rx_timer(struct lacp_port *lp) 1359{ 1360 if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) { 1361 /* CURRENT -> EXPIRED */ 1362 LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__)); 1363 lacp_sm_rx_set_expired(lp); 1364 } else { 1365 /* EXPIRED -> DEFAULTED */ 1366 LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__)); 1367 lacp_sm_rx_update_default_selected(lp); 1368 lacp_sm_rx_record_default(lp); 1369 lp->lp_state &= ~LACP_STATE_EXPIRED; 1370 } 1371} 1372 1373static void 1374lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du) 1375{ 1376 boolean_t active; 1377 uint8_t oldpstate; 1378#if defined(LACP_DEBUG) 1379 char buf[LACP_STATESTR_MAX+1]; 1380#endif 1381 1382 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1383 1384 oldpstate = lp->lp_partner.lip_state; 1385 1386 active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY) 1387 || ((lp->lp_state & LACP_STATE_ACTIVITY) && 1388 (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY)); 1389 1390 lp->lp_partner = du->ldu_actor; 1391 if (active && 1392 ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1393 LACP_STATE_AGGREGATION) && 1394 !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner)) 1395 || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) { 1396 /* XXX nothing? */ 1397 } else { 1398 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1399 } 1400 1401 lp->lp_state &= ~LACP_STATE_DEFAULTED; 1402 1403 if (oldpstate != lp->lp_partner.lip_state) { 1404 LACP_DPRINTF((lp, "old pstate %s\n", 1405 lacp_format_state(oldpstate, buf, sizeof(buf)))); 1406 LACP_DPRINTF((lp, "new pstate %s\n", 1407 lacp_format_state(lp->lp_partner.lip_state, buf, 1408 sizeof(buf)))); 1409 } 1410 1411 lacp_sm_ptx_update_timeout(lp, oldpstate); 1412} 1413 1414static void 1415lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du) 1416{ 1417 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1418 1419 if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) || 1420 !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1421 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) { 1422 LACP_DPRINTF((lp, "%s: assert ntt\n", __func__)); 1423 lacp_sm_assert_ntt(lp); 1424 } 1425} 1426 1427static void 1428lacp_sm_rx_record_default(struct lacp_port *lp) 1429{ 1430 uint8_t oldpstate; 1431 1432 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1433 1434 oldpstate = lp->lp_partner.lip_state; 1435 lp->lp_partner = lacp_partner_admin; 1436 lp->lp_state |= LACP_STATE_DEFAULTED; 1437 lacp_sm_ptx_update_timeout(lp, oldpstate); 1438} 1439 1440static void 1441lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp, 1442 const struct lacp_peerinfo *info) 1443{ 1444 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1445 1446 if (lacp_compare_peerinfo(&lp->lp_partner, info) || 1447 !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state, 1448 LACP_STATE_AGGREGATION)) { 1449 lp->lp_selected = LACP_UNSELECTED; 1450 /* mux machine will clean up lp->lp_aggregator */ 1451 } 1452} 1453 1454static void 1455lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du) 1456{ 1457 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1458 1459 lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor); 1460} 1461 1462static void 1463lacp_sm_rx_update_default_selected(struct lacp_port *lp) 1464{ 1465 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1466 1467 lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin); 1468} 1469 1470/* transmit machine */ 1471 1472static void 1473lacp_sm_tx(struct lacp_port *lp) 1474{ 1475 int error; 1476 1477 if (!(lp->lp_state & LACP_STATE_AGGREGATION) 1478#if 1 1479 || (!(lp->lp_state & LACP_STATE_ACTIVITY) 1480 && !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) 1481#endif 1482 ) { 1483 lp->lp_flags &= ~LACP_PORT_NTT; 1484 } 1485 1486 if (!(lp->lp_flags & LACP_PORT_NTT)) { 1487 return; 1488 } 1489 1490 /* Rate limit to 3 PDUs per LACP_FAST_PERIODIC_TIME */ 1491 if (ppsratecheck(&lp->lp_last_lacpdu, &lp->lp_lacpdu_sent, 1492 (3 / LACP_FAST_PERIODIC_TIME)) == 0) { 1493 LACP_DPRINTF((lp, "rate limited pdu\n")); 1494 return; 1495 } 1496 1497 error = lacp_xmit_lacpdu(lp); 1498 1499 if (error == 0) { 1500 lp->lp_flags &= ~LACP_PORT_NTT; 1501 } else { 1502 LACP_DPRINTF((lp, "lacpdu transmit failure, error %d\n", 1503 error)); 1504 } 1505} 1506 1507static void 1508lacp_sm_assert_ntt(struct lacp_port *lp) 1509{ 1510 1511 lp->lp_flags |= LACP_PORT_NTT; 1512} 1513 1514static void 1515lacp_run_timers(struct lacp_port *lp) 1516{ 1517 int i; 1518 1519 for (i = 0; i < LACP_NTIMER; i++) { 1520 KASSERT(lp->lp_timer[i] >= 0, 1521 ("invalid timer value %d", lp->lp_timer[i])); 1522 if (lp->lp_timer[i] == 0) { 1523 continue; 1524 } else if (--lp->lp_timer[i] <= 0) { 1525 if (lacp_timer_funcs[i]) { 1526 (*lacp_timer_funcs[i])(lp); 1527 } 1528 } 1529 } 1530} 1531 1532int 1533lacp_marker_input(struct lagg_port *lgp, struct mbuf *m) 1534{ 1535 struct lacp_port *lp = LACP_PORT(lgp); 1536 struct markerdu *mdu; 1537 int error = 0; 1538 1539 LAGG_LOCK_ASSERT(lgp->lp_lagg); 1540 1541 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 1542 goto bad; 1543 } 1544 1545 if (m->m_pkthdr.len != sizeof(*mdu)) { 1546 goto bad; 1547 } 1548 1549 if ((m->m_flags & M_MCAST) == 0) { 1550 goto bad; 1551 } 1552 1553 if (m->m_len < sizeof(*mdu)) { 1554 m = m_pullup(m, sizeof(*mdu)); 1555 if (m == NULL) { 1556 return (ENOMEM); 1557 } 1558 } 1559 1560 mdu = mtod(m, struct markerdu *); 1561 1562 if (memcmp(&mdu->mdu_eh.ether_dhost, 1563 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 1564 goto bad; 1565 } 1566 1567 /* XXX 1568 KASSERT(mdu->mdu_sph.sph_subtype == SLOWPROTOCOLS_SUBTYPE_MARKER, 1569 ("a very bad kassert!")); 1570 */ 1571 1572 if (mdu->mdu_sph.sph_version != 1) { 1573 goto bad; 1574 } 1575 1576 switch (mdu->mdu_tlv.tlv_type) { 1577 case MARKER_TYPE_INFO: 1578 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1579 marker_info_tlv_template, TRUE)) { 1580 goto bad; 1581 } 1582 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1583 memcpy(&mdu->mdu_eh.ether_dhost, 1584 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1585 memcpy(&mdu->mdu_eh.ether_shost, 1586 lgp->lp_lladdr, ETHER_ADDR_LEN); 1587 error = lagg_enqueue(lp->lp_ifp, m); 1588 break; 1589 1590 case MARKER_TYPE_RESPONSE: 1591 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1592 marker_response_tlv_template, TRUE)) { 1593 goto bad; 1594 } 1595 /* 1596 * we are not interested in responses as 1597 * we don't have a marker sender. 1598 */ 1599 /* FALLTHROUGH */ 1600 default: 1601 goto bad; 1602 } 1603 1604 return (error); 1605 1606bad: 1607 m_freem(m); 1608 return (EINVAL); 1609} 1610 1611static int 1612tlv_check(const void *p, size_t size, const struct tlvhdr *tlv, 1613 const struct tlv_template *tmpl, boolean_t check_type) 1614{ 1615 while (/* CONSTCOND */ 1) { 1616 if ((const char *)tlv - (const char *)p + sizeof(*tlv) > size) { 1617 return (EINVAL); 1618 } 1619 if ((check_type && tlv->tlv_type != tmpl->tmpl_type) || 1620 tlv->tlv_length != tmpl->tmpl_length) { 1621 return (EINVAL); 1622 } 1623 if (tmpl->tmpl_type == 0) { 1624 break; 1625 } 1626 tlv = (const struct tlvhdr *) 1627 ((const char *)tlv + tlv->tlv_length); 1628 tmpl++; 1629 } 1630 1631 return (0); 1632} 1633 1634#if defined(LACP_DEBUG) 1635const char * 1636lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) 1637{ 1638 snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", 1639 (int)mac[0], 1640 (int)mac[1], 1641 (int)mac[2], 1642 (int)mac[3], 1643 (int)mac[4], 1644 (int)mac[5]); 1645 1646 return (buf); 1647} 1648 1649const char * 1650lacp_format_systemid(const struct lacp_systemid *sysid, 1651 char *buf, size_t buflen) 1652{ 1653 char macbuf[LACP_MACSTR_MAX+1]; 1654 1655 snprintf(buf, buflen, "%04X,%s", 1656 ntohs(sysid->lsi_prio), 1657 lacp_format_mac(sysid->lsi_mac, macbuf, sizeof(macbuf))); 1658 1659 return (buf); 1660} 1661 1662const char * 1663lacp_format_portid(const struct lacp_portid *portid, char *buf, size_t buflen) 1664{ 1665 snprintf(buf, buflen, "%04X,%04X", 1666 ntohs(portid->lpi_prio), 1667 ntohs(portid->lpi_portno)); 1668 1669 return (buf); 1670} 1671 1672const char * 1673lacp_format_partner(const struct lacp_peerinfo *peer, char *buf, size_t buflen) 1674{ 1675 char sysid[LACP_SYSTEMIDSTR_MAX+1]; 1676 char portid[LACP_PORTIDSTR_MAX+1]; 1677 1678 snprintf(buf, buflen, "(%s,%04X,%s)", 1679 lacp_format_systemid(&peer->lip_systemid, sysid, sizeof(sysid)), 1680 ntohs(peer->lip_key), 1681 lacp_format_portid(&peer->lip_portid, portid, sizeof(portid))); 1682 1683 return (buf); 1684} 1685 1686const char * 1687lacp_format_lagid(const struct lacp_peerinfo *a, 1688 const struct lacp_peerinfo *b, char *buf, size_t buflen) 1689{ 1690 char astr[LACP_PARTNERSTR_MAX+1]; 1691 char bstr[LACP_PARTNERSTR_MAX+1]; 1692 1693#if 0 1694 /* 1695 * there's a convention to display small numbered peer 1696 * in the left. 1697 */ 1698 1699 if (lacp_compare_peerinfo(a, b) > 0) { 1700 const struct lacp_peerinfo *t; 1701 1702 t = a; 1703 a = b; 1704 b = t; 1705 } 1706#endif 1707 1708 snprintf(buf, buflen, "[%s,%s]", 1709 lacp_format_partner(a, astr, sizeof(astr)), 1710 lacp_format_partner(b, bstr, sizeof(bstr))); 1711 1712 return (buf); 1713} 1714 1715const char * 1716lacp_format_lagid_aggregator(const struct lacp_aggregator *la, 1717 char *buf, size_t buflen) 1718{ 1719 if (la == NULL) { 1720 return ("(none)"); 1721 } 1722 1723 return (lacp_format_lagid(&la->la_actor, &la->la_partner, buf, buflen)); 1724} 1725 1726const char * 1727lacp_format_state(uint8_t state, char *buf, size_t buflen) 1728{ 1729 snprintf(buf, buflen, "%b", state, LACP_STATE_BITS); 1730 return (buf); 1731} 1732 1733static void 1734lacp_dump_lacpdu(const struct lacpdu *du) 1735{ 1736 char buf[LACP_PARTNERSTR_MAX+1]; 1737 char buf2[LACP_STATESTR_MAX+1]; 1738 1739 printf("actor=%s\n", 1740 lacp_format_partner(&du->ldu_actor, buf, sizeof(buf))); 1741 printf("actor.state=%s\n", 1742 lacp_format_state(du->ldu_actor.lip_state, buf2, sizeof(buf2))); 1743 printf("partner=%s\n", 1744 lacp_format_partner(&du->ldu_partner, buf, sizeof(buf))); 1745 printf("partner.state=%s\n", 1746 lacp_format_state(du->ldu_partner.lip_state, buf2, sizeof(buf2))); 1747 1748 printf("maxdelay=%d\n", ntohs(du->ldu_collector.lci_maxdelay)); 1749} 1750 1751static void 1752lacp_dprintf(const struct lacp_port *lp, const char *fmt, ...) 1753{ 1754 va_list va; 1755 1756 if (lp) { 1757 printf("%s: ", lp->lp_ifp->if_xname); 1758 } 1759 1760 va_start(va, fmt); 1761 vprintf(fmt, va); 1762 va_end(va); 1763} 1764#endif
|