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