1 /* $NetBSD: if_lagg.c,v 1.72 2024/07/05 04:31:53 rin Exp $ */
2
3 /*
4 * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org>
6 * Copyright (c) 2014, 2016 Marcelo Araujo <araujo@FreeBSD.org>
7 * Copyright (c) 2021, Internet Initiative Japan Inc.
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/cdefs.h>
23 __KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.72 2024/07/05 04:31:53 rin Exp $");
24
25 #ifdef _KERNEL_OPT
26 #include "opt_inet.h"
27 #include "opt_lagg.h"
28 #endif
29
30 #include <sys/param.h>
31 #include <sys/types.h>
32
33 #include <sys/cprng.h>
34 #include <sys/cpu.h>
35 #include <sys/device.h>
36 #include <sys/evcnt.h>
37 #include <sys/hash.h>
38 #include <sys/kmem.h>
39 #include <sys/module.h>
40 #include <sys/pserialize.h>
41 #include <sys/pslist.h>
42 #include <sys/psref.h>
43 #include <sys/sysctl.h>
44 #include <sys/syslog.h>
45 #include <sys/workqueue.h>
46
47 #include <net/bpf.h>
48 #include <net/if.h>
49 #include <net/if_dl.h>
50 #include <net/if_ether.h>
51 #include <net/if_media.h>
52 #include <net/if_types.h>
53 #include <net/if_vlanvar.h>
54 #include <netinet/ip.h>
55 #include <netinet/ip6.h>
56 #include <netinet/tcp.h>
57 #include <netinet/udp.h>
58
59 #if defined(INET) || defined(INET6)
60 #include <netinet/in.h>
61 #endif
62
63 #ifdef INET6
64 #include <netinet6/in6_ifattach.h>
65 #include <netinet6/in6_var.h>
66 #endif
67
68 #include <net/lagg/if_lagg.h>
69 #include <net/lagg/if_laggproto.h>
70
71 #include "ioconf.h"
72
73 enum lagg_portctrl {
74 LAGG_PORTCTRL_ALLOC,
75 LAGG_PORTCTRL_FREE,
76 LAGG_PORTCTRL_START,
77 LAGG_PORTCTRL_STOP
78 };
79
80 enum lagg_iftypes {
81 LAGG_IF_TYPE_ETHERNET,
82 };
83
84 static const struct lagg_proto lagg_protos[] = {
85 [LAGG_PROTO_NONE] = {
86 .pr_num = LAGG_PROTO_NONE,
87 .pr_attach = lagg_none_attach,
88 },
89 [LAGG_PROTO_LACP] = {
90 .pr_num = LAGG_PROTO_LACP,
91 .pr_attach = lacp_attach,
92 .pr_detach = lacp_detach,
93 .pr_up = lacp_up,
94 .pr_down = lacp_down,
95 .pr_transmit = lacp_transmit,
96 .pr_input = lacp_input,
97 .pr_allocport = lacp_allocport,
98 .pr_freeport = lacp_freeport,
99 .pr_startport = lacp_startport,
100 .pr_stopport = lacp_stopport,
101 .pr_protostat = lacp_protostat,
102 .pr_portstat = lacp_portstat,
103 .pr_linkstate = lacp_linkstate_ifnet_locked,
104 .pr_ioctl = lacp_ioctl,
105 },
106 [LAGG_PROTO_FAILOVER] = {
107 .pr_num = LAGG_PROTO_FAILOVER,
108 .pr_attach = lagg_fail_attach,
109 .pr_detach = lagg_common_detach,
110 .pr_transmit = lagg_fail_transmit,
111 .pr_input = lagg_fail_input,
112 .pr_allocport = lagg_common_allocport,
113 .pr_freeport = lagg_common_freeport,
114 .pr_startport = lagg_common_startport,
115 .pr_stopport = lagg_common_stopport,
116 .pr_portstat = lagg_fail_portstat,
117 .pr_linkstate = lagg_common_linkstate_ifnet_locked,
118 .pr_ioctl = lagg_fail_ioctl,
119 },
120 [LAGG_PROTO_LOADBALANCE] = {
121 .pr_num = LAGG_PROTO_LOADBALANCE,
122 .pr_attach = lagg_lb_attach,
123 .pr_detach = lagg_common_detach,
124 .pr_transmit = lagg_lb_transmit,
125 .pr_input = lagg_lb_input,
126 .pr_allocport = lagg_common_allocport,
127 .pr_freeport = lagg_common_freeport,
128 .pr_startport = lagg_lb_startport,
129 .pr_stopport = lagg_lb_stopport,
130 .pr_portstat = lagg_lb_portstat,
131 .pr_linkstate = lagg_common_linkstate_ifnet_locked,
132 },
133 };
134
135 static int lagg_chg_sadl(struct ifnet *, const uint8_t *, size_t);
136 static void lagg_input_ethernet(struct ifnet *, struct mbuf *);
137 static int lagg_clone_create(struct if_clone *, int);
138 static int lagg_clone_destroy(struct ifnet *);
139 static int lagg_init(struct ifnet *);
140 static int lagg_init_locked(struct lagg_softc *);
141 static void lagg_stop(struct ifnet *, int);
142 static void lagg_stop_locked(struct lagg_softc *);
143 static int lagg_ioctl(struct ifnet *, u_long, void *);
144 static int lagg_transmit(struct ifnet *, struct mbuf *);
145 static void lagg_start(struct ifnet *);
146 static int lagg_media_change(struct ifnet *);
147 static void lagg_media_status(struct ifnet *, struct ifmediareq *);
148 static int lagg_vlan_cb(struct ethercom *, uint16_t, bool);
149 static void lagg_linkstate_changed(void *);
150 static void lagg_ifdetach(void *);
151 static struct lagg_softc *
152 lagg_softc_alloc(enum lagg_iftypes);
153 static void lagg_softc_free(struct lagg_softc *);
154 static int lagg_setup_sysctls(struct lagg_softc *);
155 static void lagg_teardown_sysctls(struct lagg_softc *);
156 static int lagg_proto_attach(struct lagg_softc *, lagg_proto,
157 struct lagg_proto_softc **);
158 static void lagg_proto_detach(struct lagg_variant *);
159 static int lagg_proto_up(struct lagg_softc *);
160 static void lagg_proto_down(struct lagg_softc *);
161 static int lagg_proto_allocport(struct lagg_softc *, struct lagg_port *);
162 static void lagg_proto_freeport(struct lagg_softc *, struct lagg_port *);
163 static void lagg_proto_startport(struct lagg_softc *,
164 struct lagg_port *);
165 static void lagg_proto_stopport(struct lagg_softc *,
166 struct lagg_port *);
167 static struct mbuf *
168 lagg_proto_input(struct lagg_softc *, struct lagg_port *,
169 struct mbuf *);
170 static void lagg_proto_linkstate(struct lagg_softc *, struct lagg_port *);
171 static int lagg_proto_ioctl(struct lagg_softc *, struct lagg_req *);
172 static int lagg_get_stats(struct lagg_softc *, struct lagg_req *, size_t);
173 static int lagg_pr_attach(struct lagg_softc *, lagg_proto);
174 static void lagg_pr_detach(struct lagg_softc *);
175 static int lagg_addport(struct lagg_softc *, struct ifnet *);
176 static int lagg_delport(struct lagg_softc *, struct ifnet *);
177 static int lagg_delport_all(struct lagg_softc *);
178 static int lagg_port_ioctl(struct ifnet *, u_long, void *);
179 static int lagg_port_output(struct ifnet *, struct mbuf *,
180 const struct sockaddr *, const struct rtentry *);
181 static void lagg_config_promisc(struct lagg_softc *, struct lagg_port *);
182 static void lagg_unconfig_promisc(struct lagg_softc *, struct lagg_port *);
183 static struct lagg_variant *
184 lagg_variant_getref(struct lagg_softc *, struct psref *);
185 static void lagg_variant_putref(struct lagg_variant *, struct psref *);
186 static int lagg_ether_addmulti(struct lagg_softc *, struct ifreq *);
187 static int lagg_ether_delmulti(struct lagg_softc *, struct ifreq *);
188 static void lagg_port_syncmulti(struct lagg_softc *, struct lagg_port *);
189 static void lagg_port_purgemulti(struct lagg_softc *, struct lagg_port *);
190 static int lagg_port_setup(struct lagg_softc *, struct lagg_port *,
191 struct ifnet *);
192 static void lagg_port_teardown(struct lagg_softc *, struct lagg_port *,
193 bool);
194 static void lagg_port_syncvlan(struct lagg_softc *, struct lagg_port *);
195 static void lagg_port_purgevlan(struct lagg_softc *, struct lagg_port *);
196 static void lagg_capabilities_update(struct lagg_softc *);
197 static void lagg_sync_ifcaps(struct lagg_softc *);
198 static void lagg_sync_ethcaps(struct lagg_softc *);
199 static void lagg_sync_sadl(struct lagg_softc *);
200
201 static struct if_clone lagg_cloner =
202 IF_CLONE_INITIALIZER("lagg", lagg_clone_create, lagg_clone_destroy);
203 static unsigned int lagg_count;
204 static struct psref_class
205 *lagg_psref_class __read_mostly;
206 static struct psref_class
207 *lagg_port_psref_class __read_mostly;
208
209 static enum lagg_iftypes
210 lagg_iftype = LAGG_IF_TYPE_ETHERNET;
211
212 #ifdef LAGG_DEBUG
213 #define __LAGGDEBUGUSED
214 #define LAGG_DPRINTF(_sc, _fmt, _args...) do { \
215 printf("%s: " _fmt, (_sc) != NULL ? \
216 (_sc)->sc_if.if_xname : "lagg", ##_args); \
217 } while (0)
218 #else
219 #define __LAGGDEBUGUSED __unused
220 #define LAGG_DPRINTF(_sc, _fmt, _args...) __nothing
221 #endif
222
223 #ifndef LAGG_SETCAPS_RETRY
224 #define LAGG_SETCAPS_RETRY (LAGG_MAX_PORTS * 2)
225 #endif
226
227 static size_t
lagg_sizeof_softc(enum lagg_iftypes ift)228 lagg_sizeof_softc(enum lagg_iftypes ift)
229 {
230 struct lagg_softc *_dummy = NULL;
231 size_t s;
232
233 s = sizeof(*_dummy) - sizeof(_dummy->sc_if);
234
235 switch (ift) {
236 case LAGG_IF_TYPE_ETHERNET:
237 s += sizeof(struct ethercom);
238 break;
239 default:
240 s += sizeof(struct ifnet);
241 break;
242 }
243
244 return s;
245 }
246
247 static void
lagg_evcnt_attach(struct lagg_softc * sc,struct evcnt * ev,const char * name)248 lagg_evcnt_attach(struct lagg_softc *sc,
249 struct evcnt *ev, const char *name)
250 {
251
252 evcnt_attach_dynamic(ev, EVCNT_TYPE_MISC, NULL,
253 sc->sc_evgroup, name);
254 }
255
256 static void
lagg_in6_ifattach(struct ifnet * ifp)257 lagg_in6_ifattach(struct ifnet *ifp)
258 {
259
260 #ifdef INET6
261 KERNEL_LOCK_UNLESS_NET_MPSAFE();
262 if (in6_present) {
263 if (ISSET(ifp->if_flags, IFF_UP))
264 in6_ifattach(ifp, NULL);
265 }
266 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
267 #endif
268 }
269
270 static void
lagg_in6_ifdetach(struct ifnet * ifp)271 lagg_in6_ifdetach(struct ifnet *ifp)
272 {
273
274 #ifdef INET6
275 KERNEL_LOCK_UNLESS_NET_MPSAFE();
276 if (in6_present)
277 in6_ifdetach(ifp);
278 KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
279 #endif
280 }
281
282 static int
lagg_lp_ioctl(struct lagg_port * lp,u_long cmd,void * data)283 lagg_lp_ioctl(struct lagg_port *lp, u_long cmd, void *data)
284 {
285 struct ifnet *ifp_port;
286 int error;
287
288 if (lp->lp_ioctl == NULL)
289 return EINVAL;
290
291 ifp_port = lp->lp_ifp;
292 IFNET_LOCK(ifp_port);
293 error = lp->lp_ioctl(ifp_port, cmd, data);
294 IFNET_UNLOCK(ifp_port);
295
296 return error;
297 }
298
299 static bool
lagg_lladdr_equal(const uint8_t * a,const uint8_t * b)300 lagg_lladdr_equal(const uint8_t *a, const uint8_t *b)
301 {
302
303 if (memcmp(a, b, ETHER_ADDR_LEN) == 0)
304 return true;
305
306 return false;
307 }
308
309 static void
lagg_lladdr_cpy(uint8_t * dst,const uint8_t * src)310 lagg_lladdr_cpy(uint8_t *dst, const uint8_t *src)
311 {
312
313 memcpy(dst, src, ETHER_ADDR_LEN);
314 }
315
316 void
laggattach(int n)317 laggattach(int n)
318 {
319
320 /*
321 * Nothing to do here, initialization is handled by the
322 * module initialization code in lagginit() below).
323 */
324 }
325
326 static void
lagginit(void)327 lagginit(void)
328 {
329 size_t i;
330
331 lagg_psref_class = psref_class_create("laggvariant", IPL_SOFTNET);
332 lagg_port_psref_class = psref_class_create("laggport", IPL_SOFTNET);
333
334 for (i = 0; i < LAGG_PROTO_MAX; i++) {
335 if (lagg_protos[i].pr_init != NULL)
336 lagg_protos[i].pr_init();
337 }
338
339 if_clone_attach(&lagg_cloner);
340 }
341
342 static int
laggdetach(void)343 laggdetach(void)
344 {
345 size_t i;
346
347 if (lagg_count > 0)
348 return EBUSY;
349
350 if_clone_detach(&lagg_cloner);
351
352 for (i = 0; i < LAGG_PROTO_MAX; i++) {
353 if (lagg_protos[i].pr_fini != NULL)
354 lagg_protos[i].pr_fini();
355 }
356
357 psref_class_destroy(lagg_port_psref_class);
358 psref_class_destroy(lagg_psref_class);
359
360 return 0;
361 }
362
363 static int
lagg_clone_create(struct if_clone * ifc,int unit)364 lagg_clone_create(struct if_clone *ifc, int unit)
365 {
366 struct lagg_softc *sc;
367 struct ifnet *ifp;
368 struct ethercom *ec;
369 int error;
370
371 sc = lagg_softc_alloc(lagg_iftype);
372 ifp = &sc->sc_if;
373
374 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTNET);
375 sc->sc_psz = pserialize_create();
376 SIMPLEQ_INIT(&sc->sc_ports);
377 LIST_INIT(&sc->sc_mclist);
378 TAILQ_INIT(&sc->sc_vtags);
379 sc->sc_hash_mac = true;
380 sc->sc_hash_ipaddr = true;
381 sc->sc_hash_ip6addr = true;
382 sc->sc_hash_tcp = true;
383 sc->sc_hash_udp = true;
384
385 if_initname(ifp, ifc->ifc_name, unit);
386 ifp->if_softc = sc;
387 ifp->if_init = lagg_init;
388 ifp->if_stop = lagg_stop;
389 ifp->if_ioctl = lagg_ioctl;
390 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
391 ifp->if_extflags = IFEF_MPSAFE;
392 ifp->if_transmit = lagg_transmit;
393 ifp->if_start = lagg_start;
394 IFQ_SET_READY(&ifp->if_snd);
395
396 error = lagg_setup_sysctls(sc);
397 if (error != 0)
398 goto destroy_psz;
399
400 /*XXX dependent on ethernet */
401 ifmedia_init_with_lock(&sc->sc_media, 0, lagg_media_change,
402 lagg_media_status, &sc->sc_lock);
403 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
404 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
405
406 if_initialize(ifp);
407
408 switch (lagg_iftype) {
409 case LAGG_IF_TYPE_ETHERNET:
410 ec = (struct ethercom *)ifp;
411 cprng_fast(sc->sc_lladdr_rand, sizeof(sc->sc_lladdr_rand));
412 sc->sc_lladdr_rand[0] &= 0xFE; /* clear I/G bit */
413 sc->sc_lladdr_rand[0] |= 0x02; /* set G/L bit */
414 lagg_lladdr_cpy(sc->sc_lladdr, sc->sc_lladdr_rand);
415 ether_set_vlan_cb(ec, lagg_vlan_cb);
416
417 /*
418 * notify ETHERCAP_VLAN_HWTAGGING to ether_ifattach
419 * to handle VLAN tag, stripped by hardware, in bpf(4)
420 */
421 ec->ec_capabilities = ETHERCAP_VLAN_HWTAGGING;
422
423 ether_ifattach(ifp, sc->sc_lladdr_rand);
424 break;
425 default:
426 panic("unknown if type");
427 }
428
429 snprintf(sc->sc_evgroup, sizeof(sc->sc_evgroup),
430 "%s", ifp->if_xname);
431 lagg_evcnt_attach(sc, &sc->sc_novar, "no lagg variant");
432 if_link_state_change(&sc->sc_if, LINK_STATE_DOWN);
433 lagg_setup_sysctls(sc);
434 (void)lagg_pr_attach(sc, LAGG_PROTO_NONE);
435 if_register(ifp);
436 lagg_count++;
437
438 return 0;
439
440 destroy_psz:
441 pserialize_destroy(sc->sc_psz);
442 mutex_destroy(&sc->sc_lock);
443 lagg_softc_free(sc);
444
445 return error;
446 }
447
448 static int
lagg_clone_destroy(struct ifnet * ifp)449 lagg_clone_destroy(struct ifnet *ifp)
450 {
451 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
452 struct lagg_port *lp;
453
454 lagg_stop(ifp, 1);
455
456 IFNET_LOCK(ifp);
457 LAGG_LOCK(sc);
458 while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) {
459 lagg_port_teardown(sc, lp, false);
460 }
461 LAGG_UNLOCK(sc);
462 IFNET_UNLOCK(ifp);
463
464 switch (ifp->if_type) {
465 case IFT_ETHER:
466 ether_ifdetach(ifp);
467 KASSERT(TAILQ_EMPTY(&sc->sc_vtags));
468 break;
469 }
470
471 if_detach(ifp);
472 ifmedia_fini(&sc->sc_media);
473 lagg_pr_detach(sc);
474 evcnt_detach(&sc->sc_novar);
475 lagg_teardown_sysctls(sc);
476
477 pserialize_destroy(sc->sc_psz);
478 mutex_destroy(&sc->sc_lock);
479 lagg_softc_free(sc);
480
481 if (lagg_count > 0)
482 lagg_count--;
483
484 return 0;
485 }
486
487 static int
lagg_init(struct ifnet * ifp)488 lagg_init(struct ifnet *ifp)
489 {
490 struct lagg_softc *sc;
491 int rv;
492
493 sc = ifp->if_softc;
494 LAGG_LOCK(sc);
495 rv = lagg_init_locked(sc);
496 LAGG_UNLOCK(sc);
497
498 return rv;
499 }
500
501 static int
lagg_init_locked(struct lagg_softc * sc)502 lagg_init_locked(struct lagg_softc *sc)
503 {
504 struct ifnet *ifp = &sc->sc_if;
505 int rv;
506
507 KASSERT(LAGG_LOCKED(sc));
508
509 if (ISSET(ifp->if_flags, IFF_RUNNING))
510 lagg_stop_locked(sc);
511
512 lagg_sync_sadl(sc);
513
514 SET(ifp->if_flags, IFF_RUNNING);
515
516 rv = lagg_proto_up(sc);
517 if (rv != 0)
518 lagg_stop_locked(sc);
519
520 return rv;
521 }
522
523 static void
lagg_stop(struct ifnet * ifp,int disable __unused)524 lagg_stop(struct ifnet *ifp, int disable __unused)
525 {
526 struct lagg_softc *sc;
527
528 sc = ifp->if_softc;
529 LAGG_LOCK(sc);
530 lagg_stop_locked(sc);
531 LAGG_UNLOCK(sc);
532 }
533
534 static void
lagg_stop_locked(struct lagg_softc * sc)535 lagg_stop_locked(struct lagg_softc *sc)
536 {
537 struct ifnet *ifp = &sc->sc_if;
538
539 KASSERT(LAGG_LOCKED(sc));
540
541 if (!ISSET(ifp->if_flags, IFF_RUNNING))
542 return;
543
544 CLR(ifp->if_flags, IFF_RUNNING);
545 lagg_proto_down(sc);
546
547 }
548
549 static int
lagg_config(struct lagg_softc * sc,struct lagg_req * lrq)550 lagg_config(struct lagg_softc *sc, struct lagg_req *lrq)
551 {
552 struct ifnet *ifp_port;
553 struct laggreqport *rp;
554 struct lagg_port *lp;
555 struct psref psref;
556 size_t i;
557 int error, bound;
558
559 error = 0;
560 bound = curlwp_bind();
561
562 switch (lrq->lrq_ioctl) {
563 case LAGGIOC_SETPROTO:
564 if (lrq->lrq_proto >= LAGG_PROTO_MAX) {
565 error = EPROTONOSUPPORT;
566 break;
567 }
568
569 error = lagg_delport_all(sc);
570 if (error != 0)
571 break;
572 error = lagg_pr_attach(sc, lrq->lrq_proto);
573 if (error != 0)
574 break;
575
576 for (i = 0; i < lrq->lrq_nports; i++) {
577 rp = &lrq->lrq_reqports[i];
578 ifp_port = if_get(rp->rp_portname, &psref);
579 if (ifp_port == NULL) {
580 error = ENOENT;
581 break; /* break for */
582 }
583
584 error = lagg_addport(sc, ifp_port);
585 if_put(ifp_port, &psref);
586
587 if (error != 0)
588 break; /* break for */
589 }
590 break; /* break switch */
591 case LAGGIOC_ADDPORT:
592 rp = &lrq->lrq_reqports[0];
593 ifp_port = if_get(rp->rp_portname, &psref);
594 if (ifp_port == NULL) {
595 error = ENOENT;
596 break;
597 }
598
599 error = lagg_addport(sc, ifp_port);
600 if_put(ifp_port, &psref);
601 break;
602 case LAGGIOC_DELPORT:
603 rp = &lrq->lrq_reqports[0];
604 ifp_port = if_get(rp->rp_portname, &psref);
605 if (ifp_port == NULL) {
606 error = ENOENT;
607 break;
608 }
609
610 error = lagg_delport(sc, ifp_port);
611 if_put(ifp_port, &psref);
612 break;
613 case LAGGIOC_SETPORTPRI:
614 rp = &lrq->lrq_reqports[0];
615 ifp_port = if_get(rp->rp_portname, &psref);
616 if (ifp_port == NULL) {
617 error = ENOENT;
618 break;
619 }
620
621 lp = ifp_port->if_lagg;
622 if (lp == NULL || lp->lp_softc != sc) {
623 if_put(ifp_port, &psref);
624 error = ENOENT;
625 break;
626 }
627
628 lp->lp_prio = rp->rp_prio;
629
630 /* restart protocol */
631 LAGG_LOCK(sc);
632 lagg_proto_stopport(sc, lp);
633 lagg_proto_startport(sc, lp);
634 LAGG_UNLOCK(sc);
635 if_put(ifp_port, &psref);
636 break;
637 case LAGGIOC_SETPROTOOPT:
638 error = lagg_proto_ioctl(sc, lrq);
639 break;
640 default:
641 error = ENOTTY;
642 }
643
644 curlwp_bindx(bound);
645 return error;
646 }
647
648 static int
lagg_ioctl(struct ifnet * ifp,u_long cmd,void * data)649 lagg_ioctl(struct ifnet *ifp, u_long cmd, void *data)
650 {
651 struct lagg_softc *sc;
652 struct ifreq *ifr = (struct ifreq *)data;
653 struct lagg_req laggreq, *laggresp;
654 struct lagg_port *lp;
655 size_t allocsiz, outlen, nports;
656 char *outbuf;
657 void *buf;
658 int error = 0, rv;
659
660 sc = ifp->if_softc;
661
662 switch (cmd) {
663 case SIOCGLAGG:
664 error = copyin(ifr->ifr_data, &laggreq, sizeof(laggreq));
665 if (error != 0)
666 break;
667
668 nports = sc->sc_nports;
669 nports = MIN(nports, laggreq.lrq_nports);
670
671 allocsiz = sizeof(*laggresp)
672 + sizeof(laggresp->lrq_reqports[0]) * nports;
673 laggresp = kmem_zalloc(allocsiz, KM_SLEEP);
674
675 rv = lagg_get_stats(sc, laggresp, nports);
676
677 outbuf = (char *)laggresp;
678
679 nports = MIN(laggresp->lrq_nports, nports);
680 outlen = sizeof(*laggresp)
681 + sizeof(laggresp->lrq_reqports[0]) * nports;
682
683 error = copyout(outbuf, ifr->ifr_data, outlen);
684 kmem_free(outbuf, allocsiz);
685
686 if (error == 0 && rv != 0)
687 error = rv;
688
689 break;
690 case SIOCSLAGG:
691 error = copyin(ifr->ifr_data, &laggreq, sizeof(laggreq));
692 if (error != 0)
693 break;
694
695 nports = laggreq.lrq_nports;
696 if (nports > LAGG_MAX_PORTS) {
697 error = ENOMEM;
698 break;
699 } else if (nports > 0) {
700 allocsiz = sizeof(struct lagg_req)
701 + sizeof(struct laggreqport) * nports;
702 buf = kmem_alloc(allocsiz, KM_SLEEP);
703
704 error = copyin(ifr->ifr_data, buf, allocsiz);
705 if (error != 0) {
706 kmem_free(buf, allocsiz);
707 break;
708 }
709 } else {
710 buf = (void *)&laggreq;
711 allocsiz = 0;
712 }
713
714 error = lagg_config(sc, buf);
715 if (allocsiz > 0)
716 kmem_free(buf, allocsiz);
717 break;
718 case SIOCSIFFLAGS:
719 error = ifioctl_common(ifp, cmd, data);
720 if (error != 0)
721 break;
722
723 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
724 case IFF_RUNNING:
725 if_stop(ifp, 1);
726 break;
727 case IFF_UP:
728 error = if_init(ifp);
729 break;
730 }
731
732 if (error != 0)
733 break;
734
735 /* Set flags on ports too */
736 LAGG_LOCK(sc);
737 LAGG_PORTS_FOREACH(sc, lp) {
738 (void)lagg_config_promisc(sc, lp);
739 }
740 LAGG_UNLOCK(sc);
741 break;
742 case SIOCSIFMTU:
743 /* set the MTU to each port */
744 LAGG_LOCK(sc);
745 LAGG_PORTS_FOREACH(sc, lp) {
746 error = lagg_lp_ioctl(lp, cmd, (void *)ifr);
747
748 if (error != 0) {
749 LAGG_LOG(sc, LOG_ERR,
750 "failed to change MTU to %d on port %s, "
751 "reverting all ports to original "
752 "MTU(%" PRIu64 ")\n",
753 ifr->ifr_mtu, lp->lp_ifp->if_xname,
754 ifp->if_mtu);
755 break;
756 }
757 }
758 LAGG_UNLOCK(sc);
759
760 /* set the MTU to the lagg interface */
761 if (error == 0)
762 error = ether_ioctl(ifp, cmd, data);
763
764 if (error != 0) {
765 /* undo the changed MTU */
766 ifr->ifr_mtu = ifp->if_mtu;
767
768 LAGG_LOCK(sc);
769 LAGG_PORTS_FOREACH(sc, lp) {
770 if (lp->lp_ioctl != NULL)
771 lagg_lp_ioctl(lp, cmd, (void *)ifr);
772 }
773 LAGG_UNLOCK(sc);
774 }
775 break;
776 case SIOCADDMULTI:
777 if (sc->sc_if.if_type == IFT_ETHER) {
778 error = lagg_ether_addmulti(sc, ifr);
779 } else {
780 error = EPROTONOSUPPORT;
781 }
782 break;
783 case SIOCDELMULTI:
784 if (sc->sc_if.if_type == IFT_ETHER) {
785 error = lagg_ether_delmulti(sc, ifr);
786 } else {
787 error = EPROTONOSUPPORT;
788 }
789 break;
790 case SIOCSIFCAP:
791 error = ether_ioctl(ifp, cmd, data);
792 if (error == 0)
793 lagg_sync_ifcaps(sc);
794 break;
795 case SIOCSETHERCAP:
796 error = ether_ioctl(ifp, cmd, data);
797 if (error == 0)
798 lagg_sync_ethcaps(sc);
799 break;
800 default:
801 error = ether_ioctl(ifp, cmd, data);
802 }
803 return error;
804 }
805
806 static int
lagg_setup_sysctls(struct lagg_softc * sc)807 lagg_setup_sysctls(struct lagg_softc *sc)
808 {
809 struct sysctllog **slog;
810 const struct sysctlnode **rnode, *hashnode;
811 const char *ifname;
812 int error;
813
814 slog = &sc->sc_sysctllog;
815 rnode = &sc->sc_sysctlnode;
816 ifname = sc->sc_if.if_xname;
817
818 error = sysctl_createv(slog, 0, NULL, rnode,
819 CTLFLAG_PERMANENT, CTLTYPE_NODE, ifname,
820 SYSCTL_DESCR("lagg information and settings"),
821 NULL, 0, NULL, 0, CTL_NET, CTL_CREATE, CTL_EOL);
822 if (error != 0)
823 goto done;
824
825 error = sysctl_createv(slog, 0, rnode, &hashnode,
826 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hash",
827 SYSCTL_DESCR("hash calculation settings"),
828 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
829 if (error != 0)
830 goto done;
831
832 error = sysctl_createv(slog, 0, &hashnode, NULL,
833 CTLFLAG_READWRITE, CTLTYPE_BOOL, "macaddr",
834 SYSCTL_DESCR("use src/dst mac addresses"),
835 NULL, 0, &sc->sc_hash_mac, 0, CTL_CREATE, CTL_EOL);
836 if (error != 0)
837 goto done;
838
839 error = sysctl_createv(slog, 0, &hashnode, NULL,
840 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ipaddr",
841 SYSCTL_DESCR("use src/dst IPv4 addresses"),
842 NULL, 0, &sc->sc_hash_ipaddr, 0, CTL_CREATE, CTL_EOL);
843 if (error != 0)
844 goto done;
845
846 error = sysctl_createv(slog, 0, &hashnode, NULL,
847 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ip6addr",
848 SYSCTL_DESCR("use src/dst IPv6 addresses"),
849 NULL, 0, &sc->sc_hash_ip6addr, 0, CTL_CREATE, CTL_EOL);
850 if (error != 0)
851 goto done;
852
853 error = sysctl_createv(slog, 0, &hashnode, NULL,
854 CTLFLAG_READWRITE, CTLTYPE_BOOL, "tcp",
855 SYSCTL_DESCR("use TCP src/dst port"),
856 NULL, 0, &sc->sc_hash_tcp, 0, CTL_CREATE, CTL_EOL);
857 if (error != 0)
858 goto done;
859
860 error = sysctl_createv(slog, 0, &hashnode, NULL,
861 CTLFLAG_READWRITE, CTLTYPE_BOOL, "udp",
862 SYSCTL_DESCR("use UDP src/dst port"),
863 NULL, 0, &sc->sc_hash_udp, 0, CTL_CREATE, CTL_EOL);
864 done:
865 if (error != 0) {
866 LAGG_LOG(sc, LOG_ERR, "unable to create sysctl node\n");
867 sysctl_teardown(slog);
868 }
869
870 return error;
871 }
872
873 static void
lagg_teardown_sysctls(struct lagg_softc * sc)874 lagg_teardown_sysctls(struct lagg_softc *sc)
875 {
876
877 sc->sc_sysctlnode = NULL;
878 sysctl_teardown(&sc->sc_sysctllog);
879 }
880
881 uint32_t
lagg_hashmbuf(struct lagg_softc * sc,struct mbuf * m)882 lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m)
883 {
884 union {
885 struct ether_header _eh;
886 struct ether_vlan_header _evl;
887 struct ip _ip;
888 struct ip6_hdr _ip6;
889 struct tcphdr _th;
890 struct udphdr _uh;
891 } buf;
892 const struct ether_header *eh;
893 const struct ether_vlan_header *evl;
894 const struct ip *ip;
895 const struct ip6_hdr *ip6;
896 const struct tcphdr *th;
897 const struct udphdr *uh;
898 uint32_t hash, hash_src, hash_dst;
899 uint32_t flowlabel;
900 uint16_t etype, vlantag;
901 uint8_t proto;
902 size_t off;
903
904 KASSERT(ISSET(m->m_flags, M_PKTHDR));
905
906 hash = HASH32_BUF_INIT;
907 hash_src = HASH32_BUF_INIT;
908 hash_dst = HASH32_BUF_INIT;
909
910 #define LAGG_HASH_ADD(hp, v) do { \
911 *(hp) = hash32_buf(&(v), sizeof(v), *(hp)); \
912 } while(0)
913
914 eh = lagg_m_extract(m, 0, sizeof(*eh), __alignof(*eh), &buf);
915 if (eh == NULL)
916 goto out;
917
918 off = ETHER_HDR_LEN;
919 etype = ntohs(eh->ether_type);
920
921 if (etype == ETHERTYPE_VLAN) {
922 evl = lagg_m_extract(m, 0, sizeof(*evl), __alignof(*evl),
923 &buf);
924 if (evl == NULL)
925 goto out;
926
927 vlantag = ntohs(evl->evl_tag);
928 etype = ntohs(evl->evl_proto);
929 off += ETHER_VLAN_ENCAP_LEN;
930 } else if (vlan_has_tag(m)) {
931 vlantag = vlan_get_tag(m);
932 } else {
933 vlantag = 0;
934 }
935
936 if (sc->sc_hash_mac) {
937 LAGG_HASH_ADD(&hash_dst, eh->ether_dhost);
938 LAGG_HASH_ADD(&hash_src, eh->ether_shost);
939 LAGG_HASH_ADD(&hash, vlantag);
940 }
941
942 switch (etype) {
943 case ETHERTYPE_IP:
944 ip = lagg_m_extract(m, off, sizeof(*ip), __alignof(*ip), &buf);
945 if (ip == NULL)
946 goto out;
947
948 if (sc->sc_hash_ipaddr) {
949 LAGG_HASH_ADD(&hash_src, ip->ip_src);
950 LAGG_HASH_ADD(&hash_dst, ip->ip_dst);
951 LAGG_HASH_ADD(&hash, ip->ip_p);
952 }
953 off += ip->ip_hl << 2;
954 proto = ip->ip_p;
955 break;
956 case ETHERTYPE_IPV6:
957 ip6 = lagg_m_extract(m, off, sizeof(*ip6), __alignof(*ip6),
958 &buf);
959 if (ip6 == NULL)
960 goto out;
961
962 if (sc->sc_hash_ip6addr) {
963 LAGG_HASH_ADD(&hash_src, ip6->ip6_src);
964 LAGG_HASH_ADD(&hash_dst, ip6->ip6_dst);
965 flowlabel = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
966 LAGG_HASH_ADD(&hash, flowlabel);
967 }
968 proto = ip6->ip6_nxt;
969 off += sizeof(*ip6);
970 break;
971
972 default:
973 return hash;
974 }
975
976 switch (proto) {
977 case IPPROTO_TCP:
978 th = lagg_m_extract(m, off, sizeof(*th), __alignof(*th), &buf);
979 if (th == NULL)
980 goto out;
981
982 if (sc->sc_hash_tcp) {
983 LAGG_HASH_ADD(&hash_src, th->th_sport);
984 LAGG_HASH_ADD(&hash_dst, th->th_dport);
985 }
986 break;
987 case IPPROTO_UDP:
988 uh = lagg_m_extract(m, off, sizeof(*uh), __alignof(*uh), &buf);
989 if (uh == NULL)
990 goto out;
991
992 if (sc->sc_hash_udp) {
993 LAGG_HASH_ADD(&hash_src, uh->uh_sport);
994 LAGG_HASH_ADD(&hash_dst, uh->uh_dport);
995 }
996 break;
997 }
998
999 out:
1000 hash_src ^= hash_dst;
1001 LAGG_HASH_ADD(&hash, hash_src);
1002 #undef LAGG_HASH_ADD
1003
1004 return hash;
1005 }
1006
1007 static int
lagg_tx_common(struct ifnet * ifp,struct mbuf * m)1008 lagg_tx_common(struct ifnet *ifp, struct mbuf *m)
1009 {
1010 struct lagg_variant *var;
1011 lagg_proto pr;
1012 struct psref psref;
1013 int error;
1014
1015 var = lagg_variant_getref(ifp->if_softc, &psref);
1016
1017 if (__predict_false(var == NULL)) {
1018 m_freem(m);
1019 if_statinc(ifp, if_oerrors);
1020 return ENOENT;
1021 }
1022
1023 pr = var->lv_proto;
1024 if (__predict_true(lagg_protos[pr].pr_transmit != NULL)) {
1025 error = lagg_protos[pr].pr_transmit(var->lv_psc, m);
1026 /* mbuf is already freed */
1027 } else {
1028 m_freem(m);
1029 if_statinc(ifp, if_oerrors);
1030 error = EIO;
1031 }
1032
1033 lagg_variant_putref(var, &psref);
1034
1035 return error;
1036 }
1037
1038 static int
lagg_transmit(struct ifnet * ifp,struct mbuf * m)1039 lagg_transmit(struct ifnet *ifp, struct mbuf *m)
1040 {
1041
1042 return lagg_tx_common(ifp, m);
1043 }
1044
1045 static void
lagg_start(struct ifnet * ifp)1046 lagg_start(struct ifnet *ifp)
1047 {
1048 struct mbuf *m;
1049
1050 for (;;) {
1051 IFQ_DEQUEUE(&ifp->if_snd, m);
1052 if (m == NULL)
1053 break;
1054
1055 (void)lagg_tx_common(ifp, m);
1056 }
1057 }
1058
1059 void
lagg_output(struct lagg_softc * sc,struct lagg_port * lp,struct mbuf * m)1060 lagg_output(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
1061 {
1062 struct ifnet *ifp;
1063 int len, error;
1064 short mflags;
1065
1066 ifp = &sc->sc_if;
1067 len = m->m_pkthdr.len;
1068 mflags = m->m_flags;
1069
1070 error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT);
1071 if (error != 0) {
1072 m_freem(m);
1073 return;
1074 }
1075 bpf_mtap(ifp, m, BPF_D_OUT);
1076
1077 error = lagg_port_xmit(lp, m);
1078 if (error) {
1079 /* mbuf is already freed */
1080 if_statinc(ifp, if_oerrors);
1081 } else {
1082 net_stat_ref_t nsr = IF_STAT_GETREF(ifp);
1083 if_statinc_ref(ifp, nsr, if_opackets);
1084 if_statadd_ref(ifp, nsr, if_obytes, len);
1085 if (mflags & M_MCAST)
1086 if_statinc_ref(ifp, nsr, if_omcasts);
1087 IF_STAT_PUTREF(ifp);
1088 }
1089 }
1090
1091 static struct mbuf *
lagg_proto_input(struct lagg_softc * sc,struct lagg_port * lp,struct mbuf * m)1092 lagg_proto_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
1093 {
1094 struct psref psref;
1095 struct lagg_variant *var;
1096 lagg_proto pr;
1097
1098 var = lagg_variant_getref(sc, &psref);
1099
1100 if (var == NULL) {
1101 sc->sc_novar.ev_count++;
1102 m_freem(m);
1103 return NULL;
1104 }
1105
1106 pr = var->lv_proto;
1107
1108 if (lagg_protos[pr].pr_input != NULL) {
1109 m = lagg_protos[pr].pr_input(var->lv_psc, lp, m);
1110 } else {
1111 m_freem(m);
1112 m = NULL;
1113 }
1114
1115 lagg_variant_putref(var, &psref);
1116
1117 return m;
1118 }
1119
1120 static void
lagg_input_ethernet(struct ifnet * ifp_port,struct mbuf * m)1121 lagg_input_ethernet(struct ifnet *ifp_port, struct mbuf *m)
1122 {
1123 struct ifnet *ifp;
1124 struct psref psref;
1125 struct lagg_port *lp;
1126 struct ether_header *eh;
1127 int s;
1128
1129 /* sanity check */
1130 s = pserialize_read_enter();
1131 lp = atomic_load_consume(&ifp_port->if_lagg);
1132 if (lp == NULL) {
1133 /* This interface is not a member of lagg */
1134 pserialize_read_exit(s);
1135 m_freem(m);
1136 if_statinc(ifp_port, if_ierrors);
1137 return;
1138 }
1139 lagg_port_getref(lp, &psref);
1140 pserialize_read_exit(s);
1141
1142 ifp = &lp->lp_softc->sc_if;
1143
1144 if (__predict_false(m->m_len < (int)sizeof(*eh))) {
1145 if ((m = m_pullup(m, sizeof(*eh))) == NULL) {
1146 if_statinc(ifp, if_ierrors);
1147 goto out;
1148 }
1149 }
1150
1151 eh = mtod(m, struct ether_header *);
1152
1153 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
1154 /*
1155 * If this is not a simplex interface, drop the packet
1156 * if it came from us.
1157 */
1158 if ((ifp->if_flags & IFF_SIMPLEX) == 0 &&
1159 memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost,
1160 ETHER_ADDR_LEN) == 0) {
1161 goto drop;
1162 }
1163
1164 if_statinc(ifp_port, if_imcasts);
1165 } else {
1166 /*
1167 * Drop promiscuously received packets
1168 * if we are not in promiscuous mode.
1169 */
1170 if ((ifp->if_flags & IFF_PROMISC) == 0 &&
1171 (ifp_port->if_flags & IFF_PROMISC) != 0 &&
1172 memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
1173 ETHER_ADDR_LEN) != 0)
1174 goto drop;
1175 }
1176
1177 if_statadd(ifp_port, if_ibytes, m->m_pkthdr.len);
1178
1179 if (pfil_run_hooks(ifp_port->if_pfil, &m,
1180 ifp_port, PFIL_IN) != 0) {
1181 m_freem(m);
1182 m = NULL;
1183 goto out;
1184 }
1185
1186 m = lagg_proto_input(lp->lp_softc, lp, m);
1187 if (m != NULL) {
1188 m_set_rcvif(m, ifp);
1189 m->m_flags &= ~M_PROMISC;
1190 if_input(ifp, m);
1191 }
1192
1193 out:
1194 lagg_port_putref(lp, &psref);
1195 return;
1196
1197 drop:
1198 lagg_port_putref(lp, &psref);
1199 m_freem(m);
1200 if_statinc(ifp_port, if_iqdrops);
1201 return;
1202 }
1203
1204 static int
lagg_media_change(struct ifnet * ifp)1205 lagg_media_change(struct ifnet *ifp)
1206 {
1207
1208 if (ISSET(ifp->if_flags, IFF_DEBUG))
1209 printf("%s: ignore media change\n", ifp->if_xname);
1210
1211 return 0;
1212 }
1213
1214 static void
lagg_media_status(struct ifnet * ifp,struct ifmediareq * imr)1215 lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1216 {
1217 struct lagg_softc *sc;
1218 struct lagg_port *lp;
1219
1220 sc = ifp->if_softc;
1221
1222 imr->ifm_status = IFM_AVALID;
1223 imr->ifm_active = IFM_ETHER | IFM_AUTO;
1224
1225 LAGG_LOCK(sc);
1226
1227 imr->ifm_active |= sc->sc_media_active;
1228
1229 LAGG_PORTS_FOREACH(sc, lp) {
1230 if (lagg_portactive(lp))
1231 imr->ifm_status |= IFM_ACTIVE;
1232 }
1233 LAGG_UNLOCK(sc);
1234 }
1235
1236 static uint64_t
lagg_search_media_type(uint64_t linkspeed)1237 lagg_search_media_type(uint64_t linkspeed)
1238 {
1239
1240 if (linkspeed == IF_Gbps(40))
1241 return IFM_40G_T | IFM_FDX;
1242
1243 if (linkspeed == IF_Gbps(25))
1244 return IFM_25G_T | IFM_FDX;
1245
1246 if (linkspeed == IF_Gbps(10))
1247 return IFM_10G_T | IFM_FDX;
1248
1249 if (linkspeed == IF_Gbps(5))
1250 return IFM_5000_T | IFM_FDX;
1251
1252 if (linkspeed == IF_Mbps(2500))
1253 return IFM_2500_T | IFM_FDX;
1254
1255 if (linkspeed == IF_Gbps(1))
1256 return IFM_1000_T | IFM_FDX;
1257
1258 if (linkspeed == IF_Mbps(100))
1259 return IFM_100_TX | IFM_FDX;
1260
1261 if (linkspeed == IF_Mbps(10))
1262 return IFM_10_T | IFM_FDX;
1263
1264 return 0;
1265 }
1266
1267 void
lagg_set_linkspeed(struct lagg_softc * sc,uint64_t linkspeed)1268 lagg_set_linkspeed(struct lagg_softc *sc, uint64_t linkspeed)
1269 {
1270 struct ifnet *ifp;
1271
1272 ifp = &sc->sc_if;
1273
1274 KASSERT(LAGG_LOCKED(sc));
1275
1276 ifp->if_baudrate = linkspeed;
1277
1278 sc->sc_media_active =
1279 lagg_search_media_type(linkspeed);
1280 }
1281
1282 static int
lagg_port_vlan_cb(struct lagg_port * lp,struct lagg_vlantag * lvt,bool set)1283 lagg_port_vlan_cb(struct lagg_port *lp,
1284 struct lagg_vlantag *lvt, bool set)
1285 {
1286 struct ifnet *ifp_port;
1287 int error;
1288
1289 if (lp->lp_iftype != IFT_ETHER)
1290 return 0;
1291
1292 error = 0;
1293 ifp_port = lp->lp_ifp;
1294
1295 if (set) {
1296 error = ether_add_vlantag(ifp_port,
1297 lvt->lvt_vtag, NULL);
1298 } else {
1299 error = ether_del_vlantag(ifp_port,
1300 lvt->lvt_vtag);
1301 }
1302
1303 return error;
1304 }
1305
1306 static int
lagg_vlan_cb(struct ethercom * ec,uint16_t vtag,bool set)1307 lagg_vlan_cb(struct ethercom *ec, uint16_t vtag, bool set)
1308 {
1309 struct ifnet *ifp;
1310 struct lagg_softc *sc;
1311 struct lagg_vlantag *lvt, *lvt0;
1312 struct lagg_port *lp;
1313 int error;
1314
1315 ifp = (struct ifnet *)ec;
1316 sc = ifp->if_softc;
1317
1318 if (set) {
1319 lvt = kmem_zalloc(sizeof(*lvt), KM_SLEEP);
1320 lvt->lvt_vtag = vtag;
1321 TAILQ_INSERT_TAIL(&sc->sc_vtags, lvt, lvt_entry);
1322 } else {
1323 TAILQ_FOREACH_SAFE(lvt, &sc->sc_vtags, lvt_entry, lvt0) {
1324 if (lvt->lvt_vtag == vtag) {
1325 TAILQ_REMOVE(&sc->sc_vtags, lvt, lvt_entry);
1326 break;
1327 }
1328 }
1329
1330 if (lvt == NULL)
1331 return ENOENT;
1332 }
1333
1334 KASSERT(lvt != NULL);
1335 LAGG_PORTS_FOREACH(sc, lp) {
1336 error = lagg_port_vlan_cb(lp, lvt, set);
1337 if (error != 0) {
1338 LAGG_LOG(sc, LOG_WARNING,
1339 "%s failed to configure vlan on %d\n",
1340 lp->lp_ifp->if_xname, error);
1341 }
1342 }
1343
1344 return 0;
1345 }
1346
1347 static struct lagg_softc *
lagg_softc_alloc(enum lagg_iftypes ift)1348 lagg_softc_alloc(enum lagg_iftypes ift)
1349 {
1350 struct lagg_softc *sc;
1351 size_t s;
1352
1353 s = lagg_sizeof_softc(ift);
1354 KASSERT(s > 0);
1355
1356 sc = kmem_zalloc(s, KM_SLEEP);
1357 KASSERT(sc != NULL);
1358
1359 return sc;
1360 }
1361
1362 static void
lagg_softc_free(struct lagg_softc * sc)1363 lagg_softc_free(struct lagg_softc *sc)
1364 {
1365
1366 kmem_free(sc,
1367 lagg_sizeof_softc(sc->sc_iftype));
1368 }
1369
1370 static void
lagg_variant_update(struct lagg_softc * sc,struct lagg_variant * newvar)1371 lagg_variant_update(struct lagg_softc *sc, struct lagg_variant *newvar)
1372 {
1373 struct lagg_variant *oldvar;
1374
1375 KASSERT(LAGG_LOCKED(sc));
1376
1377 psref_target_init(&newvar->lv_psref, lagg_psref_class);
1378
1379 oldvar = sc->sc_var;
1380 atomic_store_release(&sc->sc_var, newvar);
1381 pserialize_perform(sc->sc_psz);
1382
1383 if (__predict_true(oldvar != NULL))
1384 psref_target_destroy(&oldvar->lv_psref, lagg_psref_class);
1385 }
1386
1387 static struct lagg_variant *
lagg_variant_getref(struct lagg_softc * sc,struct psref * psref)1388 lagg_variant_getref(struct lagg_softc *sc, struct psref *psref)
1389 {
1390 struct lagg_variant *var;
1391 int s;
1392
1393 s = pserialize_read_enter();
1394 var = atomic_load_consume(&sc->sc_var);
1395 if (var == NULL) {
1396 pserialize_read_exit(s);
1397 return NULL;
1398 }
1399
1400 psref_acquire(psref, &var->lv_psref, lagg_psref_class);
1401 pserialize_read_exit(s);
1402
1403 return var;
1404 }
1405
1406 static void
lagg_variant_putref(struct lagg_variant * var,struct psref * psref)1407 lagg_variant_putref(struct lagg_variant *var, struct psref *psref)
1408 {
1409
1410 if (__predict_false(var == NULL))
1411 return;
1412 psref_release(psref, &var->lv_psref, lagg_psref_class);
1413 }
1414
1415 static int
lagg_proto_attach(struct lagg_softc * sc,lagg_proto pr,struct lagg_proto_softc ** psc)1416 lagg_proto_attach(struct lagg_softc *sc, lagg_proto pr,
1417 struct lagg_proto_softc **psc)
1418 {
1419
1420 KASSERT(lagg_protos[pr].pr_attach != NULL);
1421 return lagg_protos[pr].pr_attach(sc, psc);
1422 }
1423
1424 static void
lagg_proto_detach(struct lagg_variant * oldvar)1425 lagg_proto_detach(struct lagg_variant *oldvar)
1426 {
1427 lagg_proto pr;
1428
1429 pr = oldvar->lv_proto;
1430
1431 if (lagg_protos[pr].pr_detach == NULL)
1432 return;
1433
1434 lagg_protos[pr].pr_detach(oldvar->lv_psc);
1435 }
1436
1437 static int
lagg_proto_updown(struct lagg_softc * sc,bool is_up)1438 lagg_proto_updown(struct lagg_softc *sc, bool is_up)
1439 {
1440 struct lagg_variant *var;
1441 struct psref psref;
1442 lagg_proto pr;
1443 int error, bound;
1444
1445 error = 0;
1446 bound = curlwp_bind();
1447
1448 var = lagg_variant_getref(sc, &psref);
1449 if (var == NULL) {
1450 curlwp_bindx(bound);
1451 return ENXIO;
1452 }
1453
1454 pr = var->lv_proto;
1455
1456 if (is_up && lagg_protos[pr].pr_up != NULL) {
1457 error = lagg_protos[pr].pr_up(var->lv_psc);
1458 } else if (!is_up && lagg_protos[pr].pr_down != NULL) {
1459 lagg_protos[pr].pr_down(var->lv_psc);
1460 }
1461
1462 lagg_variant_putref(var, &psref);
1463 curlwp_bindx(bound);
1464
1465 return error;
1466 }
1467
1468 static int
lagg_proto_up(struct lagg_softc * sc)1469 lagg_proto_up(struct lagg_softc *sc)
1470 {
1471
1472 return lagg_proto_updown(sc, true);
1473 }
1474
1475 static void
lagg_proto_down(struct lagg_softc * sc)1476 lagg_proto_down(struct lagg_softc *sc)
1477 {
1478
1479 (void)lagg_proto_updown(sc, false);
1480 }
1481
1482 static int
lagg_proto_portctrl(struct lagg_softc * sc,struct lagg_port * lp,enum lagg_portctrl ctrl)1483 lagg_proto_portctrl(struct lagg_softc *sc, struct lagg_port *lp,
1484 enum lagg_portctrl ctrl)
1485 {
1486 struct lagg_variant *var;
1487 struct psref psref;
1488 lagg_proto pr;
1489 int error, bound;
1490
1491 error = 0;
1492 bound = curlwp_bind();
1493
1494 var = lagg_variant_getref(sc, &psref);
1495 if (var == NULL) {
1496 curlwp_bindx(bound);
1497 return ENXIO;
1498 }
1499
1500 pr = var->lv_proto;
1501
1502 switch (ctrl) {
1503 case LAGG_PORTCTRL_ALLOC:
1504 if (lagg_protos[pr].pr_allocport == NULL) {
1505 goto nosupport;
1506 }
1507 error = lagg_protos[pr].pr_allocport(var->lv_psc, lp);
1508 break;
1509 case LAGG_PORTCTRL_FREE:
1510 if (lagg_protos[pr].pr_freeport == NULL) {
1511 goto nosupport;
1512 }
1513 lagg_protos[pr].pr_freeport(var->lv_psc, lp);
1514 break;
1515 case LAGG_PORTCTRL_START:
1516 if (lagg_protos[pr].pr_startport == NULL) {
1517 goto nosupport;
1518 }
1519 lagg_protos[pr].pr_startport(var->lv_psc, lp);
1520 break;
1521 case LAGG_PORTCTRL_STOP:
1522 if (lagg_protos[pr].pr_stopport == NULL) {
1523 goto nosupport;
1524 }
1525 lagg_protos[pr].pr_stopport(var->lv_psc, lp);
1526 break;
1527 default:
1528 goto nosupport;
1529 }
1530
1531 lagg_variant_putref(var, &psref);
1532 curlwp_bindx(bound);
1533 return error;
1534
1535 nosupport:
1536 lagg_variant_putref(var, &psref);
1537 curlwp_bindx(bound);
1538 return EPROTONOSUPPORT;
1539 }
1540
1541 static int
lagg_proto_allocport(struct lagg_softc * sc,struct lagg_port * lp)1542 lagg_proto_allocport(struct lagg_softc *sc, struct lagg_port *lp)
1543 {
1544
1545 return lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_ALLOC);
1546 }
1547
1548 static void
lagg_proto_freeport(struct lagg_softc * sc,struct lagg_port * lp)1549 lagg_proto_freeport(struct lagg_softc *sc, struct lagg_port *lp)
1550 {
1551
1552 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_FREE);
1553 }
1554
1555 static void
lagg_proto_startport(struct lagg_softc * sc,struct lagg_port * lp)1556 lagg_proto_startport(struct lagg_softc *sc, struct lagg_port *lp)
1557 {
1558
1559 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_START);
1560 }
1561
1562 static void
lagg_proto_stopport(struct lagg_softc * sc,struct lagg_port * lp)1563 lagg_proto_stopport(struct lagg_softc *sc, struct lagg_port *lp)
1564 {
1565
1566 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_STOP);
1567 }
1568
1569 static void
lagg_proto_linkstate(struct lagg_softc * sc,struct lagg_port * lp)1570 lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp)
1571 {
1572 struct lagg_variant *var;
1573 struct psref psref;
1574 lagg_proto pr;
1575 int bound;
1576
1577 KASSERT(IFNET_LOCKED(lp->lp_ifp));
1578
1579 bound = curlwp_bind();
1580 var = lagg_variant_getref(sc, &psref);
1581
1582 if (var == NULL) {
1583 curlwp_bindx(bound);
1584 return;
1585 }
1586
1587 pr = var->lv_proto;
1588
1589 if (lagg_protos[pr].pr_linkstate)
1590 lagg_protos[pr].pr_linkstate(var->lv_psc, lp);
1591
1592 lagg_variant_putref(var, &psref);
1593 curlwp_bindx(bound);
1594 }
1595
1596 static void
lagg_proto_stat(struct lagg_variant * var,struct laggreqproto * resp)1597 lagg_proto_stat(struct lagg_variant *var, struct laggreqproto *resp)
1598 {
1599 lagg_proto pr;
1600
1601 pr = var->lv_proto;
1602
1603 if (lagg_protos[pr].pr_protostat != NULL)
1604 lagg_protos[pr].pr_protostat(var->lv_psc, resp);
1605 }
1606
1607 static void
lagg_proto_portstat(struct lagg_variant * var,struct lagg_port * lp,struct laggreqport * resp)1608 lagg_proto_portstat(struct lagg_variant *var, struct lagg_port *lp,
1609 struct laggreqport *resp)
1610 {
1611 lagg_proto pr;
1612
1613 pr = var->lv_proto;
1614
1615 if (lagg_protos[pr].pr_portstat != NULL)
1616 lagg_protos[pr].pr_portstat(var->lv_psc, lp, resp);
1617 }
1618
1619 static int
lagg_proto_ioctl(struct lagg_softc * sc,struct lagg_req * lreq)1620 lagg_proto_ioctl(struct lagg_softc *sc, struct lagg_req *lreq)
1621 {
1622 struct lagg_variant *var;
1623 struct psref psref;
1624 lagg_proto pr;
1625 int bound, error;
1626
1627 error = ENOTTY;
1628 bound = curlwp_bind();
1629 var = lagg_variant_getref(sc, &psref);
1630
1631 if (var == NULL) {
1632 error = ENXIO;
1633 goto done;
1634 }
1635
1636 pr = var->lv_proto;
1637 if (pr != lreq->lrq_proto) {
1638 error = EBUSY;
1639 goto done;
1640 }
1641
1642 if (lagg_protos[pr].pr_ioctl != NULL) {
1643 error = lagg_protos[pr].pr_ioctl(var->lv_psc,
1644 &lreq->lrq_reqproto);
1645 }
1646
1647 done:
1648 if (var != NULL)
1649 lagg_variant_putref(var, &psref);
1650 curlwp_bindx(bound);
1651 return error;
1652 }
1653
1654 static int
lagg_pr_attach(struct lagg_softc * sc,lagg_proto pr)1655 lagg_pr_attach(struct lagg_softc *sc, lagg_proto pr)
1656 {
1657 struct lagg_variant *newvar, *oldvar;
1658 struct lagg_proto_softc *psc;
1659 int error;
1660
1661 error = 0;
1662 newvar = kmem_alloc(sizeof(*newvar), KM_SLEEP);
1663
1664 LAGG_LOCK(sc);
1665 oldvar = sc->sc_var;
1666
1667 if (oldvar != NULL && oldvar->lv_proto == pr) {
1668 error = 0;
1669 goto failed;
1670 }
1671
1672 error = lagg_proto_attach(sc, pr, &psc);
1673 if (error != 0)
1674 goto failed;
1675
1676 newvar->lv_proto = pr;
1677 newvar->lv_psc = psc;
1678 lagg_variant_update(sc, newvar);
1679 lagg_set_linkspeed(sc, 0);
1680 LAGG_UNLOCK(sc);
1681
1682 if (oldvar != NULL) {
1683 lagg_proto_detach(oldvar);
1684 kmem_free(oldvar, sizeof(*oldvar));
1685 }
1686
1687 return 0;
1688
1689 failed:
1690 LAGG_UNLOCK(sc);
1691 kmem_free(newvar, sizeof(*newvar));
1692
1693 return error;
1694 }
1695
1696 static void
lagg_pr_detach(struct lagg_softc * sc)1697 lagg_pr_detach(struct lagg_softc *sc)
1698 {
1699 struct lagg_variant *var;
1700
1701 LAGG_LOCK(sc);
1702 var = sc->sc_var;
1703 atomic_store_release(&sc->sc_var, NULL);
1704 LAGG_UNLOCK(sc);
1705 pserialize_perform(sc->sc_psz);
1706
1707 if (var != NULL)
1708 lagg_proto_detach(var);
1709
1710
1711 if (var != NULL)
1712 kmem_free(var, sizeof(*var));
1713 }
1714
1715 static int
lagg_ether_addmulti(struct lagg_softc * sc,struct ifreq * ifr)1716 lagg_ether_addmulti(struct lagg_softc *sc, struct ifreq *ifr)
1717 {
1718 struct lagg_port *lp;
1719 struct lagg_mc_entry *mc;
1720 struct ethercom *ec;
1721 const struct sockaddr *sa;
1722 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1723 int error;
1724
1725 if (sc->sc_if.if_type != IFT_ETHER)
1726 return EPROTONOSUPPORT;
1727
1728 ec = (struct ethercom *)&sc->sc_if;
1729 sa = ifreq_getaddr(SIOCADDMULTI, ifr);
1730
1731 error = ether_addmulti(sa, ec);
1732 if (error != ENETRESET)
1733 return error;
1734
1735 error = ether_multiaddr(sa, addrlo, addrhi);
1736 KASSERT(error == 0);
1737
1738 mc = kmem_zalloc(sizeof(*mc), KM_SLEEP);
1739
1740 ETHER_LOCK(ec);
1741 mc->mc_enm = ether_lookup_multi(addrlo, addrhi, ec);
1742 ETHER_UNLOCK(ec);
1743
1744 KASSERT(mc->mc_enm != NULL);
1745
1746 LAGG_LOCK(sc);
1747 LAGG_PORTS_FOREACH(sc, lp) {
1748 (void)lagg_lp_ioctl(lp, SIOCADDMULTI, (void *)ifr);
1749 }
1750 LAGG_UNLOCK(sc);
1751
1752 KASSERT(sa->sa_len <= sizeof(mc->mc_addr));
1753 memcpy(&mc->mc_addr, sa, sa->sa_len);
1754 LIST_INSERT_HEAD(&sc->sc_mclist, mc, mc_entry);
1755
1756 return 0;
1757 }
1758
1759 static int
lagg_ether_delmulti(struct lagg_softc * sc,struct ifreq * ifr)1760 lagg_ether_delmulti(struct lagg_softc *sc, struct ifreq *ifr)
1761 {
1762 struct lagg_port *lp;
1763 struct lagg_mc_entry *mc;
1764 const struct sockaddr *sa;
1765 struct ethercom *ec;
1766 struct ether_multi *enm;
1767 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1768 int error;
1769
1770 ec = (struct ethercom *)&sc->sc_if;
1771 sa = ifreq_getaddr(SIOCDELMULTI, ifr);
1772 error = ether_multiaddr(sa, addrlo, addrhi);
1773 if (error != 0)
1774 return error;
1775
1776 ETHER_LOCK(ec);
1777 enm = ether_lookup_multi(addrlo, addrhi, ec);
1778 ETHER_UNLOCK(ec);
1779
1780 if (enm == NULL)
1781 return ENOENT;
1782
1783 LIST_FOREACH(mc, &sc->sc_mclist, mc_entry) {
1784 if (mc->mc_enm == enm)
1785 break;
1786 }
1787
1788 if (mc == NULL)
1789 return ENOENT;
1790
1791 error = ether_delmulti(sa, ec);
1792 if (error != ENETRESET)
1793 return error;
1794
1795 LAGG_LOCK(sc);
1796 LAGG_PORTS_FOREACH(sc, lp) {
1797 (void)lagg_lp_ioctl(lp, SIOCDELMULTI, (void *)ifr);
1798 }
1799 LAGG_UNLOCK(sc);
1800
1801 LIST_REMOVE(mc, mc_entry);
1802 kmem_free(mc, sizeof(*mc));
1803
1804 return 0;
1805 }
1806
1807 static void
lagg_port_multi(struct lagg_softc * sc,struct lagg_port * lp,u_long cmd)1808 lagg_port_multi(struct lagg_softc *sc, struct lagg_port *lp,
1809 u_long cmd)
1810 {
1811 struct lagg_mc_entry *mc;
1812 struct ifreq ifr;
1813 struct ifnet *ifp_port;
1814 const struct sockaddr *sa;
1815
1816 ifp_port = lp->lp_ifp;
1817
1818 memset(&ifr, 0, sizeof(ifr));
1819 strlcpy(ifr.ifr_name, ifp_port->if_xname, sizeof(ifr.ifr_name));
1820
1821 LIST_FOREACH(mc, &sc->sc_mclist, mc_entry) {
1822 sa = (struct sockaddr *)&mc->mc_addr;
1823 KASSERT(sizeof(ifr.ifr_space) >= sa->sa_len);
1824 memcpy(&ifr.ifr_addr, sa, sa->sa_len);
1825 (void)lagg_lp_ioctl(lp, cmd, (void *)&ifr);
1826 }
1827
1828 }
1829
1830 static void
lagg_port_syncmulti(struct lagg_softc * sc,struct lagg_port * lp)1831 lagg_port_syncmulti(struct lagg_softc *sc, struct lagg_port *lp)
1832 {
1833
1834 lagg_port_multi(sc, lp, SIOCADDMULTI);
1835 }
1836
1837 static void
lagg_port_purgemulti(struct lagg_softc * sc,struct lagg_port * lp)1838 lagg_port_purgemulti(struct lagg_softc *sc, struct lagg_port *lp)
1839 {
1840
1841 lagg_port_multi(sc, lp, SIOCDELMULTI);
1842 }
1843
1844 static void
lagg_port_vlan(struct lagg_softc * sc,struct lagg_port * lp,bool set)1845 lagg_port_vlan(struct lagg_softc *sc, struct lagg_port *lp,
1846 bool set)
1847 {
1848 struct lagg_vlantag *lvt;
1849 int error;
1850
1851 TAILQ_FOREACH(lvt, &sc->sc_vtags, lvt_entry) {
1852 error = lagg_port_vlan_cb(lp, lvt, set);
1853 if (error != 0) {
1854 LAGG_LOG(sc, LOG_WARNING,
1855 "%s failed to configure vlan on %d\n",
1856 lp->lp_ifp->if_xname, error);
1857 }
1858 }
1859 }
1860
1861 static void
lagg_port_syncvlan(struct lagg_softc * sc,struct lagg_port * lp)1862 lagg_port_syncvlan(struct lagg_softc *sc, struct lagg_port *lp)
1863
1864 {
1865 lagg_port_vlan(sc, lp, true);
1866 }
1867
1868 static void
lagg_port_purgevlan(struct lagg_softc * sc,struct lagg_port * lp)1869 lagg_port_purgevlan(struct lagg_softc *sc, struct lagg_port *lp)
1870 {
1871
1872 lagg_port_vlan(sc, lp, false);
1873 }
1874
1875 static int
lagg_setifcaps(struct lagg_port * lp,uint64_t cap)1876 lagg_setifcaps(struct lagg_port *lp, uint64_t cap)
1877 {
1878 struct ifcapreq ifcr;
1879 int error;
1880
1881 if (lp->lp_ifp->if_capenable == cap)
1882 return 0;
1883
1884 memset(&ifcr, 0, sizeof(ifcr));
1885 ifcr.ifcr_capenable = cap;
1886
1887 IFNET_LOCK(lp->lp_ifp);
1888 error = LAGG_PORT_IOCTL(lp, SIOCSIFCAP, &ifcr);
1889 IFNET_UNLOCK(lp->lp_ifp);
1890
1891 return error;
1892 }
1893
1894 static void
lagg_sync_ifcaps(struct lagg_softc * sc)1895 lagg_sync_ifcaps(struct lagg_softc *sc)
1896 {
1897 struct lagg_port *lp;
1898 struct ifnet *ifp;
1899 int error = 0;
1900
1901 ifp = (struct ifnet *)&sc->sc_if;
1902
1903 LAGG_LOCK(sc);
1904 LAGG_PORTS_FOREACH(sc, lp) {
1905 error = lagg_setifcaps(lp, ifp->if_capenable);
1906
1907 if (error != 0) {
1908 LAGG_LOG(sc, LOG_WARNING,
1909 "failed to update capabilities "
1910 "of %s, error=%d\n",
1911 lp->lp_ifp->if_xname, error);
1912 }
1913 }
1914 LAGG_UNLOCK(sc);
1915 }
1916
1917 static int
lagg_setethcaps(struct lagg_port * lp,int cap)1918 lagg_setethcaps(struct lagg_port *lp, int cap)
1919 {
1920 struct ethercom *ec;
1921 struct eccapreq eccr;
1922 int error;
1923
1924 KASSERT(lp->lp_iftype == IFT_ETHER);
1925 ec = (struct ethercom *)lp->lp_ifp;
1926
1927 if (ec->ec_capenable == cap)
1928 return 0;
1929
1930 memset(&eccr, 0, sizeof(eccr));
1931 eccr.eccr_capenable = cap;
1932
1933 IFNET_LOCK(lp->lp_ifp);
1934 error = LAGG_PORT_IOCTL(lp, SIOCSETHERCAP, &eccr);
1935 IFNET_UNLOCK(lp->lp_ifp);
1936
1937 return error;
1938 }
1939
1940 static void
lagg_sync_ethcaps(struct lagg_softc * sc)1941 lagg_sync_ethcaps(struct lagg_softc *sc)
1942 {
1943 struct ethercom *ec;
1944 struct lagg_port *lp;
1945 int error;
1946
1947 ec = (struct ethercom *)&sc->sc_if;
1948
1949 LAGG_LOCK(sc);
1950 LAGG_PORTS_FOREACH(sc, lp) {
1951 if (lp->lp_iftype != IFT_ETHER)
1952 continue;
1953
1954 error = lagg_setethcaps(lp, ec->ec_capenable);
1955 if (error != 0) {
1956 LAGG_LOG(sc, LOG_WARNING,
1957 "failed to update ether "
1958 "capabilities"" of %s, error=%d\n",
1959 lp->lp_ifp->if_xname, error);
1960 }
1961
1962 }
1963 LAGG_UNLOCK(sc);
1964 }
1965
1966 static void
lagg_ifcap_update(struct lagg_softc * sc)1967 lagg_ifcap_update(struct lagg_softc *sc)
1968 {
1969 struct ifnet *ifp;
1970 struct lagg_port *lp;
1971 uint64_t cap, ena, pena;
1972 size_t i;
1973
1974 KASSERT(LAGG_LOCKED(sc));
1975
1976 /* Get common capabilities for the lagg ports */
1977 ena = ~(uint64_t)0;
1978 cap = ~(uint64_t)0;
1979 LAGG_PORTS_FOREACH(sc, lp) {
1980 ena &= lp->lp_ifp->if_capenable;
1981 cap &= lp->lp_ifp->if_capabilities;
1982 }
1983
1984 if (ena == ~(uint64_t)0)
1985 ena = 0;
1986 if (cap == ~(uint64_t)0)
1987 cap = 0;
1988
1989 /*
1990 * Apply common enabled capabilities back to the lagg ports.
1991 * May require several iterations if they are dependent.
1992 */
1993 for (i = 0; i < LAGG_SETCAPS_RETRY; i++) {
1994 pena = ena;
1995 LAGG_PORTS_FOREACH(sc, lp) {
1996 lagg_setifcaps(lp, ena);
1997 ena &= lp->lp_ifp->if_capenable;
1998 }
1999
2000 if (pena == ena)
2001 break;
2002 }
2003
2004 if (pena != ena) {
2005 LAGG_LOG(sc, LOG_DEBUG, "couldn't set "
2006 "capabilities 0x%08"PRIx64"\n", pena);
2007 }
2008
2009 ifp = &sc->sc_if;
2010
2011 if (ifp->if_capabilities != cap ||
2012 ifp->if_capenable != ena) {
2013 ifp->if_capabilities = cap;
2014 ifp->if_capenable = ena;
2015
2016 LAGG_LOG(sc, LOG_DEBUG,"capabilities "
2017 "0x%08"PRIx64" enabled 0x%08"PRIx64"\n",
2018 cap, ena);
2019 }
2020 }
2021
2022 static void
lagg_ethercap_update(struct lagg_softc * sc)2023 lagg_ethercap_update(struct lagg_softc *sc)
2024 {
2025 struct ethercom *ec;
2026 struct lagg_port *lp;
2027 int cap, ena, pena;
2028 size_t i;
2029
2030 KASSERT(LAGG_LOCKED(sc));
2031
2032 if (sc->sc_if.if_type != IFT_ETHER)
2033 return;
2034
2035 if (SIMPLEQ_EMPTY(&sc->sc_ports)) {
2036 ena = 0;
2037 cap = ETHERCAP_VLAN_HWTAGGING;
2038 } else {
2039 /* Get common enabled capabilities for the lagg ports */
2040 ena = ~0;
2041 cap = ~0;
2042 LAGG_PORTS_FOREACH(sc, lp) {
2043 switch (lp->lp_iftype) {
2044 case IFT_ETHER:
2045 ec = (struct ethercom *)lp->lp_ifp;
2046 ena &= ec->ec_capenable;
2047 cap &= ec->ec_capabilities;
2048 break;
2049 case IFT_L2TP:
2050 ena &= (ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU);
2051 cap &= (ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU);
2052 break;
2053 default:
2054 ena = 0;
2055 cap = 0;
2056 }
2057 }
2058 }
2059
2060 /*
2061 * Apply common enabled capabilities back to the lagg ports.
2062 * May require several iterations if they are dependent.
2063 */
2064 for (i = 0; i < LAGG_SETCAPS_RETRY; i++) {
2065 pena = ena;
2066 LAGG_PORTS_FOREACH(sc, lp) {
2067 if (lp->lp_iftype != IFT_ETHER)
2068 continue;
2069
2070 ec = (struct ethercom *)lp->lp_ifp;
2071 lagg_setethcaps(lp, ena);
2072 ena &= ec->ec_capenable;
2073 }
2074
2075 if (pena == ena)
2076 break;
2077 }
2078
2079 if (pena != ena) {
2080 LAGG_LOG(sc, LOG_DEBUG, "couldn't set "
2081 "ether capabilities 0x%08x\n", pena);
2082 }
2083
2084 ec = (struct ethercom *)&sc->sc_if;
2085
2086 if (ec->ec_capabilities != cap ||
2087 ec->ec_capenable != ena) {
2088 ec->ec_capabilities = cap;
2089 ec->ec_capenable = ena;
2090
2091 LAGG_LOG(sc, LOG_DEBUG,
2092 "ether capabilities 0x%08x"
2093 " enabled 0x%08x\n", cap, ena);
2094 }
2095 }
2096
2097 static void
lagg_capabilities_update(struct lagg_softc * sc)2098 lagg_capabilities_update(struct lagg_softc *sc)
2099 {
2100
2101 lagg_ifcap_update(sc);
2102 lagg_ethercap_update(sc);
2103 }
2104
2105 static int
lagg_setmtu(struct ifnet * ifp,uint64_t mtu)2106 lagg_setmtu(struct ifnet *ifp, uint64_t mtu)
2107 {
2108 struct lagg_softc *sc __LAGGDEBUGUSED;
2109 struct lagg_port *lp;
2110 struct ifreq ifr;
2111 int error;
2112
2113 KASSERT(IFNET_LOCKED(ifp));
2114
2115 memset(&ifr, 0, sizeof(ifr));
2116 ifr.ifr_mtu = mtu;
2117 lp = ifp->if_lagg;
2118
2119 if (lp != NULL) {
2120 /* ioctl for port interface */
2121 error = lp->lp_ioctl(ifp, SIOCSIFMTU, &ifr);
2122 sc = lp->lp_softc;
2123 } else {
2124 /* ioctl for lagg interface */
2125 error = ether_ioctl(ifp, SIOCSIFMTU, &ifr);
2126 sc = ifp->if_softc;
2127 }
2128
2129 if (error != 0) {
2130 LAGG_DPRINTF(sc,
2131 "couldn't change MTU for %s\n",
2132 ifp->if_xname);
2133 }
2134
2135 return error;
2136 }
2137
2138 static void
lagg_port_setsadl(struct lagg_port * lp,const uint8_t * lladdr)2139 lagg_port_setsadl(struct lagg_port *lp, const uint8_t *lladdr)
2140 {
2141 struct ifnet *ifp_port;
2142 int error;
2143
2144 ifp_port = lp->lp_ifp;
2145
2146 KASSERT(LAGG_LOCKED(lp->lp_softc));
2147 KASSERT(IFNET_LOCKED(ifp_port));
2148
2149 switch (lp->lp_iftype) {
2150 case IFT_ETHER:
2151 if (lladdr == NULL) {
2152 lladdr = lp->lp_lladdr;
2153 } else {
2154 if (lagg_lladdr_equal(lladdr,
2155 CLLADDR(ifp_port->if_sadl)))
2156 break;
2157 }
2158
2159 lagg_chg_sadl(ifp_port,
2160 lladdr, ETHER_ADDR_LEN);
2161
2162 if (ifp_port->if_init != NULL) {
2163 error = 0;
2164 /* Apply updated ifp_port->if_sadl to the device */
2165 if (ISSET(ifp_port->if_flags, IFF_RUNNING))
2166 error = if_init(ifp_port);
2167
2168 if (error != 0) {
2169 LAGG_LOG(lp->lp_softc, LOG_WARNING,
2170 "%s failed to if_init() on %d\n",
2171 ifp_port->if_xname, error);
2172 }
2173 }
2174 break;
2175 default:
2176 if_alloc_sadl(ifp_port);
2177 break;
2178 }
2179 }
2180
2181 static void
lagg_if_setsadl(struct lagg_softc * sc,uint8_t * lladdr)2182 lagg_if_setsadl(struct lagg_softc *sc, uint8_t *lladdr)
2183 {
2184 struct ifnet *ifp;
2185
2186 KASSERT(LAGG_LOCKED(sc));
2187
2188 ifp = &sc->sc_if;
2189
2190 if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl), lladdr))
2191 return;
2192
2193 lagg_chg_sadl(ifp, lladdr, ETHER_ADDR_LEN);
2194
2195 LAGG_UNLOCK(sc);
2196 lagg_in6_ifdetach(ifp);
2197 lagg_in6_ifattach(ifp);
2198 LAGG_LOCK(sc);
2199
2200 lagg_sync_sadl(sc);
2201 }
2202
2203 static void
lagg_sync_sadl(struct lagg_softc * sc)2204 lagg_sync_sadl(struct lagg_softc *sc)
2205 {
2206 struct ifnet *ifp;
2207 struct lagg_port *lp;
2208 const uint8_t *lla;
2209
2210 ifp = &sc->sc_if;
2211 KASSERT(IFNET_LOCKED(ifp));
2212
2213 lla = CLLADDR(ifp->if_sadl);
2214 if (lagg_lladdr_equal(lla, sc->sc_lladdr))
2215 return;
2216
2217 lagg_lladdr_cpy(sc->sc_lladdr, lla);
2218
2219 LAGG_PORTS_FOREACH(sc, lp) {
2220 IFNET_LOCK(lp->lp_ifp);
2221 lagg_port_setsadl(lp, lla);
2222 IFNET_UNLOCK(lp->lp_ifp);
2223 }
2224 }
2225
2226 static int
lagg_port_setup(struct lagg_softc * sc,struct lagg_port * lp,struct ifnet * ifp_port)2227 lagg_port_setup(struct lagg_softc *sc,
2228 struct lagg_port *lp, struct ifnet *ifp_port)
2229 {
2230 struct ifnet *ifp;
2231 u_char if_type;
2232 int error;
2233 bool stopped, use_lagg_sadl;
2234
2235 KASSERT(LAGG_LOCKED(sc));
2236 IFNET_ASSERT_UNLOCKED(ifp_port);
2237
2238 ifp = &sc->sc_if;
2239
2240 use_lagg_sadl = true;
2241 if (SIMPLEQ_EMPTY(&sc->sc_ports) &&
2242 ifp_port->if_type == IFT_ETHER) {
2243 if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl),
2244 sc->sc_lladdr_rand))
2245 use_lagg_sadl = false;
2246 }
2247
2248 if (&sc->sc_if == ifp_port) {
2249 LAGG_DPRINTF(sc, "cannot add a lagg to itself as a port\n");
2250 return EINVAL;
2251 }
2252
2253 if (sc->sc_nports > LAGG_MAX_PORTS)
2254 return ENOSPC;
2255
2256 if (ifp_port->if_lagg != NULL) {
2257 lp = (struct lagg_port *)ifp_port->if_lagg;
2258 if (lp->lp_softc == sc)
2259 return EEXIST;
2260 return EBUSY;
2261 }
2262
2263 switch (ifp_port->if_type) {
2264 case IFT_ETHER:
2265 case IFT_L2TP:
2266 if (VLAN_ATTACHED((struct ethercom *)ifp_port))
2267 return EBUSY;
2268
2269 if_type = IFT_IEEE8023ADLAG;
2270 break;
2271 default:
2272 return ENOTSUP;
2273 }
2274
2275 error = 0;
2276 stopped = false;
2277 lp->lp_softc = sc;
2278 lp->lp_prio = LAGG_PORT_PRIO;
2279 lp->lp_linkstate_hook = if_linkstate_change_establish(ifp_port,
2280 lagg_linkstate_changed, ifp_port);
2281 lp->lp_ifdetach_hook = ether_ifdetachhook_establish(ifp_port,
2282 lagg_ifdetach, ifp_port);
2283 psref_target_init(&lp->lp_psref, lagg_port_psref_class);
2284
2285 IFNET_LOCK(ifp_port);
2286 /* stop packet processing */
2287 if (ISSET(ifp_port->if_flags, IFF_RUNNING) &&
2288 ifp_port->if_init != NULL) {
2289 if_stop(ifp_port, 0);
2290 stopped = true;
2291 }
2292
2293 /* to delete ipv6 link local address */
2294 lagg_in6_ifdetach(ifp_port);
2295
2296 /* backup members */
2297 lp->lp_iftype = ifp_port->if_type;
2298 lp->lp_ioctl = ifp_port->if_ioctl;
2299 lp->lp_input = ifp_port->_if_input;
2300 lp->lp_output = ifp_port->if_output;
2301 lp->lp_ifcapenable = ifp_port->if_capenable;
2302 lp->lp_mtu = ifp_port->if_mtu;
2303 if (lp->lp_iftype == IFT_ETHER) {
2304 struct ethercom *ec;
2305 ec = (struct ethercom *)ifp_port;
2306
2307 lagg_lladdr_cpy(lp->lp_lladdr, CLLADDR(ifp_port->if_sadl));
2308 lp->lp_eccapenable = ec->ec_capenable;
2309 }
2310
2311 /* change callbacks and others */
2312 atomic_store_release(&ifp_port->if_lagg, (void *)lp);
2313 ifp_port->if_type = if_type;
2314 ifp_port->if_ioctl = lagg_port_ioctl;
2315 ifp_port->_if_input = lagg_input_ethernet;
2316 ifp_port->if_output = lagg_port_output;
2317
2318 /* update Link address */
2319 if (use_lagg_sadl) {
2320 lagg_port_setsadl(lp, CLLADDR(ifp->if_sadl));
2321 } else {
2322 /* update if_type in if_sadl */
2323 if (lp->lp_iftype != ifp_port->if_type)
2324 lagg_port_setsadl(lp, NULL);
2325 }
2326
2327 error = lagg_setmtu(ifp_port, ifp->if_mtu);
2328 if (error != 0)
2329 goto restore_sadl;
2330
2331 error = lagg_proto_allocport(sc, lp);
2332 if (error != 0)
2333 goto restore_mtu;
2334
2335 /* restart packet processing */
2336 if (stopped) {
2337 error = if_init(ifp_port);
2338 if (error != 0)
2339 goto free_port;
2340 }
2341
2342 /* setup of ifp_port is complete */
2343 IFNET_UNLOCK(ifp_port);
2344
2345 /* copy sadl from added port to lagg */
2346 if (!use_lagg_sadl)
2347 lagg_if_setsadl(sc, lp->lp_lladdr);
2348
2349 SIMPLEQ_INSERT_TAIL(&sc->sc_ports, lp, lp_entry);
2350 sc->sc_nports++;
2351
2352 lagg_capabilities_update(sc);
2353 lagg_port_syncmulti(sc, lp);
2354 lagg_port_syncvlan(sc, lp);
2355 lagg_config_promisc(sc, lp);
2356
2357 lagg_proto_startport(sc, lp);
2358
2359 return 0;
2360
2361 free_port:
2362 KASSERT(IFNET_LOCKED(ifp_port));
2363 lagg_proto_freeport(sc, lp);
2364 restore_mtu:
2365 KASSERT(IFNET_LOCKED(ifp_port));
2366 if (ifp_port->if_mtu != lp->lp_mtu)
2367 lagg_setmtu(ifp_port, lp->lp_mtu);
2368 restore_sadl:
2369 KASSERT(IFNET_LOCKED(ifp_port));
2370
2371 /* restore if_type before changing sadl */
2372 if_type = ifp_port->if_type;
2373 ifp_port->if_type = lp->lp_iftype;
2374
2375 if (!SIMPLEQ_EMPTY(&sc->sc_ports)) {
2376 lagg_port_setsadl(lp, lp->lp_lladdr);
2377 } else {
2378 if (ifp_port->if_type != if_type)
2379 lagg_port_setsadl(lp, NULL);
2380 }
2381
2382 lagg_in6_ifattach(ifp_port);
2383 if (stopped) {
2384 if (if_init(ifp_port) != 0) {
2385 LAGG_LOG(sc, LOG_WARNING,
2386 "couldn't re-start port %s\n",
2387 ifp_port->if_xname);
2388 }
2389 }
2390
2391 ifp_port->if_ioctl = lp->lp_ioctl;
2392 ifp_port->_if_input = lp->lp_input;
2393 ifp_port->if_output = lp->lp_output;
2394 atomic_store_release(&ifp_port->if_lagg, NULL);
2395 IFNET_UNLOCK(ifp_port);
2396
2397 psref_target_destroy(&lp->lp_psref, lagg_port_psref_class);
2398 if_linkstate_change_disestablish(ifp_port,
2399 lp->lp_linkstate_hook, NULL);
2400 ether_ifdetachhook_disestablish(ifp_port,
2401 lp->lp_ifdetach_hook, &sc->sc_lock);
2402
2403 return error;
2404 }
2405
2406 static void
lagg_port_teardown(struct lagg_softc * sc,struct lagg_port * lp,bool is_ifdetach)2407 lagg_port_teardown(struct lagg_softc *sc, struct lagg_port *lp,
2408 bool is_ifdetach)
2409 {
2410 struct ifnet *ifp, *ifp_port;
2411 bool stopped, is_1st_port, iftype_changed;
2412
2413 KASSERT(LAGG_LOCKED(sc));
2414
2415 ifp = &sc->sc_if;
2416 ifp_port = lp->lp_ifp;
2417 stopped = false;
2418 is_1st_port =
2419 SIMPLEQ_FIRST(&sc->sc_ports) == lp ? true : false;
2420
2421 ether_ifdetachhook_disestablish(ifp_port,
2422 lp->lp_ifdetach_hook, &sc->sc_lock);
2423
2424 if (ifp_port->if_lagg == NULL) {
2425 /* already done in lagg_ifdetach() */
2426 return;
2427 }
2428
2429 if_linkstate_change_disestablish(ifp_port,
2430 lp->lp_linkstate_hook, NULL);
2431
2432 lagg_proto_stopport(sc, lp);
2433
2434 lagg_port_purgemulti(sc, lp);
2435 lagg_port_purgevlan(sc, lp);
2436 if (is_ifdetach == false) {
2437 lagg_unconfig_promisc(sc, lp);
2438 lagg_setifcaps(lp, lp->lp_ifcapenable);
2439 if (lp->lp_iftype == IFT_ETHER)
2440 lagg_setethcaps(lp, lp->lp_eccapenable);
2441 }
2442
2443 SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry);
2444 sc->sc_nports--;
2445
2446 if (is_1st_port) {
2447 if (lp->lp_iftype == IFT_ETHER &&
2448 lagg_lladdr_equal(lp->lp_lladdr,
2449 CLLADDR(ifp->if_sadl))) {
2450 struct lagg_port *lp0;
2451 uint8_t *lla;
2452
2453 lp0 = SIMPLEQ_FIRST(&sc->sc_ports);
2454 if (lp0 != NULL &&
2455 lp0->lp_iftype == IFT_ETHER) {
2456 lla = lp0->lp_lladdr;
2457 } else {
2458 lla = sc->sc_lladdr_rand;
2459 }
2460
2461 lagg_if_setsadl(sc, lla);
2462 }
2463 }
2464
2465 IFNET_LOCK(ifp_port);
2466 /* stop packet processing */
2467 if (ISSET(ifp_port->if_flags, IFF_RUNNING) &&
2468 ifp_port->if_init != NULL) {
2469 if_stop(ifp_port, 0);
2470 stopped = true;
2471 }
2472
2473 lagg_proto_freeport(sc, lp);
2474
2475 /* change if_type before set sadl */
2476 iftype_changed = ifp_port->if_type != lp->lp_iftype ?
2477 true : false;
2478 ifp_port->if_type = lp->lp_iftype;
2479
2480 if (is_ifdetach == false) {
2481 if (iftype_changed &&
2482 lagg_lladdr_equal(CLLADDR(ifp_port->if_sadl),
2483 lp->lp_lladdr)) {
2484 lagg_port_setsadl(lp, NULL);
2485 }
2486 lagg_port_setsadl(lp, lp->lp_lladdr);
2487 lagg_in6_ifattach(ifp_port);
2488 (void)lagg_setmtu(ifp_port, lp->lp_mtu);
2489 }
2490
2491 ifp_port->_if_input = lp->lp_input;
2492 ifp_port->if_output = lp->lp_output;
2493 if (ifp_port->if_ioctl == lagg_port_ioctl)
2494 ifp_port->if_ioctl = lp->lp_ioctl;
2495 atomic_store_release(&ifp_port->if_lagg, NULL);
2496 pserialize_perform(sc->sc_psz);
2497
2498 /* to assign ipv6 link local address */
2499 if (is_ifdetach == false) {
2500 lagg_in6_ifattach(ifp_port);
2501 }
2502
2503 /* restart packet processing */
2504 if (stopped) {
2505 int error;
2506 error = if_init(ifp_port);
2507 if (error != 0) {
2508 LAGG_LOG(sc, LOG_WARNING,
2509 "%s failed to if_init() on %d\n",
2510 ifp_port->if_xname, error);
2511 }
2512 }
2513 IFNET_UNLOCK(ifp_port);
2514
2515 psref_target_destroy(&lp->lp_psref, lagg_port_psref_class);
2516 kmem_free(lp, sizeof(*lp));
2517 }
2518
2519 static int
lagg_addport(struct lagg_softc * sc,struct ifnet * ifp_port)2520 lagg_addport(struct lagg_softc *sc, struct ifnet *ifp_port)
2521 {
2522 struct lagg_port *lp;
2523 int error;
2524
2525 lp = kmem_zalloc(sizeof(*lp), KM_SLEEP);
2526 lp->lp_ifp = ifp_port;
2527
2528 LAGG_LOCK(sc);
2529 error = lagg_port_setup(sc, lp, ifp_port);
2530 LAGG_UNLOCK(sc);
2531
2532 if (error != 0)
2533 kmem_free(lp, sizeof(*lp));
2534
2535 return error;
2536 }
2537
2538 static int
lagg_delport(struct lagg_softc * sc,struct ifnet * ifp_port)2539 lagg_delport(struct lagg_softc *sc, struct ifnet *ifp_port)
2540 {
2541 struct lagg_port *lp;
2542 int error;
2543
2544 KASSERT(IFNET_LOCKED(&sc->sc_if));
2545
2546 error = 0;
2547 LAGG_LOCK(sc);
2548 lp = ifp_port->if_lagg;
2549 if (lp == NULL || lp->lp_softc != sc) {
2550 error = ENOENT;
2551 goto out;
2552 }
2553
2554 if (lp->lp_ifdetaching) {
2555 error = EBUSY;
2556 goto out;
2557 }
2558
2559 lagg_port_teardown(sc, lp, false);
2560
2561 out:
2562 LAGG_UNLOCK(sc);
2563
2564 return error;
2565 }
2566
2567 static int
lagg_delport_all(struct lagg_softc * sc)2568 lagg_delport_all(struct lagg_softc *sc)
2569 {
2570 struct lagg_port *lp;
2571 int error;
2572
2573 KASSERT(IFNET_LOCKED(&sc->sc_if));
2574
2575 error = 0;
2576
2577 LAGG_LOCK(sc);
2578 while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) {
2579 if (lp->lp_ifdetaching) {
2580 error = EBUSY;
2581 continue;
2582 }
2583
2584 lagg_port_teardown(sc, lp, false);
2585 }
2586
2587 LAGG_UNLOCK(sc);
2588
2589 return error;
2590 }
2591
2592 static int
lagg_get_stats(struct lagg_softc * sc,struct lagg_req * resp,size_t nports)2593 lagg_get_stats(struct lagg_softc *sc, struct lagg_req *resp,
2594 size_t nports)
2595 {
2596 struct lagg_variant *var;
2597 struct lagg_port *lp;
2598 struct laggreqport *port;
2599 struct psref psref;
2600 struct ifnet *ifp;
2601 int bound;
2602 size_t n;
2603
2604 bound = curlwp_bind();
2605 var = lagg_variant_getref(sc, &psref);
2606 if (var == NULL) {
2607 curlwp_bindx(bound);
2608 return ENOENT;
2609 }
2610
2611 resp->lrq_proto = var->lv_proto;
2612
2613 lagg_proto_stat(var, &resp->lrq_reqproto);
2614
2615 n = 0;
2616 LAGG_LOCK(sc);
2617 LAGG_PORTS_FOREACH(sc, lp) {
2618 if (n < nports) {
2619 port = &resp->lrq_reqports[n];
2620
2621 ifp = lp->lp_ifp;
2622 strlcpy(port->rp_portname, ifp->if_xname,
2623 sizeof(port->rp_portname));
2624
2625 port->rp_prio = lp->lp_prio;
2626 port->rp_flags = lp->lp_flags;
2627 lagg_proto_portstat(var, lp, port);
2628 }
2629 n++;
2630 }
2631 LAGG_UNLOCK(sc);
2632
2633 resp->lrq_nports = n;
2634
2635 lagg_variant_putref(var, &psref);
2636 curlwp_bindx(bound);
2637
2638 if (resp->lrq_nports > nports) {
2639 return ENOBUFS;
2640 }
2641 return 0;
2642 }
2643
2644 static void
lagg_config_promisc(struct lagg_softc * sc,struct lagg_port * lp)2645 lagg_config_promisc(struct lagg_softc *sc, struct lagg_port *lp)
2646 {
2647 struct ifnet *ifp, *ifp_port;
2648 int error;
2649 bool promisc;
2650
2651 KASSERT(LAGG_LOCKED(sc));
2652
2653 ifp = &sc->sc_if;
2654 ifp_port = lp->lp_ifp;
2655
2656 if (lp->lp_iftype == IFT_ETHER) {
2657 promisc = ISSET(ifp->if_flags, IFF_PROMISC) ?
2658 true : false;
2659 } else {
2660 promisc = true;
2661 }
2662
2663 if (lp->lp_promisc == promisc)
2664 return;
2665
2666 error = ifpromisc(ifp_port, promisc ? 1 : 0);
2667 if (error == ENETRESET) {
2668 error = ifp_port->if_init(ifp_port);
2669 }
2670
2671 if (error == 0) {
2672 lp->lp_promisc = promisc;
2673 } else {
2674 LAGG_LOG(sc, LOG_WARNING,
2675 "couldn't %s promisc on %s\n",
2676 promisc ? "set" : "unset",
2677 ifp_port->if_xname);
2678 }
2679 }
2680
2681 static void
lagg_unconfig_promisc(struct lagg_softc * sc,struct lagg_port * lp)2682 lagg_unconfig_promisc(struct lagg_softc *sc, struct lagg_port *lp)
2683 {
2684 struct ifnet *ifp_port;
2685 int error;
2686
2687 KASSERT(LAGG_LOCKED(sc));
2688
2689 ifp_port = lp->lp_ifp;
2690
2691 if (lp->lp_promisc == false)
2692 return;
2693
2694 error = ifpromisc(ifp_port, 0);
2695 if (error == ENETRESET) {
2696 error = ifp_port->if_init(ifp_port);
2697 }
2698
2699 if (error != 0) {
2700 LAGG_LOG(sc, LOG_WARNING,
2701 "couldn't unset promisc on %s\n",
2702 ifp_port->if_xname);
2703 }
2704 }
2705
2706 static int
lagg_port_ioctl(struct ifnet * ifp,u_long cmd,void * data)2707 lagg_port_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2708 {
2709 struct lagg_softc *sc;
2710 struct lagg_port *lp;
2711 int error = 0;
2712 u_int ifflags;
2713
2714 if ((lp = ifp->if_lagg) == NULL)
2715 goto fallback;
2716
2717 sc = lp->lp_softc;
2718 KASSERT(sc != NULL);
2719
2720 KASSERT(IFNET_LOCKED(lp->lp_ifp));
2721
2722 switch (cmd) {
2723 case SIOCSIFCAP:
2724 case SIOCSIFMTU:
2725 case SIOCSETHERCAP:
2726 /* Do not allow the setting to be cahanged once joined */
2727 error = EINVAL;
2728 break;
2729 case SIOCSIFFLAGS:
2730 ifflags = ifp->if_flags;
2731 error = LAGG_PORT_IOCTL(lp, cmd, data);
2732 ifflags ^= ifp->if_flags;
2733
2734 if ((ifflags & (IFF_UP | IFF_RUNNING)) != 0)
2735 lagg_proto_linkstate(sc, lp);
2736 break;
2737 default:
2738 goto fallback;
2739 }
2740
2741 return error;
2742 fallback:
2743 if (lp != NULL) {
2744 error = LAGG_PORT_IOCTL(lp, cmd, data);
2745 } else {
2746 error = ENOTTY;
2747 }
2748
2749 return error;
2750 }
2751
2752 static int
lagg_port_output(struct ifnet * ifp,struct mbuf * m,const struct sockaddr * dst,const struct rtentry * rt)2753 lagg_port_output(struct ifnet *ifp, struct mbuf *m,
2754 const struct sockaddr *dst, const struct rtentry *rt)
2755 {
2756 struct lagg_port *lp = ifp->if_lagg;
2757 int error = 0;
2758
2759 switch (dst->sa_family) {
2760 case pseudo_AF_HDRCMPLT:
2761 case AF_UNSPEC:
2762 if (lp != NULL)
2763 error = lp->lp_output(ifp, m, dst, rt);
2764 else
2765 error = ENETDOWN;
2766 break;
2767 default:
2768 m_freem(m);
2769 error = ENETDOWN;
2770 }
2771
2772 return error;
2773 }
2774
2775 void
lagg_ifdetach(void * xifp_port)2776 lagg_ifdetach(void *xifp_port)
2777 {
2778 struct ifnet *ifp_port = xifp_port;
2779 struct lagg_port *lp;
2780 struct lagg_softc *sc;
2781 int s;
2782
2783 IFNET_ASSERT_UNLOCKED(ifp_port);
2784
2785 s = pserialize_read_enter();
2786 lp = atomic_load_consume(&ifp_port->if_lagg);
2787 if (lp == NULL) {
2788 pserialize_read_exit(s);
2789 return;
2790 } else {
2791 sc = lp->lp_softc;
2792 KASSERT(sc != NULL);
2793 }
2794 pserialize_read_exit(s);
2795
2796 LAGG_LOCK(sc);
2797 lp = ifp_port->if_lagg;
2798 if (lp == NULL) {
2799 LAGG_UNLOCK(sc);
2800 return;
2801 }
2802
2803 /*
2804 * mark as a detaching to prevent other
2805 * lagg_port_teardown() processings with IFNET_LOCK() held
2806 */
2807 lp->lp_ifdetaching = true;
2808
2809 LAGG_UNLOCK(sc);
2810
2811 IFNET_LOCK(&sc->sc_if);
2812 LAGG_LOCK(sc);
2813 lp = ifp_port->if_lagg;
2814 if (lp != NULL) {
2815 lagg_port_teardown(sc, lp, true);
2816 }
2817 LAGG_UNLOCK(sc);
2818 IFNET_UNLOCK(&sc->sc_if);
2819 }
2820
2821 void
lagg_linkstate_changed(void * xifp)2822 lagg_linkstate_changed(void *xifp)
2823 {
2824 struct ifnet *ifp = xifp;
2825 struct lagg_port *lp;
2826 struct psref psref;
2827 int s, bound;
2828
2829 s = pserialize_read_enter();
2830 lp = atomic_load_consume(&ifp->if_lagg);
2831 if (lp != NULL) {
2832 bound = curlwp_bind();
2833 lagg_port_getref(lp, &psref);
2834 } else {
2835 pserialize_read_exit(s);
2836 return;
2837 }
2838 pserialize_read_exit(s);
2839
2840 IFNET_LOCK(lp->lp_ifp);
2841 lagg_proto_linkstate(lp->lp_softc, lp);
2842 IFNET_UNLOCK(lp->lp_ifp);
2843
2844 lagg_port_putref(lp, &psref);
2845 curlwp_bindx(bound);
2846 }
2847
2848 void
lagg_port_getref(struct lagg_port * lp,struct psref * psref)2849 lagg_port_getref(struct lagg_port *lp, struct psref *psref)
2850 {
2851
2852 psref_acquire(psref, &lp->lp_psref, lagg_port_psref_class);
2853 }
2854
2855 void
lagg_port_putref(struct lagg_port * lp,struct psref * psref)2856 lagg_port_putref(struct lagg_port *lp, struct psref *psref)
2857 {
2858
2859 psref_release(psref, &lp->lp_psref, lagg_port_psref_class);
2860 }
2861
2862 static void
lagg_workq_work(struct work * wk,void * context)2863 lagg_workq_work(struct work *wk, void *context)
2864 {
2865 struct lagg_work *lw;
2866
2867 lw = container_of(wk, struct lagg_work, lw_cookie);
2868
2869 atomic_cas_uint(&lw->lw_state, LAGG_WORK_ENQUEUED, LAGG_WORK_IDLE);
2870 lw->lw_func(lw, lw->lw_arg);
2871 }
2872
2873 struct workqueue *
lagg_workq_create(const char * name,pri_t prio,int ipl,int flags)2874 lagg_workq_create(const char *name, pri_t prio, int ipl, int flags)
2875 {
2876 struct workqueue *wq;
2877 int error;
2878
2879 error = workqueue_create(&wq, name, lagg_workq_work,
2880 NULL, prio, ipl, flags);
2881
2882 if (error)
2883 return NULL;
2884
2885 return wq;
2886 }
2887
2888 void
lagg_workq_destroy(struct workqueue * wq)2889 lagg_workq_destroy(struct workqueue *wq)
2890 {
2891
2892 workqueue_destroy(wq);
2893 }
2894
2895 void
lagg_workq_add(struct workqueue * wq,struct lagg_work * lw)2896 lagg_workq_add(struct workqueue *wq, struct lagg_work *lw)
2897 {
2898
2899 if (atomic_cas_uint(&lw->lw_state, LAGG_WORK_IDLE,
2900 LAGG_WORK_ENQUEUED) != LAGG_WORK_IDLE)
2901 return;
2902
2903 KASSERT(lw->lw_func != NULL);
2904 kpreempt_disable();
2905 workqueue_enqueue(wq, &lw->lw_cookie, NULL);
2906 kpreempt_enable();
2907 }
2908
2909 void
lagg_workq_wait(struct workqueue * wq,struct lagg_work * lw)2910 lagg_workq_wait(struct workqueue *wq, struct lagg_work *lw)
2911 {
2912
2913 atomic_swap_uint(&lw->lw_state, LAGG_WORK_STOPPING);
2914 workqueue_wait(wq, &lw->lw_cookie);
2915 }
2916
2917 static int
lagg_chg_sadl(struct ifnet * ifp,const uint8_t * lla,size_t lla_len)2918 lagg_chg_sadl(struct ifnet *ifp, const uint8_t *lla, size_t lla_len)
2919 {
2920 struct psref psref_cur, psref_next;
2921 struct ifaddr *ifa_cur, *ifa_next, *ifa_lla;
2922 const struct sockaddr_dl *sdl, *nsdl;
2923 int s, error;
2924
2925 KASSERT(!cpu_intr_p() && !cpu_softintr_p());
2926 KASSERT(IFNET_LOCKED(ifp));
2927 KASSERT(ifp->if_addrlen == lla_len);
2928
2929 error = 0;
2930 ifa_lla = NULL;
2931
2932 /* Renew all AF_LINK address to update sdl_type */
2933 while (1) {
2934 /* find a Link-Level address that has the previous sdl_type */
2935 s = pserialize_read_enter();
2936 IFADDR_READER_FOREACH(ifa_cur, ifp) {
2937 sdl = satocsdl(ifa_cur->ifa_addr);
2938 if (sdl->sdl_family != AF_LINK)
2939 continue;
2940
2941 if (sdl->sdl_type != ifp->if_type) {
2942 ifa_acquire(ifa_cur, &psref_cur);
2943 break;
2944 }
2945 }
2946 pserialize_read_exit(s);
2947
2948 if (ifa_cur == NULL)
2949 break;
2950 /*
2951 * create a new address that has new sdl_type,
2952 * and copy address from the previous.
2953 */
2954 ifa_next = if_dl_create(ifp, &nsdl);
2955 if (ifa_next == NULL) {
2956 error = ENOMEM;
2957 ifa_release(ifa_cur, &psref_cur);
2958 goto done;
2959 }
2960 ifa_acquire(ifa_next, &psref_next);
2961 (void)sockaddr_dl_setaddr(__UNCONST(nsdl), nsdl->sdl_len,
2962 CLLADDR(sdl), ifp->if_addrlen);
2963 ifa_insert(ifp, ifa_next);
2964
2965 /* the next Link-Level address is already set */
2966 if (ifa_lla == NULL &&
2967 memcmp(CLLADDR(sdl), lla, lla_len) == 0) {
2968 ifa_lla = ifa_next;
2969 ifaref(ifa_lla);
2970 }
2971
2972 if (ifa_cur == ifp->if_dl)
2973 if_activate_sadl(ifp, ifa_next, nsdl);
2974
2975 if (ifa_cur == ifp->if_hwdl) {
2976 ifp->if_hwdl = ifa_next;
2977 ifaref(ifa_next);
2978 ifafree(ifa_cur);
2979 }
2980
2981 /* remove the old address */
2982 ifaref(ifa_cur);
2983 ifa_release(ifa_cur, &psref_cur);
2984 ifa_remove(ifp, ifa_cur);
2985 KASSERTMSG(ifa_cur->ifa_refcnt == 1,
2986 "ifa_refcnt=%d", ifa_cur->ifa_refcnt);
2987 ifafree(ifa_cur);
2988 ifa_release(ifa_next, &psref_next);
2989 }
2990
2991 /* acquire or create the next Link-Level address */
2992 if (ifa_lla != NULL) {
2993 ifa_next = ifa_lla;
2994
2995 ifa_acquire(ifa_next, &psref_next);
2996 ifafree(ifa_lla);
2997
2998 nsdl = satocsdl(ifa_next->ifa_addr);
2999 } else {
3000 ifa_next = if_dl_create(ifp, &nsdl);
3001 if (ifa_next == NULL) {
3002 error = ENOMEM;
3003 goto done;
3004 }
3005 ifa_acquire(ifa_next, &psref_next);
3006 (void)sockaddr_dl_setaddr(__UNCONST(nsdl),
3007 nsdl->sdl_len, lla, ifp->if_addrlen);
3008 ifa_insert(ifp, ifa_next);
3009 }
3010
3011 /* Activate the next Link-Level address */
3012 if (__predict_true(ifa_next != ifp->if_dl)) {
3013 /* save the current address */
3014 ifa_cur = ifp->if_dl;
3015 if (ifa_cur != NULL)
3016 ifa_acquire(ifa_cur, &psref_cur);
3017
3018 if_activate_sadl(ifp, ifa_next, nsdl);
3019
3020 /*
3021 * free the saved address after switching,
3022 * if the address is not if_hwdl.
3023 */
3024 if (ifa_cur != NULL) {
3025 if (ifa_cur != ifp->if_hwdl) {
3026 ifaref(ifa_cur);
3027 ifa_release(ifa_cur, &psref_cur);
3028 ifa_remove(ifp, ifa_cur);
3029 KASSERTMSG(ifa_cur->ifa_refcnt == 1,
3030 "ifa_refcnt=%d",
3031 ifa_cur->ifa_refcnt);
3032 ifafree(ifa_cur);
3033 } else {
3034 ifa_release(ifa_cur, &psref_cur);
3035 }
3036 }
3037 }
3038
3039 ifa_release(ifa_next, &psref_next);
3040
3041 done:
3042 return error;
3043 }
3044
3045 /*
3046 * Module infrastructure
3047 */
3048 #include <net/if_module.h>
3049
3050 IF_MODULE(MODULE_CLASS_DRIVER, lagg, NULL)
3051