xref: /illumos-gate/usr/src/uts/common/sys/mac_soft_ring.h (revision d38bfb8cc94d5c5e6d1f059edf2ffddc3ac987de)
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 /*
23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright 2017 Joyent, Inc.
26  * Copyright 2026 Oxide Computer Company
27  */
28 
29 #ifndef	_SYS_MAC_SOFT_RING_H
30 #define	_SYS_MAC_SOFT_RING_H
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 #include <sys/types.h>
37 #include <sys/cpuvar.h>
38 #include <sys/cpupart.h>
39 #include <sys/processor.h>
40 #include <sys/stream.h>
41 #include <sys/squeue.h>
42 #include <sys/dlpi.h>
43 #include <sys/mac_impl.h>
44 #include <sys/mac_stat.h>
45 
46 #define	S_RING_NAMELEN 64
47 
48 #define	MAX_SR_FANOUT	24
49 
50 extern boolean_t mac_soft_ring_enable;
51 extern boolean_t mac_latency_optimize;
52 
53 typedef struct mac_soft_ring_s mac_soft_ring_t;
54 typedef struct mac_soft_ring_set_s mac_soft_ring_set_t;
55 
56 typedef void (*mac_soft_ring_drain_func_t)(mac_soft_ring_t *);
57 typedef mac_tx_cookie_t (*mac_tx_func_t)(mac_soft_ring_set_t *, mblk_t *,
58     uintptr_t, uint16_t, mblk_t **);
59 
60 /* Tx notify callback */
61 typedef struct mac_tx_notify_cb_s {
62 	mac_cb_t		mtnf_link;	/* Linked list of callbacks */
63 	mac_tx_notify_t		mtnf_fn;	/* The callback function */
64 	void			*mtnf_arg;	/* Callback function argument */
65 } mac_tx_notify_cb_t;
66 
67 /*
68  * Flagset of immutable and datapath-altered aspects of a softring.
69  *
70  * Flags prefixed by `ST_` identify static characteristics of how a ring should
71  * process packets, whereas those prefixed `S_RING` reflect the current state
72  * of datapath processing.
73  *
74  * Gaps in flag allocation correspond to former flag definitions (such that
75  * existing flags mapped to their historic values). New flags can be placed in
76  * these gaps without issue. See issue 17920.
77  */
78 typedef enum {
79 	/*
80 	 * Packets may only be drained from this softring by its own worker
81 	 * thread, and cannot be handled inline by the SRS or its caller..
82 	 *
83 	 * Immutable.
84 	 */
85 	ST_RING_WORKER_ONLY	= 1 << 0,
86 	/*
87 	 * This softring is dedicated to handling TCP/IPv4 traffic when DLS
88 	 * bypass is configured.
89 	 *
90 	 * Immutable.
91 	 */
92 	ST_RING_TCP		= 1 << 2,
93 	/*
94 	 * This softring is dedicated to handling UDP/IPv4 traffic when DLS
95 	 * bypass is configured.
96 	 *
97 	 * Immutable.
98 	 */
99 	ST_RING_UDP		= 1 << 3,
100 	/*
101 	 * This softring handles all traffic which is ineligible for DLS bypass.
102 	 *
103 	 * Immutable.
104 	 */
105 	ST_RING_OTH		= 1 << 4,
106 	/*
107 	 * If set, this is a transmit softring. Packets will be directed via
108 	 * `mac_tx_send` to an underlying provider's ring.
109 	 *
110 	 * If absent, this is a receive softring. Packets will be delivered to a
111 	 * client via `s_ring_rx_func`.
112 	 *
113 	 * Immutable.
114 	 */
115 	ST_RING_TX		= 1 << 6,
116 	/*
117 	 * This softring is dedicated to handling TCP/IPv6 traffic when DLS
118 	 * bypass is configured.
119 	 *
120 	 * Immutable.
121 	 */
122 	ST_RING_TCP6		= 1 << 7,
123 	/*
124 	 * This softring is dedicated to handling UDP/IPv6 traffic when DLS
125 	 * bypass is configured.
126 	 *
127 	 * Immutable.
128 	 */
129 	ST_RING_UDP6		= 1 << 8,
130 	/*
131 	 * A thread is currently processing packets from this softring, and has
132 	 * relinquished its hold on `s_ring_lock` to allow more packets to be
133 	 * enqueued while it does so.
134 	 *
135 	 * Rx/Tx process methods will always enqueue packets if set, with the
136 	 * expectation that whoever is draining the thread will continue to
137 	 * do so.
138 	 */
139 	S_RING_PROC		= 1 << 16,
140 	/*
141 	 * The worker thread of this softring has been bound to a specific CPU.
142 	 */
143 	S_RING_BOUND		= 1 << 17,
144 	/*
145 	 * This softring is a TX softring and has run out of descriptors on the
146 	 * underlying ring/NIC.
147 	 *
148 	 * Any outbound packets will be queued until the underlying provider
149 	 * marks more descriptors as available via `mac_tx_ring_update`.
150 	 */
151 	S_RING_BLOCK		= 1 << 18,
152 	/*
153 	 * This softring is a TX softring and is flow controlled: more than
154 	 * `s_ring_tx_hiwat` packets are currently enqueued.
155 	 *
156 	 * Any outbound packets will be enqueued, and drained by the softring
157 	 * worker. Senders will receive a cookie -- they will be informed when
158 	 * any cookie is no longer flow controlled if they have registered a
159 	 * callback via `mac_client_tx_notify`.
160 	 */
161 	S_RING_TX_HIWAT		= 1 << 19,
162 	/*
163 	 * This softring is a TX softring and has returned a cookie to at least
164 	 * one sender who has set `MAC_TX_NO_ENQUEUE` regardless of watermark
165 	 * state.
166 	 *
167 	 * When the softring is drained, notify the client via its
168 	 * `mac_client_tx_notify` callback that it may send.
169 	 */
170 	S_RING_WAKEUP_CLIENT	= 1 << 20,
171 	/*
172 	 * This RX softring is client pollable and its client has called
173 	 * `mac_soft_ring_intr_disble` to stop MAC from delivering frames via
174 	 * `s_ring_rx_func`.
175 	 *
176 	 * Packets may _only_ be delivered by client polling. The client may
177 	 * undo this using `mac_soft_ring_intr_enable`.
178 	 */
179 	S_RING_BLANK		= 1 << 21,
180 	/*
181 	 * Request the thread processing packets to notify a waiting client when
182 	 * it is safe to alter the `s_ring_rx_func` callback and its arguments.
183 	 */
184 	S_RING_CLIENT_WAIT	= 1 << 22,
185 	/*
186 	 * This softring is marked for deletion.
187 	 *
188 	 * No further packets can be admitted into the softring, and enqueued
189 	 * packets must not be processed.
190 	 */
191 	S_RING_CONDEMNED	= 1 << 24,
192 	/*
193 	 * The softring worker has completed any teardown in response to
194 	 * `S_RING_CONDEMNED`.
195 	 *
196 	 * Requires `S_RING_QUIESCE_DONE`.
197 	 */
198 	S_RING_CONDEMNED_DONE	= 1 << 25,
199 	/*
200 	 * This softring has been signalled to stop processing any packets.
201 	 *
202 	 * The presence of this flag implies that the parent SRS has
203 	 * *also* been asked to quiesce. It will not enqueue any packets here.
204 	 */
205 	S_RING_QUIESCE		= 1 << 26,
206 	/*
207 	 * The softring has ceased processing any enqueued/arriving packets, and
208 	 * is awaiting a signal of either `S_RING_CONDEMNED` or `S_RING_RESTART`
209 	 * to wake up.
210 	 */
211 	S_RING_QUIESCE_DONE	= 1 << 27,
212 	/*
213 	 * The softring has been signalled to resume processing traffic.
214 	 *
215 	 * The worker thread should unset this and any `QUIESCE` flags and
216 	 * resume processing packets.
217 	 */
218 	S_RING_RESTART		= 1 << 28,
219 	/*
220 	 * This TX softring has packets enqueued, which the worker thread is
221 	 * responsible for draining.
222 	 */
223 	S_RING_ENQUEUED		= 1 << 29,
224 } mac_soft_ring_state_t;
225 
226 /*
227  * Used to verify whether a given value is allowed to be used as the
228  * `type` of a softring during creation.
229  */
230 #define	SR_STATE	0xffff0000
231 
232 struct mac_soft_ring_s {
233 	/* Keep the most used members 64bytes cache aligned */
234 	kmutex_t	s_ring_lock;	/* lock before using any member */
235 	mac_soft_ring_state_t	s_ring_state;	/* processing model and state */
236 	uint32_t	s_ring_count;	/* # of mblocks in mac_soft_ring */
237 	size_t		s_ring_size;	/* Size of data queued */
238 	mblk_t		*s_ring_first;	/* first mblk chain or NULL */
239 	mblk_t		*s_ring_last;	/* last mblk chain or NULL */
240 
241 	/* Protected by s_ring_lock + !S_RING_PROC */
242 	mac_direct_rx_t		s_ring_rx_func;
243 	void			*s_ring_rx_arg1;
244 	mac_resource_handle_t	s_ring_rx_arg2;
245 
246 	/*
247 	 * Threshold after which packets get dropped.
248 	 * Is always greater than s_ring_tx_hiwat
249 	 */
250 	uint32_t	s_ring_tx_max_q_cnt;
251 	/* # of mblocks after which to apply flow control */
252 	uint32_t	s_ring_tx_hiwat;
253 	/* # of mblocks after which to relieve flow control */
254 	uint32_t	s_ring_tx_lowat;
255 	boolean_t	s_ring_tx_woken_up;
256 	uint32_t	s_ring_hiwat_cnt;	/* times blocked for Tx descs */
257 
258 	/* Arguments for `mac_tx_send`, called by `mac_tx_soft_ring_drain` */
259 	mac_client_impl_t	*s_ring_tx_arg1;
260 	mac_ring_t		*s_ring_tx_arg2;
261 
262 	/* Tx notify callback */
263 	mac_cb_info_t	s_ring_notify_cb_info;		/* cb list info */
264 	mac_cb_t	*s_ring_notify_cb_list;		/* The cb list */
265 
266 	clock_t		s_ring_awaken;	/* time async thread was awakened */
267 
268 	kthread_t	*s_ring_run;	/* Current thread processing sq */
269 	processorid_t	s_ring_cpuid;	/* processor to bind to */
270 	processorid_t	s_ring_cpuid_save;	/* saved cpuid during offline */
271 	kcondvar_t	s_ring_async;	/* async thread blocks on */
272 	clock_t		s_ring_wait;	/* lbolts to wait after a fill() */
273 	timeout_id_t	s_ring_tid;	/* timer id of pending timeout() */
274 	kthread_t	*s_ring_worker;	/* kernel thread id */
275 	char		s_ring_name[S_RING_NAMELEN + 1];
276 	uint64_t	s_ring_total_inpkt;
277 	uint64_t	s_ring_total_rbytes;
278 	uint64_t	s_ring_drops;
279 	mac_client_impl_t *s_ring_mcip;
280 	kstat_t		*s_ring_ksp;
281 
282 	/* Teardown, poll disable control ops */
283 	kcondvar_t	s_ring_client_cv; /* Client wait for control op */
284 
285 	mac_soft_ring_set_t *s_ring_set;   /* The SRS this ring belongs to */
286 	mac_soft_ring_t	*s_ring_next;
287 	mac_soft_ring_t	*s_ring_prev;
288 	mac_soft_ring_drain_func_t s_ring_drain_func;
289 
290 	mac_tx_stats_t	s_st_stat;
291 };
292 
293 /*
294  * soft ring set (SRS) Tx modes
295  */
296 typedef enum {
297 	SRS_TX_DEFAULT = 0,
298 	SRS_TX_SERIALIZE,
299 	SRS_TX_FANOUT,
300 	SRS_TX_BW,
301 	SRS_TX_BW_FANOUT,
302 	SRS_TX_AGGR,
303 	SRS_TX_BW_AGGR
304 } mac_tx_srs_mode_t;
305 
306 /* Transmit side Soft Ring Set */
307 typedef struct mac_srs_tx_s {
308 	/* Members for Tx-side processing */
309 	mac_tx_srs_mode_t		st_mode;
310 	mac_tx_func_t			st_func;
311 
312 	/* Arguments for `mac_tx_send` when called within `st_func` */
313 	mac_client_impl_t	*st_arg1;
314 	mac_ring_t		*st_arg2;
315 
316 	mac_group_t	*st_group;	/* TX group for share */
317 	boolean_t	st_woken_up;
318 
319 	/*
320 	 * st_max_q_cnt is the queue depth threshold to limit
321 	 * outstanding packets on the Tx SRS. Once the limit
322 	 * is reached, Tx SRS will drop packets until the
323 	 * limit goes below the threshold.
324 	 */
325 	uint32_t	st_max_q_cnt;	/* max. outstanding packets */
326 	/*
327 	 * st_hiwat is used Tx serializer and bandwidth mode.
328 	 * This is the queue depth threshold upto which
329 	 * packets will get buffered with no flow-control
330 	 * back pressure applied to the caller. Once this
331 	 * threshold is reached, back pressure will be
332 	 * applied to the caller of mac_tx() (mac_tx() starts
333 	 * returning a cookie to indicate a blocked SRS).
334 	 * st_hiwat should always be lesser than or equal to
335 	 * st_max_q_cnt.
336 	 */
337 	uint32_t	st_hiwat;	/* mblk cnt to apply flow control */
338 	uint32_t	st_lowat;	/* mblk cnt to relieve flow control */
339 	uint32_t	st_hiwat_cnt; /* times blocked for Tx descs */
340 	mac_tx_stats_t	st_stat;
341 	mac_capab_aggr_t	st_capab_aggr;
342 	/*
343 	 * st_soft_rings is used as an array to store aggr Tx soft
344 	 * rings. When aggr_find_tx_ring() returns a pseudo ring,
345 	 * the associated soft ring has to be found. st_soft_rings
346 	 * array stores the soft ring associated with a pseudo Tx
347 	 * ring and it can be accessed using the pseudo ring
348 	 * index (mr_index). Note that the ring index is unique
349 	 * for each ring in a group.
350 	 */
351 	mac_soft_ring_t **st_soft_rings;
352 } mac_srs_tx_t;
353 
354 /* Receive side Soft Ring Set */
355 typedef struct mac_srs_rx_s {
356 	/*
357 	 * Upcall function for Rx processing when `SRST_NO_SOFT_RINGS` is set.
358 	 * Rx softring callbacks for non-bypass traffic should use the same
359 	 * function and initial argument.
360 	 * Argument 2 of `sr_func` would be a client-provided handle, but is
361 	 * always `NULL` in this context as SRSes themselves cannot be used as
362 	 * part of client polling.
363 	 *
364 	 * Protected by srs_lock + !SRS_PROC.
365 	 */
366 	mac_direct_rx_t		sr_func;
367 	void			*sr_arg1;
368 
369 	mac_rx_func_t		sr_lower_proc;	/* Atomically changed */
370 	uint32_t		sr_poll_pkt_cnt;
371 	uint32_t		sr_poll_thres;
372 
373 	/* mblk cnt to apply flow control */
374 	uint32_t		sr_hiwat;
375 	/* mblk cnt to relieve flow control */
376 	uint32_t		sr_lowat;
377 	mac_rx_stats_t		sr_stat;
378 
379 	/* Times polling was enabled */
380 	uint32_t		sr_poll_on;
381 	/* Times polling was enabled by worker thread */
382 	uint32_t		sr_worker_poll_on;
383 	/* Times polling was disabled */
384 	uint32_t		sr_poll_off;
385 	/* Poll thread signalled count */
386 	uint32_t		sr_poll_thr_sig;
387 	/* Poll thread busy */
388 	uint32_t		sr_poll_thr_busy;
389 	/* SRS drains, stays in poll mode but doesn't poll */
390 	uint32_t		sr_poll_drain_no_poll;
391 	/*
392 	 * SRS has nothing to do and no packets in H/W but
393 	 * there is a backlog in softrings. SRS stays in
394 	 * poll mode but doesn't do polling.
395 	 */
396 	uint32_t		sr_poll_no_poll;
397 	/* Active polling restarted */
398 	uint32_t		sr_below_hiwat;
399 	/* Found packets in last poll so try and poll again */
400 	uint32_t		sr_poll_again;
401 	/*
402 	 * Packets in queue but poll thread not allowed to process so
403 	 * signal the worker thread.
404 	 */
405 	uint32_t		sr_poll_sig_worker;
406 	/*
407 	 * Poll thread has nothing to do and H/W has nothing so
408 	 * reenable the interrupts.
409 	 */
410 	uint32_t		sr_poll_intr_enable;
411 	/*
412 	 * Poll thread has nothing to do and worker thread was already
413 	 * running so it can decide to reenable interrupt or poll again.
414 	 */
415 	uint32_t		sr_poll_goto_sleep;
416 	/* Worker thread goes back to draining the queue */
417 	uint32_t		sr_drain_again;
418 	/* More Packets in queue so signal the poll thread to drain */
419 	uint32_t		sr_drain_poll_sig;
420 	/* More Packets in queue so signal the worker thread to drain */
421 	uint32_t		sr_drain_worker_sig;
422 	/* Poll thread is already running so worker has nothing to do */
423 	uint32_t		sr_drain_poll_running;
424 	/* We have packets already queued so keep polling */
425 	uint32_t		sr_drain_keep_polling;
426 	/* Drain is done and interrupts are reenabled */
427 	uint32_t		sr_drain_finish_intr;
428 	/* Polling thread needs to schedule worker wakeup */
429 	uint32_t		sr_poll_worker_wakeup;
430 } mac_srs_rx_t;
431 
432 /*
433  * Flagset of immutable and slowly-varying aspects of a softring set (SRS).
434  *
435  * These identify mainly static characteristics (Tx/Rx, whether the SRS
436  * corresponds to the entrypoint on a MAC client) as well as state on an
437  * administrative timescale (fanout behaviour, bandwidth control).
438  *
439  * See the commentary on `mac_soft_ring_state_t` for commentary on gaps in the
440  * numbering of flags for this type.
441  */
442 enum mac_soft_ring_set_type {
443 	/*
444 	 * The flow entry underpinning this SRS belongs to a MAC client for
445 	 * a link.
446 	 *
447 	 * Immutable.
448 	 */
449 	SRST_LINK			= 1 << 0,
450 	/*
451 	 * The flow entry underpinning this SRS belongs to a flow classifier
452 	 * attached to a given MAC client.
453 	 *
454 	 * Immutable.
455 	 */
456 	SRST_FLOW			= 1 << 1,
457 	/*
458 	 * This SRS does not have any softrings assigned.
459 	 *
460 	 * A Tx SRS has no rings and will send packets directly to the NIC,
461 	 * and an Rx SRS will handle packets inline via `sr_func`.
462 	 *
463 	 * Mutable for Tx SRSes.
464 	 */
465 	SRST_NO_SOFT_RINGS		= 1 << 2,
466 	/*
467 	 * Set on all Rx SRSes when the tunable `mac_latency_optimize` is
468 	 * `true`.
469 	 *
470 	 * If set, packets may be processed inline by any caller who arrives
471 	 * with more packets to enqueue if there is no existing backlog.
472 	 * The worker thread will share a CPU binding with the poll thread.
473 	 * Wakeups sent to worker threads will be instantaneous (loopback,
474 	 * teardown, and bandwidth-controlled cases).
475 	 *
476 	 * If unset on an Rx SRS, packets may only be moved to softrings by the
477 	 * worker thread. `SRST_ENQUEUE` will also be set in this case.
478 	 *
479 	 * Immutable. Requires !`SRST_TX`.
480 	 */
481 	SRST_LATENCY_OPT		= 1 << 3,
482 	/*
483 	 * This Rx SRS has softrings assigned, and has at least one per traffic
484 	 * class. Traffic must move to a softring for processing, but may still
485 	 * drain inline if the SRS is quiet.
486 	 *
487 	 * Immutable. Requires !`SRST_TX`. Mutually exclusive with
488 	 * `SRST_NO_SOFT_RINGS`.
489 	 */
490 	SRST_FANOUT_PROTO		= 1 << 4,
491 	/*
492 	 * This receive SRS has more than one softring for each traffic class,
493 	 * and must hash/round-robin received packets amongst a class's rings.
494 	 *
495 	 * Mutable. Requires !`SRST_TX`.
496 	 */
497 	SRST_FANOUT_SRC_IP		= 1 << 5,
498 	/*
499 	 * All softrings will be initialised with `ST_RING_WORKER_ONLY`.
500 	 *
501 	 * Set when `SRST_LATENCY_OPT` is disabled, or when the underlying ring
502 	 * requires `MAC_RING_RX_ENQUEUE` (sun4v).
503 	 *
504 	 * Immutable. Requires !`SRST_TX`.
505 	 */
506 	SRST_ENQUEUE			= 1 << 6,
507 	/*
508 	 * The SRS's client is placed on the default group (either due to
509 	 * oversubscription, or the device admits only one group).
510 	 *
511 	 * A hardware classified ring of this type will receive additional
512 	 * traffic when moved into full or all-multicast promiscuous mode.
513 	 *
514 	 * Mutable. Requires !`SRST_TX`.
515 	 */
516 	SRST_DEFAULT_GRP		= 1 << 7,
517 	/*
518 	 * If present, this is a transmit SRS. Otherwise it is a receive SRS.
519 	 *
520 	 * Transmit SRSes use softrings as mappings to underlying Tx rings
521 	 * from the hardware.
522 	 *
523 	 * The validity of `srs_tx`/`srs_rx` are gated on this flag, as are the
524 	 * choice of drain functions, enqueue behaviours, etc.
525 	 *
526 	 * Immutable.
527 	 */
528 	SRST_TX				= 1 << 8,
529 	/*
530 	 * `srs_bw` is enabled, and the queue size and egress rate of this SRS
531 	 * are limited accordingly.
532 	 *
533 	 * Mutable.
534 	 */
535 	SRST_BW_CONTROL			= 1 << 9,
536 	/*
537 	 * The SRS's MAC client has had a callback plumbed from IP to allow
538 	 * matching IPv4 packets to bypass DLS.
539 	 *
540 	 * When set, `ST_RING_TCP` and `ST_RING_UDP` must make use of this
541 	 * callback. The Rx path will send eligible traffic to these softrings
542 	 * in this case.
543 	 *
544 	 * Mutable under quiescence. Requires !`SRST_TX`.
545 	 */
546 	SRST_DLS_BYPASS_V4		= 1 << 12,
547 	/*
548 	 * The SRS's MAC client has had a callback plumbed from IP to allow
549 	 * matching IPv6 packets to bypass DLS.
550 	 *
551 	 * When set, `ST_RING_TCP6` and `ST_RING_UDP6` must make use of this
552 	 * callback. The Rx path will send eligible traffic to these softrings
553 	 * in this case.
554 	 *
555 	 * Mutable under quiescence. Requires !`SRST_TX`.
556 	 */
557 	SRST_DLS_BYPASS_V6		= 1 << 13,
558 	/*
559 	 * The underlying MAC client has had a `mac_resource_cb_t` plumbed down
560 	 * from IP for TCP/IPv4 classified traffic. MAC must inform IP of the
561 	 * addition, removal, and other state changes to any `ST_RING_TCP`
562 	 * softrings.
563 	 *
564 	 * Mutable under quiescence. Requires !`SRST_TX`.
565 	 */
566 	SRST_CLIENT_POLL_V4		= 1 << 14,
567 	/*
568 	 * The underlying MAC client has had a `mac_resource_cb_t` plumbed down
569 	 * from IP for TCP/IPv6 classified traffic. MAC must inform IP of the
570 	 * addition, removal, and other state changes to any `ST_RING_TCP6`
571 	 * softrings.
572 	 *
573 	 * Mutable under quiescence. Requires !`SRST_TX`.
574 	 */
575 	SRST_CLIENT_POLL_V6		= 1 << 15,
576 };
577 
578 /*
579  * Flagset reflecting the current state of datapath processing for a given SRS.
580  *
581  * See the commentary on `mac_soft_ring_state_t` for commentary on gaps in the
582  * numbering of flags for this type.
583  */
584 typedef enum {
585 	/*
586 	 * This SRS's worker thread is explicitly bound to a single CPU.
587 	 */
588 	SRS_WORKER_BOUND	= 1 << 1,
589 	/*
590 	 * This Rx SRS's poll thread is explicitly bound to a single CPU.
591 	 */
592 	SRS_POLL_BOUND		= 1 << 2,
593 	/*
594 	 * This Rx SRS is created on top of (and has exclusive
595 	 * use of) a dedicated ring. When under sufficient load, MAC will
596 	 * disable interrupts and pull packets into the SRS by polling the
597 	 * NIC/ring, and will set `SRS_POLLING` when this is the case.
598 	 *
599 	 * This flag may be added/removed as SRSes move between
600 	 * hardware/software classification (e.g., if groups must be shared).
601 	 */
602 	SRS_POLLING_CAPAB	= 1 << 3,
603 	/*
604 	 * A thread is currently processing packets from this SRS, and
605 	 * has relinquished its hold on `srs_lock` to allow more packets to be
606 	 * enqueued while it does so.
607 	 *
608 	 * SRS processing will always enqueue packets if set, with the
609 	 * expectation that whoever is draining the thread will continue to
610 	 * do so.
611 	 *
612 	 * Requires qualification of what thread is doing the processing: either
613 	 * `SRS_WORKER`, `SRS_PROC_FAST`, or `SRS_POLL_PROC`.
614 	 */
615 	SRS_PROC		= 1 << 4,
616 	/*
617 	 * The Rx poll thread should request more packets from the underlying
618 	 * device.
619 	 *
620 	 * Requires `SRS_POLLING`.
621 	 */
622 	SRS_GET_PKTS		= 1 << 5,
623 	/*
624 	 * This Rx SRS has been moved into poll mode. Interrupts from
625 	 * the underlying device are disabled, and the poll thread is
626 	 * exclusively responsible for moving packets into the SRS.
627 	 *
628 	 * Requires `SRS_POLLING_CAPAB`.
629 	 */
630 	SRS_POLLING		= 1 << 6,
631 	/*
632 	 * The SRS worker thread currently holds `SRS_PROC`.
633 	 *
634 	 * Requires `SRS_PROC`.
635 	 */
636 	SRS_WORKER		= 1 << 8,
637 	/*
638 	 * Packets have been enqueued on this TX SRS due to either flow control
639 	 * or a lack of Tx descriptors on the NIC.
640 	 */
641 	SRS_ENQUEUED		= 1 << 9,
642 	/*
643 	 * `SRS_PROC` is held by the caller of `mac_rx_srs_process` (typically
644 	 * the interrupt context) and packets are being processed inline.
645 	 *
646 	 * Requires `SRS_PROC`.
647 	 */
648 	SRS_PROC_FAST		= 1 << 11,
649 	/*
650 	 * The Rx SRS poll thread currently holds `SRS_PROC`.
651 	 *
652 	 * Requires `SRS_PROC`.
653 	 */
654 	SRS_POLL_PROC		= 1 << 12,
655 	/*
656 	 * This Tx SRS has run out of descriptors on the underlying NIC.
657 	 *
658 	 * Any outbound packets will be queued until the underlying provider
659 	 * marks more descriptors as available via `mac_tx_ring_update`.
660 	 */
661 	SRS_TX_BLOCKED		= 1 << 13,
662 	/*
663 	 * This Tx SRS is flow controlled: more than `st_hiwat` packets are
664 	 * currently enqueued.
665 	 *
666 	 * Any outbound packets will be enqueued, and drained by the SRS
667 	 * worker. Senders will receive a cookie -- they will be informed when
668 	 * any cookie is no longer flow controlled if they have registered a
669 	 * callback via `mac_client_tx_notify`.
670 	 */
671 	SRS_TX_HIWAT		= 1 << 14,
672 	/*
673 	 * This Tx SRS has returned a cookie to at least one sender who has set
674 	 * `MAC_TX_NO_ENQUEUE` regardless of watermark state.
675 	 *
676 	 * When the SRS is drained, notify the client via its
677 	 * `mac_client_tx_notify` callback that it may send.
678 	 */
679 	SRS_TX_WAKEUP_CLIENT	= 1 << 15,
680 	/*
681 	 * `SRS_PROC` is held by the SRS drain function, which is handling
682 	 * packets inline because it is of type `SRST_NO_SOFT_RINGS`.
683 	 *
684 	 * Requires `SRS_PROC`.
685 	 */
686 	SRS_CLIENT_PROC		= 1 << 16,
687 	/*
688 	 * This SRS has been signalled to stop processing any packets.
689 	 *
690 	 * Downstack entrypoints (rings, flows) which can call into this SRS
691 	 * should be quiesced such that no more packets will be enqueued while
692 	 * this is set.
693 	 *
694 	 * The SRS worker thread will propagate the request to any softrings.
695 	 */
696 	SRS_QUIESCE		= 1 << 18,
697 	/*
698 	 * The SRS has ceased processing any enqueued packets, the worker thread
699 	 * has finished quiescing any softrings and is awaiting a signal
700 	 * of either `SRS_CONDEMNED` or `SRS_RESTART` to wake up.
701 	 */
702 	SRS_QUIESCE_DONE	= 1 << 19,
703 	/*
704 	 * This SRS is marked for deletion.
705 	 *
706 	 * Downstack entrypoints (rings, flows) which can call into this SRS
707 	 * should be quiesced such that no more packets will be enqueued while
708 	 * this is set.
709 	 *
710 	 * The SRS worker thread will propagate the request to any softrings.
711 	 */
712 	SRS_CONDEMNED		= 1 << 20,
713 	/*
714 	 * The SRS worker has completed any teardown in response to
715 	 * `SRS_CONDEMNED`.
716 	 *
717 	 * Requires `SRS_CONDEMNED_DONE`.
718 	 */
719 	SRS_CONDEMNED_DONE	= 1 << 21,
720 	/*
721 	 * This Rx SRS's poll thread has quiesced in response to `SRS_QUIESCE`.
722 	 */
723 	SRS_POLL_THR_QUIESCED	= 1 << 22,
724 	/*
725 	 * The SRS has been signalled to resume processing traffic.
726 	 *
727 	 * The worker thread should unset this and any `QUIESCE` flags,
728 	 * propagate the request to softrings and the poll thread, and
729 	 * resume processing packets.
730 	 */
731 	SRS_RESTART		= 1 << 23,
732 	/*
733 	 * The SRS has successfully restarted all of its softrings and poll
734 	 * thread, if present.
735 	 */
736 	SRS_RESTART_DONE	= 1 << 24,
737 	/*
738 	 * This Rx SRS's worker thread has signalled the poll thread to resume
739 	 * in response to `SRS_RESTART`.
740 	 */
741 	SRS_POLL_THR_RESTART	= 1 << 25,
742 	/*
743 	 * This SRS is part of the global list `mac_srs_g_list`. Its siblings
744 	 * are accessed via `srs_next` and `srs_prev`.
745 	 */
746 	SRS_IN_GLIST		= 1 << 26,
747 	/*
748 	 * This Rx SRS's poll thread has terminated in response to
749 	 * `SRS_CONDEMN`.
750 	 */
751 	SRS_POLL_THR_EXITED	= 1 << 27,
752 	/*
753 	 * This SRS is semi-permanently quiesced, and should not accept
754 	 * `SRS_RESTART` requests.
755 	 */
756 	SRS_QUIESCE_PERM	= 1 << 28,
757 } mac_soft_ring_set_state_t;
758 
759 /*
760  * SRS fanout states.
761  *
762  * These are set during SRS initialisation and by the flow CPU init methods to
763  * indicate whether any work is needing done to adjust the softrings.
764  */
765 typedef enum {
766 	/*
767 	 * This is a new SRS. Softrings have not yet been created.
768 	 */
769 	SRS_FANOUT_UNINIT = 0,
770 	/*
771 	 * The SRS's bindings and fanout count match the underlying CPU spec.
772 	 */
773 	SRS_FANOUT_INIT,
774 	/*
775 	 * CPU count and/or bindings have changed and the SRS needs to be
776 	 * modified accordingly.
777 	 */
778 	SRS_FANOUT_REINIT
779 } mac_srs_fanout_state_t;
780 
781 typedef void (*mac_srs_drain_proc_t)(mac_soft_ring_set_t *,
782     const mac_soft_ring_set_state_t);
783 
784 /*
785  * mac_soft_ring_set_s:
786  * This is used both for Tx and Rx side. The srs_type identifies Rx or
787  * Tx type.
788  *
789  * Note that the structure is carefully crafted, with Rx elements coming
790  * first followed by Tx specific members. Future additions to this
791  * structure should follow the same guidelines.
792  *
793  * Rx-side notes:
794  * mac_rx_classify_flow_add() always creates a mac_soft_ring_set_t and fn_flow
795  * points to info from it (func = srs_lower_proc, arg = soft_ring_set). On
796  * interrupt path, srs_lower_proc does B/W adjustment and switch to polling mode
797  * (if poll capable) and feeds the packets to soft_ring_list via choosen
798  * fanout type (specified by srs_type). In poll mode, the poll thread which is
799  * also a pointer can pick up the packets and feed them to various
800  * soft_ring_list.
801  *
802  * The srs_type can either be protocol based or fanout based where fanout itelf
803  * can be various types
804  *
805  * The polling works by turning off interrupts as soon as a packets
806  * are queued on the soft ring set. Once the backlog is clear and poll
807  * thread return empty handed i.e. Rx ring doesn't have anything, the
808  * interrupt is turned back on. For this purpose we keep a separate
809  * srs_poll_pkt_cnt counter which tracks the packets queued between SRS
810  * and the soft rings as well. The counter is incremented when packets
811  * are queued and decremented when SRS processes them (in case it has
812  * no soft rings) or the soft ring process them. Its important that
813  * in case SRS has softrings, the decrement doesn't happen till the
814  * packet is processed by the soft rings since it takes very little time
815  * for SRS to queue packet from SRS to soft rings and it will keep
816  * bringing more packets in the system faster than soft rings can
817  * process them.
818  *
819  * Tx side notes:
820  * The srs structure acts as a serializer with a worker thread. The
821  * default behavior of srs though is to act as a pass-thru. The queues
822  * (srs_first, srs_last, srs_count) get used when Tx ring runs out of Tx
823  * descriptors or to enforce bandwidth limits.
824  *
825  * When multiple Tx rings are present, the SRS state will be set to
826  * SRS_FANOUT_OTH. Outgoing packets coming into mac_tx_srs_process()
827  * function will be fanned out to one of the Tx side soft rings based on
828  * a hint passed in mac_tx_srs_process(). Each soft ring, in turn, will
829  * be associated with a distinct h/w Tx ring.
830  */
831 struct mac_soft_ring_set_s {
832 	/*
833 	 * Common elements, common to both Rx and Tx SRS type.
834 	 * The following block of fields are protected by srs_lock
835 	 */
836 	kmutex_t	srs_lock;
837 	mac_soft_ring_set_type_t	srs_type;
838 	mac_soft_ring_set_state_t	srs_state;
839 
840 	/*
841 	 * The SRS's packet queue.
842 	 */
843 	mblk_t		*srs_first;	/* first mblk chain or NULL */
844 	mblk_t		*srs_last;	/* last mblk chain or NULL */
845 	size_t		srs_size;	/* Size of packets queued in bytes */
846 	uint32_t	srs_count;
847 
848 	kcondvar_t	srs_async;	/* cv for worker thread */
849 	kcondvar_t	srs_cv;		/* cv for poll thread */
850 	timeout_id_t	srs_tid;	/* timeout id for pending timeout */
851 
852 	/*
853 	 * List of soft rings & processing function.
854 	 * The following block is protected by Rx quiescence.
855 	 * i.e. they can be changed only after quiescing the SRS
856 	 * Protected by srs_lock.
857 	 */
858 	mac_soft_ring_t	*srs_soft_ring_head;
859 	mac_soft_ring_t	*srs_soft_ring_tail;
860 	int		srs_soft_ring_count;
861 	int		srs_soft_ring_quiesced_count;
862 	int		srs_soft_ring_condemned_count;
863 
864 	kcondvar_t	srs_quiesce_done_cv;	/* cv for removal */
865 
866 	mac_soft_ring_t	**srs_tcp_soft_rings;
867 	mac_soft_ring_t	**srs_udp_soft_rings;
868 	mac_soft_ring_t	**srs_tcp6_soft_rings;
869 	mac_soft_ring_t	**srs_udp6_soft_rings;
870 	mac_soft_ring_t	**srs_oth_soft_rings;
871 	/*
872 	 * srs_tx_soft_rings is used by tx_srs in
873 	 * when operating in multi tx ring mode.
874 	 */
875 	mac_soft_ring_t	**srs_tx_soft_rings;
876 	int		srs_tcp_ring_count;
877 	int		srs_udp_ring_count;
878 	int		srs_tcp6_ring_count;
879 	int		srs_udp6_ring_count;
880 	int		srs_oth_ring_count;
881 	int		srs_tx_ring_count;
882 
883 	/*
884 	 * Bandwidth control related members.
885 	 * They are common to both Rx- and Tx-side.
886 	 * Following protected by srs_lock
887 	 */
888 	mac_bw_ctl_t	*srs_bw;
889 	pri_t		srs_pri;
890 
891 	mac_soft_ring_set_t	*srs_next;	/* mac_srs_g_lock */
892 	mac_soft_ring_set_t	*srs_prev;	/* mac_srs_g_lock */
893 
894 	/* Attribute specific drain func (BW ctl vs non-BW ctl)	*/
895 	mac_srs_drain_proc_t	srs_drain_func;	/* Write once (WO) */
896 
897 	/*
898 	 * If the associated ring is exclusively used by a mac client, e.g.,
899 	 * an aggregation, this fields is used to keep a reference to the
900 	 * MAC client's pseudo ring.
901 	 */
902 	mac_resource_handle_t	srs_mrh;
903 	/*
904 	 * The following blocks are write once (WO) and valid for the life
905 	 * of the SRS
906 	 */
907 	mac_client_impl_t *srs_mcip;	/* back ptr to mac client */
908 	flow_entry_t	*srs_flent;	/* back ptr to flent */
909 	mac_ring_t	*srs_ring;	/*  Ring Descriptor */
910 
911 	kthread_t	*srs_worker;	/* WO, worker thread */
912 	kthread_t	*srs_poll_thr;	/* WO, poll thread */
913 
914 	uint_t		srs_ind;	/* Round Robin indx for picking up SR */
915 	processorid_t	srs_worker_cpuid;	/* processor to bind to */
916 	processorid_t	srs_worker_cpuid_save;	/* saved cpuid during offline */
917 	processorid_t	srs_poll_cpuid;		/* processor to bind to */
918 	processorid_t	srs_poll_cpuid_save;	/* saved cpuid during offline */
919 	mac_srs_fanout_state_t	srs_fanout_state;
920 	mac_cpus_t	srs_cpu;
921 
922 	mac_srs_rx_t	srs_rx;
923 	mac_srs_tx_t	srs_tx;
924 	kstat_t		*srs_ksp;
925 };
926 
927 /*
928  * The total number of softring protocol lanes: TCP, TCP6, UDP, UDP6, OTH.
929  */
930 #define	ST_RING_NUM_PROTO	5
931 
932 /*
933  * arguments for processors to bind to
934  */
935 #define	S_RING_BIND_NONE	-1
936 
937 /*
938  * soft ring set flags. These bits are dynamic in nature and get
939  * applied to srs_state. They reflect the state of SRS at any
940  * point of time
941  */
942 
943 /*
944  * This flag pertains to `mac_bw_ctl_t` (mac_flow_impl.h), and should not live
945  * here.
946  *
947  * See illumos#17917.
948  */
949 #define	SRS_BW_ENFORCED		1
950 
951 #define	SRS_QUIESCED(srs)	(srs->srs_state & SRS_QUIESCE_DONE)
952 
953 /*
954  * If the SRS_QUIESCE_PERM flag is set, the SRS worker thread will not be
955  * able to be restarted.
956  */
957 #define	SRS_QUIESCED_PERMANENT(srs)	(srs->srs_state & SRS_QUIESCE_PERM)
958 
959 /*
960  * Structure for dls statistics
961  */
962 struct dls_kstats {
963 	kstat_named_t	dlss_soft_ring_pkt_drop;
964 };
965 
966 extern struct dls_kstats dls_kstat;
967 
968 #define	DLS_BUMP_STAT(x, y)	(dls_kstat.x.value.ui32 += y)
969 
970 /* Turn dynamic polling off */
971 #define	MAC_SRS_POLLING_OFF(mac_srs) {					\
972 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
973 	if (((mac_srs)->srs_state & (SRS_POLLING_CAPAB|SRS_POLLING)) == \
974 	    (SRS_POLLING_CAPAB|SRS_POLLING)) {				\
975 		(mac_srs)->srs_state &= ~SRS_POLLING;			\
976 		(void) mac_hwring_enable_intr((mac_ring_handle_t)	\
977 		    (mac_srs)->srs_ring);				\
978 		(mac_srs)->srs_rx.sr_poll_off++;			\
979 	}								\
980 }
981 
982 #define	MAC_COUNT_CHAIN(mac_srs, head, tail, cnt, sz)	{	\
983 	mblk_t		*tmp;					\
984 	boolean_t	bw_ctl = B_FALSE;			\
985 								\
986 	ASSERT((head) != NULL);					\
987 	cnt = 0;						\
988 	sz = 0;							\
989 	if ((mac_srs)->srs_type & SRST_BW_CONTROL)		\
990 		bw_ctl = B_TRUE;				\
991 	tmp = tail = (head);					\
992 	if ((head)->b_next == NULL) {				\
993 		cnt = 1;					\
994 		if (bw_ctl)					\
995 			sz += msgdsize(head);			\
996 	} else {						\
997 		while (tmp != NULL) {				\
998 			tail = tmp;				\
999 			cnt++;					\
1000 			if (bw_ctl)				\
1001 				sz += msgdsize(tmp);		\
1002 			tmp = tmp->b_next;			\
1003 		}						\
1004 	}							\
1005 }
1006 
1007 /*
1008  * Decrement the cumulative packet count in SRS and its
1009  * soft rings. If the srs_poll_pkt_cnt goes below lowat, then check
1010  * if if the interface was left in a polling mode and no one
1011  * is really processing the queue (to get the interface out
1012  * of poll mode). If no one is processing the queue, then
1013  * acquire the PROC and signal the poll thread to check the
1014  * interface for packets and get the interface back to interrupt
1015  * mode if nothing is found.
1016  */
1017 #define	MAC_UPDATE_SRS_COUNT_LOCKED(mac_srs, cnt) {		        \
1018 	mac_srs_rx_t	*srs_rx = &(mac_srs)->srs_rx;			\
1019 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
1020 									\
1021 	srs_rx->sr_poll_pkt_cnt -= cnt;					\
1022 	if ((srs_rx->sr_poll_pkt_cnt <= srs_rx->sr_poll_thres) &&	\
1023 	    (((mac_srs)->srs_state &					\
1024 	    (SRS_POLLING|SRS_PROC|SRS_GET_PKTS)) == SRS_POLLING))	\
1025 	{								\
1026 		(mac_srs)->srs_state |= (SRS_PROC|SRS_GET_PKTS);	\
1027 		cv_signal(&(mac_srs)->srs_cv);				\
1028 		srs_rx->sr_below_hiwat++;				\
1029 	}								\
1030 }
1031 
1032 /*
1033  * The following two macros are used to update the inbound packet and byte.
1034  * count. The packet and byte count reflect the packets and bytes that are
1035  * taken out of the SRS's queue, i.e. indicating they are being delivered.
1036  * The srs_count and srs_size are updated in different locations as the
1037  * srs_size is also used to take into account any bandwidth limits. The
1038  * srs_size is updated only when a soft ring, if any, sends a packet up,
1039  * as opposed to updating it when the SRS sends a packet to the SR, i.e.
1040  * the srs_size reflects the packets in the SRS and SRs. These
1041  * macros decrement the srs_size and srs_count and also increment the
1042  * ipackets and ibytes stats resp.
1043  *
1044  * xxx-venu These are done under srs_lock, for now we still update
1045  * mci_stat_ibytes/mci_stat_ipackets atomically, need to check if
1046  * just updating them would be accurate enough.
1047  *
1048  * If we are updating these for a sub-flow SRS, then we need to also
1049  * updated it's MAC client bandwidth info, if the MAC client is also
1050  * bandwidth regulated.
1051  */
1052 #define	MAC_UPDATE_SRS_SIZE_LOCKED(srs, sz) {				\
1053 	if ((srs)->srs_type & SRST_BW_CONTROL) {			\
1054 		mutex_enter(&(srs)->srs_bw->mac_bw_lock);		\
1055 		(srs)->srs_bw->mac_bw_sz -= (sz);			\
1056 		(srs)->srs_bw->mac_bw_used += (sz);			\
1057 		mutex_exit(&(srs)->srs_bw->mac_bw_lock);		\
1058 	}								\
1059 }
1060 
1061 #define	MAC_TX_UPDATE_BW_INFO(srs, sz) {				\
1062 	(srs)->srs_bw->mac_bw_sz -= (sz);				\
1063 	(srs)->srs_bw->mac_bw_used += (sz);				\
1064 }
1065 
1066 #define	MAC_TX_SOFT_RINGS(mac_srs) ((mac_srs)->srs_tx_ring_count >= 1)
1067 
1068 /* Soft ring flags for teardown */
1069 #define	SRS_POLL_THR_OWNER	(SRS_PROC | SRS_POLLING | SRS_GET_PKTS)
1070 #define	SRS_PAUSE		(SRS_CONDEMNED | SRS_QUIESCE)
1071 #define	S_RING_PAUSE		(S_RING_CONDEMNED | S_RING_QUIESCE)
1072 
1073 /* Soft rings */
1074 extern void mac_soft_ring_init(void);
1075 extern void mac_soft_ring_finish(void);
1076 extern void mac_fanout_setup(mac_client_impl_t *, flow_entry_t *,
1077     mac_resource_props_t *, mac_direct_rx_t, void *, cpupart_t *);
1078 
1079 extern void mac_soft_ring_worker_wakeup(mac_soft_ring_t *);
1080 extern mblk_t *mac_soft_ring_poll(mac_soft_ring_t *, size_t);
1081 extern void mac_soft_ring_dls_bypass_enable(mac_soft_ring_t *, mac_direct_rx_t,
1082     void *);
1083 extern void mac_soft_ring_dls_bypass_disable(mac_soft_ring_t *,
1084     mac_client_impl_t *);
1085 extern void mac_soft_ring_poll_enable(mac_soft_ring_t *, mac_direct_rx_t,
1086     void *, mac_resource_cb_t *, uint32_t);
1087 extern void mac_soft_ring_poll_disable(mac_soft_ring_t *, mac_resource_cb_t *,
1088     mac_client_impl_t *);
1089 
1090 /* SRS */
1091 extern void mac_srs_free(mac_soft_ring_set_t *);
1092 extern void mac_srs_signal(mac_soft_ring_set_t *,
1093     const mac_soft_ring_set_state_t);
1094 
1095 extern void mac_rx_srs_retarget_intr(mac_soft_ring_set_t *, processorid_t);
1096 extern void mac_tx_srs_retarget_intr(mac_soft_ring_set_t *);
1097 
1098 extern void mac_srs_client_poll_enable(mac_client_impl_t *,
1099     mac_soft_ring_set_t *, boolean_t);
1100 extern void mac_srs_client_poll_disable(mac_client_impl_t *,
1101     mac_soft_ring_set_t *, boolean_t);
1102 extern void mac_srs_client_poll_quiesce(mac_client_impl_t *,
1103     mac_soft_ring_set_t *);
1104 extern void mac_srs_client_poll_restart(mac_client_impl_t *,
1105     mac_soft_ring_set_t *);
1106 extern void mac_rx_srs_quiesce(mac_soft_ring_set_t *,
1107     const mac_soft_ring_set_state_t);
1108 extern void mac_rx_srs_restart(mac_soft_ring_set_t *);
1109 extern void mac_tx_srs_quiesce(mac_soft_ring_set_t *,
1110     const mac_soft_ring_set_state_t);
1111 
1112 /* Tx SRS, Tx softring */
1113 extern void mac_tx_srs_wakeup(mac_soft_ring_set_t *, mac_ring_handle_t);
1114 extern void mac_tx_srs_setup(mac_client_impl_t *, flow_entry_t *);
1115 extern mac_tx_func_t mac_tx_get_func(uint32_t);
1116 extern mblk_t *mac_tx_send(mac_client_impl_t *, mac_ring_t *, mblk_t *,
1117     mac_tx_stats_t *);
1118 extern boolean_t mac_tx_srs_ring_present(mac_soft_ring_set_t *, mac_ring_t *);
1119 extern mac_soft_ring_t *mac_tx_srs_get_soft_ring(mac_soft_ring_set_t *,
1120     mac_ring_t *);
1121 extern void mac_tx_srs_add_ring(mac_soft_ring_set_t *, mac_ring_t *);
1122 extern void mac_tx_srs_del_ring(mac_soft_ring_set_t *, mac_ring_t *);
1123 extern mac_tx_cookie_t mac_tx_srs_no_desc(mac_soft_ring_set_t *, mblk_t *,
1124     uint16_t, mblk_t **);
1125 
1126 /* Subflow specific stuff */
1127 extern void mac_srs_update_bwlimit(flow_entry_t *, mac_resource_props_t *);
1128 extern void mac_update_srs_priority(mac_soft_ring_set_t *, pri_t);
1129 extern void mac_client_update_classifier(mac_client_impl_t *, boolean_t);
1130 extern void mac_rx_srs_subflow_process(void *, mac_resource_handle_t, mblk_t *,
1131     boolean_t);
1132 
1133 /* Resource callbacks for clients */
1134 extern int mac_soft_ring_intr_enable(void *);
1135 extern boolean_t mac_soft_ring_intr_disable(void *);
1136 extern cpu_t *mac_soft_ring_bind(mac_soft_ring_t *, processorid_t);
1137 extern void mac_soft_ring_unbind(mac_soft_ring_t *);
1138 
1139 extern mac_soft_ring_t *mac_soft_ring_create_rx(int, clock_t,
1140     const mac_soft_ring_state_t, pri_t, mac_client_impl_t *,
1141     mac_soft_ring_set_t *, processorid_t, mac_direct_rx_t, void *);
1142 extern mac_soft_ring_t *mac_soft_ring_create_tx(int, clock_t,
1143     const mac_soft_ring_state_t, pri_t, mac_client_impl_t *,
1144     mac_soft_ring_set_t *, processorid_t, mac_ring_t *);
1145 extern void mac_soft_ring_free(mac_soft_ring_t *);
1146 extern void mac_soft_ring_signal(mac_soft_ring_t *,
1147     const mac_soft_ring_state_t);
1148 extern void mac_rx_soft_ring_process(mac_client_impl_t *, mac_soft_ring_t *,
1149     mblk_t *, mblk_t *, int, size_t);
1150 extern mac_tx_cookie_t mac_tx_soft_ring_process(mac_soft_ring_t *,
1151     mblk_t *, uint16_t, mblk_t **);
1152 extern void mac_srs_worker_quiesce(mac_soft_ring_set_t *);
1153 extern void mac_srs_worker_restart(mac_soft_ring_set_t *);
1154 
1155 extern void mac_rx_srs_drain_bw(mac_soft_ring_set_t *,
1156     const mac_soft_ring_set_state_t);
1157 extern void mac_rx_srs_drain(mac_soft_ring_set_t *,
1158     const mac_soft_ring_set_state_t);
1159 extern void mac_rx_srs_process(void *, mac_resource_handle_t, mblk_t *,
1160     boolean_t);
1161 extern void mac_srs_worker(mac_soft_ring_set_t *);
1162 extern void mac_rx_srs_poll_ring(mac_soft_ring_set_t *);
1163 extern void mac_tx_srs_drain(mac_soft_ring_set_t *,
1164     const mac_soft_ring_set_state_t);
1165 
1166 extern void mac_tx_srs_restart(mac_soft_ring_set_t *);
1167 extern void mac_rx_srs_remove(mac_soft_ring_set_t *);
1168 
1169 #ifdef	__cplusplus
1170 }
1171 #endif
1172 
1173 #endif	/* _SYS_MAC_SOFT_RING_H */
1174