if_lagg_lacp.c revision 1.7 1 /* $NetBSD: if_lagg_lacp.c,v 1.7 2021/11/16 04:01:11 yamaguchi Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
5 *
6 * Copyright (c)2005 YAMAMOTO Takashi,
7 * Copyright (c)2008 Andrew Thompson <thompsa (at) FreeBSD.org>
8 * Copyright (c)2021 Internet Initiative Japan, Inc.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.7 2021/11/16 04:01:11 yamaguchi Exp $");
35
36 #ifdef _KERNEL_OPT
37 #include "opt_lagg.h"
38 #endif
39
40 #include <sys/param.h>
41 #include <sys/types.h>
42
43 #include <sys/evcnt.h>
44 #include <sys/kmem.h>
45 #include <sys/pslist.h>
46 #include <sys/sysctl.h>
47 #include <sys/syslog.h>
48 #include <sys/workqueue.h>
49
50 #include <net/if.h>
51 #include <net/if_dl.h>
52 #include <net/if_ether.h>
53 #include <net/if_media.h>
54
55 #include <net/lagg/if_lagg.h>
56 #include <net/lagg/if_laggproto.h>
57 #include <net/lagg/if_lagg_lacp.h>
58
59 #define LACP_SYSTEMIDSTR_LEN 32
60
61 enum {
62 LACP_TIMER_CURRENT_WHILE = 0,
63 LACP_TIMER_PERIODIC,
64 LACP_TIMER_WAIT_WHILE,
65 LACP_NTIMER
66 };
67
68 enum {
69 LACP_PTIMER_DISTRIBUTING = 0,
70 LACP_NPTIMER
71 };
72
73 enum lacp_selected {
74 LACP_UNSELECTED,
75 LACP_STANDBY,
76 LACP_SELECTED,
77 };
78
79 enum lacp_mux_state {
80 LACP_MUX_DETACHED,
81 LACP_MUX_WAITING,
82 LACP_MUX_STANDBY,
83 LACP_MUX_ATTACHED,
84 LACP_MUX_COLLECTING,
85 LACP_MUX_DISTRIBUTING,
86 LACP_MUX_INIT,
87 };
88
89 struct lacp_aggregator_systemid {
90 uint16_t sid_prio;
91 uint16_t sid_key;
92 uint8_t sid_mac[LACP_MAC_LEN];
93 };
94
95 struct lacp_aggregator {
96 TAILQ_ENTRY(lacp_aggregator)
97 la_q;
98 LIST_HEAD(, lacp_port)
99 la_ports;
100 ssize_t la_attached_port;
101
102 struct lacp_aggregator_systemid
103 la_sid;
104 };
105
106 struct lacp_portinfo {
107 uint8_t lpi_state;
108 uint16_t lpi_portno;
109 #define LACP_PORTNO_NONE 0
110 uint16_t lpi_portprio;
111 };
112
113 struct lacp_port {
114 struct lagg_port *lp_laggport;
115 bool lp_added_multi;
116 int lp_timer[LACP_NTIMER];
117 uint32_t lp_marker_xid;
118 enum lacp_selected lp_selected;
119 enum lacp_mux_state lp_mux_state;
120
121 struct lacp_portinfo lp_actor;
122 struct lacp_portinfo lp_partner;
123 struct lacp_aggregator *lp_aggregator;
124 struct lacp_aggregator_systemid
125 lp_aggregator_sidbuf;
126 uint32_t lp_media;
127 int lp_pending;
128 LIST_ENTRY(lacp_port) lp_entry_la;
129 struct timeval lp_last_lacpdu;
130 int lp_lacpdu_sent;
131 bool lp_collector;
132
133 unsigned int lp_flags;
134 #define LACP_PORT_NTT __BIT(0)
135 #define LACP_PORT_MARK __BIT(1)
136
137 struct lagg_work lp_work_smtx;
138 struct lagg_work lp_work_marker;
139 };
140
141 struct lacp_portmap {
142 size_t pm_count;
143 struct lagg_port *pm_ports[LACP_MAX_PORTS];
144 };
145
146 struct lacp_softc {
147 struct lagg_softc *lsc_softc;
148 kmutex_t lsc_lock;
149 pserialize_t lsc_psz;
150 bool lsc_running;
151 bool lsc_suppress_distributing;
152 int lsc_timer[LACP_NPTIMER];
153 uint8_t lsc_system_mac[LACP_MAC_LEN];
154 uint16_t lsc_system_prio;
155 uint16_t lsc_key;
156 size_t lsc_max_ports;
157 size_t lsc_activemap;
158 struct lacp_portmap lsc_portmaps[2]; /* active & idle */
159 struct lacp_aggregator *lsc_aggregator;
160 TAILQ_HEAD(, lacp_aggregator)
161 lsc_aggregators;
162 struct workqueue *lsc_workq;
163 struct lagg_work lsc_work_tick;
164 callout_t lsc_tick;
165
166 char lsc_evgroup[32];
167 struct evcnt lsc_mgethdr_failed;
168 struct evcnt lsc_mpullup_failed;
169 struct evcnt lsc_badlacpdu;
170 struct evcnt lsc_badmarkerdu;
171
172 bool lsc_optimistic;
173 bool lsc_stop_lacpdu;
174 bool lsc_dump_du;
175 bool lsc_multi_linkspeed;
176 };
177
178 /*
179 * Locking notes:
180 * - Items in struct lacp_softc are protected by
181 * lsc_lock (an adaptive mutex)
182 * - lsc_activemap is protected by pserialize (lsc_psz)
183 * - Items of struct lagg_port in lsc_portmaps are protected by
184 * protected by both pserialize (lsc_psz) and psref (lp_psref)
185 * - Updates for lsc_activemap and lsc_portmaps is serialized by
186 * sc_lock in struct lagg_softc
187 * - Other locking notes are described in if_laggproto.h
188 */
189
190 static void lacp_dprintf(const struct lacp_softc *,
191 const struct lacp_port *, const char *, ...)
192 __attribute__((__format__(__printf__, 3, 4)));
193
194 #ifdef LACP_DEBUG
195 #define LACP_DPRINTF(a) do { lacp_dprintf a; } while (/*CONSTCOND*/ 0)
196 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) \
197 lacp_peerinfo_idstr(_pi, _b, _bs)
198 #define LACP_STATE_STR(_s, _b, _bs) lacp_state_str(_s, _b, _bs)
199 #define LACP_AGGREGATOR_STR(_a, _b, _bs) \
200 lacp_aggregator_str(_a, _b, _bs)
201 #define __LACPDEBUGUSED
202 #else
203 #define LACP_DPRINTF(a) __nothing
204 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) __nothing
205 #define LACP_STATE_STR(_s, _b, _bs) __nothing
206 #define LACP_AGGREGATOR_STR(_a, _b, _bs) __nothing
207 #define __LACPDEBUGUSED __unused
208 #endif
209
210 #define LACP_LOCK(_sc) mutex_enter(&(_sc)->lsc_lock)
211 #define LACP_UNLOCK(_sc) mutex_exit(&(_sc)->lsc_lock)
212 #define LACP_LOCKED(_sc) mutex_owned(&(_sc)->lsc_lock)
213 #define LACP_LINKSTATE(_sc, _lp) \
214 lacp_linkstate((struct lagg_proto_softc *)(_sc), (_lp))
215 #define LACP_TIMER_ARM(_lacpp, _timer, _val) \
216 (_lacpp)->lp_timer[(_timer)] = (_val)
217 #define LACP_TIMER_DISARM(_lacpp, _timer) \
218 LACP_TIMER_ARM((_lacpp), (_timer), 0)
219 #define LACP_TIMER_ISARMED(_lacpp, _timer) \
220 ((_lacpp)->lp_timer[(_timer)] > 0)
221 #define LACP_PTIMER_ARM(_sc, _timer, _val) \
222 (_sc)->lsc_timer[(_timer)] = (_val)
223 #define LACP_PTIMER_DISARM(_sc, _timer) \
224 LACP_PTIMER_ARM((_sc), (_timer), 0)
225 #define LACP_PTIMER_ISARMED(_sc, _timer) \
226 ((_sc)->lsc_timer[(_timer)] > 0)
227 #define LACP_STATE_EQ(_s1, _s2, _mask) (!ISSET((_s1) ^ (_s2), (_mask)))
228 #define LACP_PORT_XNAME(_lacpp) (_lacpp != NULL) ? \
229 (_lacpp)->lp_laggport->lp_ifp->if_xname : "(unknown)"
230 #define LACP_ISDUMPING(_sc) (_sc)->lsc_dump_du
231 #define LACP_PORTMAP_ACTIVE(_sc) \
232 atomic_load_consume(&(_sc)->lsc_activemap)
233 #define LACP_PORTMAP_NEXT(_sc) \
234 (((LACP_PORTMAP_ACTIVE((_sc))) ^ 0x01) &0x01)
235 #define LACP_SYS_PRI(_la) ntohs((_la)->la_sid.sid_prio)
236 #define LACP_TLV_PARSE(_du, _st, _name, _tlvlist) \
237 tlv_parse(&(_du)->_name, \
238 sizeof(_st) - offsetof(_st, _name), \
239 (_tlvlist))
240
241 static void lacp_tick(void *);
242 static void lacp_tick_work(struct lagg_work *, void *);
243 static uint32_t lacp_ifmedia2lacpmedia(u_int);
244 static void lacp_port_disable(struct lacp_softc *, struct lacp_port *);
245 static void lacp_port_enable(struct lacp_softc *, struct lacp_port *);
246 static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *,
247 struct lacpdu_peerinfo *);
248 static void lacp_peerinfo_partner(struct lacp_port *,
249 struct lacpdu_peerinfo *);
250 static struct lagg_port *
251 lacp_select_tx_port(struct lacp_softc *, struct mbuf *,
252 struct psref *);
253 static void lacp_suppress_distributing(struct lacp_softc *);
254 static void lacp_distributing_timer(struct lacp_softc *);
255
256 static void lacp_select(struct lacp_softc *, struct lacp_port *);
257 static void lacp_unselect(struct lacp_softc *, struct lacp_port *);
258 static void lacp_selected_update(struct lacp_softc *,
259 struct lacp_aggregator *);
260 static void lacp_sm_port_init(struct lacp_softc *,
261 struct lacp_port *, struct lagg_port *);
262 static int lacp_set_mux(struct lacp_softc *,
263 struct lacp_port *, enum lacp_mux_state);
264 static void lacp_sm_mux(struct lacp_softc *, struct lacp_port *);
265 static void lacp_sm_mux_timer(struct lacp_softc *, struct lacp_port *);
266 static void lacp_sm_rx(struct lacp_softc *, struct lacp_port *,
267 struct lacpdu_peerinfo *, struct lacpdu_peerinfo *);
268 static void lacp_sm_rx_set_expired(struct lacp_port *);
269 static void lacp_sm_rx_timer(struct lacp_softc *, struct lacp_port *);
270 static void lacp_sm_rx_record_default(struct lacp_softc *,
271 struct lacp_port *);
272
273 static void lacp_sm_tx(struct lacp_softc *, struct lacp_port *);
274 static void lacp_sm_tx_work(struct lagg_work *, void *);
275 static void lacp_sm_ptx_timer(struct lacp_softc *, struct lacp_port *);
276 static void lacp_sm_ptx_schedule(struct lacp_port *);
277 static void lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t);
278
279 static void lacp_marker_work(struct lagg_work *, void *);
280 static void lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *,
281 const struct lacpdu_peerinfo *,
282 const struct lacpdu_collectorinfo *);
283 static void lacp_dump_markertlv(const struct markerdu_info *,
284 const struct markerdu_info *);
285
286 typedef void (*lacp_timer_func_t)(struct lacp_softc *, struct lacp_port *);
287 static const lacp_timer_func_t lacp_timer_funcs[] = {
288 [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer,
289 [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer,
290 [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer,
291 };
292 typedef void (*lacp_prototimer_func_t)(struct lacp_softc *);
293 static const lacp_prototimer_func_t lacp_ptimer_funcs[] = {
294 [LACP_PTIMER_DISTRIBUTING] = lacp_distributing_timer,
295 };
296
297 static void
298 lacp_dprintf(const struct lacp_softc *lsc, const struct lacp_port *lacpp,
299 const char *fmt, ...)
300 {
301 struct lagg_softc *sc;
302 va_list va;
303
304 if (lsc != NULL && lsc->lsc_softc != NULL) {
305 sc = lsc->lsc_softc;
306 printf("%s", sc->sc_if.if_xname);
307 } else {
308 printf("lacp");
309 }
310
311 if (lacpp != NULL)
312 printf("(%s)", LACP_PORT_XNAME(lacpp));
313
314 printf(": ");
315
316 va_start(va, fmt);
317 vprintf(fmt, va);
318 va_end(va);
319 }
320
321 static inline void
322 lacp_evcnt_attach(struct lacp_softc *lsc,
323 struct evcnt *ev, const char *name)
324 {
325
326 evcnt_attach_dynamic(ev, EVCNT_TYPE_MISC, NULL,
327 lsc->lsc_evgroup, name);
328 }
329
330 static inline bool
331 lacp_iscollecting(struct lacp_port *lacpp)
332 {
333
334 return atomic_load_relaxed(&lacpp->lp_collector);
335 }
336
337 static inline bool
338 lacp_isdistributing(struct lacp_port *lacpp)
339 {
340
341 return ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
342 }
343
344 static inline bool
345 lacp_isactive(struct lacp_softc *lsc, struct lacp_port *lacpp)
346 {
347
348 if (lacpp->lp_selected != LACP_SELECTED)
349 return false;
350
351 if (lacpp->lp_aggregator == NULL)
352 return false;
353
354 if (lacpp->lp_aggregator != lsc->lsc_aggregator)
355 return false;
356
357 return true;
358 }
359
360 static inline void
361 lacp_mcastaddr(struct ifreq *ifr, const char *if_xname)
362 {
363 static const uint8_t addr[ETHER_ADDR_LEN] =
364 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
365
366 memset(ifr, 0, sizeof(*ifr));
367
368 strlcpy(ifr->ifr_name, if_xname,
369 sizeof(ifr->ifr_name));
370 ifr->ifr_addr.sa_len = sizeof(ifr->ifr_addr);
371 ifr->ifr_addr.sa_family = AF_UNSPEC;
372
373 KASSERT(sizeof(ifr->ifr_addr) >= sizeof(addr));
374 memcpy(&ifr->ifr_addr.sa_data, addr, sizeof(addr));
375 }
376
377 static inline u_int
378 lacp_portmap_linkstate(struct lacp_portmap *pm)
379 {
380
381 if (pm->pm_count == 0)
382 return LINK_STATE_DOWN;
383
384 return LINK_STATE_UP;
385 }
386
387 static inline struct lacp_port *
388 lacp_port_priority_max(struct lacp_port *a, struct lacp_port *b)
389 {
390 uint16_t pri_a, pri_b;
391
392 pri_a = ntohs(a->lp_actor.lpi_portprio);
393 pri_b = ntohs(b->lp_actor.lpi_portprio);
394
395 if (pri_a < pri_b)
396 return a;
397 if (pri_b < pri_a)
398 return b;
399
400 pri_a = ntohs(a->lp_partner.lpi_portprio);
401 pri_b = ntohs(b->lp_partner.lpi_portprio);
402
403 if (pri_a < pri_b)
404 return a;
405 if (pri_b < pri_a)
406 return b;
407
408 if (a->lp_media > b->lp_media)
409 return a;
410 if (b->lp_media > a->lp_media)
411 return b;
412
413 return a;
414 }
415
416 static void
417 tlv_parse(void *vp, size_t len, struct tlv *list)
418 {
419 struct tlvhdr *th;
420 uint8_t *p;
421 size_t l, i;
422
423 th = (struct tlvhdr *)vp;
424 p = (uint8_t *)vp;
425
426 for (l = 0; l < len; l += th->tlv_length) {
427 th = (struct tlvhdr *)(p + l);
428
429 if (th->tlv_type == TLV_TYPE_TERMINATE)
430 break;
431
432 for (i = 0; list[i].tlv_t != TLV_TYPE_TERMINATE; i++) {
433 if (th->tlv_type != list[i].tlv_t)
434 continue;
435
436 if (th->tlv_length - sizeof(*th) != list[i].tlv_l)
437 break;
438
439 if (list[i].tlv_v == NULL) {
440 list[i].tlv_v =
441 (void *)((uint8_t *)th + sizeof(*th));
442 }
443
444 break;
445 }
446 }
447 }
448
449 int
450 lacp_attach(struct lagg_softc *sc, struct lagg_proto_softc **lscp)
451 {
452 struct lacp_softc *lsc;
453 char xnamebuf[MAXCOMLEN];
454 int error;
455
456 KASSERT(LAGG_LOCKED(sc));
457
458 lsc = kmem_zalloc(sizeof(*lsc), KM_NOSLEEP);
459 if (lsc == NULL)
460 return ENOMEM;
461
462 mutex_init(&lsc->lsc_lock, MUTEX_DEFAULT, IPL_SOFTNET);
463 lsc->lsc_softc = sc;
464 lsc->lsc_key = htons(if_get_index(&sc->sc_if));
465 lsc->lsc_system_prio = htons(LACP_SYSTEM_PRIO);
466 lsc->lsc_running = false;
467 lsc->lsc_max_ports = LACP_MAX_PORTS;
468 lsc->lsc_multi_linkspeed = true;
469 TAILQ_INIT(&lsc->lsc_aggregators);
470
471 lagg_work_set(&lsc->lsc_work_tick, lacp_tick_work, lsc);
472 snprintf(xnamebuf, sizeof(xnamebuf), "%s.lacp",
473 sc->sc_if.if_xname);
474 lsc->lsc_workq = lagg_workq_create(xnamebuf,
475 PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
476 if (lsc->lsc_workq == NULL) {
477 lagg_log(sc, LOG_ERR, "workqueue create failed\n");
478 error = ENOMEM;
479 goto destroy_lock;
480 }
481
482 lsc->lsc_psz = pserialize_create();
483
484 callout_init(&lsc->lsc_tick, CALLOUT_MPSAFE);
485 callout_setfunc(&lsc->lsc_tick, lacp_tick, lsc);
486
487 snprintf(lsc->lsc_evgroup, sizeof(lsc->lsc_evgroup),
488 "%s-lacp", sc->sc_if.if_xname);
489 lacp_evcnt_attach(lsc, &lsc->lsc_mgethdr_failed, "MGETHDR failed");
490 lacp_evcnt_attach(lsc, &lsc->lsc_mpullup_failed, "m_pullup failed");
491 lacp_evcnt_attach(lsc, &lsc->lsc_badlacpdu, "Bad LACPDU recieved");
492 lacp_evcnt_attach(lsc, &lsc->lsc_badmarkerdu, "Bad MarkerDU recieved");
493
494 if_link_state_change(&sc->sc_if, LINK_STATE_DOWN);
495
496 *lscp = (struct lagg_proto_softc *)lsc;
497 return 0;
498
499 destroy_lock:
500 mutex_destroy(&lsc->lsc_lock);
501
502 return error;
503 }
504
505 void
506 lacp_detach(struct lagg_proto_softc *xlsc)
507 {
508 struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
509 struct lagg_softc *sc __diagused = lsc->lsc_softc;
510
511 KASSERT(LAGG_LOCKED(lsc->lsc_softc));
512 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators));
513 KASSERT(SIMPLEQ_EMPTY(&sc->sc_ports));
514
515 lacp_down(xlsc);
516
517 evcnt_detach(&lsc->lsc_mgethdr_failed);
518 evcnt_detach(&lsc->lsc_mpullup_failed);
519 evcnt_detach(&lsc->lsc_badlacpdu);
520 evcnt_detach(&lsc->lsc_badmarkerdu);
521 lagg_workq_destroy(lsc->lsc_workq);
522 pserialize_destroy(lsc->lsc_psz);
523 mutex_destroy(&lsc->lsc_lock);
524 kmem_free(lsc, sizeof(*lsc));
525 }
526
527 int
528 lacp_up(struct lagg_proto_softc *xlsc)
529 {
530 struct lagg_softc *sc;
531 struct lagg_port *lp;
532 struct lacp_softc *lsc;
533
534 lsc = (struct lacp_softc *)xlsc;
535 sc = lsc->lsc_softc;
536
537 KASSERT(LAGG_LOCKED(sc));
538
539 LACP_LOCK(lsc);
540 if (memcmp(lsc->lsc_system_mac, LAGG_CLLADDR(sc),
541 sizeof(lsc->lsc_system_mac)) != 0) {
542 memcpy(lsc->lsc_system_mac, LAGG_CLLADDR(sc),
543 sizeof(lsc->lsc_system_mac));
544 }
545 lsc->lsc_running = true;
546 callout_schedule(&lsc->lsc_tick, hz);
547 LACP_UNLOCK(lsc);
548
549 LAGG_PORTS_FOREACH(sc, lp) {
550 lacp_linkstate(xlsc, lp);
551 }
552
553 LACP_DPRINTF((lsc, NULL, "lacp start\n"));
554
555 return 0;
556 }
557
558 static void
559 lacp_down_locked(struct lacp_softc *lsc)
560 {
561 struct lagg_softc *sc;
562 struct lagg_port *lp;
563
564 sc = lsc->lsc_softc;
565
566 KASSERT(LAGG_LOCKED(sc));
567 KASSERT(LACP_LOCKED(lsc));
568
569 lsc->lsc_running = false;
570 callout_halt(&lsc->lsc_tick, &lsc->lsc_lock);
571
572 LAGG_PORTS_FOREACH(sc, lp) {
573 lacp_port_disable(lsc, lp->lp_proto_ctx);
574 }
575
576 memset(lsc->lsc_system_mac, 0,
577 sizeof(lsc->lsc_system_mac));
578
579 LACP_DPRINTF((lsc, NULL, "lacp stopped\n"));
580 }
581
582 void
583 lacp_down(struct lagg_proto_softc *xlsc)
584 {
585 struct lacp_softc *lsc;
586
587 lsc = (struct lacp_softc *)xlsc;
588
589 KASSERT(LAGG_LOCKED(lsc->lsc_softc));
590
591 LACP_LOCK(lsc);
592 lacp_down_locked(lsc);
593 LACP_UNLOCK(lsc);
594 }
595
596 int
597 lacp_transmit(struct lagg_proto_softc *xlsc, struct mbuf *m)
598 {
599 struct lacp_softc *lsc;
600 struct lagg_port *lp;
601 struct ifnet *ifp;
602 struct psref psref;
603
604 lsc = (struct lacp_softc *)xlsc;
605
606 if (__predict_false(lsc->lsc_suppress_distributing)) {
607 LACP_DPRINTF((lsc, NULL, "waiting transit\n"));
608 m_freem(m);
609 return ENOBUFS;
610 }
611
612 lp = lacp_select_tx_port(lsc, m, &psref);
613 if (__predict_false(lp == NULL)) {
614 LACP_DPRINTF((lsc, NULL, "no distributing port\n"));
615 ifp = &lsc->lsc_softc->sc_if;
616 if_statinc(ifp, if_oerrors);
617 m_freem(m);
618 return ENOENT;
619 }
620
621 lagg_enqueue(lsc->lsc_softc, lp, m);
622 lagg_port_putref(lp, &psref);
623
624 return 0;
625 }
626
627 int
628 lacp_allocport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
629 {
630 struct lagg_softc *sc;
631 struct lacp_softc *lsc;
632 struct lacp_port *lacpp;
633 struct ifreq ifr;
634 bool added_multi;
635 int error;
636
637 lsc = (struct lacp_softc *)xlsc;
638 sc = lsc->lsc_softc;
639
640 KASSERT(LAGG_LOCKED(sc));
641
642 IFNET_LOCK(lp->lp_ifp);
643 lacp_mcastaddr(&ifr, lp->lp_ifp->if_xname);
644 error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr);
645 IFNET_UNLOCK(lp->lp_ifp);
646
647 switch (error) {
648 case 0:
649 added_multi = true;
650 break;
651 case EAFNOSUPPORT:
652 added_multi = false;
653 break;
654 default:
655 lagg_log(sc, LOG_ERR, "SIOCADDMULTI failed on %s\n",
656 lp->lp_ifp->if_xname);
657 return error;
658 }
659
660 lacpp = kmem_zalloc(sizeof(*lacpp), KM_NOSLEEP);
661 if (lacpp == NULL)
662 return ENOMEM;
663
664 lacpp->lp_added_multi = added_multi;
665 lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc);
666 lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc);
667
668 LACP_LOCK(lsc);
669 lacp_sm_port_init(lsc, lacpp, lp);
670 LACP_UNLOCK(lsc);
671
672 lp->lp_proto_ctx = (void *)lacpp;
673 lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio);
674 LACP_LINKSTATE(lsc, lp);
675
676 return 0;
677 }
678
679 void
680 lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
681 {
682 struct lacp_port *lacpp;
683 uint16_t prio;
684
685 lacpp = lp->lp_proto_ctx;
686
687 prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX);
688 lacpp->lp_actor.lpi_portprio = htons(prio);
689
690 LACP_LINKSTATE((struct lacp_softc *)xlsc, lp);
691 }
692
693 void
694 lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
695 {
696 struct lacp_softc *lsc;
697 struct lacp_port *lacpp;
698 int i;
699
700 lsc = (struct lacp_softc *)xlsc;
701 lacpp = lp->lp_proto_ctx;
702
703 KASSERT(LAGG_LOCKED(lsc->lsc_softc));
704
705 LACP_LOCK(lsc);
706 for (i = 0; i < LACP_NTIMER; i++) {
707 LACP_TIMER_DISARM(lacpp, i);
708 }
709
710 lacp_port_disable(lsc, lacpp);
711 LACP_UNLOCK(lsc);
712 }
713
714 void
715 lacp_freeport(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
716 {
717 struct lacp_softc *lsc;
718 struct lacp_port *lacpp;
719 struct ifreq ifr;
720
721 lsc = (struct lacp_softc *)xlsc;
722 lacpp = lp->lp_proto_ctx;
723
724 KASSERT(LAGG_LOCKED(lsc->lsc_softc));
725
726 lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx);
727 lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker);
728
729 if (lacpp->lp_added_multi) {
730 lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp));
731
732 IFNET_LOCK(lp->lp_ifp);
733 (void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr);
734 IFNET_UNLOCK(lp->lp_ifp);
735 }
736
737 lp->lp_proto_ctx = NULL;
738 kmem_free(lacpp, sizeof(*lacpp));
739 }
740
741 void
742 lacp_protostat(struct lagg_proto_softc *xlsc, struct laggreqproto *resp)
743 {
744 struct laggreq_lacp *rplacp;
745 struct lacp_softc *lsc;
746 struct lacp_aggregator *la;
747 struct lacp_aggregator_systemid *sid;
748
749 lsc = (struct lacp_softc *)xlsc;
750
751 LACP_LOCK(lsc);
752 la = lsc->lsc_aggregator;
753 rplacp = &resp->rp_lacp;
754
755 if (lsc->lsc_optimistic)
756 SET(rplacp->flags, LAGGREQLACP_OPTIMISTIC);
757 if (lsc->lsc_dump_du)
758 SET(rplacp->flags, LAGGREQLACP_DUMPDU);
759 if (lsc->lsc_stop_lacpdu)
760 SET(rplacp->flags, LAGGREQLACP_STOPDU);
761 if (lsc->lsc_multi_linkspeed)
762 SET(rplacp->flags, LAGGREQLACP_MULTILS);
763
764 rplacp->maxports = lsc->lsc_max_ports;
765 rplacp->actor_prio = ntohs(lsc->lsc_system_prio);
766 memcpy(rplacp->actor_mac, lsc->lsc_system_mac,
767 sizeof(rplacp->actor_mac));
768 rplacp->actor_key = ntohs(lsc->lsc_key);
769
770 if (la != NULL) {
771 sid = &la->la_sid;
772 rplacp->partner_prio = ntohs(sid->sid_prio);
773 memcpy(rplacp->partner_mac, sid->sid_mac,
774 sizeof(rplacp->partner_mac));
775 rplacp->partner_key = ntohs(sid->sid_key);
776 }
777 LACP_UNLOCK(lsc);
778 }
779
780 void
781 lacp_portstat(struct lagg_proto_softc *xlsc, struct lagg_port *lp,
782 struct laggreqport *resp)
783 {
784 struct laggreq_lacpport *llp;
785 struct lacp_softc *lsc;
786 struct lacp_port *lacpp;
787 struct lacp_aggregator *la;
788 struct lacp_aggregator_systemid *sid;
789
790 lsc = (struct lacp_softc *)xlsc;
791 lacpp = lp->lp_proto_ctx;
792 la = lacpp->lp_aggregator;
793 llp = &resp->rp_lacpport;
794
795 if (lacp_isactive(lsc, lacpp))
796 SET(resp->rp_flags, LAGG_PORT_ACTIVE);
797 if (lacp_iscollecting(lacpp))
798 SET(resp->rp_flags, LAGG_PORT_COLLECTING);
799 if (lacp_isdistributing(lacpp))
800 SET(resp->rp_flags, LAGG_PORT_DISTRIBUTING);
801 if (lacpp->lp_selected == LACP_STANDBY)
802 SET(resp->rp_flags, LAGG_PORT_STANDBY);
803
804 if (la != NULL) {
805 sid = &la->la_sid;
806 llp->partner_prio = ntohs(sid->sid_prio);
807 memcpy(llp->partner_mac, sid->sid_mac,
808 sizeof(llp->partner_mac));
809 llp->partner_key = ntohs(sid->sid_key);
810 }
811
812 llp->actor_portprio = ntohs(lacpp->lp_actor.lpi_portprio);
813 llp->actor_portno = ntohs(lacpp->lp_actor.lpi_portno);
814 llp->actor_state = lacpp->lp_actor.lpi_state;
815
816 llp->partner_portprio = ntohs(lacpp->lp_partner.lpi_portprio);
817 llp->partner_portno = ntohs(lacpp->lp_partner.lpi_portno);
818 llp->partner_state = lacpp->lp_partner.lpi_state;
819 }
820
821 void
822 lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp)
823 {
824 struct lacp_softc *lsc;
825 struct lacp_port *lacpp;
826 struct ifmediareq ifmr;
827 struct ifnet *ifp_port;
828 uint8_t old_state;
829 uint32_t media, old_media;
830 int error;
831
832 lsc = (struct lacp_softc *)xlsc;
833
834 ifp_port = lp->lp_ifp;
835 lacpp = lp->lp_proto_ctx;
836 media = LACP_MEDIA_DEFAULT;
837
838 memset(&ifmr, 0, sizeof(ifmr));
839 ifmr.ifm_count = 0;
840 error = ifp_port->if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr);
841 if (error == 0) {
842 media = lacp_ifmedia2lacpmedia(ifmr.ifm_active);
843 } else if (error != ENOTTY){
844 LACP_DPRINTF((lsc, lacpp,
845 "SIOCGIFMEDIA failed (%d)\n", error));
846 return;
847 }
848
849 LACP_LOCK(lsc);
850 if (lsc->lsc_running) {
851 old_media = lacpp->lp_media;
852 old_state = lacpp->lp_actor.lpi_state;
853
854 if (lacpp->lp_media != media) {
855 LACP_DPRINTF((lsc, lacpp,
856 "media changed 0x%"PRIx32"->0x%"PRIx32", "
857 "ether = %d, fdx = %d, link = %d, running = %d\n",
858 lacpp->lp_media, media,
859 ISSET(media, LACP_MEDIA_ETHER) != 0,
860 ISSET(media, LACP_MEDIA_FDX) != 0,
861 ifp_port->if_link_state != LINK_STATE_DOWN,
862 ISSET(ifp_port->if_flags, IFF_RUNNING) != 0));
863 lacpp->lp_media = media;
864 }
865
866 if (ISSET(media, LACP_MEDIA_ETHER) &&
867 ISSET(media, LACP_MEDIA_FDX) &&
868 ifp_port->if_link_state != LINK_STATE_DOWN &&
869 ISSET(ifp_port->if_flags, IFF_RUNNING)) {
870 lacp_port_enable(lsc, lacpp);
871 } else {
872 lacp_port_disable(lsc, lacpp);
873 }
874
875 if (old_state != lacpp->lp_actor.lpi_state ||
876 old_media != media) {
877 LACP_DPRINTF((lsc, lacpp,
878 "state changed to UNSELECTED\n"));
879 lacpp->lp_selected = LACP_UNSELECTED;
880 }
881 } else {
882 LACP_DPRINTF((lsc, lacpp,
883 "LACP is inactive, skip linkstate\n"));
884 }
885
886 LACP_UNLOCK(lsc);
887 }
888
889 int
890 lacp_ioctl(struct lagg_proto_softc *xlsc, struct laggreqproto *lreq)
891 {
892 struct lacp_softc *lsc;
893 struct laggreq_lacp *rplacp;
894 struct lacp_aggregator *la;
895 int error;
896 size_t maxports;
897 bool set;
898
899 lsc = (struct lacp_softc *)xlsc;
900 rplacp = &lreq->rp_lacp;
901 error = 0;
902
903 switch (rplacp->command) {
904 case LAGGIOC_LACPSETFLAGS:
905 case LAGGIOC_LACPCLRFLAGS:
906 set = (rplacp->command == LAGGIOC_LACPSETFLAGS) ?
907 true : false;
908
909 LACP_LOCK(lsc);
910
911 if (ISSET(rplacp->flags, LAGGREQLACP_OPTIMISTIC))
912 lsc->lsc_optimistic = set;
913 if (ISSET(rplacp->flags, LAGGREQLACP_DUMPDU))
914 lsc->lsc_dump_du = set;
915 if (ISSET(rplacp->flags, LAGGREQLACP_STOPDU))
916 lsc->lsc_stop_lacpdu = set;
917 if (ISSET(rplacp->flags, LAGGREQLACP_MULTILS))
918 lsc->lsc_multi_linkspeed = set;
919
920 LACP_UNLOCK(lsc);
921 break;
922 case LAGGIOC_LACPSETMAXPORTS:
923 case LAGGIOC_LACPCLRMAXPORTS:
924 maxports = (rplacp->command == LAGGIOC_LACPSETMAXPORTS) ?
925 rplacp->maxports : LACP_MAX_PORTS;
926 if (0 == maxports || LACP_MAX_PORTS < maxports) {
927 error = ERANGE;
928 break;
929 }
930
931 LACP_LOCK(lsc);
932 if (lsc->lsc_max_ports != maxports) {
933 lsc->lsc_max_ports = maxports;
934 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
935 lacp_selected_update(lsc, la);
936 }
937 }
938 LACP_UNLOCK(lsc);
939 break;
940 default:
941 error = ENOTTY;
942 }
943
944 return error;
945 }
946
947 static int
948 lacp_pdu_input(struct lacp_softc *lsc, struct lacp_port *lacpp, struct mbuf *m)
949 {
950 enum {
951 LACP_TLV_ACTOR = 0,
952 LACP_TLV_PARTNER,
953 LACP_TLV_COLLECTOR,
954 LACP_TLV_TERM,
955 LACP_TLV_NUM
956 };
957
958 struct lacpdu *du;
959 struct lacpdu_peerinfo *pi_actor, *pi_partner;
960 struct lacpdu_collectorinfo *lci;
961 struct tlv tlvlist_lacp[LACP_TLV_NUM] = {
962 [LACP_TLV_ACTOR] = {
963 .tlv_t = LACP_TYPE_ACTORINFO,
964 .tlv_l = sizeof(*pi_actor)},
965 [LACP_TLV_PARTNER] = {
966 .tlv_t = LACP_TYPE_PARTNERINFO,
967 .tlv_l = sizeof(*pi_partner)},
968 [LACP_TLV_COLLECTOR] = {
969 .tlv_t = LACP_TYPE_COLLECTORINFO,
970 .tlv_l = sizeof(*lci)},
971 [LACP_TLV_TERM] = {
972 .tlv_t = TLV_TYPE_TERMINATE,
973 .tlv_l = 0},
974 };
975
976 if (m->m_pkthdr.len != sizeof(*du))
977 goto bad;
978
979 if ((m->m_flags & M_MCAST) == 0)
980 goto bad;
981
982 if (m->m_len < (int)sizeof(*du)) {
983 m = m_pullup(m, sizeof(*du));
984 if (m == NULL) {
985 lsc->lsc_mpullup_failed.ev_count++;
986 return ENOMEM;
987 }
988 }
989
990 du = mtod(m, struct lacpdu *);
991
992 if (memcmp(&du->ldu_eh.ether_dhost,
993 ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0)
994 goto bad;
995
996 LACP_TLV_PARSE(du, struct lacpdu, ldu_tlv_actor,
997 tlvlist_lacp);
998
999 pi_actor = tlvlist_lacp[LACP_TLV_ACTOR].tlv_v;
1000 pi_partner = tlvlist_lacp[LACP_TLV_PARTNER].tlv_v;
1001 lci = tlvlist_lacp[LACP_TLV_COLLECTOR].tlv_v;
1002
1003 if (pi_actor == NULL || pi_partner == NULL)
1004 goto bad;
1005
1006 if (LACP_ISDUMPING(lsc)) {
1007 lacp_dprintf(lsc, lacpp, "lacpdu received\n");
1008 lacp_dump_lacpdutlv(pi_actor, pi_partner, lci);
1009 }
1010
1011 LACP_LOCK(lsc);
1012 lacp_sm_rx(lsc, lacpp, pi_partner, pi_actor);
1013 LACP_UNLOCK(lsc);
1014
1015 m_freem(m);
1016 return 0;
1017 bad:
1018 lsc->lsc_badlacpdu.ev_count++;
1019 m_freem(m);
1020 return EINVAL;
1021 }
1022
1023 static int
1024 marker_cmp(struct markerdu_info *mi,
1025 struct lacp_softc *lsc, struct lacp_port *lacpp)
1026 {
1027
1028 KASSERT(LACP_LOCKED(lsc));
1029
1030 if (mi->mi_rq_port != lacpp->lp_actor.lpi_portno)
1031 return -1;
1032
1033 if (ntohl(mi->mi_rq_xid) != lacpp->lp_marker_xid)
1034 return -1;
1035
1036 return memcmp(mi->mi_rq_system, lsc->lsc_system_mac,
1037 LACP_MAC_LEN);
1038 }
1039
1040 static void
1041 lacp_marker_reply(struct lacp_softc *lsc, struct lacp_port *lacpp,
1042 struct mbuf *m_info)
1043 {
1044 struct lagg_port *lp;
1045 struct markerdu *mdu;
1046 struct ifnet *ifp_port;
1047 struct psref psref;
1048
1049 LACP_LOCK(lsc);
1050 lp = lacpp->lp_laggport;
1051 lagg_port_getref(lp, &psref);
1052 LACP_UNLOCK(lsc);
1053
1054 ifp_port = lp->lp_ifp;
1055 mdu = mtod(m_info, struct markerdu *);
1056
1057 mdu->mdu_tlv_info.tlv_type = MARKER_TYPE_RESPONSE;
1058 /* ether_dhost is already equals to multicast address */
1059 memcpy(mdu->mdu_eh.ether_shost,
1060 CLLADDR(ifp_port->if_sadl), ETHER_ADDR_LEN);
1061
1062 if (LACP_ISDUMPING(lsc)) {
1063 lacp_dprintf(lsc, lacpp, "markerdu reply\n");
1064 lacp_dump_markertlv(NULL, &mdu->mdu_info);
1065 }
1066
1067 lagg_port_xmit(lp, m_info);
1068 lagg_port_putref(lp, &psref);
1069 }
1070
1071 static int
1072 lacp_marker_recv_response(struct lacp_softc *lsc, struct lacp_port *lacpp,
1073 struct markerdu_info *mi_res)
1074 {
1075 struct lagg_softc *sc;
1076 struct lagg_port *lp0;
1077 struct lacp_port *lacpp0;
1078 bool pending;
1079
1080 sc = lsc->lsc_softc;
1081
1082 LACP_LOCK(lsc);
1083 if (marker_cmp(mi_res, lsc, lacpp) != 0) {
1084 LACP_UNLOCK(lsc);
1085 return -1;
1086 }
1087 CLR(lacpp->lp_flags, LACP_PORT_MARK);
1088 LACP_UNLOCK(lsc);
1089
1090 LAGG_LOCK(sc);
1091 LACP_LOCK(lsc);
1092
1093 if (lsc->lsc_suppress_distributing) {
1094 pending = false;
1095 LAGG_PORTS_FOREACH(sc, lp0) {
1096 lacpp0 = lp0->lp_proto_ctx;
1097 if (ISSET(lacpp0->lp_flags, LACP_PORT_MARK)) {
1098 pending = true;
1099 break;
1100 }
1101 }
1102
1103 if (!pending) {
1104 LACP_DPRINTF((lsc, NULL, "queue flush complete\n"));
1105 LACP_PTIMER_DISARM(lsc, LACP_PTIMER_DISTRIBUTING);
1106 lsc->lsc_suppress_distributing = false;
1107 }
1108 }
1109
1110 LACP_UNLOCK(lsc);
1111 LAGG_UNLOCK(sc);
1112
1113 return 0;
1114 }
1115
1116 static int
1117 lacp_marker_input(struct lacp_softc *lsc, struct lacp_port *lacpp,
1118 struct mbuf *m)
1119 {
1120 enum {
1121 MARKER_TLV_INFO = 0,
1122 MARKER_TLV_RESPONSE,
1123 MARKER_TLV_TERM,
1124 MARKER_TLV_NUM
1125 };
1126
1127 struct markerdu *mdu;
1128 struct markerdu_info *mi_info, *mi_res;
1129 int error;
1130 struct tlv tlvlist_marker[MARKER_TLV_NUM] = {
1131 [MARKER_TLV_INFO] = {
1132 .tlv_t = MARKER_TYPE_INFO,
1133 .tlv_l = sizeof(*mi_info)},
1134 [MARKER_TLV_RESPONSE] = {
1135 .tlv_t = MARKER_TYPE_RESPONSE,
1136 .tlv_l = sizeof(*mi_res)},
1137 [MARKER_TLV_TERM] = {
1138 .tlv_t = TLV_TYPE_TERMINATE,
1139 .tlv_l = 0},
1140 };
1141
1142 if (m->m_pkthdr.len != sizeof(*mdu))
1143 goto bad;
1144
1145 if ((m->m_flags & M_MCAST) == 0)
1146 goto bad;
1147
1148 if (m->m_len < (int)sizeof(*mdu)) {
1149 m = m_pullup(m, sizeof(*mdu));
1150 if (m == NULL) {
1151 lsc->lsc_mpullup_failed.ev_count++;
1152 return ENOMEM;
1153 }
1154 }
1155
1156 mdu = mtod(m, struct markerdu *);
1157
1158 if (memcmp(mdu->mdu_eh.ether_dhost,
1159 ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0)
1160 goto bad;
1161
1162 LACP_TLV_PARSE(mdu, struct markerdu, mdu_tlv_info,
1163 tlvlist_marker);
1164
1165 mi_info = tlvlist_marker[MARKER_TLV_INFO].tlv_v;
1166 mi_res = tlvlist_marker[MARKER_TLV_RESPONSE].tlv_v;
1167
1168 if (LACP_ISDUMPING(lsc)) {
1169 lacp_dprintf(lsc, lacpp, "markerdu received\n");
1170 lacp_dump_markertlv(mi_info, mi_res);
1171 }
1172
1173 if (mi_info != NULL && mi_res == NULL) {
1174 lacp_marker_reply(lsc, lacpp, m);
1175 } else if (mi_info == NULL && mi_res != NULL) {
1176 error = lacp_marker_recv_response(lsc, lacpp,
1177 mi_res);
1178 if (error != 0) {
1179 goto bad;
1180 } else {
1181 m_freem(m);
1182 }
1183 } else {
1184 goto bad;
1185 }
1186
1187 return 0;
1188 bad:
1189 lsc->lsc_badmarkerdu.ev_count++;
1190 m_freem(m);
1191 return EINVAL;
1192 }
1193
1194 struct mbuf *
1195 lacp_input(struct lagg_proto_softc *xlsc, struct lagg_port *lp, struct mbuf *m)
1196 {
1197 struct ifnet *ifp;
1198 struct lacp_softc *lsc;
1199 struct lacp_port *lacpp;
1200 struct ether_header *eh;
1201 uint8_t subtype;
1202
1203 eh = mtod(m, struct ether_header *);
1204 lsc = (struct lacp_softc *)xlsc;
1205 ifp = &lsc->lsc_softc->sc_if;
1206 lacpp = lp->lp_proto_ctx;
1207
1208 if (!vlan_has_tag(m) &&
1209 eh->ether_type == htons(ETHERTYPE_SLOWPROTOCOLS)) {
1210 if (m->m_pkthdr.len < (int)(sizeof(*eh) + sizeof(subtype))) {
1211 m_freem(m);
1212 return NULL;
1213 }
1214
1215 m_copydata(m, sizeof(struct ether_header),
1216 sizeof(subtype), &subtype);
1217 switch (subtype) {
1218 case SLOWPROTOCOLS_SUBTYPE_LACP:
1219 (void)lacp_pdu_input(lsc, lacpp, m);
1220 return NULL;
1221 case SLOWPROTOCOLS_SUBTYPE_MARKER:
1222 (void)lacp_marker_input(lsc, lacpp, m);
1223 return NULL;
1224 }
1225 }
1226
1227 if (!lacp_iscollecting(lacpp) || !lacp_isactive(lsc, lacpp)) {
1228 if_statinc(ifp, if_ierrors);
1229 m_freem(m);
1230 return NULL;
1231 }
1232
1233 return m;
1234 }
1235
1236 static bool
1237 lacp_port_need_to_tell(struct lacp_port *lacpp)
1238 {
1239
1240 if (!ISSET(lacpp->lp_actor.lpi_state,
1241 LACP_STATE_AGGREGATION)) {
1242 return false;
1243 }
1244
1245 if (!ISSET(lacpp->lp_actor.lpi_state,
1246 LACP_STATE_ACTIVITY)
1247 && !ISSET(lacpp->lp_partner.lpi_state,
1248 LACP_STATE_ACTIVITY)) {
1249 return false;
1250 }
1251
1252 if (!ISSET(lacpp->lp_flags, LACP_PORT_NTT))
1253 return false;
1254
1255 if (ppsratecheck(&lacpp->lp_last_lacpdu, &lacpp->lp_lacpdu_sent,
1256 (3 / LACP_FAST_PERIODIC_TIME)) == 0)
1257 return false;
1258
1259 return true;
1260 }
1261
1262 static void
1263 lacp_sm_assert_ntt(struct lacp_port *lacpp)
1264 {
1265
1266 SET(lacpp->lp_flags, LACP_PORT_NTT);
1267 }
1268
1269 static void
1270 lacp_sm_negate_ntt(struct lacp_port *lacpp)
1271 {
1272
1273 CLR(lacpp->lp_flags, LACP_PORT_NTT);
1274 }
1275
1276 static struct mbuf *
1277 lacp_lacpdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp)
1278 {
1279 struct ifnet *ifp_port;
1280 struct mbuf *m;
1281 struct lacpdu *du;
1282
1283 KASSERT(LACP_LOCKED(lsc));
1284
1285 ifp_port = lacpp->lp_laggport->lp_ifp;
1286
1287 MGETHDR(m, M_DONTWAIT, MT_DATA);
1288 if (m == NULL) {
1289 lsc->lsc_mgethdr_failed.ev_count++;
1290 return NULL;
1291 }
1292
1293 m->m_pkthdr.len = m->m_len = sizeof(*du);
1294
1295 du = mtod(m, struct lacpdu *);
1296 memset(du, 0, sizeof(*du));
1297
1298 m->m_flags |= M_MCAST;
1299 memcpy(du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
1300 ETHER_ADDR_LEN);
1301 memcpy(du->ldu_eh.ether_shost, CLLADDR(ifp_port->if_sadl),
1302 ETHER_ADDR_LEN);
1303 du->ldu_eh.ether_type = htons(ETHERTYPE_SLOWPROTOCOLS);
1304 du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP;
1305 du->ldu_sph.sph_version = 1;
1306
1307 tlv_set(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO,
1308 sizeof(du->ldu_actor));
1309 lacp_peerinfo_actor(lsc, lacpp, &du->ldu_actor);
1310
1311 tlv_set(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO,
1312 sizeof(du->ldu_partner));
1313 lacp_peerinfo_partner(lacpp, &du->ldu_partner);
1314
1315 tlv_set(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO,
1316 sizeof(du->ldu_collector));
1317 du->ldu_collector.lci_maxdelay = 0;
1318
1319 du->ldu_tlv_term.tlv_type = LACP_TYPE_TERMINATE;
1320 du->ldu_tlv_term.tlv_length = 0;
1321
1322 return m;
1323 }
1324
1325 static void
1326 lacp_sm_tx_work(struct lagg_work *lw, void *xlsc)
1327 {
1328 struct lacp_softc *lsc;
1329 struct lacp_port *lacpp;
1330 struct lagg_port *lp;
1331 struct lacpdu *du;
1332 struct mbuf *m;
1333 struct psref psref;
1334 int bound;
1335
1336 lsc = xlsc;
1337 lacpp = container_of(lw, struct lacp_port, lp_work_smtx);
1338
1339 if (lsc->lsc_stop_lacpdu)
1340 return;
1341
1342 LACP_LOCK(lsc);
1343 m = lacp_lacpdu_mbuf(lsc, lacpp);
1344 if (m == NULL) {
1345 LACP_UNLOCK(lsc);
1346 return;
1347 }
1348 lacp_sm_negate_ntt(lacpp);
1349 lp = lacpp->lp_laggport;
1350 bound = curlwp_bind();
1351 lagg_port_getref(lp, &psref);
1352 LACP_UNLOCK(lsc);
1353
1354 if (LACP_ISDUMPING(lsc)) {
1355 lacp_dprintf(lsc, lacpp, "lacpdu transmit\n");
1356 du = mtod(m, struct lacpdu *);
1357 lacp_dump_lacpdutlv(&du->ldu_actor,
1358 &du->ldu_partner, &du->ldu_collector);
1359 }
1360
1361 lagg_port_xmit(lp, m);
1362 lagg_port_putref(lp, &psref);
1363 curlwp_bindx(bound);
1364 }
1365
1366 static void
1367 lacp_sm_tx(struct lacp_softc *lsc, struct lacp_port *lacpp)
1368 {
1369
1370 if (!lacp_port_need_to_tell(lacpp))
1371 return;
1372
1373 lagg_workq_add(lsc->lsc_workq, &lacpp->lp_work_smtx);
1374 }
1375
1376 static void
1377 lacp_tick(void *xlsc)
1378 {
1379 struct lacp_softc *lsc;
1380
1381 lsc = xlsc;
1382
1383 lagg_workq_add(lsc->lsc_workq, &lsc->lsc_work_tick);
1384
1385 LACP_LOCK(lsc);
1386 callout_schedule(&lsc->lsc_tick, hz);
1387 LACP_UNLOCK(lsc);
1388 }
1389
1390 static void
1391 lacp_run_timers(struct lacp_softc *lsc, struct lacp_port *lacpp)
1392 {
1393 size_t i;
1394
1395 for (i = 0; i < LACP_NTIMER; i++) {
1396 KASSERT(lacpp->lp_timer[i] >= 0);
1397
1398 if (lacpp->lp_timer[i] == 0)
1399 continue;
1400 if (--lacpp->lp_timer[i] > 0)
1401 continue;
1402
1403 KASSERT(lacp_timer_funcs[i] != NULL);
1404 lacp_timer_funcs[i](lsc, lacpp);
1405 }
1406 }
1407
1408 static void
1409 lacp_run_prototimers(struct lacp_softc *lsc)
1410 {
1411 size_t i;
1412
1413 for (i = 0; i < LACP_NPTIMER; i++) {
1414 KASSERT(lsc->lsc_timer[i] >= 0);
1415
1416 if (lsc->lsc_timer[i] == 0)
1417 continue;
1418 if (--lsc->lsc_timer[i] > 0)
1419 continue;
1420
1421 KASSERT(lacp_ptimer_funcs[i] != NULL);
1422 lacp_ptimer_funcs[i](lsc);
1423 }
1424 }
1425
1426 static void
1427 lacp_tick_work(struct lagg_work *lw __unused, void *xlsc)
1428 {
1429 struct lacp_softc *lsc;
1430 struct lacp_port *lacpp;
1431 struct lagg_softc *sc;
1432 struct lagg_port *lp;
1433
1434 lsc = xlsc;
1435 sc = lsc->lsc_softc;
1436
1437 LACP_LOCK(lsc);
1438 lacp_run_prototimers(lsc);
1439 LACP_UNLOCK(lsc);
1440
1441 LAGG_LOCK(sc);
1442 LACP_LOCK(lsc);
1443 LAGG_PORTS_FOREACH(sc, lp) {
1444 lacpp = lp->lp_proto_ctx;
1445 if (!ISSET(lacpp->lp_actor.lpi_state,
1446 LACP_STATE_AGGREGATION)) {
1447 continue;
1448 }
1449
1450 lacp_run_timers(lsc, lacpp);
1451 lacp_select(lsc, lacpp);
1452 lacp_sm_mux(lsc, lacpp);
1453 lacp_sm_tx(lsc, lacpp);
1454 lacp_sm_ptx_schedule(lacpp);
1455 }
1456
1457 LACP_UNLOCK(lsc);
1458 LAGG_UNLOCK(sc);
1459 }
1460
1461 static void
1462 lacp_systemid_str(char *buf, size_t buflen,
1463 uint16_t prio, const uint8_t *mac, uint16_t key)
1464 {
1465
1466 snprintf(buf, buflen,
1467 "%04X,"
1468 "%02X-%02X-%02X-%02X-%02X-%02X,"
1469 "%04X",
1470 (unsigned int)ntohs(prio),
1471 (int)mac[0], (int)mac[1], (int)mac[2],
1472 (int)mac[3], (int)mac[4], (int)mac[5],
1473 (unsigned int)htons(key));
1474
1475 }
1476
1477 __LACPDEBUGUSED static void
1478 lacp_aggregator_str(struct lacp_aggregator *la, char *buf, size_t buflen)
1479 {
1480
1481 lacp_systemid_str(buf, buflen, la->la_sid.sid_prio,
1482 la->la_sid.sid_mac, la->la_sid.sid_key);
1483 }
1484
1485 static void
1486 lacp_peerinfo_idstr(const struct lacpdu_peerinfo *pi,
1487 char *buf, size_t buflen)
1488 {
1489
1490 lacp_systemid_str(buf, buflen, pi->lpi_system_prio,
1491 pi->lpi_system_mac, pi->lpi_key);
1492 }
1493
1494 static void
1495 lacp_state_str(uint8_t state, char *buf, size_t buflen)
1496 {
1497
1498 snprintb(buf, buflen, LACP_STATE_BITS, state);
1499 }
1500
1501 static struct lagg_port *
1502 lacp_select_tx_port(struct lacp_softc *lsc, struct mbuf *m,
1503 struct psref *psref)
1504 {
1505 struct lacp_portmap *pm;
1506 struct lagg_port *lp;
1507 uint32_t hash;
1508 size_t act;
1509 int s;
1510
1511 hash = lagg_hashmbuf(lsc->lsc_softc, m);
1512
1513 s = pserialize_read_enter();
1514 act = LACP_PORTMAP_ACTIVE(lsc);
1515 pm = &lsc->lsc_portmaps[act];
1516
1517 if (pm->pm_count == 0) {
1518 pserialize_read_exit(s);
1519 return NULL;
1520 }
1521
1522 hash %= pm->pm_count;
1523 lp = pm->pm_ports[hash];
1524 lagg_port_getref(lp, psref);
1525
1526 pserialize_read_exit(s);
1527
1528 return lp;
1529 }
1530
1531 static void
1532 lacp_peerinfo_actor(struct lacp_softc *lsc, struct lacp_port *lacpp,
1533 struct lacpdu_peerinfo *dst)
1534 {
1535
1536 memcpy(dst->lpi_system_mac, lsc->lsc_system_mac, LACP_MAC_LEN);
1537 dst->lpi_system_prio = lsc->lsc_system_prio;
1538 dst->lpi_key = lsc->lsc_key;
1539 dst->lpi_port_no = lacpp->lp_actor.lpi_portno;
1540 dst->lpi_port_prio = lacpp->lp_actor.lpi_portprio;
1541 dst->lpi_state = lacpp->lp_actor.lpi_state;
1542 }
1543
1544 static void
1545 lacp_peerinfo_partner(struct lacp_port *lacpp, struct lacpdu_peerinfo *dst)
1546 {
1547 struct lacp_aggregator *la;
1548
1549 la = lacpp->lp_aggregator;
1550
1551 if (la != NULL) {
1552 memcpy(dst->lpi_system_mac, la->la_sid.sid_mac, LACP_MAC_LEN);
1553 dst->lpi_system_prio = la->la_sid.sid_prio;
1554 dst->lpi_key = la->la_sid.sid_key;
1555 } else {
1556 memset(dst->lpi_system_mac, 0, LACP_MAC_LEN);
1557 dst->lpi_system_prio = 0;
1558 dst->lpi_key = 0;
1559 }
1560 dst->lpi_port_no = lacpp->lp_partner.lpi_portno;
1561 dst->lpi_port_prio = lacpp->lp_partner.lpi_portprio;
1562 dst->lpi_state = lacpp->lp_partner.lpi_state;
1563 }
1564
1565 static int
1566 lacp_compare_peerinfo(struct lacpdu_peerinfo *a, struct lacpdu_peerinfo *b)
1567 {
1568
1569 return memcmp(a, b, offsetof(struct lacpdu_peerinfo, lpi_state));
1570 }
1571
1572 static void
1573 lacp_sm_rx_record_default(struct lacp_softc *lsc, struct lacp_port *lacpp)
1574 {
1575 uint8_t oldpstate;
1576 struct lacp_portinfo *pi;
1577 char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED;
1578
1579 pi = &lacpp->lp_partner;
1580
1581 oldpstate = pi->lpi_state;
1582 pi->lpi_portno = htons(LACP_PORTNO_NONE);
1583 pi->lpi_portprio = htons(0xffff);
1584
1585 if (lsc->lsc_optimistic)
1586 pi->lpi_state = LACP_PARTNER_ADMIN_OPTIMISTIC;
1587 else
1588 pi->lpi_state = LACP_PARTNER_ADMIN_STRICT;
1589
1590 SET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED);
1591
1592 if (oldpstate != pi->lpi_state) {
1593 LACP_STATE_STR(oldpstate, buf, sizeof(buf));
1594 LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf));
1595
1596 LACP_STATE_STR(pi->lpi_state, buf, sizeof(buf));
1597 LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf));
1598 }
1599 }
1600
1601 static inline bool
1602 lacp_port_is_synced(struct lacp_softc *lsc, struct lacp_port *lacpp,
1603 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
1604 {
1605 struct lacpdu_peerinfo actor;
1606
1607 if (!ISSET(peer_pi->lpi_state, LACP_STATE_ACTIVITY) &&
1608 (!ISSET(my_pi->lpi_state, LACP_STATE_ACTIVITY) ||
1609 !ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY)))
1610 return false;
1611
1612 if (!ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION))
1613 return false;
1614
1615 lacp_peerinfo_actor(lsc, lacpp, &actor);
1616 if (lacp_compare_peerinfo(&actor, my_pi) != 0)
1617 return false;
1618
1619 if (!LACP_STATE_EQ(actor.lpi_state, my_pi->lpi_state,
1620 LACP_STATE_AGGREGATION)) {
1621 return false;
1622 }
1623
1624 return true;
1625 }
1626
1627 static void
1628 lacp_sm_rx_record_peerinfo(struct lacp_softc *lsc, struct lacp_port *lacpp,
1629 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
1630 {
1631 char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED;
1632 uint8_t oldpstate;
1633 struct lacp_portinfo *pi;
1634 struct lacp_aggregator_systemid *sid;
1635
1636 pi = &lacpp->lp_partner;
1637 sid = &lacpp->lp_aggregator_sidbuf;
1638
1639 oldpstate = lacpp->lp_partner.lpi_state;
1640
1641 sid->sid_prio = peer_pi->lpi_system_prio;
1642 sid->sid_key = peer_pi->lpi_key;
1643 memcpy(sid->sid_mac, peer_pi->lpi_system_mac,
1644 sizeof(sid->sid_mac));
1645
1646 pi->lpi_portno = peer_pi->lpi_port_no;
1647 pi->lpi_portprio = peer_pi->lpi_port_prio;
1648 pi->lpi_state = peer_pi->lpi_state;
1649
1650 if (lacp_port_is_synced(lsc, lacpp, my_pi, peer_pi)) {
1651 if (lsc->lsc_optimistic)
1652 SET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1653 } else {
1654 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1655 }
1656
1657 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED);
1658
1659 if (oldpstate != lacpp->lp_partner.lpi_state) {
1660 LACP_STATE_STR(oldpstate, buf, sizeof(buf));
1661 LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf));
1662
1663 LACP_STATE_STR(lacpp->lp_partner.lpi_state,
1664 buf, sizeof(buf));
1665 LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf));
1666 }
1667
1668 lacp_sm_ptx_update_timeout(lacpp, oldpstate);
1669 }
1670
1671 static void
1672 lacp_sm_rx_set_expired(struct lacp_port *lacpp)
1673 {
1674
1675 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
1676 SET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT);
1677 LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE,
1678 LACP_SHORT_TIMEOUT_TIME);
1679 SET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED);
1680 }
1681
1682 static void
1683 lacp_sm_port_init(struct lacp_softc *lsc, struct lacp_port *lacpp,
1684 struct lagg_port *lp)
1685 {
1686
1687 KASSERT(LACP_LOCKED(lsc));
1688
1689 lacpp->lp_laggport = lp;
1690 lacpp->lp_actor.lpi_state = LACP_STATE_ACTIVITY;
1691 lacpp->lp_actor.lpi_portno = htons(if_get_index(lp->lp_ifp));
1692 lacpp->lp_actor.lpi_portprio = htons(LACP_PORT_PRIO);
1693 lacpp->lp_partner.lpi_state = LACP_STATE_TIMEOUT;
1694 lacpp->lp_aggregator = NULL;
1695 lacpp->lp_marker_xid = 0;
1696 lacpp->lp_mux_state = LACP_MUX_INIT;
1697
1698 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1699 lacp_sm_rx_record_default(lsc, lacpp);
1700 }
1701
1702 static void
1703 lacp_port_disable(struct lacp_softc *lsc, struct lacp_port *lacpp)
1704 {
1705
1706 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
1707 LACP_DPRINTF((lsc, lacpp, "enable -> disable\n"));
1708
1709 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1710 lacp_sm_rx_record_default(lsc, lacpp);
1711 CLR(lacpp->lp_actor.lpi_state,
1712 LACP_STATE_AGGREGATION | LACP_STATE_EXPIRED);
1713 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_AGGREGATION);
1714 }
1715
1716 static void
1717 lacp_port_enable(struct lacp_softc *lsc __LACPDEBUGUSED,
1718 struct lacp_port *lacpp)
1719 {
1720
1721 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
1722 LACP_DPRINTF((lsc, lacpp, "disable -> enable\n"));
1723
1724 SET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION);
1725 lacp_sm_rx_set_expired(lacpp);
1726 }
1727
1728 static void
1729 lacp_sm_rx_timer(struct lacp_softc *lsc, struct lacp_port *lacpp)
1730 {
1731
1732 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED)) {
1733 /* CURRENT -> EXPIRED */
1734 LACP_DPRINTF((lsc, lacpp, "CURRENT -> EXPIRED\n"));
1735 lacp_sm_rx_set_expired(lacpp);
1736 } else {
1737 LACP_DPRINTF((lsc, lacpp, "EXPIRED -> DEFAULTED\n"));
1738 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED);
1739 lacp_sm_rx_record_default(lsc, lacpp);
1740 }
1741 }
1742
1743 static void
1744 lacp_sm_ptx_timer(struct lacp_softc *lsc __unused, struct lacp_port *lacpp)
1745 {
1746
1747 lacp_sm_assert_ntt(lacpp);
1748 }
1749
1750 static void
1751 lacp_sm_ptx_schedule(struct lacp_port *lacpp)
1752 {
1753 int timeout;
1754
1755 /* no periodic */
1756 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY) &&
1757 !ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_ACTIVITY)) {
1758 LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC);
1759 return;
1760 }
1761
1762 if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_PERIODIC))
1763 return;
1764
1765 timeout = ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_TIMEOUT) ?
1766 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME;
1767
1768 LACP_TIMER_ARM(lacpp, LACP_TIMER_PERIODIC, timeout);
1769 }
1770
1771 static void
1772 lacp_sm_ptx_update_timeout(struct lacp_port *lacpp, uint8_t oldpstate)
1773 {
1774
1775 if (LACP_STATE_EQ(oldpstate, lacpp->lp_partner.lpi_state,
1776 LACP_STATE_TIMEOUT))
1777 return;
1778
1779 LACP_DPRINTF((NULL, lacpp, "partner timeout changed\n"));
1780
1781 LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC);
1782
1783 /* if timeout has been shorted, assert NTT */
1784 if (ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT))
1785 lacp_sm_assert_ntt(lacpp);
1786 }
1787
1788 static void
1789 lacp_sm_mux_timer(struct lacp_softc *lsc __LACPDEBUGUSED,
1790 struct lacp_port *lacpp)
1791 {
1792 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1793
1794 KASSERT(lacpp->lp_pending > 0);
1795
1796 LACP_AGGREGATOR_STR(lacpp->lp_aggregator, buf, sizeof(buf));
1797 LACP_DPRINTF((lsc, lacpp, "aggregator %s, pending %d -> %d\n",
1798 buf, lacpp->lp_pending, lacpp->lp_pending -1));
1799
1800 lacpp->lp_pending--;
1801 }
1802
1803 static void
1804 lacp_sm_rx_update_selected(struct lacp_softc *lsc, struct lacp_port *lacpp,
1805 struct lacpdu_peerinfo *peer_pi)
1806 {
1807 struct lacpdu_peerinfo partner;
1808 char str0[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1809 char str1[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
1810
1811 if (lacpp->lp_aggregator == NULL)
1812 return;
1813
1814 lacp_peerinfo_partner(lacpp, &partner);
1815 if (lacp_compare_peerinfo(peer_pi, &partner) != 0) {
1816 LACP_PEERINFO_IDSTR(&partner, str0, sizeof(str0));
1817 LACP_PEERINFO_IDSTR(peer_pi, str1, sizeof(str1));
1818 LACP_DPRINTF((lsc, lacpp,
1819 "different peerinfo, %s vs %s\n", str0, str1));
1820 goto do_unselect;
1821 }
1822
1823 if (!LACP_STATE_EQ(lacpp->lp_partner.lpi_state,
1824 peer_pi->lpi_state, LACP_STATE_AGGREGATION)) {
1825 LACP_DPRINTF((lsc, lacpp,
1826 "STATE_AGGREGATION changed %d -> %d\n",
1827 ISSET(lacpp->lp_partner.lpi_state,
1828 LACP_STATE_AGGREGATION) != 0,
1829 ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION) != 0));
1830 goto do_unselect;
1831 }
1832
1833 return;
1834
1835 do_unselect:
1836 lacpp->lp_selected = LACP_UNSELECTED;
1837 /* lacpp->lp_aggregator will be released at lacp_set_mux() */
1838 }
1839
1840 static void
1841 lacp_sm_rx_update_ntt(struct lacp_softc *lsc, struct lacp_port *lacpp,
1842 struct lacpdu_peerinfo *my_pi)
1843 {
1844 struct lacpdu_peerinfo actor;
1845
1846 lacp_peerinfo_actor(lsc, lacpp, &actor);
1847
1848 if (lacp_compare_peerinfo(&actor, my_pi) != 0 ||
1849 !LACP_STATE_EQ(lacpp->lp_actor.lpi_state, my_pi->lpi_state,
1850 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) {
1851 LACP_DPRINTF((lsc, lacpp, "assert ntt\n"));
1852 lacp_sm_assert_ntt(lacpp);
1853 }
1854 }
1855
1856 static void
1857 lacp_sm_rx(struct lacp_softc *lsc, struct lacp_port *lacpp,
1858 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi)
1859 {
1860 int timeout;
1861
1862 KASSERT(LACP_LOCKED(lsc));
1863
1864 /* check LACP disabled first */
1865 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION))
1866 return;
1867
1868 /* check loopback condition */
1869 if (memcmp(lsc->lsc_system_mac, peer_pi->lpi_system_mac,
1870 LACP_MAC_LEN) == 0 &&
1871 lsc->lsc_system_prio == peer_pi->lpi_system_prio)
1872 return;
1873
1874 lacp_sm_rx_update_selected(lsc, lacpp, peer_pi);
1875 lacp_sm_rx_update_ntt(lsc, lacpp, my_pi);
1876 lacp_sm_rx_record_peerinfo(lsc, lacpp, my_pi, peer_pi);
1877
1878 timeout = ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_TIMEOUT) ?
1879 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME;
1880 LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE, timeout);
1881
1882 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED);
1883
1884 /* kick transmit machine without timeout. */
1885 lacp_sm_tx(lsc, lacpp);
1886 }
1887
1888 static void
1889 lacp_disable_collecting(struct lacp_port *lacpp)
1890 {
1891
1892 LACP_DPRINTF((NULL, lacpp, "collecting disabled\n"));
1893 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING);
1894 atomic_store_relaxed(&lacpp->lp_collector, false);
1895 }
1896
1897 static void
1898 lacp_enable_collecting(struct lacp_port *lacpp)
1899 {
1900 LACP_DPRINTF((NULL, lacpp, "collecting enabled\n"));
1901 SET(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING);
1902 atomic_store_relaxed(&lacpp->lp_collector, true);
1903 }
1904
1905 static void
1906 lacp_update_portmap(struct lacp_softc *lsc)
1907 {
1908 struct lagg_softc *sc;
1909 struct lacp_aggregator *la;
1910 struct lacp_portmap *pm_act, *pm_next;
1911 struct lacp_port *lacpp;
1912 size_t pmap, n;
1913 u_int link;
1914
1915 KASSERT(LACP_LOCKED(lsc));
1916
1917 la = lsc->lsc_aggregator;
1918
1919 pmap = LACP_PORTMAP_ACTIVE(lsc);
1920 pm_act = &lsc->lsc_portmaps[pmap];
1921
1922 pmap = LACP_PORTMAP_NEXT(lsc);
1923 pm_next = &lsc->lsc_portmaps[pmap];
1924
1925 n = 0;
1926 if (la != NULL) {
1927 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
1928 if (!ISSET(lacpp->lp_actor.lpi_state,
1929 LACP_STATE_DISTRIBUTING)) {
1930 continue;
1931 }
1932
1933 pm_next->pm_ports[n] = lacpp->lp_laggport;
1934 n++;
1935
1936 if (n >= LACP_MAX_PORTS)
1937 break;
1938 }
1939 }
1940 pm_next->pm_count = n;
1941
1942 atomic_store_release(&lsc->lsc_activemap, pmap);
1943 pserialize_perform(lsc->lsc_psz);
1944
1945 LACP_DPRINTF((lsc, NULL, "portmap count updated (%zu -> %zu)\n",
1946 pm_act->pm_count, pm_next->pm_count));
1947
1948 link = lacp_portmap_linkstate(pm_next);
1949 if (link != lacp_portmap_linkstate(pm_act)) {
1950 sc = lsc->lsc_softc;
1951 if_link_state_change(&sc->sc_if, link);
1952 }
1953
1954 /* cleanup */
1955 pm_act->pm_count = 0;
1956 memset(pm_act->pm_ports, 0, sizeof(pm_act->pm_ports));
1957 }
1958
1959 static void
1960 lacp_disable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp)
1961 {
1962 struct lacp_portmap *pm;
1963 bool do_update;
1964 size_t act, i;
1965 int s;
1966
1967 KASSERT(LACP_LOCKED(lsc));
1968
1969 LACP_DPRINTF((lsc, lacpp, "distributing disabled\n"));
1970 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
1971
1972 s = pserialize_read_enter();
1973 act = LACP_PORTMAP_ACTIVE(lsc);
1974 pm = &lsc->lsc_portmaps[act];
1975
1976 do_update = false;
1977 for (i = 0; i < pm->pm_count; i++) {
1978 if (pm->pm_ports[i] == lacpp->lp_laggport) {
1979 do_update = true;
1980 break;
1981 }
1982 }
1983 pserialize_read_exit(s);
1984
1985 if (do_update)
1986 lacp_update_portmap(lsc);
1987 }
1988
1989 static void
1990 lacp_enable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp)
1991 {
1992
1993 KASSERT(LACP_LOCKED(lsc));
1994
1995 KASSERT(lacp_isactive(lsc, lacpp));
1996
1997 LACP_DPRINTF((lsc, lacpp, "distributing enabled\n"));
1998 SET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING);
1999 lacp_suppress_distributing(lsc);
2000 lacp_update_portmap(lsc);
2001 }
2002
2003 static void
2004 lacp_select_active_aggregator(struct lacp_softc *lsc)
2005 {
2006 struct lacp_aggregator *la, *best_la;
2007 char str[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2008
2009 KASSERT(LACP_LOCKED(lsc));
2010
2011 la = lsc->lsc_aggregator;
2012 if (la != NULL && la->la_attached_port > 0) {
2013 best_la = la;
2014 } else {
2015 best_la = NULL;
2016 }
2017
2018 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
2019 if (la->la_attached_port <= 0)
2020 continue;
2021
2022 if (best_la == NULL ||
2023 LACP_SYS_PRI(la) < LACP_SYS_PRI(best_la))
2024 best_la = la;
2025 }
2026
2027 if (best_la != lsc->lsc_aggregator) {
2028 LACP_DPRINTF((lsc, NULL, "active aggregator changed\n"));
2029
2030 if (lsc->lsc_aggregator != NULL) {
2031 LACP_AGGREGATOR_STR(lsc->lsc_aggregator,
2032 str, sizeof(str));
2033 } else {
2034 snprintf(str, sizeof(str), "(null)");
2035 }
2036 LACP_DPRINTF((lsc, NULL, "old aggregator=%s\n", str));
2037
2038 if (best_la != NULL) {
2039 LACP_AGGREGATOR_STR(best_la, str, sizeof(str));
2040 } else {
2041 snprintf(str, sizeof(str), "(null)");
2042 }
2043 LACP_DPRINTF((lsc, NULL, "new aggregator=%s\n", str));
2044
2045 lsc->lsc_aggregator = best_la;
2046 }
2047 }
2048
2049 static void
2050 lacp_port_attached(struct lacp_softc *lsc, struct lacp_port *lacpp)
2051 {
2052 struct lacp_aggregator *la;
2053
2054 KASSERT(LACP_LOCKED(lsc));
2055
2056 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC))
2057 return;
2058
2059 la = lacpp->lp_aggregator;
2060 KASSERT(la != NULL);
2061 KASSERT(la->la_attached_port >= 0);
2062
2063 SET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC);
2064 la->la_attached_port++;
2065 lacp_select_active_aggregator(lsc);
2066 }
2067
2068 static void
2069 lacp_port_detached(struct lacp_softc *lsc, struct lacp_port *lacpp)
2070 {
2071 struct lacp_aggregator *la;
2072
2073 KASSERT(LACP_LOCKED(lsc));
2074
2075 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC))
2076 return;
2077
2078 la = lacpp->lp_aggregator;
2079 KASSERT(la != NULL);
2080 KASSERT(la->la_attached_port > 0);
2081
2082 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC);
2083 la->la_attached_port--;
2084 lacp_select_active_aggregator(lsc);
2085 }
2086
2087 static int
2088 lacp_set_mux(struct lacp_softc *lsc, struct lacp_port *lacpp,
2089 enum lacp_mux_state new_state)
2090 {
2091 struct lagg_softc *sc;
2092 struct ifnet *ifp;
2093
2094 KASSERT(LACP_LOCKED(lsc));
2095
2096 sc = lacpp->lp_laggport->lp_softc;
2097 ifp = &sc->sc_if;
2098
2099 if (lacpp->lp_mux_state == new_state) {
2100 return -1;
2101 }
2102
2103 switch (new_state) {
2104 case LACP_MUX_DETACHED:
2105 lacp_port_detached(lsc, lacpp);
2106 lacp_disable_distributing(lsc, lacpp);
2107 lacp_disable_collecting(lacpp);
2108 lacp_sm_assert_ntt(lacpp);
2109 /* cancel timer */
2110 if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)) {
2111 KASSERT(lacpp->lp_pending > 0);
2112 lacpp->lp_pending--;
2113 LACP_TIMER_DISARM(lacpp, LACP_TIMER_WAIT_WHILE);
2114 }
2115 lacp_unselect(lsc, lacpp);
2116 break;
2117 case LACP_MUX_WAITING:
2118 LACP_TIMER_ARM(lacpp, LACP_TIMER_WAIT_WHILE,
2119 LACP_AGGREGATE_WAIT_TIME);
2120 lacpp->lp_pending++;
2121 break;
2122 case LACP_MUX_STANDBY:
2123 case LACP_MUX_ATTACHED:
2124 lacp_port_attached(lsc, lacpp);
2125 lacp_disable_collecting(lacpp);
2126 lacp_sm_assert_ntt(lacpp);
2127 break;
2128 case LACP_MUX_COLLECTING:
2129 lacp_enable_collecting(lacpp);
2130 lacp_disable_distributing(lsc, lacpp);
2131 lacp_sm_assert_ntt(lacpp);
2132 break;
2133 case LACP_MUX_DISTRIBUTING:
2134 lacp_enable_distributing(lsc, lacpp);
2135 break;
2136 case LACP_MUX_INIT:
2137 default:
2138 panic("%s: unknown state", ifp->if_xname);
2139 }
2140
2141 LACP_DPRINTF((lsc, lacpp, "mux_state %d -> %d\n",
2142 lacpp->lp_mux_state, new_state));
2143
2144 lacpp->lp_mux_state = new_state;
2145 return 0;
2146 }
2147
2148 static void
2149 lacp_sm_mux(struct lacp_softc *lsc, struct lacp_port *lacpp)
2150 {
2151 struct lacp_aggregator *la __diagused;
2152 enum lacp_mux_state next_state;
2153 enum lacp_selected selected;
2154 bool p_sync, p_collecting;
2155
2156 p_sync = ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC);
2157 p_collecting = ISSET(lacpp->lp_partner.lpi_state,
2158 LACP_STATE_COLLECTING);
2159
2160 do {
2161 next_state = lacpp->lp_mux_state;
2162 la = lacpp->lp_aggregator;
2163 selected = lacpp->lp_selected;
2164 KASSERT(la != NULL ||
2165 lacpp->lp_mux_state == LACP_MUX_DETACHED);
2166
2167 switch (lacpp->lp_mux_state) {
2168 case LACP_MUX_DETACHED:
2169 if (selected != LACP_UNSELECTED)
2170 next_state = LACP_MUX_WAITING;
2171 break;
2172 case LACP_MUX_WAITING:
2173 KASSERTMSG((lacpp->lp_pending > 0 ||
2174 !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)),
2175 "lp_pending=%d, timer=%d", lacpp->lp_pending,
2176 !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2177
2178 if (selected == LACP_UNSELECTED) {
2179 next_state = LACP_MUX_DETACHED;
2180 } else if (lacpp->lp_pending == 0) {
2181 if (selected == LACP_SELECTED) {
2182 next_state = LACP_MUX_ATTACHED;
2183 } else if (selected == LACP_STANDBY) {
2184 next_state = LACP_MUX_STANDBY;
2185 } else {
2186 next_state = LACP_MUX_DETACHED;
2187 }
2188 }
2189 break;
2190 case LACP_MUX_STANDBY:
2191 if (selected == LACP_SELECTED) {
2192 next_state = LACP_MUX_ATTACHED;
2193 } else if (selected != LACP_STANDBY) {
2194 next_state = LACP_MUX_DETACHED;
2195 }
2196 break;
2197 case LACP_MUX_ATTACHED:
2198 if (selected != LACP_SELECTED) {
2199 next_state = LACP_MUX_DETACHED;
2200 } else if (lacp_isactive(lsc, lacpp) && p_sync) {
2201 next_state = LACP_MUX_COLLECTING;
2202 }
2203 break;
2204 case LACP_MUX_COLLECTING:
2205 if (selected != LACP_SELECTED ||
2206 !lacp_isactive(lsc, lacpp)
2207 || !p_sync) {
2208 next_state = LACP_MUX_ATTACHED;
2209 } else if (p_collecting) {
2210 next_state = LACP_MUX_DISTRIBUTING;
2211 }
2212 break;
2213 case LACP_MUX_DISTRIBUTING:
2214 if (selected != LACP_SELECTED ||
2215 !lacp_isactive(lsc, lacpp)
2216 || !p_sync || !p_collecting) {
2217 next_state = LACP_MUX_COLLECTING;
2218 LACP_DPRINTF((lsc, lacpp,
2219 "Interface stopped DISTRIBUTING,"
2220 " possible flapping\n"));
2221 }
2222 break;
2223 case LACP_MUX_INIT:
2224 default:
2225 panic("%s: unknown state",
2226 lsc->lsc_softc->sc_if.if_xname);
2227 }
2228 } while (lacp_set_mux(lsc, lacpp, next_state) == 0);
2229 }
2230
2231 static bool
2232 lacp_aggregator_is_match(struct lacp_aggregator_systemid *a,
2233 struct lacp_aggregator_systemid *b)
2234 {
2235
2236 if (a->sid_prio != b->sid_prio)
2237 return false;
2238
2239 if (a->sid_key != b->sid_key)
2240 return false;
2241
2242 if (memcmp(a->sid_mac, b->sid_mac, sizeof(a->sid_mac)) != 0)
2243 return false;
2244
2245 return true;
2246 }
2247
2248 static void
2249 lacp_selected_update(struct lacp_softc *lsc, struct lacp_aggregator *la)
2250 {
2251 struct lacp_port *lacpp;
2252 size_t nselected;
2253 uint32_t media;
2254
2255 KASSERT(LACP_LOCKED(lsc));
2256
2257 lacpp = LIST_FIRST(&la->la_ports);
2258 if (lacpp == NULL)
2259 return;
2260
2261 media = lacpp->lp_media;
2262 nselected = 0;
2263 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
2264 if (nselected >= lsc->lsc_max_ports ||
2265 (!lsc->lsc_multi_linkspeed && media != lacpp->lp_media)) {
2266 if (lacpp->lp_selected == LACP_SELECTED)
2267 lacpp->lp_selected = LACP_STANDBY;
2268 continue;
2269 }
2270
2271 switch (lacpp->lp_selected) {
2272 case LACP_STANDBY:
2273 lacpp->lp_selected = LACP_SELECTED;
2274 /* fall through */
2275 case LACP_SELECTED:
2276 nselected++;
2277 break;
2278 default:
2279 /* do nothing */
2280 break;
2281 }
2282 }
2283 }
2284
2285 static void
2286 lacp_select(struct lacp_softc *lsc, struct lacp_port *lacpp)
2287 {
2288 struct lacp_aggregator *la;
2289 struct lacp_aggregator_systemid *sid;
2290 struct lacp_port *lacpp0;
2291 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2292 bool insert_after;
2293
2294 if (lacpp->lp_aggregator != NULL)
2295 return;
2296
2297 /* If we haven't heard from our peer, skip this step. */
2298 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED))
2299 return
2300
2301 KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2302
2303 sid = &lacpp->lp_aggregator_sidbuf;
2304
2305 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) {
2306 if (lacp_aggregator_is_match(&la->la_sid, sid))
2307 break;
2308 }
2309
2310 if (la == NULL) {
2311 la = kmem_zalloc(sizeof(*la), KM_NOSLEEP);
2312 if (la == NULL) {
2313 LACP_DPRINTF((lsc, lacpp,
2314 "couldn't allocate aggregator\n"));
2315 /* will retry the next tick. */
2316 return;
2317 }
2318 LIST_INIT(&la->la_ports);
2319
2320 la->la_sid = *sid;
2321 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q);
2322 LACP_DPRINTF((lsc, lacpp, "a new aggregator created\n"));
2323 } else {
2324 LACP_DPRINTF((lsc, lacpp, "aggregator found\n"));
2325 }
2326
2327 KASSERT(la != NULL);
2328 LACP_AGGREGATOR_STR(la, buf, sizeof(buf));
2329 LACP_DPRINTF((lsc, lacpp, "aggregator lagid=%s\n", buf));
2330
2331 lacpp->lp_aggregator = la;
2332 lacpp->lp_selected = LACP_STANDBY;
2333
2334 insert_after = false;
2335
2336 LIST_FOREACH(lacpp0, &la->la_ports, lp_entry_la) {
2337 if (lacp_port_priority_max(lacpp0, lacpp) == lacpp)
2338 break;
2339
2340 if (LIST_NEXT(lacpp0, lp_entry_la) == NULL) {
2341 insert_after = true;
2342 break;
2343 }
2344 }
2345
2346 if (lacpp0 == NULL) {
2347 LIST_INSERT_HEAD(&la->la_ports, lacpp, lp_entry_la);
2348 } else if (insert_after) {
2349 LIST_INSERT_AFTER(lacpp0, lacpp, lp_entry_la);
2350 } else {
2351 LIST_INSERT_BEFORE(lacpp0, lacpp, lp_entry_la);
2352 }
2353
2354 lacp_selected_update(lsc, la);
2355 }
2356
2357 static void
2358 lacp_unselect(struct lacp_softc *lsc, struct lacp_port *lacpp)
2359 {
2360 struct lacp_aggregator *la;
2361 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED;
2362 bool remove_actaggr;
2363
2364 KASSERT(LACP_LOCKED(lsc));
2365 KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE));
2366
2367 la = lacpp->lp_aggregator;
2368 lacpp->lp_selected = LACP_UNSELECTED;
2369
2370 if (la == NULL)
2371 return;
2372
2373 KASSERT(!LIST_EMPTY(&la->la_ports));
2374
2375 LACP_AGGREGATOR_STR(la, buf, sizeof(buf));
2376 LACP_DPRINTF((lsc, lacpp, "unselect aggregator lagid=%s\n", buf));
2377
2378 LIST_REMOVE(lacpp, lp_entry_la);
2379 lacpp->lp_aggregator = NULL;
2380
2381 if (LIST_EMPTY(&la->la_ports)) {
2382 remove_actaggr = false;
2383
2384 if (la == lsc->lsc_aggregator) {
2385 LACP_DPRINTF((lsc, NULL, "remove active aggregator\n"));
2386 lsc->lsc_aggregator = NULL;
2387 remove_actaggr = true;
2388 }
2389
2390 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q);
2391 kmem_free(la, sizeof(*la));
2392
2393 if (remove_actaggr) {
2394 lacp_select_active_aggregator(lsc);
2395 }
2396 } else {
2397 lacp_selected_update(lsc, la);
2398 }
2399 }
2400
2401 static void
2402 lacp_suppress_distributing(struct lacp_softc *lsc)
2403 {
2404 struct lacp_aggregator *la;
2405 struct lacp_port *lacpp;
2406
2407 KASSERT(LACP_LOCKED(lsc));
2408
2409 la = lsc->lsc_aggregator;
2410
2411 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) {
2412 if (ISSET(lacpp->lp_actor.lpi_state,
2413 LACP_STATE_DISTRIBUTING)) {
2414 lagg_workq_add(lsc->lsc_workq,
2415 &lacpp->lp_work_marker);
2416 }
2417 }
2418
2419 LACP_PTIMER_ARM(lsc, LACP_PTIMER_DISTRIBUTING,
2420 LACP_TRANSIT_DELAY);
2421 }
2422
2423 static void
2424 lacp_distributing_timer(struct lacp_softc *lsc)
2425 {
2426
2427 KASSERT(LACP_LOCKED(lsc));
2428
2429 if (lsc->lsc_suppress_distributing) {
2430 LACP_DPRINTF((lsc, NULL,
2431 "disable suppress distributing\n"));
2432 lsc->lsc_suppress_distributing = false;
2433 }
2434 }
2435
2436 static struct mbuf *
2437 lacp_markerdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp)
2438 {
2439 struct ifnet *ifp_port;
2440 struct mbuf *m;
2441 struct markerdu *mdu;
2442 struct markerdu_info *mi;
2443
2444 KASSERT(LACP_LOCKED(lsc));
2445
2446 ifp_port = lacpp->lp_laggport->lp_ifp;
2447
2448 MGETHDR(m, M_DONTWAIT, MT_DATA);
2449 if (m == NULL) {
2450 lsc->lsc_mgethdr_failed.ev_count++;
2451 return NULL;
2452 }
2453
2454 m->m_pkthdr.len = m->m_len = sizeof(*mdu);
2455
2456 mdu = mtod(m, struct markerdu *);
2457
2458 memset(mdu, 0, sizeof(*mdu));
2459
2460 m->m_flags |= M_MCAST;
2461 memcpy(mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols,
2462 ETHER_ADDR_LEN);
2463 memcpy(mdu->mdu_eh.ether_shost, CLLADDR(ifp_port->if_sadl),
2464 ETHER_ADDR_LEN);
2465 mdu->mdu_eh.ether_type = ntohs(ETHERTYPE_SLOWPROTOCOLS);
2466 mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER;
2467 mdu->mdu_sph.sph_version = 1;
2468
2469 mi = &mdu->mdu_info;
2470 tlv_set(&mdu->mdu_tlv_info, MARKER_TYPE_INFO,
2471 sizeof(*mi));
2472 mi->mi_rq_port = lacpp->lp_actor.lpi_portno;
2473 mi->mi_rq_xid = htonl(lacpp->lp_marker_xid);
2474 memcpy(mi->mi_rq_system, lsc->lsc_system_mac, LACP_MAC_LEN);
2475
2476 mdu->mdu_tlv_term.tlv_type = MARKER_TYPE_TERMINATE;
2477 mdu->mdu_tlv_term.tlv_length = 0;
2478
2479 return m;
2480 }
2481
2482 static void
2483 lacp_marker_work(struct lagg_work *lw, void *xlsc)
2484 {
2485 struct lacp_softc *lsc;
2486 struct lacp_port *lacpp;
2487 struct lagg_port *lp;
2488 struct markerdu *mdu;
2489 struct mbuf *m;
2490 struct psref psref;
2491 int bound;
2492
2493 lsc = xlsc;
2494 lacpp = container_of(lw, struct lacp_port, lp_work_marker);
2495
2496 LACP_LOCK(lsc);
2497 lacpp->lp_marker_xid++;
2498 m = lacp_markerdu_mbuf(lsc, lacpp);
2499 if (m == NULL) {
2500 LACP_UNLOCK(lsc);
2501 return;
2502 }
2503 SET(lacpp->lp_flags, LACP_PORT_MARK);
2504 lsc->lsc_suppress_distributing = true;
2505 lp = lacpp->lp_laggport;
2506 bound = curlwp_bind();
2507 lagg_port_getref(lp, &psref);
2508 LACP_UNLOCK(lsc);
2509
2510 if (LACP_ISDUMPING(lsc)) {
2511 lacp_dprintf(lsc, lacpp, "markerdu transmit\n");
2512 mdu = mtod(m, struct markerdu *);
2513 lacp_dump_markertlv(&mdu->mdu_info, NULL);
2514 }
2515
2516 lagg_port_xmit(lp, m);
2517 lagg_port_putref(lp, &psref);
2518 curlwp_bindx(bound);
2519 }
2520
2521 static void
2522 lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *pi_actor,
2523 const struct lacpdu_peerinfo *pi_partner,
2524 const struct lacpdu_collectorinfo *lci)
2525 {
2526 char str[LACP_STATESTR_LEN];
2527
2528 if (pi_actor != NULL) {
2529 lacp_peerinfo_idstr(pi_actor, str, sizeof(str));
2530 printf("actor=%s\n", str);
2531 lacp_state_str(pi_actor->lpi_state,
2532 str, sizeof(str));
2533 printf("actor.state=%s portno=%d portprio=0x%04x\n",
2534 str,
2535 ntohs(pi_actor->lpi_port_no),
2536 ntohs(pi_actor->lpi_port_prio));;
2537 } else {
2538 printf("no actor info\n");
2539 }
2540
2541 if (pi_partner != NULL) {
2542 lacp_peerinfo_idstr(pi_partner, str, sizeof(str));
2543 printf("partner=%s\n", str);
2544 lacp_state_str(pi_partner->lpi_state,
2545 str, sizeof(str));
2546 printf("partner.state=%s portno=%d portprio=0x%04x\n",
2547 str,
2548 ntohs(pi_partner->lpi_port_no),
2549 ntohs(pi_partner->lpi_port_prio));
2550 } else {
2551 printf("no partner info\n");
2552 }
2553
2554 if (lci != NULL) {
2555 printf("maxdelay=%d\n", ntohs(lci->lci_maxdelay));
2556 } else {
2557 printf("no collector info\n");
2558 }
2559 }
2560
2561 static void
2562 lacp_dump_markertlv(const struct markerdu_info *mi_info,
2563 const struct markerdu_info *mi_res)
2564 {
2565
2566 if (mi_info != NULL) {
2567 printf("marker info: port=%d, sys=%s, id=%u\n",
2568 ntohs(mi_info->mi_rq_port),
2569 ether_sprintf(mi_info->mi_rq_system),
2570 ntohl(mi_info->mi_rq_xid));
2571 }
2572
2573 if (mi_res != NULL) {
2574 printf("marker resp: port=%d, sys=%s, id=%u\n",
2575 ntohs(mi_res->mi_rq_port),
2576 ether_sprintf(mi_res->mi_rq_system),
2577 ntohl(mi_res->mi_rq_xid));
2578
2579 }
2580 }
2581
2582 static uint32_t
2583 lacp_ifmedia2lacpmedia(u_int ifmedia)
2584 {
2585 uint32_t rv;
2586
2587 switch (IFM_SUBTYPE(ifmedia)) {
2588 case IFM_10_T:
2589 case IFM_10_2:
2590 case IFM_10_5:
2591 case IFM_10_STP:
2592 case IFM_10_FL:
2593 rv = LACP_LINKSPEED_10;
2594 break;
2595 case IFM_100_TX:
2596 case IFM_100_FX:
2597 case IFM_100_T4:
2598 case IFM_100_VG:
2599 case IFM_100_T2:
2600 rv = LACP_LINKSPEED_100;
2601 break;
2602 case IFM_1000_SX:
2603 case IFM_1000_LX:
2604 case IFM_1000_CX:
2605 case IFM_1000_T:
2606 case IFM_1000_BX10:
2607 case IFM_1000_KX:
2608 rv = LACP_LINKSPEED_1000;
2609 break;
2610 case IFM_2500_SX:
2611 case IFM_2500_KX:
2612 rv = LACP_LINKSPEED_2500;
2613 break;
2614 case IFM_5000_T:
2615 rv = LACP_LINKSPEED_5000;
2616 break;
2617 case IFM_10G_LR:
2618 case IFM_10G_SR:
2619 case IFM_10G_CX4:
2620 case IFM_10G_TWINAX:
2621 case IFM_10G_TWINAX_LONG:
2622 case IFM_10G_LRM:
2623 case IFM_10G_T:
2624 rv = LACP_LINKSPEED_10G;
2625 break;
2626 default:
2627 rv = LACP_LINKSPEED_UNKNOWN;
2628 }
2629
2630 if (IFM_TYPE(ifmedia) == IFM_ETHER)
2631 SET(rv, LACP_MEDIA_ETHER);
2632 if ((ifmedia & IFM_FDX) != 0)
2633 SET(rv, LACP_MEDIA_FDX);
2634
2635 return rv;
2636 }
2637