Deleted Added
full compact
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(&ethermulticastaddr_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(&ethermulticastaddr_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(&ethermulticastaddr_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(&ethermulticastaddr_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 &ethermulticastaddr_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 &ethermulticastaddr_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 ---