1 /*        $NetBSD: if_bridgevar.h,v 1.40 2025/04/22 05:47:51 ozaki-r Exp $      */
2 
3 /*
4  * Copyright 2001 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *        This product includes software developed for the NetBSD Project by
20  *        Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
40  * All rights reserved.
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  * 3. All advertising materials mentioning features or use of this software
51  *    must display the following acknowledgement:
52  *        This product includes software developed by Jason L. Wright
53  * 4. The name of the author may not be used to endorse or promote products
54  *    derived from this software without specific prior written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
58  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
60  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
61  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
64  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
65  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66  * POSSIBILITY OF SUCH DAMAGE.
67  *
68  * OpenBSD: if_bridge.h,v 1.14 2001/03/22 03:48:29 jason Exp
69  */
70 
71 /*
72  * Data structure and control definitions for bridge interfaces.
73  */
74 
75 #ifndef _NET_IF_BRIDGEVAR_H_
76 #define _NET_IF_BRIDGEVAR_H_
77 
78 #include <sys/callout.h>
79 #include <sys/queue.h>
80 #include <sys/mutex.h>
81 #include <sys/condvar.h>
82 
83 /*
84  * Commands used in the SIOCSDRVSPEC ioctl.  Note the lookup of the
85  * bridge interface itself is keyed off the ifdrv structure.
86  */
87 #define   BRDGADD                       0         /* add bridge member (ifbreq) */
88 #define   BRDGDEL                       1         /* delete bridge member (ifbreq) */
89 #define   BRDGGIFFLGS                   2         /* get member if flags (ifbreq) */
90 #define   BRDGSIFFLGS                   3         /* set member if flags (ifbreq) */
91 #define   BRDGSCACHE                    4         /* set cache size (ifbrparam) */
92 #define   BRDGGCACHE                    5         /* get cache size (ifbrparam) */
93 #define   OBRDGGIFS           6         /* get member list (ifbifconf) */
94 #define   OBRDGRTS            7         /* get address list (ifbaconf) */
95 #define   BRDGSADDR           8         /* set static address (ifbareq) */
96 #define   BRDGSTO                       9         /* set cache timeout (ifbrparam) */
97 #define   BRDGGTO                       10        /* get cache timeout (ifbrparam) */
98 #define   BRDGDADDR           11        /* delete address (ifbareq) */
99 #define   BRDGFLUSH           12        /* flush address cache (ifbreq) */
100 
101 #define   BRDGGPRI            13        /* get priority (ifbrparam) */
102 #define   BRDGSPRI            14        /* set priority (ifbrparam) */
103 #define   BRDGGHT                       15        /* get hello time (ifbrparam) */
104 #define   BRDGSHT                       16        /* set hello time (ifbrparam) */
105 #define   BRDGGFD                       17        /* get forward delay (ifbrparam) */
106 #define   BRDGSFD                       18        /* set forward delay (ifbrparam) */
107 #define   BRDGGMA                       19        /* get max age (ifbrparam) */
108 #define   BRDGSMA                       20        /* set max age (ifbrparam) */
109 #define   BRDGSIFPRIO                   21        /* set if priority (ifbreq) */
110 #define BRDGSIFCOST           22        /* set if path cost (ifbreq) */
111 #define BRDGGFILT           23          /* get filter flags (ifbrparam) */
112 #define BRDGSFILT           24          /* set filter flags (ifbrparam) */
113 
114 #define   BRDGGIFS            25        /* get member list */
115 #define   BRDGRTS                       26        /* get address list */
116 
117 /*
118  * Generic bridge control request.
119  */
120 struct ifbreq {
121           char                ifbr_ifsname[IFNAMSIZ];       /* member if name */
122           uint32_t  ifbr_ifsflags;                /* member if flags */
123           uint8_t             ifbr_state;                   /* member if STP state */
124           uint8_t             ifbr_priority;                /* member if STP priority */
125           uint8_t             ifbr_path_cost;               /* member if STP cost */
126           uint8_t             ifbr_portno;                  /* member if port number */
127 };
128 
129 /* BRDGGIFFLAGS, BRDGSIFFLAGS */
130 #define   IFBIF_LEARNING                0x01      /* if can learn */
131 #define   IFBIF_DISCOVER                0x02      /* if sends packets w/ unknown dest. */
132 #define   IFBIF_STP           0x04      /* if participates in spanning tree */
133 #define   IFBIF_PROTECTED               0x08      /* if participates in protected mode */
134 
135 #define   IFBIFBITS "\020\1LEARNING\2DISCOVER\3STP\4PROTECTED"
136 
137 /* BRDGFLUSH */
138 #define   IFBF_FLUSHDYN                 0x00      /* flush learned addresses only */
139 #define   IFBF_FLUSHALL                 0x01      /* flush all addresses */
140 
141 /* BRDGSFILT */
142 #define IFBF_FILT_USEIPF      0x00000001 /* enable ipf on bridge */
143 #define IFBF_FILT_MASK                  0x00000001 /* mask of valid values */
144 
145 /* STP port states */
146 #define   BSTP_IFSTATE_DISABLED         0
147 #define   BSTP_IFSTATE_LISTENING        1
148 #define   BSTP_IFSTATE_LEARNING         2
149 #define   BSTP_IFSTATE_FORWARDING       3
150 #define   BSTP_IFSTATE_BLOCKING         4
151 
152 /*
153  * Interface list structure.
154  */
155 struct ifbifconf {
156           uint32_t  ifbic_len;          /* buffer size */
157           union {
158                     void *    ifbicu_buf;
159                     struct ifbreq *ifbicu_req;
160           } ifbic_ifbicu;
161 #define   ifbic_buf ifbic_ifbicu.ifbicu_buf
162 #define   ifbic_req ifbic_ifbicu.ifbicu_req
163 };
164 
165 /*
166  * Bridge address request.
167  */
168 struct ifbareq {
169           char                ifba_ifsname[IFNAMSIZ];       /* member if name */
170           time_t              ifba_expire;                  /* address expire time */
171           uint8_t             ifba_flags;                   /* address flags */
172           uint8_t             ifba_dst[ETHER_ADDR_LEN];/* destination address */
173 };
174 
175 #define   IFBAF_TYPEMASK      0x03      /* address type mask */
176 #define   IFBAF_DYNAMIC       0x00      /* dynamically learned address */
177 #define   IFBAF_STATIC        0x01      /* static address */
178 
179 #define   IFBAFBITS "\020\1STATIC"
180 
181 /*
182  * Address list structure.
183  */
184 struct ifbaconf {
185           uint32_t  ifbac_len;          /* buffer size */
186           union {
187                     void *ifbacu_buf;
188                     struct ifbareq *ifbacu_req;
189           } ifbac_ifbacu;
190 #define   ifbac_buf ifbac_ifbacu.ifbacu_buf
191 #define   ifbac_req ifbac_ifbacu.ifbacu_req
192 };
193 
194 /*
195  * Bridge parameter structure.
196  */
197 struct ifbrparam {
198           union {
199                     uint32_t ifbrpu_int32;
200                     uint16_t ifbrpu_int16;
201                     uint8_t ifbrpu_int8;
202           } ifbrp_ifbrpu;
203 };
204 #define   ifbrp_csize         ifbrp_ifbrpu.ifbrpu_int32     /* cache size */
205 #define   ifbrp_ctime         ifbrp_ifbrpu.ifbrpu_int32     /* cache time (sec) */
206 #define   ifbrp_prio          ifbrp_ifbrpu.ifbrpu_int16     /* bridge priority */
207 #define   ifbrp_hellotime     ifbrp_ifbrpu.ifbrpu_int8      /* hello time (sec) */
208 #define   ifbrp_fwddelay      ifbrp_ifbrpu.ifbrpu_int8      /* fwd time (sec) */
209 #define   ifbrp_maxage        ifbrp_ifbrpu.ifbrpu_int8      /* max age (sec) */
210 #define   ifbrp_filter        ifbrp_ifbrpu.ifbrpu_int32     /* filtering flags */
211 
212 #ifdef _KERNEL
213 #ifdef _KERNEL_OPT
214 #include "opt_net_mpsafe.h"
215 #endif /* _KERNEL_OPT */
216 
217 #include <sys/pserialize.h>
218 #include <sys/pslist.h>
219 #include <sys/psref.h>
220 #include <sys/workqueue.h>
221 
222 #include <net/pktqueue.h>
223 
224 /*
225  * Timekeeping structure used in spanning tree code.
226  */
227 struct bridge_timer {
228           uint16_t  active;
229           uint16_t  value;
230 };
231 
232 struct bstp_config_unit {
233           uint64_t  cu_rootid;
234           uint64_t  cu_bridge_id;
235           uint32_t  cu_root_path_cost;
236           uint16_t  cu_message_age;
237           uint16_t  cu_max_age;
238           uint16_t  cu_hello_time;
239           uint16_t  cu_forward_delay;
240           uint16_t  cu_port_id;
241           uint8_t             cu_message_type;
242           uint8_t             cu_topology_change_acknowledgment;
243           uint8_t             cu_topology_change;
244 };
245 
246 struct bstp_tcn_unit {
247           uint8_t             tu_message_type;
248 };
249 
250 /*
251  * Bridge interface list entry.
252  */
253 struct bridge_iflist {
254           struct pslist_entry bif_next;
255           uint64_t            bif_designated_root;
256           uint64_t            bif_designated_bridge;
257           uint32_t            bif_path_cost;
258           uint32_t            bif_designated_cost;
259           struct bridge_timer bif_hold_timer;
260           struct bridge_timer bif_message_age_timer;
261           struct bridge_timer bif_forward_delay_timer;
262           uint16_t            bif_port_id;
263           uint16_t            bif_designated_port;
264           struct bstp_config_unit       bif_config_bpdu;
265           uint8_t                       bif_state;
266           uint8_t                       bif_topology_change_acknowledge;
267           uint8_t                       bif_config_pending;
268           uint8_t                       bif_change_detection_enabled;
269           uint8_t                       bif_priority;
270           struct ifnet                  *bif_ifp; /* member if */
271           uint32_t            bif_flags;          /* member if flags */
272           struct psref_target bif_psref;
273           void *                        *bif_linkstate_hook;
274           void *                        *bif_ifdetach_hook;
275 };
276 
277 /*
278  * Bridge route node.
279  */
280 struct bridge_rtnode {
281           struct pslist_entry     brt_hash;       /* hash table linkage */
282           struct pslist_entry     brt_list;       /* list linkage */
283           struct ifnet                  *brt_ifp; /* destination if */
284           time_t                        brt_expire;         /* expiration time */
285           uint8_t                       brt_flags;          /* address flags */
286           uint8_t                       brt_addr[ETHER_ADDR_LEN];
287 };
288 
289 struct bridge_iflist_psref {
290           struct pslist_head  bip_iflist;         /* member interface list */
291           kmutex_t            bip_lock;
292           pserialize_t                  bip_psz;
293 };
294 
295 /*
296  * Software state for each bridge.
297  */
298 struct bridge_softc {
299           struct ifnet                  sc_if;
300           LIST_ENTRY(bridge_softc) sc_list;
301           uint64_t            sc_designated_root;
302           uint64_t            sc_bridge_id;
303           struct bridge_iflist          *sc_root_port;
304           uint32_t            sc_root_path_cost;
305           uint16_t            sc_max_age;
306           uint16_t            sc_hello_time;
307           uint16_t            sc_forward_delay;
308           uint16_t            sc_bridge_max_age;
309           uint16_t            sc_bridge_hello_time;
310           uint16_t            sc_bridge_forward_delay;
311           uint16_t            sc_topology_change_time;
312           uint16_t            sc_hold_time;
313           uint16_t            sc_bridge_priority;
314           uint8_t                       sc_topology_change_detected;
315           uint8_t                       sc_topology_change;
316           struct bridge_timer sc_hello_timer;
317           struct bridge_timer sc_topology_change_timer;
318           struct bridge_timer sc_tcn_timer;
319           uint32_t            sc_brtmax;          /* max # of addresses */
320           uint32_t            sc_brtcnt;          /* cur. # of addresses */
321           uint32_t            sc_brttimeout;      /* rt timeout in seconds */
322           callout_t           sc_brcallout;       /* bridge callout */
323           callout_t           sc_bstpcallout;     /* STP callout */
324           struct bridge_iflist_psref    sc_iflist_psref;
325           struct pslist_head  *sc_rthash;         /* our forwarding table */
326           struct pslist_head  sc_rtlist;          /* list version of above */
327           kmutex_t            *sc_rtlist_lock;
328           pserialize_t                  sc_rtlist_psz;
329           struct workqueue    *sc_rtage_wq;
330           struct work                   sc_rtage_wk;
331           uint32_t            sc_rthash_key;      /* key for hash */
332           uint32_t            sc_filter_flags; /* ipf and flags */
333           int                           sc_csum_flags_tx;
334           int                           sc_capenable;
335           bool                          sc_stopping;
336 };
337 
338 extern const uint8_t bstp_etheraddr[];
339 
340 int       bridge_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
341               const struct rtentry *);
342 
343 void      bstp_initialization(struct bridge_softc *);
344 void      bstp_stop(struct bridge_softc *);
345 void      bstp_input(struct bridge_softc *, struct bridge_iflist *, struct mbuf *);
346 
347 void      bridge_enqueue(struct bridge_softc *, struct ifnet *, struct mbuf *,
348               int);
349 
350 void      bridge_calc_csum_flags(struct bridge_softc *);
351 
352 #define BRIDGE_LOCK_OBJ(_sc)  (&(_sc)->sc_iflist_psref.bip_lock)
353 #define BRIDGE_LOCK(_sc)      mutex_enter(BRIDGE_LOCK_OBJ(_sc))
354 #define BRIDGE_UNLOCK(_sc)    mutex_exit(BRIDGE_LOCK_OBJ(_sc))
355 #define BRIDGE_LOCKED(_sc)    mutex_owned(BRIDGE_LOCK_OBJ(_sc))
356 
357 #define BRIDGE_PSZ_PERFORM(_sc)         pserialize_perform((_sc)->sc_iflist_psref.bip_psz)
358 
359 #define BRIDGE_IFLIST_READER_FOREACH(_bif, _sc) \
360           PSLIST_READER_FOREACH((_bif), &((_sc)->sc_iflist_psref.bip_iflist), \
361               struct bridge_iflist, bif_next)
362 #define BRIDGE_IFLIST_WRITER_FOREACH(_bif, _sc) \
363           PSLIST_WRITER_FOREACH((_bif), &((_sc)->sc_iflist_psref.bip_iflist), \
364               struct bridge_iflist, bif_next)
365 
366 /*
367  * Locking notes:
368  * - Updates of sc_iflist are serialized by sc_iflist_lock (an adaptive mutex)
369  *   - The mutex is also used for STP
370  * - Items of sc_iflist (bridge_iflist) is protected by both pserialize
371  *   (sc_iflist_psz) and reference counting (bridge_iflist#bif_refs)
372  * - Before destroying an item of sc_iflist, we have to do pserialize_perform
373  *   and synchronize with the reference counting via a conditional variable
374  *   (sc_iflist_cz)
375  * - Updates of sc_rtlist are serialized by sc_rtlist_lock (an adaptive mutex)
376  *   - The mutex is also used for pserialize
377  * - A workqueue is used to run bridge_rtage in LWP context via bridge_timer callout
378  *   - bridge_rtage uses pserialize that requires non-interrupt context
379  */
380 #endif /* _KERNEL */
381 #endif /* !_NET_IF_BRIDGEVAR_H_ */
382