ieee8023ad_lacp.c (168561) | ieee8023ad_lacp.c (168793) |
---|---|
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 --- 13 unchanged lines hidden (view full) --- 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> | 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 --- 13 unchanged lines hidden (view full) --- 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 168561 2007-04-10 00:27:25Z thompsa $"); | 30__FBSDID("$FreeBSD: head/sys/net/ieee8023ad_lacp.c 168793 2007-04-17 00:35:11Z 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 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 | 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_trunk.h> | 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 --- 144 unchanged lines hidden (view full) --- 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 | 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 --- 144 unchanged lines hidden (view full) --- 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 trunk_port *tp, struct mbuf *m) | 209lacp_input(struct lagg_port *lgp, struct mbuf *m) |
210{ | 210{ |
211 struct lacp_port *lp = LACP_PORT(tp); | 211 struct lacp_port *lp = LACP_PORT(lgp); |
212 struct lacpdu *du; 213 int error = 0; 214 | 212 struct lacpdu *du; 213 int error = 0; 214 |
215 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 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 } --- 55 unchanged lines hidden (view full) --- 279bad: 280 m_freem(m); 281 return (EINVAL); 282} 283 284static void 285lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info) 286{ | 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 } --- 55 unchanged lines hidden (view full) --- 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 trunk_port *tp = lp->lp_trunk; 288 struct trunk_softc *tr = tp->tp_trunk; | 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, | 289 290 info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO); 291 memcpy(&info->lip_systemid.lsi_mac, |
292 IF_LLADDR(tr->tr_ifp), ETHER_ADDR_LEN); | 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{ | 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 trunk_port *tp = lp->lp_trunk; | 301 struct lagg_port *lgp = lp->lp_lagg; |
302 struct mbuf *m; 303 struct lacpdu *du; 304 int error; 305 | 302 struct mbuf *m; 303 struct lacpdu *du; 304 int error; 305 |
306 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 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); | 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, tp->tp_lladdr, 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 --- 12 unchanged lines hidden (view full) --- 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 | 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 --- 12 unchanged lines hidden (view full) --- 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 = trunk_enqueue(lp->lp_ifp, m); | 348 error = lagg_enqueue(lp->lp_ifp, m); |
349 return (error); 350} 351 352void | 349 return (error); 350} 351 352void |
353lacp_linkstate(struct trunk_port *tp) | 353lacp_linkstate(struct lagg_port *lgp) |
354{ | 354{ |
355 struct lacp_port *lp = LACP_PORT(tp); 356 struct ifnet *ifp = tp->tp_ifp; | 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 | 357 struct ifmediareq ifmr; 358 int error = 0; 359 u_int media; 360 uint8_t old_state; 361 uint16_t old_key; 362 |
363 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 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\n", lp->lp_media, media)); --- 30 unchanged lines hidden (view full) --- 402 lacp_sm_mux(lp); 403 lacp_sm_tx(lp); 404 lacp_sm_ptx_tx_schedule(lp); 405 } 406 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 407} 408 409int | 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\n", lp->lp_media, media)); --- 30 unchanged lines hidden (view full) --- 402 lacp_sm_mux(lp); 403 lacp_sm_tx(lp); 404 lacp_sm_ptx_tx_schedule(lp); 405 } 406 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 407} 408 409int |
410lacp_port_create(struct trunk_port *tp) | 410lacp_port_create(struct lagg_port *lgp) |
411{ | 411{ |
412 struct trunk_softc *tr = tp->tp_trunk; 413 struct lacp_softc *lsc = LACP_SOFTC(tr); | 412 struct lagg_softc *lgs = lgp->lp_lagg; 413 struct lacp_softc *lsc = LACP_SOFTC(lgs); |
414 struct lacp_port *lp; | 414 struct lacp_port *lp; |
415 struct ifnet *ifp = tp->tp_ifp; | 415 struct ifnet *ifp = lgp->lp_ifp; |
416 struct sockaddr_dl sdl; 417 struct ifmultiaddr *rifma = NULL; 418 int error; 419 420 boolean_t active = TRUE; /* XXX should be configurable */ 421 boolean_t fast = FALSE; /* XXX should be configurable */ 422 | 416 struct sockaddr_dl sdl; 417 struct ifmultiaddr *rifma = NULL; 418 int error; 419 420 boolean_t active = TRUE; /* XXX should be configurable */ 421 boolean_t fast = FALSE; /* XXX should be configurable */ 422 |
423 TRUNK_LOCK_ASSERT(tr); | 423 LAGG_LOCK_ASSERT(lgs); |
424 425 bzero((char *)&sdl, sizeof(sdl)); 426 sdl.sdl_len = sizeof(sdl); 427 sdl.sdl_family = AF_LINK; 428 sdl.sdl_index = ifp->if_index; 429 sdl.sdl_type = IFT_ETHER; 430 sdl.sdl_alen = ETHER_ADDR_LEN; 431 432 bcopy(ðermulticastaddr_slowprotocols, 433 LLADDR(&sdl), ETHER_ADDR_LEN); 434 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 435 if (error) { | 424 425 bzero((char *)&sdl, sizeof(sdl)); 426 sdl.sdl_len = sizeof(sdl); 427 sdl.sdl_family = AF_LINK; 428 sdl.sdl_index = ifp->if_index; 429 sdl.sdl_type = IFT_ETHER; 430 sdl.sdl_alen = ETHER_ADDR_LEN; 431 432 bcopy(ðermulticastaddr_slowprotocols, 433 LLADDR(&sdl), ETHER_ADDR_LEN); 434 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 435 if (error) { |
436 printf("%s: ADDMULTI failed on %s\n", __func__, tp->tp_ifname); | 436 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname); |
437 return (error); 438 } 439 440 lp = malloc(sizeof(struct lacp_port), 441 M_DEVBUF, M_NOWAIT|M_ZERO); 442 if (lp == NULL) 443 return (ENOMEM); 444 | 437 return (error); 438 } 439 440 lp = malloc(sizeof(struct lacp_port), 441 M_DEVBUF, M_NOWAIT|M_ZERO); 442 if (lp == NULL) 443 return (ENOMEM); 444 |
445 tp->tp_psc = (caddr_t)lp; | 445 lgp->lp_psc = (caddr_t)lp; |
446 lp->lp_ifp = ifp; | 446 lp->lp_ifp = ifp; |
447 lp->lp_trunk = tp; | 447 lp->lp_lagg = lgp; |
448 lp->lp_lsc = lsc; 449 450 LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next); 451 452 lacp_fill_actorinfo(lp, &lp->lp_actor); 453 lp->lp_state = 454 (active ? LACP_STATE_ACTIVITY : 0) | 455 (fast ? LACP_STATE_TIMEOUT : 0); 456 lp->lp_aggregator = NULL; | 448 lp->lp_lsc = lsc; 449 450 LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next); 451 452 lacp_fill_actorinfo(lp, &lp->lp_actor); 453 lp->lp_state = 454 (active ? LACP_STATE_ACTIVITY : 0) | 455 (fast ? LACP_STATE_TIMEOUT : 0); 456 lp->lp_aggregator = NULL; |
457 lacp_linkstate(tp); | 457 lacp_linkstate(lgp); |
458 lacp_sm_rx_set_expired(lp); 459 460 return (0); 461} 462 463void | 458 lacp_sm_rx_set_expired(lp); 459 460 return (0); 461} 462 463void |
464lacp_port_destroy(struct trunk_port *tp) | 464lacp_port_destroy(struct lagg_port *lgp) |
465{ | 465{ |
466 struct lacp_port *lp = LACP_PORT(tp); 467 struct ifnet *ifp = tp->tp_ifp; | 466 struct lacp_port *lp = LACP_PORT(lgp); 467 struct ifnet *ifp = lgp->lp_ifp; |
468 struct sockaddr_dl sdl; 469 int i, error; 470 | 468 struct sockaddr_dl sdl; 469 int i, error; 470 |
471 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 471 LAGG_LOCK_ASSERT(lgp->lp_lagg); |
472 473 for (i = 0; i < LACP_NTIMER; i++) { 474 LACP_TIMER_DISARM(lp, i); 475 } 476 477 lacp_disable_collecting(lp); 478 lacp_disable_distributing(lp); 479 lacp_unselect(lp); --- 4 unchanged lines hidden (view full) --- 484 sdl.sdl_index = ifp->if_index; 485 sdl.sdl_type = IFT_ETHER; 486 sdl.sdl_alen = ETHER_ADDR_LEN; 487 488 bcopy(ðermulticastaddr_slowprotocols, 489 LLADDR(&sdl), ETHER_ADDR_LEN); 490 error = if_delmulti(ifp, (struct sockaddr *)&sdl); 491 if (error) | 472 473 for (i = 0; i < LACP_NTIMER; i++) { 474 LACP_TIMER_DISARM(lp, i); 475 } 476 477 lacp_disable_collecting(lp); 478 lacp_disable_distributing(lp); 479 lacp_unselect(lp); --- 4 unchanged lines hidden (view full) --- 484 sdl.sdl_index = ifp->if_index; 485 sdl.sdl_type = IFT_ETHER; 486 sdl.sdl_alen = ETHER_ADDR_LEN; 487 488 bcopy(ðermulticastaddr_slowprotocols, 489 LLADDR(&sdl), ETHER_ADDR_LEN); 490 error = if_delmulti(ifp, (struct sockaddr *)&sdl); 491 if (error) |
492 printf("%s: DELMULTI failed on %s\n", __func__, tp->tp_ifname); | 492 printf("%s: DELMULTI failed on %s\n", __func__, lgp->lp_ifname); |
493 494 LIST_REMOVE(lp, lp_next); 495 free(lp, M_DEVBUF); 496} 497 498int | 493 494 LIST_REMOVE(lp, lp_next); 495 free(lp, M_DEVBUF); 496} 497 498int |
499lacp_port_isactive(struct trunk_port *tp) | 499lacp_port_isactive(struct lagg_port *lgp) |
500{ | 500{ |
501 struct lacp_port *lp = LACP_PORT(tp); | 501 struct lacp_port *lp = LACP_PORT(lgp); |
502 struct lacp_softc *lsc = lp->lp_lsc; 503 struct lacp_aggregator *la = lp->lp_aggregator; 504 505 /* This port is joined to the active aggregator */ 506 if (la != NULL && la == lsc->lsc_active_aggregator) 507 return (1); 508 509 return (0); 510} 511 512static void 513lacp_disable_collecting(struct lacp_port *lp) 514{ | 502 struct lacp_softc *lsc = lp->lp_lsc; 503 struct lacp_aggregator *la = lp->lp_aggregator; 504 505 /* This port is joined to the active aggregator */ 506 if (la != NULL && la == lsc->lsc_active_aggregator) 507 return (1); 508 509 return (0); 510} 511 512static void 513lacp_disable_collecting(struct lacp_port *lp) 514{ |
515 struct trunk_port *tp = lp->lp_trunk; | 515 struct lagg_port *lgp = lp->lp_lagg; |
516 517 LACP_DPRINTF((lp, "collecting disabled\n")); 518 519 lp->lp_state &= ~LACP_STATE_COLLECTING; | 516 517 LACP_DPRINTF((lp, "collecting disabled\n")); 518 519 lp->lp_state &= ~LACP_STATE_COLLECTING; |
520 tp->tp_flags &= ~TRUNK_PORT_COLLECTING; | 520 lgp->lp_flags &= ~LAGG_PORT_COLLECTING; |
521} 522 523static void 524lacp_enable_collecting(struct lacp_port *lp) 525{ | 521} 522 523static void 524lacp_enable_collecting(struct lacp_port *lp) 525{ |
526 struct trunk_port *tp = lp->lp_trunk; | 526 struct lagg_port *lgp = lp->lp_lagg; |
527 528 LACP_DPRINTF((lp, "collecting enabled\n")); 529 530 lp->lp_state |= LACP_STATE_COLLECTING; | 527 528 LACP_DPRINTF((lp, "collecting enabled\n")); 529 530 lp->lp_state |= LACP_STATE_COLLECTING; |
531 tp->tp_flags |= TRUNK_PORT_COLLECTING; | 531 lgp->lp_flags |= LAGG_PORT_COLLECTING; |
532} 533 534static void 535lacp_disable_distributing(struct lacp_port *lp) 536{ 537 struct lacp_aggregator *la = lp->lp_aggregator; 538 struct lacp_softc *lsc = lp->lp_lsc; | 532} 533 534static void 535lacp_disable_distributing(struct lacp_port *lp) 536{ 537 struct lacp_aggregator *la = lp->lp_aggregator; 538 struct lacp_softc *lsc = lp->lp_lsc; |
539 struct trunk_port *tp = lp->lp_trunk; | 539 struct lagg_port *lgp = lp->lp_lagg; |
540#if defined(LACP_DEBUG) 541 char buf[LACP_LAGIDSTR_MAX+1]; 542#endif /* defined(LACP_DEBUG) */ 543 | 540#if defined(LACP_DEBUG) 541 char buf[LACP_LAGIDSTR_MAX+1]; 542#endif /* defined(LACP_DEBUG) */ 543 |
544 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 544 LAGG_LOCK_ASSERT(lgp->lp_lagg); |
545 546 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 547 return; 548 } 549 550 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 551 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 552 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); --- 4 unchanged lines hidden (view full) --- 557 la->la_nports, la->la_nports - 1)); 558 559 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 560 la->la_nports--; 561 562 lacp_suppress_distributing(lsc, la); 563 564 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; | 545 546 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 547 return; 548 } 549 550 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 551 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 552 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); --- 4 unchanged lines hidden (view full) --- 557 la->la_nports, la->la_nports - 1)); 558 559 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 560 la->la_nports--; 561 562 lacp_suppress_distributing(lsc, la); 563 564 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; |
565 tp->tp_flags &= ~TRUNK_PORT_DISTRIBUTING; | 565 lgp->lp_flags &= ~LAGG_PORT_DISTRIBUTING; |
566 567 if (lsc->lsc_active_aggregator == la) { 568 lacp_select_active_aggregator(lsc); 569 } 570} 571 572static void 573lacp_enable_distributing(struct lacp_port *lp) 574{ 575 struct lacp_aggregator *la = lp->lp_aggregator; 576 struct lacp_softc *lsc = lp->lp_lsc; | 566 567 if (lsc->lsc_active_aggregator == la) { 568 lacp_select_active_aggregator(lsc); 569 } 570} 571 572static void 573lacp_enable_distributing(struct lacp_port *lp) 574{ 575 struct lacp_aggregator *la = lp->lp_aggregator; 576 struct lacp_softc *lsc = lp->lp_lsc; |
577 struct trunk_port *tp = lp->lp_trunk; | 577 struct lagg_port *lgp = lp->lp_lagg; |
578#if defined(LACP_DEBUG) 579 char buf[LACP_LAGIDSTR_MAX+1]; 580#endif /* defined(LACP_DEBUG) */ 581 | 578#if defined(LACP_DEBUG) 579 char buf[LACP_LAGIDSTR_MAX+1]; 580#endif /* defined(LACP_DEBUG) */ 581 |
582 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 582 LAGG_LOCK_ASSERT(lgp->lp_lagg); |
583 584 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 585 return; 586 } 587 588 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 589 "nports %d -> %d\n", 590 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 591 la->la_nports, la->la_nports + 1)); 592 593 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 594 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 595 la->la_nports++; 596 597 lacp_suppress_distributing(lsc, la); 598 599 lp->lp_state |= LACP_STATE_DISTRIBUTING; | 583 584 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 585 return; 586 } 587 588 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 589 "nports %d -> %d\n", 590 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 591 la->la_nports, la->la_nports + 1)); 592 593 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 594 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 595 la->la_nports++; 596 597 lacp_suppress_distributing(lsc, la); 598 599 lp->lp_state |= LACP_STATE_DISTRIBUTING; |
600 tp->tp_flags |= TRUNK_PORT_DISTRIBUTING; | 600 lgp->lp_flags |= LAGG_PORT_DISTRIBUTING; |
601 602 if (lsc->lsc_active_aggregator != la) { 603 lacp_select_active_aggregator(lsc); 604 } 605} 606 607static void 608lacp_transit_expire(void *vp) 609{ 610 struct lacp_softc *lsc = vp; 611 612 LACP_DPRINTF((NULL, "%s\n", __func__)); 613 lsc->lsc_suppress_distributing = FALSE; 614} 615 616int | 601 602 if (lsc->lsc_active_aggregator != la) { 603 lacp_select_active_aggregator(lsc); 604 } 605} 606 607static void 608lacp_transit_expire(void *vp) 609{ 610 struct lacp_softc *lsc = vp; 611 612 LACP_DPRINTF((NULL, "%s\n", __func__)); 613 lsc->lsc_suppress_distributing = FALSE; 614} 615 616int |
617lacp_attach(struct trunk_softc *tr) | 617lacp_attach(struct lagg_softc *lgs) |
618{ 619 struct lacp_softc *lsc; 620 | 618{ 619 struct lacp_softc *lsc; 620 |
621 TRUNK_LOCK_ASSERT(tr); | 621 LAGG_LOCK_ASSERT(lgs); |
622 623 lsc = malloc(sizeof(struct lacp_softc), 624 M_DEVBUF, M_NOWAIT|M_ZERO); 625 if (lsc == NULL) 626 return (ENOMEM); 627 | 622 623 lsc = malloc(sizeof(struct lacp_softc), 624 M_DEVBUF, M_NOWAIT|M_ZERO); 625 if (lsc == NULL) 626 return (ENOMEM); 627 |
628 tr->tr_psc = (caddr_t)lsc; 629 lsc->lsc_trunk = tr; | 628 lgs->sc_psc = (caddr_t)lsc; 629 lsc->lsc_lagg = lgs; |
630 631 lsc->lsc_hashkey = arc4random(); 632 lsc->lsc_active_aggregator = NULL; 633 TAILQ_INIT(&lsc->lsc_aggregators); 634 LIST_INIT(&lsc->lsc_ports); 635 | 630 631 lsc->lsc_hashkey = arc4random(); 632 lsc->lsc_active_aggregator = NULL; 633 TAILQ_INIT(&lsc->lsc_aggregators); 634 LIST_INIT(&lsc->lsc_ports); 635 |
636 callout_init_mtx(&lsc->lsc_transit_callout, &tr->tr_mtx, 0); 637 callout_init_mtx(&lsc->lsc_callout, &tr->tr_mtx, 0); | 636 callout_init_mtx(&lsc->lsc_transit_callout, &lgs->sc_mtx, 0); 637 callout_init_mtx(&lsc->lsc_callout, &lgs->sc_mtx, 0); |
638 | 638 |
639 /* if the trunk is already up then do the same */ 640 if (tr->tr_ifp->if_drv_flags & IFF_DRV_RUNNING) 641 lacp_init(tr); | 639 /* if the lagg is already up then do the same */ 640 if (lgs->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) 641 lacp_init(lgs); |
642 643 return (0); 644} 645 646int | 642 643 return (0); 644} 645 646int |
647lacp_detach(struct trunk_softc *tr) | 647lacp_detach(struct lagg_softc *lgs) |
648{ | 648{ |
649 struct lacp_softc *lsc = LACP_SOFTC(tr); | 649 struct lacp_softc *lsc = LACP_SOFTC(lgs); |
650 651 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 652 ("aggregators still active")); 653 KASSERT(lsc->lsc_active_aggregator == NULL, 654 ("aggregator still attached")); 655 | 650 651 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 652 ("aggregators still active")); 653 KASSERT(lsc->lsc_active_aggregator == NULL, 654 ("aggregator still attached")); 655 |
656 tr->tr_psc = NULL; | 656 lgs->sc_psc = NULL; |
657 callout_drain(&lsc->lsc_transit_callout); 658 callout_drain(&lsc->lsc_callout); 659 660 free(lsc, M_DEVBUF); 661 return (0); 662} 663 664void | 657 callout_drain(&lsc->lsc_transit_callout); 658 callout_drain(&lsc->lsc_callout); 659 660 free(lsc, M_DEVBUF); 661 return (0); 662} 663 664void |
665lacp_init(struct trunk_softc *tr) | 665lacp_init(struct lagg_softc *lgs) |
666{ | 666{ |
667 struct lacp_softc *lsc = LACP_SOFTC(tr); | 667 struct lacp_softc *lsc = LACP_SOFTC(lgs); |
668 669 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 670} 671 672void | 668 669 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 670} 671 672void |
673lacp_stop(struct trunk_softc *tr) | 673lacp_stop(struct lagg_softc *lgs) |
674{ | 674{ |
675 struct lacp_softc *lsc = LACP_SOFTC(tr); | 675 struct lacp_softc *lsc = LACP_SOFTC(lgs); |
676 677 callout_stop(&lsc->lsc_transit_callout); 678 callout_stop(&lsc->lsc_callout); 679} 680 | 676 677 callout_stop(&lsc->lsc_transit_callout); 678 callout_stop(&lsc->lsc_callout); 679} 680 |
681struct trunk_port * 682lacp_select_tx_port(struct trunk_softc *tr, struct mbuf *m) | 681struct lagg_port * 682lacp_select_tx_port(struct lagg_softc *lgs, struct mbuf *m) |
683{ | 683{ |
684 struct lacp_softc *lsc = LACP_SOFTC(tr); | 684 struct lacp_softc *lsc = LACP_SOFTC(lgs); |
685 struct lacp_aggregator *la; 686 struct lacp_port *lp; 687 uint32_t hash; 688 int nports; 689 | 685 struct lacp_aggregator *la; 686 struct lacp_port *lp; 687 uint32_t hash; 688 int nports; 689 |
690 TRUNK_LOCK_ASSERT(tr); | 690 LAGG_LOCK_ASSERT(lgs); |
691 692 if (__predict_false(lsc->lsc_suppress_distributing)) { 693 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 694 return (NULL); 695 } 696 697 la = lsc->lsc_active_aggregator; 698 if (__predict_false(la == NULL)) { 699 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 700 return (NULL); 701 } 702 703 nports = la->la_nports; 704 KASSERT(nports > 0, ("no ports available")); 705 | 691 692 if (__predict_false(lsc->lsc_suppress_distributing)) { 693 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 694 return (NULL); 695 } 696 697 la = lsc->lsc_active_aggregator; 698 if (__predict_false(la == NULL)) { 699 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 700 return (NULL); 701 } 702 703 nports = la->la_nports; 704 KASSERT(nports > 0, ("no ports available")); 705 |
706 hash = trunk_hashmbuf(m, lsc->lsc_hashkey); | 706 hash = lagg_hashmbuf(m, lsc->lsc_hashkey); |
707 hash %= nports; 708 lp = TAILQ_FIRST(&la->la_ports); 709 while (hash--) { 710 lp = TAILQ_NEXT(lp, lp_dist_q); 711 } 712 713 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 714 ("aggregated port is not distributing")); 715 | 707 hash %= nports; 708 lp = TAILQ_FIRST(&la->la_ports); 709 while (hash--) { 710 lp = TAILQ_NEXT(lp, lp_dist_q); 711 } 712 713 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 714 ("aggregated port is not distributing")); 715 |
716 return (lp->lp_trunk); | 716 return (lp->lp_lagg); |
717} 718/* 719 * lacp_suppress_distributing: drop transmit packets for a while 720 * to preserve packet ordering. 721 */ 722 723static void 724lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) --- 50 unchanged lines hidden (view full) --- 775 lp->lp_media, la->la_nports)); 776 } 777 778 return (speed); 779} 780 781/* 782 * lacp_select_active_aggregator: select an aggregator to be used to transmit | 717} 718/* 719 * lacp_suppress_distributing: drop transmit packets for a while 720 * to preserve packet ordering. 721 */ 722 723static void 724lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) --- 50 unchanged lines hidden (view full) --- 775 lp->lp_media, la->la_nports)); 776 } 777 778 return (speed); 779} 780 781/* 782 * lacp_select_active_aggregator: select an aggregator to be used to transmit |
783 * packets from trunk(4) interface. | 783 * packets from lagg(4) interface. |
784 */ 785 786static void 787lacp_select_active_aggregator(struct lacp_softc *lsc) 788{ 789 struct lacp_aggregator *la; 790 struct lacp_aggregator *best_la = NULL; 791 uint64_t best_speed = 0; --- 46 unchanged lines hidden (view full) --- 838 lacp_suppress_distributing(lsc, best_la); 839 } 840 } 841} 842 843static uint16_t 844lacp_compose_key(struct lacp_port *lp) 845{ | 784 */ 785 786static void 787lacp_select_active_aggregator(struct lacp_softc *lsc) 788{ 789 struct lacp_aggregator *la; 790 struct lacp_aggregator *best_la = NULL; 791 uint64_t best_speed = 0; --- 46 unchanged lines hidden (view full) --- 838 lacp_suppress_distributing(lsc, best_la); 839 } 840 } 841} 842 843static uint16_t 844lacp_compose_key(struct lacp_port *lp) 845{ |
846 struct trunk_port *tp = lp->lp_trunk; 847 struct trunk_softc *tr = tp->tp_trunk; | 846 struct lagg_port *lgp = lp->lp_lagg; 847 struct lagg_softc *lgs = lgp->lp_lagg; |
848 u_int media = lp->lp_media; 849 uint16_t key; 850 851 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid interface type")); 852 853 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 854 855 /* --- 8 unchanged lines hidden (view full) --- 864 key |= 0x8000; 865 } else { 866 u_int subtype = IFM_SUBTYPE(media); 867 868 KASSERT((media & IFM_HDX) == 0, ("aggregating HDX interface")); 869 870 /* bit 0..4: IFM_SUBTYPE */ 871 key = subtype; | 848 u_int media = lp->lp_media; 849 uint16_t key; 850 851 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid interface type")); 852 853 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 854 855 /* --- 8 unchanged lines hidden (view full) --- 864 key |= 0x8000; 865 } else { 866 u_int subtype = IFM_SUBTYPE(media); 867 868 KASSERT((media & IFM_HDX) == 0, ("aggregating HDX interface")); 869 870 /* bit 0..4: IFM_SUBTYPE */ 871 key = subtype; |
872 /* bit 5..14: (some bits of) if_index of trunk device */ 873 key |= 0x7fe0 & ((tr->tr_ifp->if_index) << 5); | 872 /* bit 5..14: (some bits of) if_index of lagg device */ 873 key |= 0x7fe0 & ((lgs->sc_ifp->if_index) << 5); |
874 /* bit 15: 0 */ 875 } 876 return (htons(key)); 877} 878 879static void 880lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 881{ --- 642 unchanged lines hidden (view full) --- 1524 if (lacp_timer_funcs[i]) { 1525 (*lacp_timer_funcs[i])(lp); 1526 } 1527 } 1528 } 1529} 1530 1531int | 874 /* bit 15: 0 */ 875 } 876 return (htons(key)); 877} 878 879static void 880lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 881{ --- 642 unchanged lines hidden (view full) --- 1524 if (lacp_timer_funcs[i]) { 1525 (*lacp_timer_funcs[i])(lp); 1526 } 1527 } 1528 } 1529} 1530 1531int |
1532lacp_marker_input(struct trunk_port *tp, struct mbuf *m) | 1532lacp_marker_input(struct lagg_port *lgp, struct mbuf *m) |
1533{ | 1533{ |
1534 struct lacp_port *lp = LACP_PORT(tp); | 1534 struct lacp_port *lp = LACP_PORT(lgp); |
1535 struct markerdu *mdu; 1536 int error = 0; 1537 | 1535 struct markerdu *mdu; 1536 int error = 0; 1537 |
1538 TRUNK_LOCK_ASSERT(tp->tp_trunk); | 1538 LAGG_LOCK_ASSERT(lgp->lp_lagg); |
1539 1540 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 1541 goto bad; 1542 } 1543 1544 if (m->m_pkthdr.len != sizeof(*mdu)) { 1545 goto bad; 1546 } --- 30 unchanged lines hidden (view full) --- 1577 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1578 marker_info_tlv_template, TRUE)) { 1579 goto bad; 1580 } 1581 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1582 memcpy(&mdu->mdu_eh.ether_dhost, 1583 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1584 memcpy(&mdu->mdu_eh.ether_shost, | 1539 1540 if (__predict_false(lp->lp_flags & LACP_PORT_DETACHING)) { 1541 goto bad; 1542 } 1543 1544 if (m->m_pkthdr.len != sizeof(*mdu)) { 1545 goto bad; 1546 } --- 30 unchanged lines hidden (view full) --- 1577 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1578 marker_info_tlv_template, TRUE)) { 1579 goto bad; 1580 } 1581 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1582 memcpy(&mdu->mdu_eh.ether_dhost, 1583 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1584 memcpy(&mdu->mdu_eh.ether_shost, |
1585 tp->tp_lladdr, ETHER_ADDR_LEN); 1586 error = trunk_enqueue(lp->lp_ifp, m); | 1585 lgp->lp_lladdr, ETHER_ADDR_LEN); 1586 error = lagg_enqueue(lp->lp_ifp, m); |
1587 break; 1588 1589 case MARKER_TYPE_RESPONSE: 1590 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1591 marker_response_tlv_template, TRUE)) { 1592 goto bad; 1593 } 1594 /* --- 169 unchanged lines hidden --- | 1587 break; 1588 1589 case MARKER_TYPE_RESPONSE: 1590 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1591 marker_response_tlv_template, TRUE)) { 1592 goto bad; 1593 } 1594 /* --- 169 unchanged lines hidden --- |