xref: /illumos-gate/usr/src/uts/common/sys/softmac_impl.h (revision b32f56f8a7951364e44b65c2ab39193d1cb7f84a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * Copyright 2022 Garrett D'Amore
26  * Copyright 2025 Oxide Computer Company
27  */
28 
29 #ifndef	_SYS_SOFTMAC_IMPL_H
30 #define	_SYS_SOFTMAC_IMPL_H
31 
32 #include <sys/types.h>
33 #include <sys/ethernet.h>
34 #include <sys/taskq.h>
35 #include <sys/sunddi.h>
36 #include <sys/sunldi.h>
37 #include <sys/strsun.h>
38 #include <sys/stream.h>
39 #include <sys/dlpi.h>
40 #include <sys/mac.h>
41 #include <sys/mac_provider.h>
42 #include <sys/mac_client.h>
43 #include <sys/mac_client_priv.h>
44 #include <sys/mac_ether.h>
45 
46 #ifdef	__cplusplus
47 extern "C" {
48 #endif
49 
50 typedef void	(*softmac_rx_t)(void *, mac_resource_handle_t, mblk_t *,
51 		    mac_header_info_t *);
52 
53 typedef struct softmac_lower_rxinfo_s {
54 	softmac_rx_t	slr_rx;
55 	void		*slr_arg;
56 } softmac_lower_rxinfo_t;
57 
58 typedef struct softmac_lower_s {
59 	ldi_handle_t		sl_lh;
60 	struct softmac		*sl_softmac;
61 	queue_t			*sl_wq;
62 	struct softmac_upper_s	*sl_sup;
63 	softmac_lower_rxinfo_t	*sl_rxinfo;
64 
65 	/*
66 	 * When a control message is processed, either sl_pending_prim or
67 	 * sl_pending_ioctl will be set.  They will be cleared when the
68 	 * acknowledgement of the specific control message is received
69 	 * from the underlying legacy driver.
70 	 */
71 	kmutex_t		sl_mutex;
72 	kcondvar_t		sl_cv;
73 	t_uscalar_t		sl_pending_prim;
74 	boolean_t		sl_pending_ioctl;
75 	mblk_t			*sl_ack_mp;
76 } softmac_lower_t;
77 
78 typedef enum {
79 	SOFTMAC_UNINIT,
80 	SOFTMAC_ATTACH_INPROG,
81 	SOFTMAC_ATTACH_DONE,
82 	SOFTMAC_DETACH_INPROG,
83 } softmac_state_t;
84 
85 typedef struct softmac_dev_s {
86 	dev_t	sd_dev;
87 } softmac_dev_t;
88 
89 /*
90  * smac_flag values.
91  */
92 #define	SOFTMAC_GLDV3		0x01
93 #define	SOFTMAC_NOSUPP		0x02
94 #define	SOFTMAC_NEED_RECREATE	0x04
95 #define	SOFTMAC_NOTIFY_QUIT	0x08
96 #define	SOFTMAC_NOTIFY_DONE	0x10
97 
98 #define	SMAC_NONZERO_NODECNT(softmac)		\
99 	((softmac->smac_softmac[0] != NULL) +	\
100 	(softmac->smac_softmac[1] != NULL))
101 
102 /*
103  * The softmac structure allows all minor nodes (at most two, style-1 and
104  * style-2) for the same device to be processed.  A softmac_dev_t will be
105  * created for each minor node.
106  *
107  * We try to "register" the mac after all the softmac_dev_t's are processed so
108  * that even if DLPI operations fail (because of driver bugs) for one minor
109  * node, the other minor node can still be used to register the mac.
110  * (Specifically, an incorrect xxx_getinfo() implementation will cause style-2
111  * minor node mac registration to fail.)
112  *
113  * Locking description:
114  *	WO: write once, valid the life time.
115  */
116 typedef struct softmac {
117 	char		smac_devname[MAXNAMELEN];	/* WO */
118 	major_t		smac_umajor;			/* WO */
119 	int		smac_uppa;			/* WO */
120 	uint32_t	smac_cnt;	/* WO, # of minor nodes */
121 
122 	kmutex_t	smac_mutex;
123 	kcondvar_t	smac_cv;
124 	softmac_state_t	smac_state;		/* smac_mutex */
125 	/*
126 	 * The smac_hold_cnt field increases when softmac_hold_device() is
127 	 * called to force the dls_vlan_t of the device to be created.  The
128 	 * device pre-detach fails if this counter is not 0.
129 	 */
130 	uint32_t	smac_hold_cnt;		/* smac_mutex */
131 	uint32_t	smac_flags;		/* smac_mutex */
132 	int		smac_attacherr;		/* smac_mutex */
133 	mac_handle_t	smac_mh;
134 	softmac_dev_t	*smac_softmac[2];	/* smac_mutex */
135 
136 	/*
137 	 * Number of minor nodes whose post-attach routine has succeeded.
138 	 * This should be the same as the numbers of softmac_dev_t.
139 	 * Note that it does not imply SOFTMAC_ATTACH_DONE as the taskq might
140 	 * be still ongoing.
141 	 */
142 	uint32_t	smac_attachok_cnt;	/* smac_mutex */
143 	/*
144 	 * Number of softmac_dev_t left when pre-detach fails. This is used
145 	 * to indicate whether postattach is called because of a failed
146 	 * pre-detach.
147 	 */
148 	uint32_t	smac_attached_left;	/* smac_mutex */
149 
150 	/*
151 	 * Thread handles the DL_NOTIFY_IND message from the lower stream.
152 	 */
153 	kthread_t	*smac_notify_thread;	/* smac_mutex */
154 	/*
155 	 * Head and tail of the DL_NOTIFY_IND messsages.
156 	 */
157 	mblk_t		*smac_notify_head;	/* smac_mutex */
158 	mblk_t		*smac_notify_tail;	/* smac_mutex */
159 
160 	/*
161 	 * The remaining fields are used to register the MAC for a legacy
162 	 * device.  They are set in softmac_mac_register() and do not change.
163 	 * One can access them when mac_register() is done without locks.
164 	 */
165 
166 	/*
167 	 * media type is needed for create <link name, linkid> mapping, so
168 	 * it is set for GLDv3 device as well
169 	 */
170 	uint_t		smac_media;
171 	/* DLPI style of the underlying device */
172 	int		smac_style;
173 	dev_t		smac_dev;
174 	size_t		smac_saplen;
175 	size_t		smac_addrlen;
176 	uchar_t		smac_unicst_addr[MAXMACADDRLEN];
177 	uint_t		smac_min_sdu;
178 	uint_t		smac_max_sdu;
179 	uint32_t	smac_margin;
180 
181 	/* Notifications the underlying driver can support. */
182 	uint32_t	smac_notifications;
183 
184 	/*
185 	 * Capabilities of the underlying driver.
186 	 */
187 	uint32_t	smac_capab_flags;
188 	uint32_t	smac_hcksum_txflags;
189 	boolean_t	smac_no_capability_req;
190 
191 	/*
192 	 * Lower stream structure, accessed by the MAC provider API. The GLDv3
193 	 * framework assures it's validity.
194 	 */
195 	softmac_lower_t	*smac_lower;
196 
197 	kmutex_t	smac_active_mutex;
198 	/*
199 	 * Set by xxx_active_set() when aggregation is created.
200 	 */
201 	boolean_t	smac_active;	/* smac_active_mutex */
202 	/*
203 	 * Numbers of the bounded streams in the fast-path mode.
204 	 */
205 	uint32_t	smac_nactive;	/* smac_active_mutex */
206 
207 	kmutex_t	smac_fp_mutex;
208 	kcondvar_t	smac_fp_cv;
209 	/*
210 	 * numbers of clients that request to disable fastpath.
211 	 */
212 	uint32_t	smac_fp_disable_clients;	/* smac_fp_mutex */
213 	boolean_t	smac_fastpath_admin_disabled;	/* smac_fp_mutex */
214 
215 	/*
216 	 * stream list over this softmac.
217 	 */
218 	list_t			smac_sup_list;		/* smac_fp_mutex */
219 } softmac_t;
220 
221 typedef struct smac_ioc_start_s {
222 	softmac_lower_t	*si_slp;
223 } smac_ioc_start_t;
224 
225 #define	SMAC_IOC	('S' << 24 | 'M' << 16 | 'C' << 8)
226 #define	SMAC_IOC_START	(SMAC_IOC | 0x01)
227 
228 /*
229  * The su_mode of a non-IP/ARP stream is UNKNOWN, and the su_mode of an IP/ARP
230  * stream is either SLOWPATH or FASTPATH.
231  */
232 #define	SOFTMAC_UNKNOWN		0x00
233 #define	SOFTMAC_SLOWPATH	0x01
234 #define	SOFTMAC_FASTPATH	0x02
235 
236 typedef struct softmac_switch_req_s {
237 	list_node_t	ssq_req_list_node;
238 	uint32_t	ssq_expected_mode;
239 } softmac_switch_req_t;
240 
241 #define	DATAPATH_MODE(softmac)						\
242 	((((softmac)->smac_fp_disable_clients != 0) ||			\
243 	(softmac)->smac_fastpath_admin_disabled) ? SOFTMAC_SLOWPATH :	\
244 	SOFTMAC_FASTPATH)
245 
246 
247 /*
248  * Locking description:
249  *
250  *	WO: Set once and valid for life;
251  *	SL: Serialized by the control path (softmac_wput_nondata_task())
252  */
253 typedef struct softmac_upper_s {
254 	softmac_t		*su_softmac;	/* WO */
255 	queue_t			*su_rq;		/* WO */
256 	queue_t			*su_wq;		/* WO */
257 
258 	/*
259 	 * List of upper streams that has pending DLPI messages to be processed.
260 	 */
261 	list_node_t		su_taskq_list_node; /* softmac_taskq_lock */
262 
263 	/*
264 	 * non-NULL for IP/ARP streams in the fast-path mode
265 	 */
266 	softmac_lower_t		*su_slp;	/* SL & su_mutex */
267 
268 	/*
269 	 * List of all IP/ARP upperstreams on the same softmac (including
270 	 * the ones in both data-path modes).
271 	 */
272 	list_node_t		su_list_node;	/* smac_fp_mutex */
273 
274 	/*
275 	 * List of datapath switch requests.
276 	 */
277 	list_t			su_req_list;	/* smac_fp_mutex */
278 
279 	/*
280 	 * Place holder of RX callbacks used to handles data messages comes
281 	 * from the dedicated-lower-stream associated with the IP/ARP stream.
282 	 * Another RX callback is softmac_drop_rxinfo, which is a global
283 	 * variable.
284 	 */
285 	softmac_lower_rxinfo_t	su_rxinfo;		/* WO */
286 	softmac_lower_rxinfo_t	su_direct_rxinfo;	/* WO */
287 
288 	/*
289 	 * Used to serialize the DLPI operation and fastpath<->slowpath
290 	 * switching over operation.
291 	 */
292 	kmutex_t		su_disp_mutex;
293 	kcondvar_t		su_disp_cv;
294 	mblk_t			*su_pending_head;	/* su_disp_mutex */
295 	mblk_t			*su_pending_tail;	/* su_disp_mutex */
296 	boolean_t		su_dlpi_pending;	/* su_disp_mutex */
297 	boolean_t		su_closing;		/* su_disp_mutex */
298 
299 	uint32_t		su_bound : 1,		/* SL */
300 				su_active : 1,		/* SL */
301 				su_direct : 1,		/* SL */
302 				su_is_arp : 1,
303 				su_pad_to_32:28;
304 
305 	/*
306 	 * Used for fastpath data path.
307 	 */
308 	kmutex_t		su_mutex;
309 	kcondvar_t		su_cv;
310 	mblk_t			*su_tx_flow_mp;		/* su_mutex */
311 	boolean_t		su_tx_busy;		/* su_mutex */
312 	/*
313 	 * Number of softmac_srv() operation in fastpath processing.
314 	 */
315 	uint32_t		su_tx_inprocess;	/* su_mutex */
316 	/*
317 	 * SOFTMAC_SLOWPATH or SOFTMAC_FASTPATH
318 	 */
319 	uint32_t		su_mode;		/* SL & su_mutex */
320 
321 	/*
322 	 * Whether this stream is already scheduled in softmac_taskq_list.
323 	 */
324 	boolean_t		su_taskq_scheduled;	/* softmac_taskq_lock */
325 
326 	/*
327 	 * The DLD_CAPAB_DIRECT related notify callback.
328 	 */
329 	mac_tx_notify_t		su_tx_notify_func;	/* su_mutex */
330 	void			*su_tx_notify_arg;	/* su_mutex */
331 } softmac_upper_t;
332 
333 #define	SOFTMAC_EQ_PENDING(sup, mp) {					\
334 	if ((sup)->su_pending_head == NULL) {				\
335 		(sup)->su_pending_head = (sup)->su_pending_tail = (mp);	\
336 	} else {							\
337 		(sup)->su_pending_tail->b_next = (mp);			\
338 		(sup)->su_pending_tail = (mp);				\
339 	}								\
340 }
341 
342 #define	SOFTMAC_DQ_PENDING(sup, mpp) {					\
343 	if ((sup)->su_pending_head == NULL) {				\
344 		*(mpp) = NULL;						\
345 	} else {							\
346 		*(mpp) = (sup)->su_pending_head;			\
347 		if (((sup)->su_pending_head = (*(mpp))->b_next) == NULL)\
348 			(sup)->su_pending_tail = NULL;			\
349 		(*(mpp))->b_next = NULL;				\
350 	}								\
351 }
352 
353 /*
354  * A macro to check whether the write-queue of the lower stream is full
355  * and packets need to be enqueued.
356  *
357  * Because softmac is pushed right above the underlying device and
358  * _I_INSERT/_I_REMOVE is not processed in the lower stream, it is
359  * safe to directly access the q_next pointer.
360  */
361 #define	SOFTMAC_CANPUTNEXT(q)	\
362 	(!((q)->q_next->q_nfsrv->q_flag & QFULL) || canput((q)->q_next))
363 
364 
365 extern dev_info_t		*softmac_dip;
366 #define	SOFTMAC_DEV_NAME	"softmac"
367 
368 extern int	softmac_send_bind_req(softmac_lower_t *, uint_t);
369 extern int	softmac_send_unbind_req(softmac_lower_t *);
370 extern int	softmac_send_notify_req(softmac_lower_t *, uint32_t);
371 extern int	softmac_send_promisc_req(softmac_lower_t *, t_uscalar_t,
372     boolean_t);
373 extern void	softmac_init();
374 extern void	softmac_fini();
375 extern void	softmac_fp_init();
376 extern void	softmac_fp_fini();
377 extern boolean_t softmac_busy();
378 extern int	softmac_fill_capab(ldi_handle_t, softmac_t *);
379 extern int	softmac_capab_enable(softmac_lower_t *);
380 extern void	softmac_rput_process_notdata(queue_t *, softmac_upper_t *,
381     mblk_t *);
382 extern void	softmac_rput_process_data(softmac_lower_t *, mblk_t *);
383 extern int	softmac_output(softmac_lower_t *, mblk_t *, t_uscalar_t,
384     t_uscalar_t, mblk_t **);
385 extern int	softmac_mexchange_error_ack(mblk_t **, t_uscalar_t,
386     t_uscalar_t, t_uscalar_t);
387 
388 extern int	softmac_m_promisc(void *, boolean_t);
389 extern int	softmac_m_multicst(void *, boolean_t, const uint8_t *);
390 extern int	softmac_m_unicst(void *, const uint8_t *);
391 extern void	softmac_m_ioctl(void *, queue_t *, mblk_t *);
392 extern int	softmac_m_stat(void *, uint_t, uint64_t *);
393 extern mblk_t	*softmac_m_tx(void *, mblk_t *);
394 extern int	softmac_proto_tx(softmac_lower_t *, mblk_t *, mblk_t **);
395 extern void	softmac_ioctl_tx(softmac_lower_t *, mblk_t *, mblk_t **);
396 extern void	softmac_notify_thread(void *);
397 
398 extern int	softmac_hold(dev_t, softmac_t **);
399 extern void	softmac_rele(softmac_t *);
400 extern int	softmac_lower_setup(softmac_t *, softmac_upper_t *,
401     softmac_lower_t **);
402 extern boolean_t	softmac_active_set(void *);
403 extern void	softmac_active_clear(void *);
404 extern int	softmac_fastpath_disable(void *);
405 extern void	softmac_fastpath_enable(void *);
406 extern int	softmac_datapath_switch(softmac_t *, boolean_t, boolean_t);
407 
408 extern void	softmac_wput_data(softmac_upper_t *, mblk_t *);
409 extern void	softmac_wput_nondata(softmac_upper_t *, mblk_t *);
410 extern void	softmac_upperstream_close(softmac_upper_t *);
411 
412 #ifdef	__cplusplus
413 }
414 #endif
415 
416 #endif	/* _SYS_SOFTMAC_IMPL_H */
417