summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/ip_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/ip_impl.h')
-rw-r--r--usr/src/uts/common/inet/ip_impl.h84
1 files changed, 66 insertions, 18 deletions
diff --git a/usr/src/uts/common/inet/ip_impl.h b/usr/src/uts/common/inet/ip_impl.h
index 369ba60005..7711a2fedc 100644
--- a/usr/src/uts/common/inet/ip_impl.h
+++ b/usr/src/uts/common/inet/ip_impl.h
@@ -503,24 +503,72 @@ typedef struct ip_pdescinfo_s PDESCINFO_STRUCT(2) ip_pdescinfo_t;
#define ILL_DIRECT_CAPABLE(ill) \
(((ill)->ill_capabilities & ILL_CAPAB_DLD_DIRECT) != 0)
-#define ILL_SEND_TX(ill, ire, hint, mp, flag) { \
- if (ILL_DIRECT_CAPABLE(ill) && DB_TYPE(mp) == M_DATA) { \
- ill_dld_direct_t *idd; \
- \
- idd = &(ill)->ill_dld_capab->idc_direct; \
- /* \
- * Send the packet directly to DLD, where it \
- * may be queued depending on the availability \
- * of transmit resources at the media layer. \
- * Ignore the returned value for the time being \
- * In future, we may want to take this into \
- * account and flow control the TCP. \
- */ \
- (void) idd->idd_tx_df(idd->idd_tx_dh, mp, \
- (uintptr_t)(hint), flag); \
- } else { \
- putnext((ire)->ire_stq, mp); \
- } \
+#define ILL_SEND_TX(ill, ire, hint, mp, flag, connp) { \
+ if (ILL_DIRECT_CAPABLE(ill) && DB_TYPE(mp) == M_DATA) { \
+ ill_dld_direct_t *idd; \
+ uintptr_t cookie; \
+ conn_t *udp_connp = (conn_t *)connp; \
+ \
+ idd = &(ill)->ill_dld_capab->idc_direct; \
+ /* \
+ * Send the packet directly to DLD, where it \
+ * may be queued depending on the availability \
+ * of transmit resources at the media layer. \
+ * Ignore the returned value for the time being \
+ * In future, we may want to take this into \
+ * account and flow control the TCP. \
+ */ \
+ cookie = idd->idd_tx_df(idd->idd_tx_dh, mp, \
+ (uintptr_t)(hint), flag); \
+ \
+ /* \
+ * non-NULL cookie indicates flow control situation \
+ * and the cookie itself identifies this specific \
+ * Tx ring that is blocked. This cookie is used to \
+ * block the UDP conn that is sending packets over \
+ * this specific Tx ring. \
+ */ \
+ if ((cookie != NULL) && (udp_connp != NULL) && \
+ (udp_connp->conn_ulp == IPPROTO_UDP)) { \
+ idl_tx_list_t *idl_txl; \
+ ip_stack_t *ipst; \
+ \
+ /* \
+ * Flow controlled. \
+ */ \
+ DTRACE_PROBE2(ill__send__tx__cookie, \
+ uintptr_t, cookie, conn_t *, udp_connp); \
+ ipst = udp_connp->conn_netstack->netstack_ip; \
+ idl_txl = \
+ &ipst->ips_idl_tx_list[IDLHASHINDEX(cookie)];\
+ mutex_enter(&idl_txl->txl_lock); \
+ if (udp_connp->conn_direct_blocked || \
+ (idd->idd_tx_fctl_df(idd->idd_tx_fctl_dh, \
+ cookie) == 0)) { \
+ DTRACE_PROBE1(ill__tx__not__blocked, \
+ boolean, \
+ udp_connp->conn_direct_blocked); \
+ } else if (idl_txl->txl_cookie != NULL && \
+ idl_txl->txl_cookie != cookie) { \
+ udp_t *udp = udp_connp->conn_udp; \
+ udp_stack_t *us = udp->udp_us; \
+ \
+ DTRACE_PROBE2(ill__send__tx__collision, \
+ uintptr_t, cookie, \
+ uintptr_t, idl_txl->txl_cookie); \
+ UDP_STAT(us, udp_cookie_coll); \
+ } else { \
+ udp_connp->conn_direct_blocked = B_TRUE;\
+ idl_txl->txl_cookie = cookie; \
+ conn_drain_insert(udp_connp, idl_txl); \
+ DTRACE_PROBE1(ill__send__tx__insert, \
+ conn_t *, udp_connp); \
+ } \
+ mutex_exit(&idl_txl->txl_lock); \
+ } \
+ } else { \
+ putnext((ire)->ire_stq, mp); \
+ } \
}
#define MBLK_RX_FANOUT_SLOWPATH(mp, ipha) \