mac_soft_ring.h revision efe28d82661ce6701204798fb838fd29c6348931
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_MAC_SOFT_RING_H
#define _SYS_MAC_SOFT_RING_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/processor.h>
#include <sys/mac_impl.h>
#define S_RING_NAMELEN 64
#define MAX_SR_FANOUT 32
extern boolean_t mac_soft_ring_enable;
extern boolean_t mac_latency_optimize;
typedef struct mac_soft_ring_s mac_soft_ring_t;
typedef struct mac_soft_ring_set_s mac_soft_ring_set_t;
typedef void (*mac_soft_ring_drain_func_t)(mac_soft_ring_t *);
/* Tx notify callback */
typedef struct mac_tx_notify_cb_s {
void *mtnf_arg; /* Callback function argument */
struct mac_soft_ring_s {
/* Keep the most used members 64bytes cache aligned */
int s_ring_count; /* # of mblocks in mac_soft_ring */
void *s_ring_rx_arg1;
/*
* Threshold after which packets get dropped.
* Is always greater than s_ring_tx_hiwat
*/
int s_ring_tx_max_q_cnt;
/* # of mblocks after which to apply flow control */
int s_ring_tx_hiwat;
/* # of mblocks after which to relieve flow control */
int s_ring_tx_lowat;
void *s_ring_tx_arg1;
void *s_ring_tx_arg2;
/* Tx notify callback */
struct mac_client_impl_s *s_ring_mcip;
void *s_ring_flent;
/* Teardown, poll disable control ops */
};
/* Transmit side Soft Ring Set */
typedef struct mac_srs_tx_s {
/* Members for Tx size processing */
void *st_arg1;
void *st_arg2;
/*
* st_max_q_cnt is the queue depth threshold to limit
* outstanding packets on the Tx SRS. Once the limit
* is reached, Tx SRS will drop packets until the
* limit goes below the threshold.
*/
/*
* st_hiwat is used Tx serializer and bandwidth mode.
* This is the queue depth threshold upto which
* packets will get buffered with no flow-control
* back pressure applied to the caller. Once this
* threshold is reached, back pressure will be
* applied to the caller of mac_tx() (mac_tx() starts
* returning a cookie to indicate a blocked SRS).
* st_hiwat should always be lesser than or equal to
* st_max_q_cnt.
*/
/*
* Number of times the srs gets blocked due to lack of Tx
* desc is noted down. Corresponding wakeup from driver
* to unblock is also noted down. They should match in a
* correctly working setup. If there is less unblocks
* than blocks, then Tx side waits forever for a wakeup
* from below. The following protected by srs_lock.
*/
} mac_srs_tx_t;
/* Receive side Soft Ring Set */
typedef struct mac_srs_rx_s {
/*
* Upcall Function for fanout, Rx processing etc. Perhaps
* the same 3 members below can be used for Tx
* processing, but looking around, mac_rx_func_t has
* proliferated too much into various files at different
* places. I am leaving the consolidation battle for
* another day.
*/
void *sr_arg1; /* srs_lock */
/* mblk cnt to apply flow control */
/* mblk cnt to relieve flow control */
/* Times polling was enabled */
/* Times polling was enabled by worker thread */
/* Times polling was disabled */
/* Poll thread signalled count */
/* Poll thread busy */
/* SRS drains, stays in poll mode but doesn't poll */
/*
* SRS has nothing to do and no packets in H/W but
* there is a backlog in softrings. SRS stays in
* poll mode but doesn't do polling.
*/
/* Active polling restarted */
/* Found packets in last poll so try and poll again */
/*
* Packets in queue but poll thread not allowed to process so
* signal the worker thread.
*/
/*
* Poll thread has nothing to do and H/W has nothing so
* reenable the interrupts.
*/
/*
* Poll thread has nothing to do and worker thread was already
* running so it can decide to reenable interrupt or poll again.
*/
/* Worker thread goes back to draining the queue */
/* More Packets in queue so signal the poll thread to drain */
/* More Packets in queue so signal the worker thread to drain */
/* Poll thread is already running so worker has nothing to do */
/* We have packets already queued so keep polling */
/* Drain is done and interrupts are reenabled */
/* Polling thread needs to schedule worker wakeup */
/* Chains less than 10 pkts */
/* Chains between 10 & 50 pkts */
/* Chains over 50 pkts */
} mac_srs_rx_t;
/*
* mac_soft_ring_set_s:
* This is used both for Tx and Rx side. The srs_type identifies Rx or
* Tx type.
*
* Note that the structure is carefully crafted, with Rx elements coming
* first followed by Tx specific members. Future additions to this
* structure should follow the same guidelines.
*
* Rx-side notes:
* mac_rx_classify_flow_add() always creates a mac_soft_ring_set_t and fn_flow
* points to info from it (func = srs_lower_proc, arg = soft_ring_set). On
* interrupt path, srs_lower_proc does B/W adjustment and switch to polling mode
* (if poll capable) and feeds the packets to soft_ring_list via choosen
* fanout type (specified by srs_type). In poll mode, the poll thread which is
* also a pointer can pick up the packets and feed them to various
* soft_ring_list.
*
* The srs_type can either be protocol based or fanout based where fanout itelf
* can be various types
*
* The polling works by turning off interrupts as soon as a packets
* are queued on the soft ring set. Once the backlog is clear and poll
* thread return empty handed i.e. Rx ring doesn't have anything, the
* interrupt is turned back on. For this purpose we keep a separate
* srs_poll_pkt_cnt counter which tracks the packets queued between SRS
* and the soft rings as well. The counter is incremented when packets
* are queued and decremented when SRS processes them (in case it has
* no soft rings) or the soft ring process them. Its important that
* in case SRS has softrings, the decrement doesn't happen till the
* packet is processed by the soft rings since it takes very little time
* for SRS to queue packet from SRS to soft rings and it will keep
* bringing more packets in the system faster than soft rings can
* process them.
*
* Tx side notes:
* The srs structure acts as a serializer with a worker thread. The
* default behavior of srs though is to act as a pass-thru. The queues
* (srs_first, srs_last, srs_count) get used when Tx ring runs out of Tx
* descriptors or to enforce bandwidth limits.
*
* When multiple Tx rings are present, the SRS state will be set to
* SRS_FANOUT_OTH. Outgoing packets coming into mac_tx_srs_process()
* function will be fanned out to one of the Tx side soft rings based on
* a hint passed in mac_tx_srs_process(). Each soft ring, in turn, will
* be associated with a distinct h/w Tx ring.
*/
struct mac_soft_ring_set_s {
/*
* Common elements, common to both Rx and Tx SRS type.
* The following block of fields are protected by srs_lock
*/
/*
* List of soft rings & processing function.
* The following block is protected by Rx quiescence.
* i.e. they can be changed only after quiescing the SRS
* Protected by srs_lock.
*/
int srs_soft_ring_count;
int srs_tcp_ring_count;
int srs_udp_ring_count;
/*
* srs_oth_soft_rings is also used by tx_srs in
* when operating in multi tx ring mode.
*/
int srs_oth_ring_count;
/*
* Bandwidth control related members.
* They are common to both Rx- and Tx-side.
* Following protected by srs_lock
*/
/* Attribute specific drain func (BW ctl vs non-BW ctl) */
/*
* If the associated ring is exclusively used by a mac client, e.g.,
* an aggregation, this fields is used to keep a reference to the
* MAC client's pseudo ring.
*/
/*
* The following blocks are write once (WO) and valid for the life
* of the SRS
*/
void *srs_flent; /* back ptr to flent */
/* Teardown, disable control ops */
};
/*
* type flags - combination allowed to process and drain the queue
*/
#define ST_RING_TCP 0x0004
#define ST_RING_UDP 0x0008
#define ST_RING_OTH 0x0010
#define ST_RING_BW_CTL 0x0020
#define ST_RING_TX 0x0040
/*
* State flags.
*/
/*
* arguments for processors to bind to
*/
#define S_RING_BIND_NONE -1
/*
* defines for srs_type - identifies a link or a sub-flow
* and other static characteristics of a SRS like a tx
* srs, tcp only srs, etc.
*/
#define SRST_LINK 0x00000001
#define SRST_FLOW 0x00000002
#define SRST_NO_SOFT_RINGS 0x00000004
#define SRST_TCP_ONLY 0x00000008
#define SRST_FANOUT_PROTO 0x00000010
#define SRST_FANOUT_SRC_IP 0x00000020
#define SRST_FANOUT_OTH 0x00000040
#define SRST_DEFAULT_GRP 0x00000080
#define SRST_TX 0x00000100
#define SRST_BW_CONTROL 0x00000200
#define SRST_DIRECT_POLL 0x00000400
#define SRST_DLS_BYPASS 0x00001000
#define SRST_CLIENT_POLL_ENABLED 0x00002000
/*
* soft ring set flags. These bits are dynamic in nature and get
* applied to srs_state. They reflect the state of SRS at any
* point of time
*/
#define SRS_BLANK 0x00000001
#define SRS_WORKER_BOUND 0x00000002
#define SRS_POLL_BOUND 0x00000004
#define SRS_POLLING_CAPAB 0x00000008
#define SRS_PROC 0x00000010
#define SRS_GET_PKTS 0x00000020
#define SRS_POLLING 0x00000040
#define SRS_BW_ENFORCED 0x00000080
#define SRS_WORKER 0x00000100
#define SRS_ENQUEUED 0x00000200
#define SRS_ANY_PROCESS 0x00000400
#define SRS_PROC_FAST 0x00000800
#define SRS_POLL_PROC 0x00001000
#define SRS_CLIENT_PROC 0x00010000
#define SRS_CLIENT_WAIT 0x00020000
#define SRS_QUIESCE 0x00040000
#define SRS_QUIESCE_DONE 0x00080000
#define SRS_CONDEMNED 0x00100000
#define SRS_CONDEMNED_DONE 0x00200000
#define SRS_POLL_THR_QUIESCED 0x00400000
#define SRS_RESTART 0x00800000
#define SRS_RESTART_DONE 0x01000000
#define SRS_POLL_THR_RESTART 0x02000000
#define SRS_IN_GLIST 0x04000000
#define SRS_POLL_THR_EXITED 0x08000000
#define SRS_QUIESCE_PERM 0x10000000
#define SRS_LATENCY_OPT 0x20000000
#define SRS_SOFTRING_QUEUE 0x40000000
/*
* If the SRS_QUIESCE_PERM flag is set, the SRS worker thread will not be
* able to be restarted.
*/
/*
* soft ring set (SRS) Tx modes
*/
typedef enum {
SRS_TX_DEFAULT = 0,
/*
* SRS fanout states
*/
typedef enum {
SRS_FANOUT_UNINIT = 0,
/*
* Structure for dls statistics
*/
struct dls_kstats {
};
extern struct dls_kstats dls_kstat;
/* Turn dynamic polling off */
#define MAC_SRS_POLLING_OFF(mac_srs) { \
(SRS_POLLING_CAPAB|SRS_POLLING)) { \
(void) mac_hwring_enable_intr((mac_ring_handle_t) \
} \
}
\
cnt = 0; \
sz = 0; \
cnt = 1; \
if (bw_ctl) \
} else { \
cnt++; \
if (bw_ctl) \
} \
} \
}
/*
* Decrement the cumulative packet count in SRS and its
* soft rings. If the srs_poll_pkt_cnt goes below lowat, then check
* if if the interface was left in a polling mode and no one
* is really processing the queue (to get the interface out
* of poll mode). If no one is processing the queue, then
* acquire the PROC and signal the poll thread to check the
* interface for packets and get the interface back to interrupt
* mode if nothing is found.
*/
\
{ \
srs_rx->sr_below_hiwat++; \
} \
}
/*
* The following two macros are used to update the inbound packet and byte.
* count. The packet and byte count reflect the packets and bytes that are
* taken out of the SRS's queue, i.e. indicating they are being delivered.
* The srs_count and srs_size are updated in different locations as the
* srs_size is also used to take into account any bandwidth limits. The
* srs_size is updated only when a soft ring, if any, sends a packet up,
* as opposed to updating it when the SRS sends a packet to the SR, i.e.
* the srs_size reflects the packets in the SRS and SRs. These
* macros decrement the srs_size and srs_count and also increment the
* ipackets and ibytes stats resp.
*
* xxx-venu These are done under srs_lock, for now we still update
* mci_stat_ibytes/mci_stat_ipackets atomically, need to check if
* just updating them would be accurate enough.
*
* If we are updating these for a sub-flow SRS, then we need to also
* updated it's MAC client bandwidth info, if the MAC client is also
* bandwidth regulated.
*/
} \
}
}
#define TX_MULTI_RING_MODE(mac_srs) \
/* Soft ring flags for teardown */
/* Soft rings */
extern void mac_soft_ring_init(void);
extern void mac_soft_ring_finish(void);
extern void mac_soft_ring_worker_wakeup(mac_soft_ring_t *);
extern void mac_soft_ring_destroy(mac_soft_ring_t *);
extern void mac_soft_ring_dls_bypass(void *, mac_direct_rx_t, void *);
/* Rx SRS */
mac_ring_t *);
extern void mac_srs_free(mac_soft_ring_set_t *);
extern void mac_srs_change_upcall(void *, mac_direct_rx_t, void *);
extern void mac_srs_quiesce_initiate(mac_soft_ring_set_t *);
extern void mac_srs_client_poll_enable(struct mac_client_impl_s *,
extern void mac_srs_client_poll_disable(struct mac_client_impl_s *,
extern void mac_srs_client_poll_quiesce(struct mac_client_impl_s *,
extern void mac_srs_client_poll_restart(struct mac_client_impl_s *,
extern void mac_rx_srs_restart(mac_soft_ring_set_t *);
/* Tx SRS, Tx softring */
extern void mac_tx_srs_setup(struct mac_client_impl_s *,
flow_entry_t *, uint32_t);
mac_tx_stats_t *);
/* Subflow specific stuff */
mac_resource_props_t *, int, int, mac_direct_rx_t);
extern void mac_srs_adjust_subflow_bwlimit(struct mac_client_impl_s *);
extern void mac_srs_update_drv(struct mac_client_impl_s *);
extern void mac_soft_ring_intr_enable(void *);
extern boolean_t mac_soft_ring_intr_disable(void *);
extern void mac_soft_ring_unbind(mac_soft_ring_t *);
extern void mac_srs_worker_quiesce(mac_soft_ring_set_t *);
extern void mac_srs_worker_restart(mac_soft_ring_set_t *);
extern void mac_srs_worker(mac_soft_ring_set_t *);
extern void mac_rx_srs_poll_ring(mac_soft_ring_set_t *);
extern void mac_tx_srs_restart(mac_soft_ring_set_t *);
extern void mac_rx_srs_remove(mac_soft_ring_set_t *);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_MAC_SOFT_RING_H */