10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53448Sdh155122 * Common Development and Distribution License (the "License"). 63448Sdh155122 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*11066Srafael.vanoni@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #ifndef _INET_NCA_H 270Sstevel@tonic-gate #define _INET_NCA_H 280Sstevel@tonic-gate 290Sstevel@tonic-gate #ifdef __cplusplus 300Sstevel@tonic-gate extern "C" { 310Sstevel@tonic-gate #endif 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <sys/thread.h> 340Sstevel@tonic-gate #include <sys/door.h> 350Sstevel@tonic-gate #include <sys/disp.h> 360Sstevel@tonic-gate #include <sys/systm.h> 370Sstevel@tonic-gate #include <sys/processor.h> 380Sstevel@tonic-gate #include <sys/socket.h> 390Sstevel@tonic-gate #include <inet/common.h> 400Sstevel@tonic-gate #include <inet/ip.h> 410Sstevel@tonic-gate #include <inet/tcp.h> 420Sstevel@tonic-gate #include <inet/nca/ncadoorhdr.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* 450Sstevel@tonic-gate * The NCA debugging facilities provided via ADB and MDB depend on a 460Sstevel@tonic-gate * number of NCA implementation details. In particular, note that: 470Sstevel@tonic-gate * 480Sstevel@tonic-gate * * ADB macros *must* be revised whenever members are added or 490Sstevel@tonic-gate * removed from the following structures: 500Sstevel@tonic-gate * 510Sstevel@tonic-gate * nca_conn_t connf_t nca_cpu_t dcb_t hcb_t nca_if_t nca_io2_t 520Sstevel@tonic-gate * node_t nodef_t sqfan_t nca_squeue_t tb_t te_t ti_t tw_t 530Sstevel@tonic-gate * 540Sstevel@tonic-gate * * ADB macros should be added when new core data structures are 550Sstevel@tonic-gate * added to NCA. Generally, if you had to put it in here, you 560Sstevel@tonic-gate * need to write a macro for it. 570Sstevel@tonic-gate * 580Sstevel@tonic-gate * * MDB has many dependencies on the way core data structures 590Sstevel@tonic-gate * are connected. In general, if you break these dependencies, 600Sstevel@tonic-gate * the MDB NCA module will fail to build. However, breakage 610Sstevel@tonic-gate * may go undetected (for instance, changing a linked list 620Sstevel@tonic-gate * into a circularly linked list). If you have any doubts, 630Sstevel@tonic-gate * inspect the NCA module source before committing your changes. 640Sstevel@tonic-gate * 650Sstevel@tonic-gate * * MDB depends on the following variables (and their current 660Sstevel@tonic-gate * semantics) in order to function correctly: 670Sstevel@tonic-gate * 680Sstevel@tonic-gate * nca_conn_fanout nca_conn_fanout_size nca_gv nca_lru 690Sstevel@tonic-gate * urihash filehash 700Sstevel@tonic-gate * 710Sstevel@tonic-gate * If you change the names or *semantics* of these variables, 720Sstevel@tonic-gate * you must modify the MDB module accordingly. 730Sstevel@tonic-gate * 740Sstevel@tonic-gate * In addition, you should consider whether the changes you've 750Sstevel@tonic-gate * made should be reflected in the MDB dcmds themselves. 760Sstevel@tonic-gate */ 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* The queue to make upcall on for NCAfs */ 790Sstevel@tonic-gate extern queue_t *ncaupcallq; 800Sstevel@tonic-gate extern kmutex_t ncaupcallq_lock; 810Sstevel@tonic-gate 820Sstevel@tonic-gate extern int nca_logging_on; 830Sstevel@tonic-gate extern int nca_conn_fanout_size; 840Sstevel@tonic-gate extern boolean_t nca_deferred_oq_if; 850Sstevel@tonic-gate extern boolean_t nca_fanout_iq_if; 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* Checksum pointer for no checksum */ 880Sstevel@tonic-gate 890Sstevel@tonic-gate #define NO_CKSUM (void *)-1 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* undef any tcp.h:tcp_t members overloaded by the Solaris 8 tcp.h */ 920Sstevel@tonic-gate 930Sstevel@tonic-gate #undef tcp_last_rcv_lbolt 940Sstevel@tonic-gate #undef tcp_state 950Sstevel@tonic-gate #undef tcp_rto 960Sstevel@tonic-gate #undef tcp_snd_ts_ok 970Sstevel@tonic-gate #undef tcp_snd_ws_ok 980Sstevel@tonic-gate #undef tcp_snxt 990Sstevel@tonic-gate #undef tcp_swnd 1000Sstevel@tonic-gate #undef tcp_mss 1010Sstevel@tonic-gate #undef tcp_iss 1020Sstevel@tonic-gate #undef tcp_rnxt 1030Sstevel@tonic-gate #undef tcp_rwnd 1040Sstevel@tonic-gate #undef tcp_lport 1050Sstevel@tonic-gate #undef tcp_fport 1060Sstevel@tonic-gate #undef tcp_ports 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate /* the iph_t is no longer defined in ip.h for Solaris 8 ? */ 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* Unaligned IP header */ 1110Sstevel@tonic-gate typedef struct iph_s { 1120Sstevel@tonic-gate uchar_t iph_version_and_hdr_length; 1130Sstevel@tonic-gate uchar_t iph_type_of_service; 1140Sstevel@tonic-gate uchar_t iph_length[2]; 1150Sstevel@tonic-gate uchar_t iph_ident[2]; 1160Sstevel@tonic-gate uchar_t iph_fragment_offset_and_flags[2]; 1170Sstevel@tonic-gate uchar_t iph_ttl; 1180Sstevel@tonic-gate uchar_t iph_protocol; 1190Sstevel@tonic-gate uchar_t iph_hdr_checksum[2]; 1200Sstevel@tonic-gate uchar_t iph_src[4]; 1210Sstevel@tonic-gate uchar_t iph_dst[4]; 1220Sstevel@tonic-gate } iph_t; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate #define true B_TRUE /* used with type boolean_t */ 1260Sstevel@tonic-gate #define false B_FALSE /* used with type boolean_t */ 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * Power of 2^N Primes useful for hashing for N of 0-28, 1300Sstevel@tonic-gate * these primes are the nearest prime <= 2^N - 2^(N-2). 1310Sstevel@tonic-gate */ 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate #define P2Ps() {0, 0, 0, 5, 11, 23, 47, 89, 191, 383, 761, 1531, 3067, \ 1340Sstevel@tonic-gate 6143, 12281, 24571, 49139, 98299, 196597, 393209, \ 1350Sstevel@tonic-gate 786431, 1572853, 3145721, 6291449, 12582893, 25165813, \ 1360Sstevel@tonic-gate 50331599, 100663291, 201326557, 0} 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate /* 1390Sstevel@tonic-gate * Serialization queue type (move to strsubr.h (stream.h?) as a general 1400Sstevel@tonic-gate * purpose lightweight mechanism for mblk_t serialization ?). 1410Sstevel@tonic-gate */ 1420Sstevel@tonic-gate typedef struct nca_squeue_s { 1430Sstevel@tonic-gate uint16_t sq_state; /* state flags */ 1440Sstevel@tonic-gate uint16_t sq_count; /* message count */ 1450Sstevel@tonic-gate uint32_t sq_type; /* type flags */ 1460Sstevel@tonic-gate processorid_t sq_bind; /* processor to bind to */ 1470Sstevel@tonic-gate ddi_softintr_t sq_softid; /* softintr() id */ 1480Sstevel@tonic-gate void (*sq_init)(); /* initialize function */ 1490Sstevel@tonic-gate void *sq_init_arg; /* initialize argument */ 1500Sstevel@tonic-gate void (*sq_proc)(); /* process function */ 1510Sstevel@tonic-gate mblk_t *sq_first; /* first mblk chain or NULL */ 1520Sstevel@tonic-gate mblk_t *sq_last; /* last mblk chain or NULL */ 1530Sstevel@tonic-gate clock_t sq_wait; /* lbolts to wait after a fill() */ 1540Sstevel@tonic-gate clock_t sq_iwait; /* lbolt after nointr() */ 1550Sstevel@tonic-gate clock_t sq_pwait; /* lbolt after pause() */ 1560Sstevel@tonic-gate int sq_isintr; /* is being or was serviced by */ 1570Sstevel@tonic-gate timeout_id_t sq_tid; /* timer id of pending timeout() */ 1580Sstevel@tonic-gate kcondvar_t sq_async; /* async thread blocks on */ 1590Sstevel@tonic-gate kmutex_t sq_lock; /* lock before using any member */ 1600Sstevel@tonic-gate clock_t sq_awaken; /* time async thread was awakened */ 1610Sstevel@tonic-gate void *sq_priv; /* user defined private */ 1620Sstevel@tonic-gate kt_did_t sq_ktid; /* kernel thread id */ 1630Sstevel@tonic-gate } nca_squeue_t; 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate /* 1660Sstevel@tonic-gate * State flags and message count (i.e. properties that change) 1670Sstevel@tonic-gate * Note: The MDB NCA module depends on the values of these flags. 1680Sstevel@tonic-gate */ 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate #define SQS_CNT_TOOMANY 0x8000 /* message count toomany */ 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* nca_squeue_t state flags now only 16 bits */ 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate #define SQS_PROC 0x0001 /* being processed */ 1750Sstevel@tonic-gate #define SQS_WORKER 0x0002 /* worker thread */ 1760Sstevel@tonic-gate #define SQS_ENTER 0x0004 /* enter thread */ 1770Sstevel@tonic-gate #define SQS_FAST 0x0008 /* enter-fast thread */ 1780Sstevel@tonic-gate #define SQS_PROXY 0x0010 /* proxy thread */ 1790Sstevel@tonic-gate #define SQS_SOFTINTR 0x0020 /* softint thread */ 1800Sstevel@tonic-gate /* 0x00C0 bits not used */ 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate #define SQS_NOINTR 0x0100 /* no interrupt processing */ 1830Sstevel@tonic-gate #define SQS_PAUSE 0x0200 /* paused */ 1840Sstevel@tonic-gate #define SQS_INTRWAIT 0x0400 /* interrupt waiting */ 1850Sstevel@tonic-gate #define SQS_NOPROC 0x0800 /* no processing */ 1860Sstevel@tonic-gate /* 0x7000 bits not used */ 1870Sstevel@tonic-gate #define SQS_EXIT 0x8000 /* worker(s) exit */ 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate /* 1900Sstevel@tonic-gate * Type flags (i.e. properties that don't change). 1910Sstevel@tonic-gate * Note: The MDB NCA module depends on the values of these flags. 1920Sstevel@tonic-gate */ 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate #define SQT_BIND_MASK 0xFF000000 /* bind flags mask */ 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate #define SQT_KMEM 0x00000001 /* was kmem_alloc()ed */ 1970Sstevel@tonic-gate #define SQT_DEFERRED 0x00000002 /* deferred processing */ 1980Sstevel@tonic-gate #define SQT_SOFTINTR 0x00000004 /* use softintr() */ 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate #define SQT_BIND_ANY 0x01000000 /* bind worker thread to any CPU */ 2010Sstevel@tonic-gate #define SQT_BIND_TO 0x02000000 /* bind worker thread to speced CPU */ 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate #define SQ_STATE_IS(sqp, flags) ((sqp)->sq_state & (flags)) 2040Sstevel@tonic-gate #define SQ_TYPE_IS(sqp, flags) ((sqp)->sq_type & (flags)) 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate typedef struct sqfan_s { 2080Sstevel@tonic-gate uint32_t flg; /* flags only */ 2090Sstevel@tonic-gate uint32_t cnt; /* vector count */ 2100Sstevel@tonic-gate uint32_t ix; /* next sqv[] to process */ 2110Sstevel@tonic-gate uint32_t drain; /* max mblk(s) draind per */ 2120Sstevel@tonic-gate nca_squeue_t **sqv; /* pointer to nca_squeue_t pointer vector */ 2130Sstevel@tonic-gate } sqfan_t; 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate #define SQF_DIST_CNT 0x0001 /* sqfan_t dist by queue count */ 2160Sstevel@tonic-gate #define SQF_DIST_IPv4 0x0002 /* sqfan_t dist by IPv4 src addr */ 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* 2190Sstevel@tonic-gate * A multiphase timer is implemented using the te_t, tb_t, and ti_t structs. 2200Sstevel@tonic-gate * 2210Sstevel@tonic-gate * The multiple phases of timer entry execution are: 2220Sstevel@tonic-gate * 2230Sstevel@tonic-gate * 1) resource, execution is done from resource reclaim when the timer event 2240Sstevel@tonic-gate * is the freeing of the timed resource. 2250Sstevel@tonic-gate * 2260Sstevel@tonic-gate * 2) process, execution is done from process thread yield (idle/return). 2270Sstevel@tonic-gate * 2280Sstevel@tonic-gate * 3) time, execution is done from a timeout callback thread. 2290Sstevel@tonic-gate * 2300Sstevel@tonic-gate * Each of the phases have a seperate timer fire time represented by the 2310Sstevel@tonic-gate * the ti_t members lbolt1, lbolt2, and lbolt3. Each lbolt is an absolute 2320Sstevel@tonic-gate * lbolt value with lbolt1 <= lbolt2 <= lbolt3. 2330Sstevel@tonic-gate */ 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* 2360Sstevel@tonic-gate * te_t - timer entry. 2370Sstevel@tonic-gate */ 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate typedef struct te_s { 2400Sstevel@tonic-gate struct te_s *prev; /* prev te_t */ 2410Sstevel@tonic-gate struct te_s *next; /* next te_t */ 2420Sstevel@tonic-gate struct tb_s *tbp; /* pointer to timer bucket */ 2430Sstevel@tonic-gate void *ep; /* pointer to encapsulating struct */ 2440Sstevel@tonic-gate } te_t; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate /* 2470Sstevel@tonic-gate * tb_t - timer bucket. 2480Sstevel@tonic-gate */ 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate typedef struct tb_s { 2510Sstevel@tonic-gate struct tb_s *next; /* next tb_t in ascending time order */ 2520Sstevel@tonic-gate clock_t exec; /* te_t lbolt exec value for bucket */ 2530Sstevel@tonic-gate te_t *head; /* head of te_t list (first timer) */ 2540Sstevel@tonic-gate te_t *tail; /* tail of te_t list (last timer) */ 2550Sstevel@tonic-gate } tb_t; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate /* 2580Sstevel@tonic-gate * ti_t - timer state. 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate typedef struct ti_s { 2620Sstevel@tonic-gate clock_t exec; /* next te_t exec value (0 = NONE) */ 2630Sstevel@tonic-gate clock_t lbolt1; /* phase1 lbolt1 (0 = NONE) */ 2640Sstevel@tonic-gate clock_t lbolt2; /* phase2 lbolt2 (0 = NONE) */ 2650Sstevel@tonic-gate clock_t lbolt3; /* phase3 lbolt3 (0 = NONE) */ 2660Sstevel@tonic-gate tb_t *head; /* head of tb_t list (first timer bucket) */ 2670Sstevel@tonic-gate tb_t *tail; /* tail of tb_t list (last timer bucket) */ 2680Sstevel@tonic-gate timeout_id_t tid; /* timer id of pending timeout() (0 = NONE) */ 2690Sstevel@tonic-gate void *ep; /* pointer to encapsulating struct */ 2700Sstevel@tonic-gate } ti_t; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate #define NCA_TI_INPROC -1 /* Processing going on */ 2730Sstevel@tonic-gate #define NCA_TI_NONE 0 /* no lbolt */ 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate /* 2760Sstevel@tonic-gate * TIME_WAIT grounded doubly linked list of nca_conn_t's awaiting TIME_WAIT 2770Sstevel@tonic-gate * expiration for. This list is used for reclaim, reap, and timer based 2780Sstevel@tonic-gate * processing. 2790Sstevel@tonic-gate * 2800Sstevel@tonic-gate * A multiphase timer is used: 2810Sstevel@tonic-gate * 2820Sstevel@tonic-gate * phase 1) reclaim of connections during connection allocation 2830Sstevel@tonic-gate * 2840Sstevel@tonic-gate * phase 2) reaping of connections during nca_squeue_t inq thread unwind 2850Sstevel@tonic-gate * 2860Sstevel@tonic-gate * phase 3) timeout of connections as a result of a timeout(). 2870Sstevel@tonic-gate * 2880Sstevel@tonic-gate * Each of the phases have a seperate timer fire lbolt represented by the 2890Sstevel@tonic-gate * the members lbolt1, lbolt2, and lbolt3, each is an absolute lbolt value 2900Sstevel@tonic-gate * with lbolt1 <= lbolt2 <= lbolt3. 2910Sstevel@tonic-gate */ 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate typedef struct tw_s { 2940Sstevel@tonic-gate clock_t lbolt1; /* phase1 lbolt value (0 = NONE) */ 2950Sstevel@tonic-gate clock_t lbolt2; /* phase2 lbolt value */ 2960Sstevel@tonic-gate clock_t lbolt3; /* phase3 lbolt value */ 2977632SNick.Todd@Sun.COM struct nca_conn_s *head; /* Head of nca_conn_t list */ 2987632SNick.Todd@Sun.COM struct nca_conn_s *tail; /* Tail of nca_conn_t list */ 2990Sstevel@tonic-gate timeout_id_t tid; /* Timer id of pending timeout() (0 = NONE) */ 3000Sstevel@tonic-gate void *ep; /* pointer to encapsulating struct */ 3010Sstevel@tonic-gate } tw_t; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate #define NCA_TW_NONE 0 /* no lbolt */ 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate #define NCA_TW_MS 1000 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate #define NCA_TW_LBOLT MSEC_TO_TICK(NCA_TW_MS) 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate #define NCA_TW_LBOLTS(twp, future) { \ 3100Sstevel@tonic-gate clock_t _lbolt = (future); \ 3110Sstevel@tonic-gate clock_t _mod = _lbolt % NCA_TW_LBOLT; \ 3120Sstevel@tonic-gate \ 3130Sstevel@tonic-gate if (_mod) { \ 3140Sstevel@tonic-gate /* Roundup to next TIME_WAIT bucket */ \ 3150Sstevel@tonic-gate _lbolt += NCA_TW_LBOLT - _mod; \ 3160Sstevel@tonic-gate } \ 3170Sstevel@tonic-gate if ((twp)->lbolt1 != _lbolt) { \ 3180Sstevel@tonic-gate (twp)->lbolt1 = _lbolt; \ 3190Sstevel@tonic-gate _lbolt += NCA_TW_LBOLT; \ 3200Sstevel@tonic-gate (twp)->lbolt2 = _lbolt; \ 3210Sstevel@tonic-gate _lbolt += NCA_TW_LBOLT; \ 3220Sstevel@tonic-gate (twp)->lbolt3 = _lbolt; \ 3230Sstevel@tonic-gate if ((twp)->tid != 0) { \ 3240Sstevel@tonic-gate (void) untimeout((twp)->tid); \ 3250Sstevel@tonic-gate (twp)->tid = 0; \ 3260Sstevel@tonic-gate } \ 3270Sstevel@tonic-gate if ((_lbolt) != NCA_TW_NONE) { \ 3280Sstevel@tonic-gate (twp)->tid = timeout((pfv_t)nca_tw_fire, (twp), \ 329*11066Srafael.vanoni@sun.com (twp)->lbolt3 - ddi_get_lbolt()); \ 3300Sstevel@tonic-gate } \ 3310Sstevel@tonic-gate } \ 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* 3350Sstevel@tonic-gate * The Node Fanout structure. 3360Sstevel@tonic-gate * 3370Sstevel@tonic-gate * The hash tables and their linkage (hashnext) are protected by the 3380Sstevel@tonic-gate * per-bucket lock. Each node_t inserted in the list points back at 3390Sstevel@tonic-gate * the nodef_t that heads the bucket (hashfanout). 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate typedef struct nodef_s { 3430Sstevel@tonic-gate struct node_s *head; 3440Sstevel@tonic-gate kmutex_t lock; 3450Sstevel@tonic-gate } nodef_t; 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * A node_t is used to represent a cached byte-stream object. A node_t is 3490Sstevel@tonic-gate * in one of four active states: 3500Sstevel@tonic-gate * 3510Sstevel@tonic-gate * 1) path != NULL, member of a node_t hash list with an object description 3520Sstevel@tonic-gate * (hashnext, size, path, pathsz members valid). 3530Sstevel@tonic-gate * 3540Sstevel@tonic-gate * 2) pp != NULL, 1) + phys pages allocated (pp, plrupn, plrunn members valid). 3550Sstevel@tonic-gate * 3560Sstevel@tonic-gate * 3) data != NULL, 2) + virt mapping allocated (data, datasz, vlrupn, vlrunn 3570Sstevel@tonic-gate * members valid). 3580Sstevel@tonic-gate * 3590Sstevel@tonic-gate * 4) cksum != NULL 3) + checksum mapping allocated 3600Sstevel@tonic-gate */ 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate typedef struct node_s { 3630Sstevel@tonic-gate uint32_t ref; /* ref (see below) state */ 3640Sstevel@tonic-gate uint32_t cnt; /* ref count */ 3650Sstevel@tonic-gate int32_t size; /* object size (-1 = UNKNOWN) */ 3660Sstevel@tonic-gate uint32_t mss; /* mblk(s) in size mss */ 3670Sstevel@tonic-gate uint64_t ctag; /* usr defined cache tag, 0 => no tag */ 3680Sstevel@tonic-gate ipaddr_t laddr; /* local IP, for virtual hosting */ 3690Sstevel@tonic-gate uint16_t lport; /* local port, for virtual hosting */ 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate struct node_s *plrunn; /* Phys LRU list next node_t */ 3720Sstevel@tonic-gate struct node_s *plrupn; /* Phys LRU list previous node_t */ 3730Sstevel@tonic-gate struct node_s *vlrunn; /* Virt LRU list next node_t */ 3740Sstevel@tonic-gate struct node_s *vlrupn; /* Virt LRU list previous node_t */ 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate nodef_t *hashfanout; /* hash bucket we're part of */ 3770Sstevel@tonic-gate nodef_t *ctaghashfanout; /* ctaghash bucket we're part off */ 3780Sstevel@tonic-gate struct node_s *hashnext; /* hash list next node_t */ 3790Sstevel@tonic-gate struct node_s *ctaghashnext; /* ctaghash list next node_t */ 3807632SNick.Todd@Sun.COM struct nca_conn_s *connhead; /* head of list of conn(s) in miss */ 3817632SNick.Todd@Sun.COM struct nca_conn_s *conntail; /* tail of list of conn(s) in miss */ 3820Sstevel@tonic-gate struct node_s *next; /* needed if data is in chunks */ 3830Sstevel@tonic-gate struct node_s *back; /* needed if data is in chunks */ 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate clock_t expire; /* lbolt node_t expires (0 = NOW, -1 = NEVER) */ 3860Sstevel@tonic-gate time_t lastmod; /* HTTP "Last-Modified:" value */ 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate mblk_t *req; /* whole HTTP request (including headers) */ 3890Sstevel@tonic-gate int reqsz; /* size of above */ 3900Sstevel@tonic-gate int reqcontl; /* HTTP "Content-Length:" value */ 3910Sstevel@tonic-gate uint32_t rcv_cnt; /* rcv_list byte count */ 3920Sstevel@tonic-gate mblk_t *rcv_head; /* rcv_list head */ 3930Sstevel@tonic-gate mblk_t *rcv_tail; /* rcv_list tail */ 3940Sstevel@tonic-gate mblk_t *rcv_ptr; /* rcv_list pointer */ 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate nca_squeue_t *sqp; /* squeue node_t is being processed from */ 3970Sstevel@tonic-gate char *path; /* URI path component */ 3980Sstevel@tonic-gate int pathsz; /* size of above */ 3990Sstevel@tonic-gate uint_t method; /* HTTP request method */ 4000Sstevel@tonic-gate uint_t version; /* HTTP request version */ 4010Sstevel@tonic-gate char *reqhdr; /* HTTP request header(s) */ 4020Sstevel@tonic-gate int reqhdrsz; /* size of above */ 4030Sstevel@tonic-gate char *reqhost; /* HTTP "Host:" string */ 4040Sstevel@tonic-gate int reqhostsz; /* size of above */ 4050Sstevel@tonic-gate char *reqaccept; /* HTTP "Accept:" string */ 4060Sstevel@tonic-gate int reqacceptsz; /* size of above */ 4070Sstevel@tonic-gate char *reqacceptl; /* HTTP "Accept-Language:" string */ 4080Sstevel@tonic-gate int reqacceptlsz; /* size of above */ 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate page_t **pp; /* page pointer vector for data */ 4110Sstevel@tonic-gate char *data; /* data buffer */ 4120Sstevel@tonic-gate int datasz; /* size of above */ 4130Sstevel@tonic-gate uint16_t *cksum; /* cksum() vector for data by mss */ 4140Sstevel@tonic-gate size_t cksumlen; /* length of memory block for above vector */ 4150Sstevel@tonic-gate uint_t resbody; /* HTTP response body at &data[resbody] */ 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate int hlen; /* data buffer split header len */ 4180Sstevel@tonic-gate int fileoff; /* file include offset */ 4190Sstevel@tonic-gate int filelen; /* length of file */ 4200Sstevel@tonic-gate struct node_s *fileback; /* head node_t of a file list (-1 for death) */ 4210Sstevel@tonic-gate struct node_s *filenext; /* next node_t of a file list */ 4220Sstevel@tonic-gate struct node_s *ctagback; /* head node_t of a ctag list */ 4230Sstevel@tonic-gate struct node_s *ctagnext; /* next node_t of a ctag list */ 4240Sstevel@tonic-gate vnode_t *filevp; /* vnode for the file */ 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate kmutex_t lock; /* serializes access to node_t */ 4270Sstevel@tonic-gate frtn_t frtn; /* STREAMS free routine; always node_freeb() */ 4280Sstevel@tonic-gate boolean_t headchunk; /* true if this node is the head chunk */ 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate /* 4310Sstevel@tonic-gate * The following 4 fields are used to record node states when 4323517Smp204432 * upcalls are preempted. When preempted upcalls are not relevant, 4330Sstevel@tonic-gate * these fields should have default value 0. 4340Sstevel@tonic-gate */ 4350Sstevel@tonic-gate uint8_t advise; /* an interpreted advise from http */ 4360Sstevel@tonic-gate boolean_t last_advisory; /* preempted upcall state -- advisory bit */ 4370Sstevel@tonic-gate boolean_t advisory; /* need advisory from httpd before use */ 4380Sstevel@tonic-gate boolean_t first_upcall; /* node in first upcall, a internal state */ 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate kcondvar_t cv; /* sync upcall/downcall process on a node */ 4410Sstevel@tonic-gate int onqueue; /* == 1 if on miss_queue, debug aid */ 4420Sstevel@tonic-gate } node_t; 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate /* Note: The MDB NCA module depends on the values of these flags. */ 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate #define REF_URI 0x80000000 /* & ref = node_t URI hashed */ 4470Sstevel@tonic-gate #define REF_PHYS 0x40000000 /* & ref = phys mapping in-use */ 4480Sstevel@tonic-gate #define REF_VIRT 0x20000000 /* & ref = virt mapping in-use */ 4490Sstevel@tonic-gate #define REF_CKSUM 0x10000000 /* & ref = checksum mapping in-use */ 4500Sstevel@tonic-gate #define REF_KMEM 0x08000000 /* & ref = kmem mapped (PHYS|VIRT) */ 4510Sstevel@tonic-gate #define REF_DONE 0x04000000 /* & ref = node_t fill is done */ 4520Sstevel@tonic-gate #define REF_SAFED 0x02000000 /* & ref = node_t not safe for use */ 4530Sstevel@tonic-gate #define REF_FILE 0x01000000 /* & ref = node_t filename hashed */ 4540Sstevel@tonic-gate #define REF_RESP 0x00800000 /* & ref = node_t response header parsed */ 4550Sstevel@tonic-gate #define REF_NOLRU 0x00400000 /* & ref = node_t not safe for lru reclaim */ 4560Sstevel@tonic-gate #define REF_MISS 0x00200000 /* & ref = node_t is/will missed() proc */ 4570Sstevel@tonic-gate #define REF_ONPLRU 0x00100000 /* & ref = node_t is on Phys LRU */ 4580Sstevel@tonic-gate #define REF_ONVLRU 0x00080000 /* & ref = node_t is on Virt LRU */ 4590Sstevel@tonic-gate #define REF_PREEMPT 0x00040000 /* & ref = node_t processing preempted */ 4600Sstevel@tonic-gate #define REF_CTAG 0x00020000 /* & ref = node_t CTAG hashed */ 4610Sstevel@tonic-gate #define REF_UPCALL 0x00010000 /* & ref = node_t upcall not yet complete */ 4620Sstevel@tonic-gate #define REF_OWNED 0x00008000 /* & ref = node_t owned (won't be freed) */ 4630Sstevel@tonic-gate #define REF_ERROR 0x00004000 /* & ref = node_t errored */ 4640Sstevel@tonic-gate #define REF_VNODE 0x00002000 /* & ref = node_t vnode hashed */ 4650Sstevel@tonic-gate #define REF_NCAFS 0x00001000 /* & ref = node_t is NCAfs required */ 4660Sstevel@tonic-gate #define REF_SEGMAP 0x00000800 /* & ref = segmapped (PHYS|VIRT) */ 4670Sstevel@tonic-gate #define REF_UNUSED 0x000007FF /* & ref = UNUSED */ 4680Sstevel@tonic-gate /* 4690Sstevel@tonic-gate * Mappings where no seperate PHYS and VIRT, i.e. single mapping with a 4700Sstevel@tonic-gate * virtual address e.g. REF_KMEM and REF_SEGMAP. 4710Sstevel@tonic-gate */ 4720Sstevel@tonic-gate #define REF_NOVIRT (REF_KMEM | REF_SEGMAP) 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* Is this node safe for reclaim ? */ 4750Sstevel@tonic-gate #define REF_RECLAIM (REF_SAFED | REF_NOLRU | REF_MISS) 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * NCA node_t reference counting is more complicated than nca_conn_t reference 4790Sstevel@tonic-gate * counting because we pass parts of node_t's (masquerading as dblk 4800Sstevel@tonic-gate * buffers) into the STREAMS subsystem which eventually get freed by 4810Sstevel@tonic-gate * network drivers just like regular dblk buffers. Also, unlike nca_conn_t's, 4820Sstevel@tonic-gate * we may wish to keep a node_t around even after there are no outstanding 4830Sstevel@tonic-gate * references, since it's possible that it will be requested again. 4840Sstevel@tonic-gate * 4850Sstevel@tonic-gate * Thus, the node_t reference count reflects the number of active codepaths 4860Sstevel@tonic-gate * in Solaris making use of a given node_t -- each codepath that requires 4870Sstevel@tonic-gate * that the node_t stick around once it drops the node_t lock must acquire 4880Sstevel@tonic-gate * a reference via NODE_REFHOLD and drop that reference via NODE_REFRELE 4890Sstevel@tonic-gate * when done. Note that following a NODE_REFRELE the node that was 4900Sstevel@tonic-gate * released may no longer exist and thus it should not be referenced unless 4910Sstevel@tonic-gate * the codepath has another outstanding reference. When a node_t is passed 4920Sstevel@tonic-gate * into the STREAMS subsystem via desballoc() and related interfaces, a 4930Sstevel@tonic-gate * NODE_REFHOLD should be placed on the node_t and the free routine should 4940Sstevel@tonic-gate * be set to node_freeb(), which will in turn call NODE_REFRELE. 4950Sstevel@tonic-gate * 4960Sstevel@tonic-gate * The concept of node ownership allows NCA to express that it would like 4970Sstevel@tonic-gate * this node to hang around, even if there are no "explicit" references to 4980Sstevel@tonic-gate * it (the ownership counts as an implicit reference). All "headchunk" 4990Sstevel@tonic-gate * hashed nodes are owned when they are created. If they subsequently 5000Sstevel@tonic-gate * become disowned (currently via nca_node_del() or nca_reclaim_vlru()), 5010Sstevel@tonic-gate * they may have some or all their resources freed (via node_fr()) as soon 5020Sstevel@tonic-gate * as the last reference to them is removed. Note that it's possible that 5030Sstevel@tonic-gate * a disowned node may become of interest again before some or all of its 5040Sstevel@tonic-gate * resources were reclaimed -- in this case, it must be reowned via 5050Sstevel@tonic-gate * NODE_OWN. Note that an unhashed node should never be owned, though it 5060Sstevel@tonic-gate * of course may be held and released; this is because there is no sense 5070Sstevel@tonic-gate * in owning a node which is merely temporary (i.e., not hashed somewhere). 5080Sstevel@tonic-gate * Note that the corollary of this statement is not true -- that is, just 5090Sstevel@tonic-gate * because a node is hashed does not mean it is owned (it may have been 5100Sstevel@tonic-gate * disowned via nca_reclaim_vlru()) -- this is why code must always reown 5110Sstevel@tonic-gate * hashed nodes if it's desirable to have them stick around. 5120Sstevel@tonic-gate * 5130Sstevel@tonic-gate * All four macros *must* be called with the node lock held. However, 5140Sstevel@tonic-gate * NODE_DISOWN and NODE_REFRELE return with the lock unlocked (if there is 5150Sstevel@tonic-gate * still a lock at all), because the operation may have just removed the 5160Sstevel@tonic-gate * final reference to a node and it may no longer exist. 5170Sstevel@tonic-gate * 5180Sstevel@tonic-gate * A version of NODE_REFRELE is provided which doesn't unlock the lock but 5190Sstevel@tonic-gate * can only be used when the caller can gaurantee that it's not the last ref 5200Sstevel@tonic-gate * (e.g. the caller has another outstanding reference) as if it's the last 5210Sstevel@tonic-gate * ref the node_t may no longer exist. The new macro is NODE_REFRELE_LOCKED. 5220Sstevel@tonic-gate */ 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate #define NODE_DISOWN(np) { \ 5250Sstevel@tonic-gate \ 5260Sstevel@tonic-gate NODE_T_TRACE((np), NODE_T_TRACE_DISOWN); \ 5270Sstevel@tonic-gate ASSERT(mutex_owned(&(np)->lock)); \ 5280Sstevel@tonic-gate \ 5290Sstevel@tonic-gate if ((np)->ref & REF_OWNED) { \ 5300Sstevel@tonic-gate if ((np)->cnt == 0) { \ 5310Sstevel@tonic-gate panic("nca NODE_DISOWN: %p has no references", \ 5320Sstevel@tonic-gate (void *)(np)); \ 5330Sstevel@tonic-gate } \ 5340Sstevel@tonic-gate (np)->ref &= ~REF_OWNED; \ 5350Sstevel@tonic-gate NODE_REFRELE(np); \ 5360Sstevel@tonic-gate } else { \ 5370Sstevel@tonic-gate mutex_exit(&(np)->lock); \ 5380Sstevel@tonic-gate } \ 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate #define NODE_OWN(np) { \ 5420Sstevel@tonic-gate \ 5430Sstevel@tonic-gate NODE_T_TRACE((np), NODE_T_TRACE_OWN); \ 5440Sstevel@tonic-gate ASSERT(mutex_owned(&(np)->lock)); \ 5450Sstevel@tonic-gate \ 5460Sstevel@tonic-gate if (!((np)->ref & REF_OWNED)) { \ 5470Sstevel@tonic-gate if ((np)->cnt == UINT_MAX) \ 5480Sstevel@tonic-gate panic( \ 5490Sstevel@tonic-gate "nca NODE_OWN: %p has too many references", \ 5500Sstevel@tonic-gate (void *)(np)); \ 5510Sstevel@tonic-gate (np)->ref |= REF_OWNED; \ 5520Sstevel@tonic-gate (np)->cnt++; \ 5530Sstevel@tonic-gate } \ 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate #define NODE_REFHOLD(np) { \ 5570Sstevel@tonic-gate \ 5580Sstevel@tonic-gate NODE_T_TRACE((np), NODE_T_TRACE_REFHOLD | ((np)->cnt + 1)); \ 5590Sstevel@tonic-gate ASSERT(mutex_owned(&(np)->lock)); \ 5600Sstevel@tonic-gate \ 5610Sstevel@tonic-gate if ((np)->cnt == UINT_MAX) \ 5620Sstevel@tonic-gate panic("nca NODE_REFHOLD: %p has too many references", \ 5630Sstevel@tonic-gate (void *)(np)); \ 5640Sstevel@tonic-gate (np)->cnt++; \ 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate #define NODE_REFRELE(np) { \ 5680Sstevel@tonic-gate \ 5690Sstevel@tonic-gate NODE_T_TRACE((np), NODE_T_TRACE_REFRELE | ((np)->cnt - 1)); \ 5700Sstevel@tonic-gate ASSERT(mutex_owned(&(np)->lock)); \ 5710Sstevel@tonic-gate \ 5720Sstevel@tonic-gate if (((np)->ref & REF_OWNED) && (np)->cnt == 1) \ 5730Sstevel@tonic-gate panic( \ 5740Sstevel@tonic-gate "nca NODE_REFRELE: %p has only OWNED reference", \ 5750Sstevel@tonic-gate (void *)(np)); \ 5760Sstevel@tonic-gate if ((np)->cnt == 0) \ 5770Sstevel@tonic-gate panic("nca NODE_REFRELE: %p has no references", \ 5780Sstevel@tonic-gate (void *)(np)); \ 5790Sstevel@tonic-gate (np)->cnt--; \ 5800Sstevel@tonic-gate if ((np)->cnt == 0) { \ 5810Sstevel@tonic-gate ASSERT(((np)->ref & REF_OWNED) == 0); \ 5820Sstevel@tonic-gate node_fr(np); /* node_fr unlocks the lock */ \ 5830Sstevel@tonic-gate } else { \ 5840Sstevel@tonic-gate mutex_exit(&(np)->lock); \ 5850Sstevel@tonic-gate } \ 5860Sstevel@tonic-gate } 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate #define NODE_REFRELE_LOCKED(np) { \ 5890Sstevel@tonic-gate uint_t _cnt = (np)->cnt; \ 5900Sstevel@tonic-gate \ 5910Sstevel@tonic-gate NODE_T_TRACE((np), NODE_T_TRACE_REFRELE | (_cnt - 1)); \ 5920Sstevel@tonic-gate ASSERT(mutex_owned(&(np)->lock)); \ 5930Sstevel@tonic-gate \ 5940Sstevel@tonic-gate if ((np)->ref & REF_OWNED) \ 5950Sstevel@tonic-gate _cnt--; \ 5960Sstevel@tonic-gate if (((np)->ref & REF_OWNED) && _cnt == 0) \ 5970Sstevel@tonic-gate panic("nca NODE_REFRELE_LOCKED: " \ 5980Sstevel@tonic-gate "%p has only OWNED reference", (void *)(np)); \ 5990Sstevel@tonic-gate if (_cnt == 0) \ 6000Sstevel@tonic-gate panic("nca NODE_REFRELEL_LOCKED: " \ 6010Sstevel@tonic-gate "%p has no references", (void *)(np)); \ 6020Sstevel@tonic-gate if (_cnt == 1) \ 6030Sstevel@tonic-gate panic("nca NODE_REFRELEL_LOCKED: " \ 6040Sstevel@tonic-gate "%p has only one reference", (void *)(np)); \ 6050Sstevel@tonic-gate (np)->cnt--; \ 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* 6100Sstevel@tonic-gate * NODE_T_TRACE - trace node_t events. 6110Sstevel@tonic-gate * 6120Sstevel@tonic-gate * adb: 6130Sstevel@tonic-gate * 32 bit 6140Sstevel@tonic-gate * *node_tp,0t8192-(((*node_tp)-node_tv)%0t48)/PXXDDnPnPnPnPnPnPnPnn 6150Sstevel@tonic-gate * node_tv,((*node_tp)-node_tv)%0t48/PXXDDnPnPnPnPnPnPnPnn 6160Sstevel@tonic-gate * 6170Sstevel@tonic-gate * 64 bit 6180Sstevel@tonic-gate * *node_tp,0t8192-(((*node_tp)-node_tv)%0t56)/PXXDDnXnXnXnXnXnXnXnn 6190Sstevel@tonic-gate * node_tv,((*node_tp)-node_tv)%0t56/PXXDDnXnXnXnXnXnXnXnn 6200Sstevel@tonic-gate * 6210Sstevel@tonic-gate * For incremental node tracing, note the value of node_tp (node_tp/X) after 6220Sstevel@tonic-gate * a run, then replace that in the 2nd line for node_tv. 6230Sstevel@tonic-gate */ 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate #define NODE_T_STK_DEPTH 6 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate struct node_ts { 6280Sstevel@tonic-gate node_t *node; 6290Sstevel@tonic-gate unsigned action; 6300Sstevel@tonic-gate unsigned ref; 6310Sstevel@tonic-gate unsigned cnt; 6320Sstevel@tonic-gate int cpu; 6330Sstevel@tonic-gate pc_t stk[NODE_T_STK_DEPTH + 1]; 6340Sstevel@tonic-gate }; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate #undef NODE_T_TRACE_ON 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate #ifdef NODE_T_TRACE_ON 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate #define NODE_T_TRACE_ALLOC 0xFF000000 /* kmem_alloc() of */ 6410Sstevel@tonic-gate #define NODE_T_TRACE_ADD 0xFE000000 /* node_add() */ 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate #define NODE_T_TRACE_OWN 0xEF000000 /* node has been owned */ 6440Sstevel@tonic-gate #define NODE_T_TRACE_DISOWN 0xEE000000 /* node has been disowned */ 6450Sstevel@tonic-gate #define NODE_T_TRACE_DESBALLOC 0xED000000 /* desballoc() */ 6460Sstevel@tonic-gate #define NODE_T_TRACE_REFRELE 0xEC000000 /* refrele */ 6470Sstevel@tonic-gate #define NODE_T_TRACE_REFHOLD 0xEB000000 /* refhold */ 6480Sstevel@tonic-gate #define NODE_T_TRACE_NODE_FR 0xEA000000 /* node_fr() */ 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate #define NODE_T_TRACE_TEMPNODE 0xDF000000 /* node_temp() */ 6510Sstevel@tonic-gate #define NODE_T_TRACE_REPLACE 0xDE000000 /* node_replace() */ 6520Sstevel@tonic-gate #define NODE_T_TRACE_FLUSH 0xDD000000 /* node_flush() */ 6530Sstevel@tonic-gate #define NODE_T_TRACE_DOWNCALL 0xDC000000 /* downcall_service() */ 6540Sstevel@tonic-gate #define NODE_T_TRACE_DOWNCALL_2 0xDB000000 /* dcall_service->httpd_data */ 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate #define NODE_T_TRACE_DATA 0xCF000000 /* httpd_data() */ 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate #define NODE_T_TRACE_LRU 0xAF000000 /* nca_lru insert */ 6590Sstevel@tonic-gate #define NODE_T_TRACE_HTTPD 0xAE000000 /* call nca_httpd() */ 6600Sstevel@tonic-gate #define NODE_T_TRACE_MISS 0xAD000000 /* http_miss() */ 6610Sstevel@tonic-gate #define NODE_T_TRACE_TEMP 0xAC000000 /* np != *npp */ 6620Sstevel@tonic-gate #define NODE_T_TRACE_XMIT 0xAB000000 /* tcp_xmit() */ 6630Sstevel@tonic-gate #define NODE_T_TRACE_MISSED 0xAA000000 /* nca_missed() */ 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate #define NODE_T_TRACE_DEL 0x00000000 /* node_del() */ 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 6680Sstevel@tonic-gate #define NODE_T_TRACE_STK() { \ 6690Sstevel@tonic-gate _ix = getpcstack(&_p->stk[0], NODE_T_STK_DEPTH + 1); \ 6700Sstevel@tonic-gate if (_ix < NODE_T_STK_DEPTH + 1) { \ 6710Sstevel@tonic-gate _p->stk[_ix + 1] = 0; \ 6720Sstevel@tonic-gate } \ 6730Sstevel@tonic-gate } 6740Sstevel@tonic-gate #else 6750Sstevel@tonic-gate #define NODE_T_TRACE_STK() { \ 6760Sstevel@tonic-gate _p->stk[0] = (pc_t)callee(); \ 6770Sstevel@tonic-gate _ix = getpcstack(&_p->stk[1], NODE_T_STK_DEPTH); \ 6780Sstevel@tonic-gate if (_ix < NODE_T_STK_DEPTH) { \ 6790Sstevel@tonic-gate _p->stk[_ix + 1] = 0; \ 6800Sstevel@tonic-gate } \ 6810Sstevel@tonic-gate } 6820Sstevel@tonic-gate #endif 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate #define NODE_TV_SZ 8192 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate extern struct node_ts node_tv[NODE_TV_SZ]; 6870Sstevel@tonic-gate extern struct node_ts *node_tp; 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate #define NODE_T_TRACE(p, a) { \ 6900Sstevel@tonic-gate struct node_ts *_p; \ 6910Sstevel@tonic-gate struct node_ts *_np; \ 6920Sstevel@tonic-gate int _ix; \ 6930Sstevel@tonic-gate \ 6940Sstevel@tonic-gate do { \ 6950Sstevel@tonic-gate _p = node_tp; \ 6960Sstevel@tonic-gate if ((_np = _p + 1) == &node_tv[NODE_TV_SZ]) \ 6970Sstevel@tonic-gate _np = node_tv; \ 6980Sstevel@tonic-gate } while (casptr(&node_tp, _p, _np) != _p); \ 6990Sstevel@tonic-gate _p->node = (p); \ 7000Sstevel@tonic-gate _p->action = (a); \ 7010Sstevel@tonic-gate _p->ref = (p) ? (p)->ref : 0; \ 7020Sstevel@tonic-gate _p->cnt = (p) ? (p)->cnt : 0; \ 7030Sstevel@tonic-gate _p->cpu = CPU->cpu_seqid; \ 7040Sstevel@tonic-gate NODE_T_TRACE_STK(); \ 7050Sstevel@tonic-gate } 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate #else /* NODE_T_TRACE_ON */ 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate #define NODE_T_TRACE(p, a) 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate #endif /* NODE_T_TRACE_ON */ 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * DOOR_TRACE - trace door node_t events. 7150Sstevel@tonic-gate * 7160Sstevel@tonic-gate * adb: 7170Sstevel@tonic-gate * 32 bit 7180Sstevel@tonic-gate * *door_tp,0t8192-(((*door_tp)-door_tv)%0t112)/5XnPnPnPnPnPnPnPn64cnn 7190Sstevel@tonic-gate * door_tv,((*door_tp)-door_tv)%0t112/5XnPnPnPnPnPnPnPn64cnn 7200Sstevel@tonic-gate * 64 bit 7210Sstevel@tonic-gate * *door_tp,0t8192-(((*door_tp)-door_tv)%0t128)/PXPXXnXnXnXnXnXnXnXn64cnn 7220Sstevel@tonic-gate * door_tv,((*door_tp)-door_tv)%0t128/PXPXXnXnXnXnXnXnXnXn64cnn 7230Sstevel@tonic-gate */ 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate #define DOOR_STK_DEPTH 6 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate struct door_ts { 7287632SNick.Todd@Sun.COM struct nca_conn_s *cp; 7290Sstevel@tonic-gate unsigned action; 7300Sstevel@tonic-gate node_t *np; 7310Sstevel@tonic-gate int ref; 7320Sstevel@tonic-gate unsigned state; 7330Sstevel@tonic-gate pc_t stk[DOOR_STK_DEPTH + 1]; 7340Sstevel@tonic-gate char data[64]; 7350Sstevel@tonic-gate }; 7360Sstevel@tonic-gate 7370Sstevel@tonic-gate #undef DOOR_TRACE_ON 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate #ifdef DOOR_TRACE_ON 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate #define DOOR_TRACE_UPCALL 0xF0000000 /* upcall() */ 7420Sstevel@tonic-gate #define DOOR_TRACE_UPCALL_RAW 0xF1000000 /* upcall() RAW ? */ 7430Sstevel@tonic-gate #define DOOR_TRACE_UPCALL_RET 0xFF000000 /* upcall() return */ 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate #define DOOR_TRACE_DOWNCALL 0xE0000000 /* downcall() */ 7460Sstevel@tonic-gate #define DOOR_TRACE_CONNECT 0xE1000000 /* connect() */ 7470Sstevel@tonic-gate #define DOOR_TRACE_CONNECT_DATA 0xE2000000 /* connect() */ 7480Sstevel@tonic-gate #define DOOR_TRACE_DIRECTFROM 0xE3000000 /* tee_splice() from */ 7490Sstevel@tonic-gate #define DOOR_TRACE_DIRECTTO 0xE4000000 /* tee_splice() to */ 7500Sstevel@tonic-gate #define DOOR_TRACE_DOWNCALL_RET 0xEF000000 /* downcall() return */ 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate #define DOOR_TRACE_INIT 0x80000000 /* doorcall_init() */ 7530Sstevel@tonic-gate #define DOOR_TRACE_INIT_RET 0x88000000 /* doorcall_init() return */ 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 7560Sstevel@tonic-gate #define DOOR_TRACE_STK() { \ 7570Sstevel@tonic-gate _ix = getpcstack(&_p->stk[0], DOOR_STK_DEPTH + 1); \ 7580Sstevel@tonic-gate if (_ix < DOOR_STK_DEPTH + 1) { \ 7590Sstevel@tonic-gate _p->stk[_ix] = 0; \ 7600Sstevel@tonic-gate } \ 7610Sstevel@tonic-gate } 7620Sstevel@tonic-gate #else 7630Sstevel@tonic-gate #define DOOR_TRACE_STK() { \ 7640Sstevel@tonic-gate _p->stk[0] = (pc_t)callee(); \ 7650Sstevel@tonic-gate _ix = getpcstack(&_p->stk[1], DOOR_STK_DEPTH); \ 7660Sstevel@tonic-gate if (_ix < DOOR_STK_DEPTH) { \ 7670Sstevel@tonic-gate _p->stk[_ix + 1] = 0; \ 7680Sstevel@tonic-gate } \ 7690Sstevel@tonic-gate } 7700Sstevel@tonic-gate #endif 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate #define DOOR_TV_SZ 8192 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate extern struct door_ts door_tv[DOOR_TV_SZ]; 7750Sstevel@tonic-gate extern struct door_ts *door_tp; 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate #define DOOR_TRACE(io, d, d_sz, a) { \ 7780Sstevel@tonic-gate nca_conn_t *_cp = (io) ? (nca_conn_t *)(io)->cid : (nca_conn_t *)NULL; \ 7790Sstevel@tonic-gate node_t *_req_np = _cp ? _cp->req_np : (node_t *)NULL; \ 7800Sstevel@tonic-gate struct door_ts *_p; \ 7810Sstevel@tonic-gate struct door_ts *_np; \ 7820Sstevel@tonic-gate int _ix; \ 7830Sstevel@tonic-gate \ 7840Sstevel@tonic-gate do { \ 7850Sstevel@tonic-gate _p = door_tp; \ 7860Sstevel@tonic-gate if ((_np = _p + 1) == &door_tv[DOOR_TV_SZ]) \ 7870Sstevel@tonic-gate _np = door_tv; \ 7880Sstevel@tonic-gate } while (casptr(&door_tp, _p, _np) != _p); \ 7890Sstevel@tonic-gate _p->cp = _cp; \ 7900Sstevel@tonic-gate _p->np = _req_np; \ 7910Sstevel@tonic-gate _p->action = (a); \ 7920Sstevel@tonic-gate _p->ref = _req_np ? _req_np->ref : 0; \ 7930Sstevel@tonic-gate if ((io)) { \ 7940Sstevel@tonic-gate _p->state = ((io)->op == http_op ? 0x80000000 : 0) | \ 7950Sstevel@tonic-gate ((io)->more ? 0x40000000 : 0) | \ 7960Sstevel@tonic-gate ((io)->first ? 0x20000000 : 0) | \ 7970Sstevel@tonic-gate ((io)->advisory ? 0x10000000 : 0) | \ 7980Sstevel@tonic-gate ((io)->nocache ? 0x08000000 : 0) | \ 7990Sstevel@tonic-gate ((io)->preempt ? 0x04000000 : 0) | \ 8000Sstevel@tonic-gate ((io)->peer_len ? 0x02000000 : 0) | \ 8010Sstevel@tonic-gate ((io)->local_len ? 0x01000000 : 0) | \ 8020Sstevel@tonic-gate ((io)->data_len ? 0x00800000 : 0) | \ 8030Sstevel@tonic-gate (((io)->direct_type << 20) & 0x00700000) | \ 8040Sstevel@tonic-gate ((io)->direct_len ? 0x00080000 : 0) | \ 8050Sstevel@tonic-gate ((io)->trailer_len ? 0x00040000 : 0) | \ 8060Sstevel@tonic-gate (((io)->peer_len + (io)->local_len + \ 8070Sstevel@tonic-gate (io)->data_len + (io)->direct_len + \ 8080Sstevel@tonic-gate (io)->trailer_len) & 0x3FFFF); \ 8090Sstevel@tonic-gate } else { \ 8100Sstevel@tonic-gate _p->state = 0; \ 8110Sstevel@tonic-gate } \ 8120Sstevel@tonic-gate if ((d_sz)) { \ 8130Sstevel@tonic-gate int _n = MIN((d_sz), 63); \ 8140Sstevel@tonic-gate \ 8150Sstevel@tonic-gate bcopy((d), _p->data, _n); \ 8160Sstevel@tonic-gate bzero(&_p->data[_n], 64 - _n); \ 8170Sstevel@tonic-gate } else { \ 8180Sstevel@tonic-gate bzero(_p->data, 64); \ 8190Sstevel@tonic-gate } \ 8200Sstevel@tonic-gate DOOR_TRACE_STK(); \ 8210Sstevel@tonic-gate } 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate #else /* DOOR_TRACE_ON */ 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate #define DOOR_TRACE(io, d, d_sz, a) 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate #endif /* DOOR_TRACE_ON */ 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate /* 8300Sstevel@tonic-gate * NCA node LRU cache. Defined here so that the NCA mdb module can use it. 8310Sstevel@tonic-gate */ 8320Sstevel@tonic-gate typedef struct lru_s { 8330Sstevel@tonic-gate node_t *phead; /* Phys LRU list head (MRU) */ 8340Sstevel@tonic-gate node_t *ptail; /* Phys LRU list tail (LRU) */ 8350Sstevel@tonic-gate node_t *vhead; /* Virt LRU list head (MRU) */ 8360Sstevel@tonic-gate node_t *vtail; /* Virt LRU list tail (LRU) */ 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate uint32_t pcount; /* Phys count of node_t members */ 8390Sstevel@tonic-gate uint32_t vcount; /* Virt count of node_t members */ 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate kmutex_t lock; /* Guarantee atomic access of above */ 8420Sstevel@tonic-gate } lru_t; 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate /* 8450Sstevel@tonic-gate * Per CPU instance structure. 8460Sstevel@tonic-gate * 8470Sstevel@tonic-gate * 32-bit adb: XXXnnDnnXXnnXXnnXDnnXXnn228+na 8480Sstevel@tonic-gate * 64-bit adb: PPPnnD4+nnPPnnPPnnJDnnJ180+na 8490Sstevel@tonic-gate */ 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate typedef struct nca_cpu_s { 8520Sstevel@tonic-gate 8530Sstevel@tonic-gate node_t *persist_hdr_none; 8540Sstevel@tonic-gate node_t *persist_hdr_close; 8550Sstevel@tonic-gate node_t *persist_hdr_ka; 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate uint32_t dcb_readers; /* count of dcb_list readers for this CPU */ 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate nca_squeue_t *if_inq; /* if_t input nca_squeue_t */ 8600Sstevel@tonic-gate nca_squeue_t *if_ouq; /* if_t output nca_squeue_t */ 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate ti_t *tcp_ti; /* TCP TIMER list */ 8630Sstevel@tonic-gate tw_t *tcp_tw; /* TCP TIME_WAIT list */ 8640Sstevel@tonic-gate 8650Sstevel@tonic-gate ddi_softintr_t soft_id; /* soft interrupt id for if_inq worker */ 8660Sstevel@tonic-gate int if_inq_cnt; /* count of if_t.inq references */ 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate char pad[256 - sizeof (node_t *) - sizeof (node_t *) - 8690Sstevel@tonic-gate sizeof (node_t *) - sizeof (uint32_t) - 8700Sstevel@tonic-gate sizeof (nca_squeue_t *) - sizeof (nca_squeue_t *) - 8710Sstevel@tonic-gate sizeof (ti_t *) - sizeof (tw_t *) - 8720Sstevel@tonic-gate sizeof (ddi_softintr_t) - sizeof (int)]; 8730Sstevel@tonic-gate } nca_cpu_t; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate extern nca_cpu_t *nca_gv; /* global per CPU state indexed by cpu_seqid */ 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate /* 8780Sstevel@tonic-gate * hcb_t - host control block. 8790Sstevel@tonic-gate * 8800Sstevel@tonic-gate * Used early on in packet switching to select packets to be serviced by NCA 8810Sstevel@tonic-gate * and optionally later on by the HTTP protocol layer to further select HTTP 8820Sstevel@tonic-gate * request to be serviced. 8830Sstevel@tonic-gate * 8840Sstevel@tonic-gate * dcb_t - door control block. 8850Sstevel@tonic-gate * 8860Sstevel@tonic-gate * Used to associate one or more hcb_t(s) with a given httpd door instance. 8870Sstevel@tonic-gate * 8880Sstevel@tonic-gate * dcb_list - dcb_t global list, a singly linked grounded list of dcb_t's. 8890Sstevel@tonic-gate * 8900Sstevel@tonic-gate * Used to search for a hcb_t match, currently a singly linked grounded list 8910Sstevel@tonic-gate * of dcb_t's with a linear walk of the list. While this is adequate for the 8920Sstevel@tonic-gate * current httpd support (i.e. a single door) a move to either a hash or tree 8930Sstevel@tonic-gate * will be required for multiple httpd instance support (i.e. multiple doors). 8940Sstevel@tonic-gate * 8950Sstevel@tonic-gate * The dcb_list is protected by a custom reader/writer lock, the motivation 8960Sstevel@tonic-gate * for using a custom lock instead of a krwlock_t is that this lock is the 8970Sstevel@tonic-gate * single hot spot in NCA (i.e. all in-bound packets must acquire this lock) 8980Sstevel@tonic-gate * and a nonlocking atomic readers count scheme is used in the common case 8990Sstevel@tonic-gate * (i.e. reader lock) with a fall-back to a conventional kmutex_t for writer 9000Sstevel@tonic-gate * (i.e. ndd list add/delete). 9010Sstevel@tonic-gate */ 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate typedef struct hcb_s { 9040Sstevel@tonic-gate struct hcb_s *next; /* Next hcb_t (none: NULL) */ 9050Sstevel@tonic-gate ipaddr_t addr; /* IP address (any: INADDR_ANY or 0) */ 9060Sstevel@tonic-gate uint16_t port; /* TCP port number */ 9070Sstevel@tonic-gate char *host; /* Host: name (any: NULL) */ 9080Sstevel@tonic-gate ssize_t hostsz; /* Size of above */ 9090Sstevel@tonic-gate char *root; /* Document root ("/": NULL) */ 9100Sstevel@tonic-gate ssize_t rootsz; /* Size of above */ 9110Sstevel@tonic-gate } hcb_t; 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate typedef struct dcb_s { 9140Sstevel@tonic-gate struct dcb_s *next; /* Next dcb_t (none: NULL) */ 9150Sstevel@tonic-gate char *door; /* Door file (default: NULL) */ 9160Sstevel@tonic-gate ssize_t doorsz; /* Size of above */ 9170Sstevel@tonic-gate door_handle_t hand; /* Door handle (default: NULL) */ 9180Sstevel@tonic-gate hcb_t list; /* Head of a hcb_t list (any: NULL) */ 9190Sstevel@tonic-gate } dcb_t; 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate extern dcb_t dcb_list; 9220Sstevel@tonic-gate extern kmutex_t nca_dcb_lock; 9230Sstevel@tonic-gate extern kcondvar_t nca_dcb_wait; 9240Sstevel@tonic-gate extern kmutex_t nca_dcb_readers; 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate #define NOHANDLE ((door_handle_t)-1) 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate #define DCB_COUNT_USELOCK 0x80000000 9290Sstevel@tonic-gate #define DCB_COUNT_MASK 0x3FFFFFFF 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate #define DCB_RD_ENTER(cpu) { \ 9320Sstevel@tonic-gate uint32_t *rp; \ 9330Sstevel@tonic-gate \ 9340Sstevel@tonic-gate cpu = CPU->cpu_seqid; \ 9350Sstevel@tonic-gate rp = &nca_gv[cpu].dcb_readers; \ 9360Sstevel@tonic-gate while (atomic_add_32_nv(rp, 1) & DCB_COUNT_USELOCK) { \ 9370Sstevel@tonic-gate /* Need to use the lock, so do the dance */ \ 9380Sstevel@tonic-gate mutex_enter(&nca_dcb_lock); \ 9390Sstevel@tonic-gate if (atomic_add_32_nv(rp, -1) == DCB_COUNT_USELOCK && \ 9400Sstevel@tonic-gate CV_HAS_WAITERS(&nca_dcb_wait)) { \ 9410Sstevel@tonic-gate /* May be the last reader for this CPU */ \ 9420Sstevel@tonic-gate cv_signal(&nca_dcb_wait); \ 9430Sstevel@tonic-gate } \ 9440Sstevel@tonic-gate mutex_exit(&nca_dcb_lock); \ 9450Sstevel@tonic-gate mutex_enter(&nca_dcb_readers); \ 9460Sstevel@tonic-gate /* \ 9470Sstevel@tonic-gate * We block above waiting for the writer to exit the \ 9480Sstevel@tonic-gate * readers lock, if we didn't block then while we were \ 9490Sstevel@tonic-gate * away in the nca_dcb_lock enter the writer exited, \ 9500Sstevel@tonic-gate * we could optimize for this case by checking USELOCK \ 9510Sstevel@tonic-gate * after the decrement, but as this is an exceptional \ 9520Sstevel@tonic-gate * case not in the fast-path we'll just take the hit \ 9530Sstevel@tonic-gate * of a needless readers enter/exit. \ 9540Sstevel@tonic-gate */ \ 9550Sstevel@tonic-gate mutex_exit(&nca_dcb_readers); \ 9560Sstevel@tonic-gate } \ 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate #define DCB_RD_EXIT(cpu) { \ 9600Sstevel@tonic-gate uint32_t *rp = &nca_gv[cpu].dcb_readers; \ 9610Sstevel@tonic-gate \ 9620Sstevel@tonic-gate if (atomic_add_32_nv(rp, -1) == DCB_COUNT_USELOCK) { \ 9630Sstevel@tonic-gate mutex_enter(&nca_dcb_lock); \ 9640Sstevel@tonic-gate if (CV_HAS_WAITERS(&nca_dcb_wait)) { \ 9650Sstevel@tonic-gate /* May be the last reader for this CPU */ \ 9660Sstevel@tonic-gate cv_signal(&nca_dcb_wait); \ 9670Sstevel@tonic-gate } \ 9680Sstevel@tonic-gate mutex_exit(&nca_dcb_lock); \ 9690Sstevel@tonic-gate } \ 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate #define DCB_WR_ENTER() { \ 9730Sstevel@tonic-gate int cpu; \ 9740Sstevel@tonic-gate int readers; \ 9750Sstevel@tonic-gate \ 9760Sstevel@tonic-gate mutex_enter(&nca_dcb_readers); \ 9770Sstevel@tonic-gate mutex_enter(&nca_dcb_lock); \ 9780Sstevel@tonic-gate for (;;) { \ 9790Sstevel@tonic-gate readers = 0; \ 9800Sstevel@tonic-gate for (cpu = 0; cpu < max_ncpus; cpu++) { \ 9810Sstevel@tonic-gate int new; \ 9820Sstevel@tonic-gate uint32_t *rp = &nca_gv[cpu].dcb_readers; \ 9830Sstevel@tonic-gate int old = *rp; \ 9840Sstevel@tonic-gate \ 9850Sstevel@tonic-gate if (old & DCB_COUNT_USELOCK) { \ 9860Sstevel@tonic-gate readers += old & DCB_COUNT_MASK; \ 9870Sstevel@tonic-gate continue; \ 9880Sstevel@tonic-gate } \ 9890Sstevel@tonic-gate new = old | DCB_COUNT_USELOCK; \ 9900Sstevel@tonic-gate while (cas32(rp, old, new) != old) { \ 9910Sstevel@tonic-gate old = *rp; \ 9920Sstevel@tonic-gate new = old | DCB_COUNT_USELOCK; \ 9930Sstevel@tonic-gate } \ 9940Sstevel@tonic-gate readers += (new & DCB_COUNT_MASK); \ 9950Sstevel@tonic-gate } \ 9960Sstevel@tonic-gate if (readers == 0) \ 9970Sstevel@tonic-gate break; \ 9980Sstevel@tonic-gate cv_wait(&nca_dcb_wait, &nca_dcb_lock); \ 9990Sstevel@tonic-gate } \ 10000Sstevel@tonic-gate mutex_exit(&nca_dcb_lock); \ 10010Sstevel@tonic-gate } 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate #define DCB_WR_EXIT() { \ 10040Sstevel@tonic-gate int cpu; \ 10050Sstevel@tonic-gate \ 10060Sstevel@tonic-gate mutex_enter(&nca_dcb_lock); \ 10070Sstevel@tonic-gate for (cpu = 0; cpu < max_ncpus; cpu++) { \ 10080Sstevel@tonic-gate int new; \ 10090Sstevel@tonic-gate uint32_t *rp = &nca_gv[cpu].dcb_readers; \ 10100Sstevel@tonic-gate int old = *rp; \ 10110Sstevel@tonic-gate \ 10120Sstevel@tonic-gate new = old & ~DCB_COUNT_USELOCK; \ 10130Sstevel@tonic-gate while (cas32(rp, old, new) != old) { \ 10140Sstevel@tonic-gate old = *rp; \ 10150Sstevel@tonic-gate new = old & ~DCB_COUNT_USELOCK; \ 10160Sstevel@tonic-gate } \ 10170Sstevel@tonic-gate } \ 10180Sstevel@tonic-gate mutex_exit(&nca_dcb_lock); \ 10190Sstevel@tonic-gate mutex_exit(&nca_dcb_readers); \ 10200Sstevel@tonic-gate } 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate typedef struct nca_door_s { 10230Sstevel@tonic-gate door_handle_t handle; /* The door handle */ 10240Sstevel@tonic-gate char *name; /* The door name */ 10250Sstevel@tonic-gate kmutex_t lock; /* The door lock */ 10260Sstevel@tonic-gate kcondvar_t cv_writer; /* condvar for thread waiting */ 10270Sstevel@tonic-gate /* to do door_init */ 10280Sstevel@tonic-gate kcondvar_t cv_reader; /* condvar for thread waiting */ 10290Sstevel@tonic-gate /* for a door_init to finish */ 10300Sstevel@tonic-gate uint32_t upcalls; /* Number of upcalls in progress */ 10310Sstevel@tonic-gate boolean_t init_waiting; /* door_init thread wanting to */ 10320Sstevel@tonic-gate /* be exclusive */ 10330Sstevel@tonic-gate } nca_door_t; 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate /* 10360Sstevel@tonic-gate * if_t - interface per instance data. 10370Sstevel@tonic-gate */ 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate typedef struct if_s { 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate boolean_t dev; /* is a device instance */ 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate queue_t *rqp; /* our read-side STREAMS queue */ 10440Sstevel@tonic-gate queue_t *wqp; /* our write-side STREAMS queue */ 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate /* DLPI M_DATA IP fastpath template */ 10470Sstevel@tonic-gate size_t mac_length; 10480Sstevel@tonic-gate mblk_t *mac_mp; 10490Sstevel@tonic-gate int32_t mac_mtu; 10500Sstevel@tonic-gate int32_t mac_addr_len; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate uint32_t ip_ident; /* our IP ident value */ 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate boolean_t hwcksum; /* underlying NIC supports checksum offload */ 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate nca_squeue_t *inq; /* in-bound nca_squeue_t */ 10570Sstevel@tonic-gate nca_squeue_t *ouq; /* out-bound nca_squeue_t */ 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate /* 10600Sstevel@tonic-gate * All if_t are associated with a CPU and have a default 10610Sstevel@tonic-gate * router on link are chained in a circular linked list. 10620Sstevel@tonic-gate */ 10630Sstevel@tonic-gate struct if_s *next_if; 10640Sstevel@tonic-gate struct if_s *prev_if; 10650Sstevel@tonic-gate ipaddr_t local_addr; /* This interface's IP address. */ 10660Sstevel@tonic-gate uchar_t router_ether_addr[6]; 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate uint_t hdr_ioc_id; /* id of DL_IOC_HDR_INFO M_IOCTL sent down */ 10690Sstevel@tonic-gate boolean_t info_req_pending; 10700Sstevel@tonic-gate 10710Sstevel@tonic-gate int32_t capab_state; /* Capability probe state */ 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate /* Bound local address of a NCAfs instance. */ 10740Sstevel@tonic-gate struct sockaddr_in bound_addr; 10750Sstevel@tonic-gate } if_t; 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate /* 10780Sstevel@tonic-gate * connf_t - connection fanout data. 10790Sstevel@tonic-gate * 10800Sstevel@tonic-gate * The hash tables and their linkage (hashnextp, hashprevp) are protected 10810Sstevel@tonic-gate * by the per-bucket lock. Each nca_conn_t inserted in the list points back at 10820Sstevel@tonic-gate * the connf_t that heads the bucket. 10830Sstevel@tonic-gate */ 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate typedef struct connf_s { 10860Sstevel@tonic-gate uint32_t max; 10877632SNick.Todd@Sun.COM struct nca_conn_s *head; 10880Sstevel@tonic-gate kmutex_t lock; 10890Sstevel@tonic-gate } connf_t; 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate #ifdef CONNP_T_TRACE_ON 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate #define CONNP_TV_SZ 32 10940Sstevel@tonic-gate 10950Sstevel@tonic-gate /* 10960Sstevel@tonic-gate * Per nca_conn_t packet tracing. 10970Sstevel@tonic-gate */ 10980Sstevel@tonic-gate typedef struct connp_s { 10990Sstevel@tonic-gate clock_t lbolt; 11000Sstevel@tonic-gate clock_t tcp_ti; 11010Sstevel@tonic-gate int32_t len : 16, 11020Sstevel@tonic-gate dir : 1, 11030Sstevel@tonic-gate state : 4, 11040Sstevel@tonic-gate flags : 6, 11050Sstevel@tonic-gate xmit_np : 1, 11060Sstevel@tonic-gate xmit_head : 1, 11070Sstevel@tonic-gate unsent : 1, 11080Sstevel@tonic-gate tail_unsent : 1, 11090Sstevel@tonic-gate direct : 1; 11100Sstevel@tonic-gate uint32_t state1; 11110Sstevel@tonic-gate uint32_t state2; 11120Sstevel@tonic-gate uint32_t seq; 11130Sstevel@tonic-gate uint32_t ack; 11140Sstevel@tonic-gate uint32_t snxt; 11150Sstevel@tonic-gate uint32_t swnd; 11160Sstevel@tonic-gate } connp_t; 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate #endif /* CONNP_T_TRACE_ON */ 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate /* 11210Sstevel@tonic-gate * nca_conn_t - connection per instance data. 11220Sstevel@tonic-gate * 11230Sstevel@tonic-gate * Note: hashlock is used to provide atomic access to all nca_conn_t members 11240Sstevel@tonic-gate * above it. All other members are protected by the per CPU inq nca_squeue_t 11250Sstevel@tonic-gate * which is used to serialize access to all nca_conn_t's per interface. 11260Sstevel@tonic-gate * 11270Sstevel@tonic-gate * Note: the nca_conn_t can have up to 3 NODE_REFHOLDs: 11280Sstevel@tonic-gate * 11290Sstevel@tonic-gate * 1) if req_np != NULL then a NODE_REFHOLD(req_np) was done: 11300Sstevel@tonic-gate * 11310Sstevel@tonic-gate * 1.1) if http_refed then a NODE_REFHOLD(req_np) was done 11320Sstevel@tonic-gate * 11330Sstevel@tonic-gate * 1.2) if http_frefed then a NODE_REFHOLD(req_np->fileback) was done 11340Sstevel@tonic-gate * 11350Sstevel@tonic-gate * 11360Sstevel@tonic-gate * TODO: reorder elements in fast-path code access order. 11370Sstevel@tonic-gate * 11380Sstevel@tonic-gate * Dnn4XnXXDnnDnnXXXnnXXXnnUXnnXXXnnXXnnDDXXXDXDXDXnnDnnXXDDnXXXDDnnXXXDDnn 11390Sstevel@tonic-gate * XXXDDnnXXXDDnnXXXDDnnXXnnDXXnn 11400Sstevel@tonic-gate * b+++DDnAnDDDDDnnDnnUnnUUDXDUnnDnn20xnnXnnddnnUUUnnXXUnXXnnUUUnn 11410Sstevel@tonic-gate * DDDDDDnnUUnnXXUXUnn4UD4Unn4UnUUnn 11420Sstevel@tonic-gate * 64-bit: Xnn4+4pnnppEnEnn3pnn3pnnEJnnXXnnuunn4+ppnnXX3pD4+pD4+pD4+pnnEnnppnnD 11430Sstevel@tonic-gate */ 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate #define TCP_XMIT_MAX_IX 5 /* Max xmit descriptors */ 11460Sstevel@tonic-gate 11477632SNick.Todd@Sun.COM typedef struct nca_conn_s { 11480Sstevel@tonic-gate 11490Sstevel@tonic-gate int32_t ref; /* Reference counter */ 11500Sstevel@tonic-gate 11510Sstevel@tonic-gate te_t tcp_ti; /* TCP TIMER timer entry */ 11520Sstevel@tonic-gate 11537632SNick.Todd@Sun.COM struct nca_conn_s *twnext; /* TIME_WAIT next */ 11547632SNick.Todd@Sun.COM struct nca_conn_s *twprev; /* TIME_WAIT prev */ 11550Sstevel@tonic-gate clock_t twlbolt; /* TIME_WAIT lbolt */ 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate clock_t create; /* Create lbolt time */ 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate connf_t *hashfanout; /* Hash bucket we're part of */ 11607632SNick.Todd@Sun.COM struct nca_conn_s *hashnext; /* Hash chain next */ 11617632SNick.Todd@Sun.COM struct nca_conn_s *hashprev; /* Hash chain prev */ 11620Sstevel@tonic-gate 11637632SNick.Todd@Sun.COM struct nca_conn_s *bindnext; /* Next conn_s in bind list. */ 11647632SNick.Todd@Sun.COM struct nca_conn_s *bindprev; /* Prev conn_s in bind list. */ 11650Sstevel@tonic-gate void *tbf; /* Pointer to bind hash list struct. */ 11660Sstevel@tonic-gate /* 11670Sstevel@tonic-gate * Note: atomic access of memebers above is guaranteed by the 11680Sstevel@tonic-gate * hashfanout->lock of the hash bucket that the nca_conn_t is in. 11690Sstevel@tonic-gate */ 11700Sstevel@tonic-gate 11710Sstevel@tonic-gate size_t mac_length; /* MAC prepend length */ 11720Sstevel@tonic-gate mblk_t *mac_mp; /* MAC prepend data */ 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate ipaddr_t laddr; /* Local address */ 11750Sstevel@tonic-gate ipaddr_t faddr; /* Remote address. 0 => not connected */ 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate union { 11780Sstevel@tonic-gate struct { 11790Sstevel@tonic-gate uint16_t u_fport; /* Remote port */ 11800Sstevel@tonic-gate uint16_t u_lport; /* Local port */ 11810Sstevel@tonic-gate } u_ports1; 11820Sstevel@tonic-gate uint32_t u_ports2; /* Rem port, local port */ 11830Sstevel@tonic-gate /* Used for TCP_MATCH performance */ 11840Sstevel@tonic-gate } u_port; 11850Sstevel@tonic-gate #define conn_lport u_port.u_ports1.u_lport 11860Sstevel@tonic-gate #define conn_fport u_port.u_ports1.u_fport 11870Sstevel@tonic-gate #define conn_ports u_port.u_ports2 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate if_t *ifp; /* Interface for this connection */ 11900Sstevel@tonic-gate nca_squeue_t *inq; /* Per CPU inq for this connection */ 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate uint32_t req_tag; /* nca_io_t request tag (0 == NONE) */ 11930Sstevel@tonic-gate int req_parse; /* HTTP request parse state */ 11940Sstevel@tonic-gate node_t *req_np; /* HTTP request node_t */ 11950Sstevel@tonic-gate mblk_t *req_mp; /* HTTP request mblk_t */ 11960Sstevel@tonic-gate char *reqpath; /* HTTP request URI path component */ 11970Sstevel@tonic-gate int reqpathsz; /* size of above */ 11980Sstevel@tonic-gate char *reqrefer; /* HTTP "Referer:" string */ 11990Sstevel@tonic-gate int reqrefersz; /* size of above */ 12000Sstevel@tonic-gate char *requagent; /* HTTP "User-Agent:" string */ 12010Sstevel@tonic-gate int requagentsz; /* size of above */ 12027632SNick.Todd@Sun.COM struct nca_conn_s *nodenext; /* Node_t nca_conn_t list */ 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate clock_t http_count; /* HTTP Keep-Alive request count */ 12050Sstevel@tonic-gate 12060Sstevel@tonic-gate /* 12070Sstevel@tonic-gate * req_np xmit state used accross calls to tcp_xmit(). A reference 12080Sstevel@tonic-gate * to the req_np and to any inderect node_t (i.e. file/ctag) ... 12090Sstevel@tonic-gate */ 12100Sstevel@tonic-gate node_t *xmit_refed; /* have a ref to the uri node_t */ 12110Sstevel@tonic-gate node_t *xmit_cur; /* current node to transmit */ 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate int xmit_ix; /* current xmit[] index */ 12140Sstevel@tonic-gate int xmit_pix; /* past end xmit[] index */ 12150Sstevel@tonic-gate 12160Sstevel@tonic-gate struct { 12170Sstevel@tonic-gate node_t *np; /* node_t pointer for ref */ 12180Sstevel@tonic-gate char *dp; /* data pointer */ 12190Sstevel@tonic-gate uint16_t *cp; /* cksum array */ 12200Sstevel@tonic-gate int sz; /* remaining data to xmit */ 12210Sstevel@tonic-gate int iso; /* initial segment offset (if any) */ 12220Sstevel@tonic-gate node_t *refed; /* have a ref to the node_t */ 12230Sstevel@tonic-gate int dsz; /* remaining data for current segment */ 12240Sstevel@tonic-gate caddr_t *dvp; /* data segment virtual pointer */ 12250Sstevel@tonic-gate } xmit[TCP_XMIT_MAX_IX]; 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate /* 12280Sstevel@tonic-gate * Connection NCA_IO_DIRECT_SPLICE & NCA_IO_DIRECT_TEE reference, 12290Sstevel@tonic-gate * see direct_splice and direct_tee below for type of send too. 12300Sstevel@tonic-gate */ 12317632SNick.Todd@Sun.COM struct nca_conn_s *direct; /* nca_conn_t to send recv data too */ 12327632SNick.Todd@Sun.COM mblk_t *direct_mp; /* mblk_t to use for tcp_close() */ 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate /* 12350Sstevel@tonic-gate * nca_conn_t state. 12360Sstevel@tonic-gate */ 12370Sstevel@tonic-gate 12380Sstevel@tonic-gate int32_t tcp_state; 12390Sstevel@tonic-gate 12400Sstevel@tonic-gate uint32_t 12410Sstevel@tonic-gate tcp_urp_last_valid : 1, /* Is tcp_urp_last valid? */ 12420Sstevel@tonic-gate tcp_hard_binding : 1, /* If we've started a full bind */ 12430Sstevel@tonic-gate tcp_hard_bound : 1, /* If we've done a full bind with IP */ 12440Sstevel@tonic-gate tcp_fin_acked : 1, /* Has our FIN been acked? */ 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate tcp_fin_rcvd : 1, /* Have we seen a FIN? */ 12470Sstevel@tonic-gate tcp_fin_sent : 1, /* Have we sent our FIN yet? */ 12480Sstevel@tonic-gate tcp_ordrel_done : 1, /* Have we sent the ord_rel upstream? */ 12490Sstevel@tonic-gate tcp_flow_stopped : 1, /* Have we flow controlled xmitter? */ 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate tcp_debug : 1, /* SO_DEBUG "socket" option. */ 12520Sstevel@tonic-gate tcp_dontroute : 1, /* SO_DONTROUTE "socket" option. */ 12530Sstevel@tonic-gate tcp_broadcast : 1, /* SO_BROADCAST "socket" option. */ 12540Sstevel@tonic-gate tcp_useloopback : 1, /* SO_USELOOPBACK "socket" option. */ 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate tcp_oobinline : 1, /* SO_OOBINLINE "socket" option. */ 12570Sstevel@tonic-gate tcp_dgram_errind : 1, /* SO_DGRAM_ERRIND option */ 12580Sstevel@tonic-gate tcp_detached : 1, /* If we're detached from a stream */ 12590Sstevel@tonic-gate tcp_bind_pending : 1, /* Client is waiting for bind ack */ 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate tcp_unbind_pending : 1, /* Client sent T_UNBIND_REQ */ 12620Sstevel@tonic-gate tcp_deferred_clean_death : 1, 12630Sstevel@tonic-gate /* defer tcp endpoint cleanup etc. */ 12640Sstevel@tonic-gate tcp_co_wakeq_done : 1, /* A strwakeq() has been done */ 12650Sstevel@tonic-gate tcp_co_wakeq_force : 1, /* A strwakeq() must be done */ 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate tcp_co_norm : 1, /* In normal mode, putnext() done */ 12680Sstevel@tonic-gate tcp_co_wakeq_need : 1, /* A strwakeq() needs to be done */ 12690Sstevel@tonic-gate tcp_snd_ws_ok : 1, /* Received WSCALE from peer */ 12700Sstevel@tonic-gate tcp_snd_ts_ok : 1, /* Received TSTAMP from peer */ 12710Sstevel@tonic-gate 12720Sstevel@tonic-gate tcp_linger : 1, /* SO_LINGER turned on */ 12730Sstevel@tonic-gate tcp_zero_win_probe: 1, /* Zero win probing is in progress */ 12740Sstevel@tonic-gate tcp_loopback: 1, /* src and dst are the same machine */ 12750Sstevel@tonic-gate tcp_localnet: 1, /* src and dst are on the same subnet */ 12760Sstevel@tonic-gate 12770Sstevel@tonic-gate tcp_syn_defense: 1, /* For defense against SYN attack */ 12780Sstevel@tonic-gate #define tcp_dontdrop tcp_syn_defense 12790Sstevel@tonic-gate tcp_set_timer : 1, 12800Sstevel@tonic-gate tcp_1_junk_fill_thru_bit_31 : 2; 12810Sstevel@tonic-gate 12820Sstevel@tonic-gate uint32_t 12830Sstevel@tonic-gate tcp_active_open: 1, /* This is a active open */ 12840Sstevel@tonic-gate tcp_timeout : 1, /* qbufcall failed, qtimeout pending */ 12850Sstevel@tonic-gate tcp_rexmit : 1, /* TCP is retransmitting */ 12860Sstevel@tonic-gate tcp_snd_sack_ok : 1, /* Can use SACK for this connection */ 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate tcp_bind_proxy_addr : 1, /* proxy addr is being used */ 12890Sstevel@tonic-gate tcp_recvdstaddr : 1, /* return T_EXTCONN_IND with dst addr */ 12900Sstevel@tonic-gate tcp_refed : 1, /* nca_conn_t refed by TCP */ 12910Sstevel@tonic-gate tcp_time_wait_comp : 1, /* TIME_WAIT compressed nca_conn_t */ 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate tcp_close : 1, /* nca_conn_t close */ 12940Sstevel@tonic-gate http_persist : 3, /* HTTP persistent connection state */ 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate deferred_xmit_end : 1, /* xmit_end() deferred to xmit() */ 12970Sstevel@tonic-gate http_direct_splice : 1, /* have a connection to splice too */ 12980Sstevel@tonic-gate http_direct_tee : 1, /* have a connection to tee too */ 12990Sstevel@tonic-gate 13000Sstevel@tonic-gate tcp_2_junk_fill_thru_bit_31 : 17; 13010Sstevel@tonic-gate /* 13020Sstevel@tonic-gate * Note: all nca_conn_t members to be accessed by a tcp_time_wait_comp 13030Sstevel@tonic-gate * nca_conn_t must be above this point !!! 13040Sstevel@tonic-gate */ 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate uchar_t tcp_timer_backoff; /* Backoff shift count. */ 13070Sstevel@tonic-gate clock_t tcp_last_recv_time; /* Last time we receive a segment. */ 13080Sstevel@tonic-gate clock_t tcp_dack_set_time; /* When delayed ACK timer is set. */ 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate int tcp_ip_hdr_len; /* Byte len of our current IP header */ 13110Sstevel@tonic-gate clock_t tcp_first_timer_threshold; /* When to prod IP */ 13120Sstevel@tonic-gate clock_t tcp_second_timer_threshold; /* When to give up completely */ 13130Sstevel@tonic-gate clock_t tcp_first_ctimer_threshold; /* 1st threshold while connecting */ 13140Sstevel@tonic-gate clock_t tcp_second_ctimer_threshold; /* 2nd ... while connecting */ 13150Sstevel@tonic-gate 13160Sstevel@tonic-gate clock_t tcp_last_rcv_lbolt; /* lbolt on last packet, used for PAWS */ 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate uint32_t tcp_obsegs; /* Outbound segments on this stream */ 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate uint32_t tcp_mss; /* Max segment size */ 13220Sstevel@tonic-gate uint32_t tcp_naglim; /* Tunable nagle limit */ 13230Sstevel@tonic-gate int32_t tcp_hdr_len; /* Byte len of combined TCP/IP hdr */ 13240Sstevel@tonic-gate tcph_t *tcp_tcph; /* tcp header within combined hdr */ 13250Sstevel@tonic-gate int32_t tcp_tcp_hdr_len; /* tcp header len within combined */ 13260Sstevel@tonic-gate uint32_t tcp_valid_bits; 13270Sstevel@tonic-gate #define TCP_ISS_VALID 0x1 /* Is the tcp_iss seq num active? */ 13280Sstevel@tonic-gate #define TCP_FSS_VALID 0x2 /* Is the tcp_fss seq num active? */ 13290Sstevel@tonic-gate #define TCP_URG_VALID 0x4 /* If the tcp_urg seq num active? */ 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate int32_t tcp_xmit_hiwater; /* Send buffer high water mark. */ 13320Sstevel@tonic-gate 13330Sstevel@tonic-gate union { /* template ip header */ 13340Sstevel@tonic-gate ipha_t tcp_u_ipha; 13350Sstevel@tonic-gate char tcp_u_buf[IP_SIMPLE_HDR_LENGTH+TCP_MIN_HEADER_LENGTH]; 13360Sstevel@tonic-gate double tcp_u_aligner; 13370Sstevel@tonic-gate } tcp_u; 13380Sstevel@tonic-gate #define tcp_ipha tcp_u.tcp_u_ipha 13390Sstevel@tonic-gate #define tcp_iphc tcp_u.tcp_u_buf 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate uint32_t tcp_sum; /* checksum to compensate for source */ 13420Sstevel@tonic-gate /* routed packets. Host byte order */ 13430Sstevel@tonic-gate 13440Sstevel@tonic-gate uint16_t tcp_last_sent_len; /* Record length for nagle */ 13450Sstevel@tonic-gate uint16_t tcp_dupack_cnt; /* # of consequtive duplicate acks */ 13460Sstevel@tonic-gate 13470Sstevel@tonic-gate uint32_t tcp_rnxt; /* Seq we expect to recv next */ 13480Sstevel@tonic-gate uint32_t tcp_rwnd; /* Current receive window */ 13490Sstevel@tonic-gate uint32_t tcp_rwnd_max; /* Maximum receive window */ 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate mblk_t *tcp_rcv_head; /* Queued until push, urgent data or */ 13520Sstevel@tonic-gate mblk_t *tcp_rcv_tail; /* the count exceeds */ 13530Sstevel@tonic-gate uint32_t tcp_rcv_cnt; /* tcp_rcv_push_wait. */ 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate mblk_t *tcp_reass_head; /* Out of order reassembly list head */ 13560Sstevel@tonic-gate mblk_t *tcp_reass_tail; /* Out of order reassembly list tail */ 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate uint32_t tcp_cwnd_ssthresh; /* Congestion window */ 13590Sstevel@tonic-gate uint32_t tcp_cwnd_max; 13600Sstevel@tonic-gate uint32_t tcp_csuna; /* Clear (no rexmits in window) suna */ 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate int tcp_rttv_updates; 13630Sstevel@tonic-gate clock_t tcp_rto; /* Round trip timeout */ 13640Sstevel@tonic-gate clock_t tcp_rtt_sa; /* Round trip smoothed average */ 13650Sstevel@tonic-gate clock_t tcp_rtt_sd; /* Round trip smoothed deviation */ 13660Sstevel@tonic-gate clock_t tcp_rtt_update; /* Round trip update(s) */ 13670Sstevel@tonic-gate clock_t tcp_ms_we_have_waited; /* Total retrans time */ 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate uint32_t tcp_swl1; /* These help us avoid using stale */ 13700Sstevel@tonic-gate uint32_t tcp_swl2; /* packets to update state */ 13710Sstevel@tonic-gate 13720Sstevel@tonic-gate mblk_t *tcp_xmit_head; /* Head of rexmit list */ 13730Sstevel@tonic-gate mblk_t *tcp_xmit_last; /* last valid data seen by tcp_wput */ 13740Sstevel@tonic-gate uint32_t tcp_unsent; /* # of bytes in hand that are unsent */ 13750Sstevel@tonic-gate mblk_t *tcp_xmit_tail; /* Last rexmit data sent */ 13760Sstevel@tonic-gate uint32_t tcp_xmit_tail_unsent; /* # of unsent bytes in xmit_tail */ 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate uint32_t tcp_snxt; /* Senders next seq num */ 13790Sstevel@tonic-gate uint32_t tcp_suna; /* Sender unacknowledged */ 13800Sstevel@tonic-gate uint32_t tcp_rexmit_nxt; /* Next rexmit seq num */ 13810Sstevel@tonic-gate uint32_t tcp_rexmit_max; /* Max retran seq num */ 13820Sstevel@tonic-gate int32_t tcp_snd_burst; /* Send burst factor */ 13830Sstevel@tonic-gate uint32_t tcp_swnd; /* Senders window (relative to suna) */ 13840Sstevel@tonic-gate uint32_t tcp_cwnd; /* Congestion window */ 13850Sstevel@tonic-gate int32_t tcp_cwnd_cnt; /* cwnd cnt in congestion avoidance */ 13860Sstevel@tonic-gate uint32_t tcp_ackonly; /* Senders last ack seq num */ 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate uint32_t tcp_irs; /* Initial recv seq num */ 13890Sstevel@tonic-gate uint32_t tcp_iss; /* Initial send seq num */ 13900Sstevel@tonic-gate uint32_t tcp_fss; /* Final/fin send seq num */ 13910Sstevel@tonic-gate uint32_t tcp_urg; /* Urgent data seq num */ 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate uint32_t tcp_rack; /* Seq # we have acked */ 13940Sstevel@tonic-gate uint32_t tcp_rack_cnt; /* # of bytes we have deferred ack */ 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate uint32_t tcp_max_swnd; /* Maximum swnd we have seen */ 13970Sstevel@tonic-gate int64_t tcp_rexmit_fire_time; 13980Sstevel@tonic-gate int64_t tcp_dack_fire_time; 13990Sstevel@tonic-gate int64_t tcp_ka_fire_time; 14000Sstevel@tonic-gate int64_t tcp_http_ka_fire_time; 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate int32_t tcp_keepalive_intrvl; /* Zero means don't bother */ 14030Sstevel@tonic-gate int32_t tcp_ka_probe_sent; 14040Sstevel@tonic-gate int32_t tcp_ka_last_intrvl; 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate #define TCP_DACK_TIMER 0x1 14070Sstevel@tonic-gate #define TCP_REXMIT_TIMER 0x2 14080Sstevel@tonic-gate #define TCP_KA_TIMER 0x4 14090Sstevel@tonic-gate #define TCP_HTTP_KA_TIMER 0x8 14100Sstevel@tonic-gate int16_t tcp_running_timer; 14110Sstevel@tonic-gate int16_t tcp_pending_timer; 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate #ifdef CONNP_T_TRACE_ON 14140Sstevel@tonic-gate connp_t *pkt_tp; /* Packet tracing pointer */ 14150Sstevel@tonic-gate connp_t pkt_tv[CONNP_TV_SZ]; /* Packet tracing vector */ 14160Sstevel@tonic-gate #endif /* CONNP_T_TRACE_ON */ 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate } nca_conn_t; 14190Sstevel@tonic-gate 14200Sstevel@tonic-gate /* 14210Sstevel@tonic-gate * Active stack support parameters to control what ports NCA can use. 14220Sstevel@tonic-gate * They are declared in ncaproto.c 14230Sstevel@tonic-gate */ 14240Sstevel@tonic-gate extern struct nca_tbf_s *nca_tcp_port; 14250Sstevel@tonic-gate extern in_port_t tcp_lo_port; 14260Sstevel@tonic-gate extern in_port_t tcp_hi_port; 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate /* 14290Sstevel@tonic-gate * nca_conn_t.http_persist values and corresponding HTTP header strings are 14300Sstevel@tonic-gate * used to determine the connection persistent state of a connection and 14310Sstevel@tonic-gate * any HTTP header which needs to be sent. 14320Sstevel@tonic-gate */ 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate #define PERSIST_NONE 0 /* Not persistent */ 14350Sstevel@tonic-gate 14360Sstevel@tonic-gate #define PERSIST_CLOSE 1 /* Was persistent, send close header */ 14370Sstevel@tonic-gate #define PERSIST_TRUE 2 /* Connection is HTTP persistent */ 14380Sstevel@tonic-gate #define PERSIST_KA 3 /* Persistent, send Keep-Alive header */ 14390Sstevel@tonic-gate #define PERSIST_UPCALL 4 /* Insert "Connection: close" on */ 14400Sstevel@tonic-gate /* upcall and clear flag */ 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate #define PERSIST_HDR_NONE "\r\n" 14430Sstevel@tonic-gate #define PERSIST_HDR_CLOSE "Connection: close\r\n\r\n" 14440Sstevel@tonic-gate #define PERSIST_HDR_KA "Connection: Keep-Alive\r\n\r\n" 14450Sstevel@tonic-gate 14460Sstevel@tonic-gate /* 14470Sstevel@tonic-gate * nca_conn_t nca_squeue_ctl() flag values: 14480Sstevel@tonic-gate */ 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate #define CONN_MISS_DONE 0x0001 /* The conn miss processing is done */ 14510Sstevel@tonic-gate #define IF_TIME_WAIT 0x0002 /* A TIME_WAIT has fired */ 14520Sstevel@tonic-gate #define IF_TCP_TIMER 0x0003 /* A TCP TIMER has fired */ 14530Sstevel@tonic-gate #define NCA_CONN_TCP_TIMER 0x0004 /* A TCP TIMER needs to be execed */ 14540Sstevel@tonic-gate #define IF_TCP_CONNECT 0x0005 /* TCP connection request */ 14550Sstevel@tonic-gate #define IF_TCP_SEND 0x0006 /* A new send request. */ 14560Sstevel@tonic-gate 14570Sstevel@tonic-gate #define IF_TCP_DIRECT_TO 0x0010 /* A TCP direct i/o, step 1 */ 14580Sstevel@tonic-gate #define IF_TCP_DIRECT_FROM 0x0012 /* A TCP direct i/o, step 2 */ 14590Sstevel@tonic-gate #define IF_TCP_DIRECT_TEE 0x0001 /* If a tee else a splice */ 14600Sstevel@tonic-gate #define IF_TCP_DIRECT_CLOSE 0x001F /* A TCP direct i/o close */ 14610Sstevel@tonic-gate 14620Sstevel@tonic-gate #define NCA_CONN_T_STK_DEPTH 7 /* max stack backtrace depth */ 14630Sstevel@tonic-gate 14640Sstevel@tonic-gate struct conn_ts { 14650Sstevel@tonic-gate nca_conn_t *conn; 14660Sstevel@tonic-gate unsigned action; 14670Sstevel@tonic-gate int ref; 14680Sstevel@tonic-gate int cpu; 14690Sstevel@tonic-gate pc_t stk[NCA_CONN_T_STK_DEPTH + 1]; 14700Sstevel@tonic-gate }; 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate #undef NCA_CONN_T_TRACE_ON 14730Sstevel@tonic-gate 14740Sstevel@tonic-gate #ifdef NCA_CONN_T_TRACE_ON 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate /* 14770Sstevel@tonic-gate * adb: 14780Sstevel@tonic-gate * 32 bit 14790Sstevel@tonic-gate * *conn_tp,0t4096-(((*conn_tp)-con_tv)%0t48)/PXDDnPnPnPnPnPnPnPnPnn 14800Sstevel@tonic-gate * con_tv,((*conn_tp)-con_tv)%0t48/PXDDnPnPnPnPnPnPnPnPnn 14810Sstevel@tonic-gate * 64 bit 14820Sstevel@tonic-gate * *conn_tp,0t4096-(((*conn_tp)-con_tv)%0t56)/PXDDnXnXnXnXnXnXnXnXnn 14830Sstevel@tonic-gate * con_tv,((*conn_tp)-con_tv)%0t56/PXDDnXnXnXnXnXnXnXnXnn 14840Sstevel@tonic-gate */ 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate #define NCA_CONN_T_REFINIT 0x10000000 /* CONN_REF init() |ref value */ 14870Sstevel@tonic-gate #define NCA_CONN_T_REFINIT1 0x11000000 /* CONN_REF init() |ref value */ 14880Sstevel@tonic-gate #define NCA_CONN_T_REFINIT2 0x12000000 /* CONN_REF init() |ref value */ 14890Sstevel@tonic-gate #define NCA_CONN_T_REFNOTCP 0x13000000 /* CONN_REF no longer tcp_refed */ 14900Sstevel@tonic-gate #define NCA_CONN_T_REFHOLD 0x1A000000 /* CONN_REFHOLD() | ref value */ 14910Sstevel@tonic-gate #define NCA_CONN_T_REFRELE 0x1F000000 /* CONN_REFRELE() | ref value */ 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate #define NCA_CONN_T_HTTPCALL 0x20000000 /* call http() | rbytes */ 14940Sstevel@tonic-gate #define NCA_CONN_T_HTTPRET1 0x21000000 /* return http() */ 14950Sstevel@tonic-gate #define NCA_CONN_T_HTTPRET2 0x22000000 /* return ! http() */ 14960Sstevel@tonic-gate 14970Sstevel@tonic-gate #define NCA_CONN_T_MISSDONE 0x30000000 /* CONN_MISS_DONE */ 14980Sstevel@tonic-gate #define NCA_CONN_T_TCPTIMER 0x31000000 /* NCA_CONN_TCP_TIMER */ 14990Sstevel@tonic-gate #define NCA_CONN_T_XMIT_END 0x32000000 /* xmit_end() | tcp_unsent */ 15000Sstevel@tonic-gate #define NCA_CONN_T_XMIT_BAD 0x33000000 /* xmit_end() bad state |tcp_state */ 15010Sstevel@tonic-gate #define NCA_CONN_T_XMIT_DEF 0x34000000 /* xmit_end() deferred */ 15020Sstevel@tonic-gate #define NCA_CONN_T_TIME_WAIT 0x35000000 /* done: tcp_state == TCPS_TIME_WAIT */ 15030Sstevel@tonic-gate #define NCA_CONN_T_PKT_IN 0x36000000 /* tcp_input() | flags */ 15040Sstevel@tonic-gate #define NCA_CONN_T_PKT_OUT 0x37000000 /* tcp_input() | flags */ 15050Sstevel@tonic-gate 15060Sstevel@tonic-gate #define NCA_CONN_T_DIRECT 0x40000000 /* tcp_direct() from conn_t */ 15070Sstevel@tonic-gate #define NCA_CONN_T_DIRECT1 0x41000000 /* tcp_direct() to conn_t */ 15080Sstevel@tonic-gate #define NCA_CONN_T_DIRECT2 0x42000000 /* IF_TCP_DIRECT_TO | TEE */ 15090Sstevel@tonic-gate #define NCA_CONN_T_DIRECT3 0x43000000 /* IF_TCP_DIRECT_FROM | TEE */ 15100Sstevel@tonic-gate #define NCA_CONN_T_DIRECT4 0x44000000 /* tcp_close() */ 15110Sstevel@tonic-gate #define NCA_CONN_T_DIRECT5 0x45000000 /* IF_TCP_DIRECT_CLOSE */ 15120Sstevel@tonic-gate /* from|tcp_state */ 15130Sstevel@tonic-gate #define NCA_CONN_T_DIRECT6 0x46000000 /* IF_TCP_DIRECT_CLOSE to */ 15140Sstevel@tonic-gate 15150Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 15160Sstevel@tonic-gate #define NCA_CONN_T_TRACE_STK() { \ 15170Sstevel@tonic-gate _ix = getpcstack(&_p->stk[0], NCA_CONN_T_STK_DEPTH + 1); \ 15180Sstevel@tonic-gate if (_ix < NCA_CONN_T_STK_DEPTH + 1) { \ 15190Sstevel@tonic-gate _p->stk[_ix + 1] = 0; \ 15200Sstevel@tonic-gate } \ 15210Sstevel@tonic-gate } 15220Sstevel@tonic-gate #else 15230Sstevel@tonic-gate #define NCA_CONN_T_TRACE_STK() { \ 15240Sstevel@tonic-gate _p->stk[0] = (pc_t)callee(); \ 15250Sstevel@tonic-gate _ix = getpcstack(&_p->stk[1], NCA_CONN_T_STK_DEPTH); \ 15260Sstevel@tonic-gate if (_ix < NCA_CONN_T_STK_DEPTH) { \ 15270Sstevel@tonic-gate _p->stk[_ix + 1] = 0; \ 15280Sstevel@tonic-gate } \ 15290Sstevel@tonic-gate } 15300Sstevel@tonic-gate #endif 15310Sstevel@tonic-gate 15320Sstevel@tonic-gate #define CON_TV_SZ 4096 15330Sstevel@tonic-gate 15340Sstevel@tonic-gate extern struct conn_ts con_tv[CON_TV_SZ]; 15350Sstevel@tonic-gate extern struct conn_ts *conn_tp; 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate #define NCA_CONN_T_TRACE(p, a) { \ 15380Sstevel@tonic-gate struct conn_ts *_p; \ 15390Sstevel@tonic-gate struct conn_ts *_np; \ 15400Sstevel@tonic-gate int _ix; \ 15410Sstevel@tonic-gate \ 15420Sstevel@tonic-gate do { \ 15430Sstevel@tonic-gate _p = conn_tp; \ 15440Sstevel@tonic-gate if ((_np = _p + 1) == &con_tv[CON_TV_SZ]) \ 15450Sstevel@tonic-gate _np = con_tv; \ 15460Sstevel@tonic-gate } while (casptr(&conn_tp, _p, _np) != _p); \ 15470Sstevel@tonic-gate _p->conn = (p); \ 15480Sstevel@tonic-gate _p->action = (a); \ 15490Sstevel@tonic-gate _p->ref = (p)->ref; \ 15500Sstevel@tonic-gate _p->cpu = CPU->cpu_seqid; \ 15510Sstevel@tonic-gate NCA_CONN_T_TRACE_STK(); \ 15520Sstevel@tonic-gate } 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate #else /* NCA_CONN_T_TRACE_ON */ 15550Sstevel@tonic-gate 15560Sstevel@tonic-gate #define NCA_CONN_T_TRACE(p, a) 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate #endif /* NCA_CONN_T_TRACE_ON */ 15590Sstevel@tonic-gate 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate #define CONN_REFHOLD(connp) { \ 15620Sstevel@tonic-gate \ 15630Sstevel@tonic-gate NCA_CONN_T_TRACE((connp), NCA_CONN_T_REFHOLD | ((connp)->ref + 1)); \ 15640Sstevel@tonic-gate \ 15650Sstevel@tonic-gate if ((connp)->ref <= 0) \ 15660Sstevel@tonic-gate panic("nca CONN_REFHOLD: %p has no references", \ 15670Sstevel@tonic-gate (void *)(connp)); \ 15680Sstevel@tonic-gate (connp)->ref++; \ 15690Sstevel@tonic-gate } 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate #define CONN_REFRELE(connp) { \ 15720Sstevel@tonic-gate \ 15730Sstevel@tonic-gate NCA_CONN_T_TRACE((connp), NCA_CONN_T_REFRELE | ((connp)->ref - 1)); \ 15740Sstevel@tonic-gate \ 15750Sstevel@tonic-gate if ((connp)->tcp_refed) { \ 15760Sstevel@tonic-gate if ((connp)->ref == 1) \ 15770Sstevel@tonic-gate panic("nca CONN_REFRELE: %p " \ 15780Sstevel@tonic-gate "has only tcp_refed reference", \ 15790Sstevel@tonic-gate (void *)(connp)); \ 15800Sstevel@tonic-gate if ((connp)->ref < 1) \ 15810Sstevel@tonic-gate panic("nca CONN_REFRELE: %p has no references", \ 15820Sstevel@tonic-gate (void *)(connp)); \ 15830Sstevel@tonic-gate } else { \ 15840Sstevel@tonic-gate if ((connp)->ref <= 0) \ 15850Sstevel@tonic-gate panic("nca CONN_REFRELE: %p has no references", \ 15860Sstevel@tonic-gate (void *)(connp)); \ 15870Sstevel@tonic-gate } \ 15880Sstevel@tonic-gate (connp)->ref--; \ 15890Sstevel@tonic-gate if ((connp)->ref == 0) { \ 15900Sstevel@tonic-gate /* Last ref of a nca_conn_t, so free it */ \ 15910Sstevel@tonic-gate kmutex_t *lock = &(connp)->hashfanout->lock; \ 15920Sstevel@tonic-gate mutex_enter(lock); \ 15930Sstevel@tonic-gate nca_conn_free(connp); \ 15940Sstevel@tonic-gate /* Note: nca_conn_free exits lock */ \ 15950Sstevel@tonic-gate } \ 15960Sstevel@tonic-gate } 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate /* 15990Sstevel@tonic-gate * The nca_io2_shadow_t is used by the kernel to contian a copy of a user- 16000Sstevel@tonic-gate * land nca_io2_t and the the user-land nca_io2_t address and size. 16010Sstevel@tonic-gate */ 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate typedef struct nca_io2_shadow_s { 16040Sstevel@tonic-gate nca_io2_t io; /* copy of user-land nca_io2_t */ 16050Sstevel@tonic-gate void *data_ptr; /* copy of door_arg_t.data_ptr */ 16060Sstevel@tonic-gate size_t data_size; /* copy of door_arg_t.data_size */ 16070Sstevel@tonic-gate } nca_io2_shadow_t; 16080Sstevel@tonic-gate 16090Sstevel@tonic-gate #define SHADOW_NONE 0x00 /* nca_io2_t.shadow NONE */ 16100Sstevel@tonic-gate #define SHADOW_DOORSRV 0x01 /* nca_io2_t.shadow door_srv() */ 16110Sstevel@tonic-gate #define SHADOW_NCAFS 0x02 /* nca_io2_t.shadow NCAfs */ 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate 16140Sstevel@tonic-gate /* 16150Sstevel@tonic-gate * Given a ptr to a nca_io2_t, a field and the field_length, write data 16160Sstevel@tonic-gate * into buffer (Note: word aligned offsets). 16170Sstevel@tonic-gate */ 16180Sstevel@tonic-gate #define NCA_IO_WDATA(val, vsize, p, n_used, len, off) \ 16190Sstevel@tonic-gate /*CONSTCOND*/ \ 16200Sstevel@tonic-gate if ((val) == NULL) { \ 16210Sstevel@tonic-gate (p)->len = vsize; \ 16220Sstevel@tonic-gate (p)->off = 0; \ 16230Sstevel@tonic-gate } else { \ 16240Sstevel@tonic-gate (p)->len = (vsize); \ 16250Sstevel@tonic-gate (p)->off = ((n_used) + sizeof (uint32_t) - 1) & \ 16260Sstevel@tonic-gate (~(sizeof (uint32_t) - 1)); \ 16270Sstevel@tonic-gate bcopy((char *)(val), \ 16280Sstevel@tonic-gate ((char *)(p) + (p)->off), (vsize)); \ 16290Sstevel@tonic-gate (n_used) = (p)->off + (p)->len; \ 16300Sstevel@tonic-gate } 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate /* 16330Sstevel@tonic-gate * Given a ptr to an nca_io2_t, a field length member name, append data to 16340Sstevel@tonic-gate * it in the buffer. Note: must be the last field a WDATA() was done for. 16350Sstevel@tonic-gate * 16360Sstevel@tonic-gate * Note: a NULL NCA_IO_WDATA() can be followed by a NCA_IO_ADATA() only if 16370Sstevel@tonic-gate * vsize was == -1. 16380Sstevel@tonic-gate * 16390Sstevel@tonic-gate */ 16400Sstevel@tonic-gate #define NCA_IO_ADATA(val, vsize, p, n_used, len, off) \ 16410Sstevel@tonic-gate if ((p)->len == -1) { \ 16420Sstevel@tonic-gate (p)->len = 0; \ 16430Sstevel@tonic-gate (p)->off = ((n_used) + sizeof (uint32_t) - 1) & \ 16440Sstevel@tonic-gate (~(sizeof (uint32_t) - 1)); \ 16450Sstevel@tonic-gate } \ 16460Sstevel@tonic-gate bcopy((char *)(val), ((char *)(p) + \ 16470Sstevel@tonic-gate (p)->off + (p)->len), (vsize)); \ 16480Sstevel@tonic-gate (p)->len += (vsize); \ 16490Sstevel@tonic-gate (n_used) += (vsize); 16500Sstevel@tonic-gate 16510Sstevel@tonic-gate /* 16520Sstevel@tonic-gate * Given a ptr to a nca_io2_t and a field construct a pointer. 16530Sstevel@tonic-gate */ 16540Sstevel@tonic-gate #define NCA_IO_PDATA(p, off) ((char *)(p) + (p)->off) 16550Sstevel@tonic-gate 16560Sstevel@tonic-gate 16570Sstevel@tonic-gate #ifndef isdigit 16580Sstevel@tonic-gate #define isdigit(c) ((c) >= '0' && (c) <= '9') 16590Sstevel@tonic-gate #endif 16600Sstevel@tonic-gate 16610Sstevel@tonic-gate #ifndef tolower 16620Sstevel@tonic-gate #define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) | 0x20 : (c)) 16630Sstevel@tonic-gate #endif 16640Sstevel@tonic-gate 16650Sstevel@tonic-gate #ifndef isalpha 16660Sstevel@tonic-gate #define isalpha(c) (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) 16670Sstevel@tonic-gate #endif 16680Sstevel@tonic-gate 16690Sstevel@tonic-gate #ifndef isspace 16700Sstevel@tonic-gate #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || \ 16710Sstevel@tonic-gate (c) == '\r' || (c) == '\f' || (c) == '\013') 16720Sstevel@tonic-gate #endif 16730Sstevel@tonic-gate 16740Sstevel@tonic-gate extern char *strnchr(const char *, int, size_t); 16750Sstevel@tonic-gate extern char *strnstr(const char *, const char *, size_t); 16760Sstevel@tonic-gate extern char *strncasestr(const char *, const char *, size_t); 16770Sstevel@tonic-gate extern char *strrncasestr(const char *, const char *, size_t); 16780Sstevel@tonic-gate extern int atoin(const char *, size_t); 16790Sstevel@tonic-gate extern int digits(int); 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate extern void nca_conn_free(nca_conn_t *); 16820Sstevel@tonic-gate extern void nca_logit_off(void); 16830Sstevel@tonic-gate extern void node_fr(node_t *); 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate extern nca_squeue_t *nca_squeue_init(nca_squeue_t *, uint32_t, 16860Sstevel@tonic-gate processorid_t, void (*)(), void *, void (*)(), clock_t, pri_t); 16870Sstevel@tonic-gate extern void nca_squeue_fini(nca_squeue_t *); 16880Sstevel@tonic-gate extern void nca_squeue_enter(nca_squeue_t *, mblk_t *, void *); 16890Sstevel@tonic-gate extern void nca_squeue_fill(nca_squeue_t *, mblk_t *, void *); 16900Sstevel@tonic-gate extern mblk_t *nca_squeue_remove(nca_squeue_t *); 16910Sstevel@tonic-gate extern void nca_squeue_worker(nca_squeue_t *); 16920Sstevel@tonic-gate extern mblk_t *nca_squeue_ctl(mblk_t *, void *, unsigned short); 16930Sstevel@tonic-gate extern void nca_squeue_signal(nca_squeue_t *); 16940Sstevel@tonic-gate extern void nca_squeue_exit(nca_squeue_t *); 16950Sstevel@tonic-gate extern void sqfan_init(sqfan_t *, uint32_t, uint32_t, uint32_t); 16960Sstevel@tonic-gate extern nca_squeue_t *sqfan_ixinit(sqfan_t *, uint32_t, nca_squeue_t *, uint32_t, 16970Sstevel@tonic-gate processorid_t, void (*)(), void *, void (*)(), clock_t, pri_t); 16980Sstevel@tonic-gate extern void sqfan_fini(sqfan_t *); 16990Sstevel@tonic-gate extern void sqfan_fill(sqfan_t *, mblk_t *, void *); 17000Sstevel@tonic-gate extern mblk_t *sqfan_remove(sqfan_t *); 17010Sstevel@tonic-gate extern void nca_squeue_nointr(nca_squeue_t *, mblk_t *, void *, int); 17020Sstevel@tonic-gate extern void nca_squeue_pause(nca_squeue_t *, mblk_t *, void *, int, boolean_t); 17030Sstevel@tonic-gate extern void nca_squeue_willproxy(nca_squeue_t *); 17040Sstevel@tonic-gate extern void nca_squeue_proxy(nca_squeue_t *, nca_squeue_t *); 17050Sstevel@tonic-gate extern void nca_squeue_bind(nca_squeue_t *, uint32_t, processorid_t); 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate extern int nca_tcp_clean_death(nca_conn_t *, int); 17080Sstevel@tonic-gate extern nca_conn_t *nca_tcp_connect(ipaddr_t, in_port_t, boolean_t); 17090Sstevel@tonic-gate extern void nca_tcp_send(nca_conn_t *, mblk_t *); 17100Sstevel@tonic-gate extern void nca_tcp_direct(nca_conn_t *, nca_conn_t *, uint32_t); 17110Sstevel@tonic-gate 17120Sstevel@tonic-gate /* Functions prototypes from ncadoorsrv.c */ 17130Sstevel@tonic-gate extern node_t *nca_node_flush(node_t *); 17140Sstevel@tonic-gate extern void nca_downcall_service(void *, door_arg_t *, void (**)(void *, 17150Sstevel@tonic-gate void *), void **, int *); 17160Sstevel@tonic-gate extern node_t *ctag_lookup(uint64_t, unsigned *); 17170Sstevel@tonic-gate extern node_t *node_replace(node_t *, nca_conn_t *); 17180Sstevel@tonic-gate extern node_t *node_temp(node_t *, nca_conn_t *); 17190Sstevel@tonic-gate extern void find_ctags(node_t *, nca_io2_t *, int *); 17200Sstevel@tonic-gate extern void nca_ncafs_srv(nca_io2_t *, struct uio *, queue_t *); 17210Sstevel@tonic-gate extern boolean_t nca_reclaim_vlru(void); 17220Sstevel@tonic-gate extern boolean_t nca_reclaim_plru(boolean_t, boolean_t); 17230Sstevel@tonic-gate 17240Sstevel@tonic-gate /* 17250Sstevel@tonic-gate * NCA_COUNTER() is used to add a signed long value to a unsigned long 17260Sstevel@tonic-gate * counter, in general these counters are used to maintain NCA state. 17270Sstevel@tonic-gate * 17280Sstevel@tonic-gate * NCA_DEBUG_COUNTER() is used like NCA_COUNTER() but for counters used 17290Sstevel@tonic-gate * to maintain additional debug state, by default these counters aren't 17300Sstevel@tonic-gate * updated unless the global value nca_debug_counter is set to a value 17310Sstevel@tonic-gate * other then zero. 17320Sstevel@tonic-gate * 17330Sstevel@tonic-gate * Also, if NCA_COUNTER_TRACE is defined a time ordered wrapping trace 17340Sstevel@tonic-gate * buffer is maintained with hrtime_t stamps, counter address, value to 17350Sstevel@tonic-gate * add, and new value entries for all NCA_COUNTER() and NCA_DEBUG_COUNTER() 17360Sstevel@tonic-gate * use. 17370Sstevel@tonic-gate */ 17380Sstevel@tonic-gate 17390Sstevel@tonic-gate #undef NCA_COUNTER_TRACE 17400Sstevel@tonic-gate 17410Sstevel@tonic-gate #ifdef NCA_COUNTER_TRACE 17420Sstevel@tonic-gate 17430Sstevel@tonic-gate #define NCA_COUNTER_TRACE_SZ 1024 17440Sstevel@tonic-gate 17450Sstevel@tonic-gate typedef struct nca_counter_s { 17460Sstevel@tonic-gate hrtime_t t; 17470Sstevel@tonic-gate unsigned long *p; 17480Sstevel@tonic-gate unsigned long v; 17490Sstevel@tonic-gate unsigned long nv; 17500Sstevel@tonic-gate } nca_counter_t; 17510Sstevel@tonic-gate 17520Sstevel@tonic-gate extern nca_counter_t nca_counter_tv[]; 17530Sstevel@tonic-gate extern nca_counter_t *nca_counter_tp; 17540Sstevel@tonic-gate 17550Sstevel@tonic-gate #define NCA_COUNTER(_p, _v) { \ 17560Sstevel@tonic-gate unsigned long *p = _p; \ 17570Sstevel@tonic-gate long v = _v; \ 17580Sstevel@tonic-gate unsigned long _nv; \ 17590Sstevel@tonic-gate nca_counter_t *_otp; \ 17600Sstevel@tonic-gate nca_counter_t *_ntp; \ 17610Sstevel@tonic-gate \ 17620Sstevel@tonic-gate _nv = atomic_add_long_nv(p, v); \ 17630Sstevel@tonic-gate do { \ 17640Sstevel@tonic-gate _otp = nca_counter_tp; \ 17650Sstevel@tonic-gate _ntp = _otp + 1; \ 17660Sstevel@tonic-gate if (_ntp == &nca_counter_tv[NCA_COUNTER_TRACE_SZ]) \ 17670Sstevel@tonic-gate _ntp = nca_counter_tv; \ 17680Sstevel@tonic-gate } while (casptr((void *)&nca_counter_tp, (void *)_otp, \ 17690Sstevel@tonic-gate (void *)_ntp) != (void *)_otp); \ 17700Sstevel@tonic-gate _ntp->t = gethrtime(); \ 17710Sstevel@tonic-gate _ntp->p = p; \ 17720Sstevel@tonic-gate _ntp->v = v; \ 17730Sstevel@tonic-gate _ntp->nv = _nv; \ 17740Sstevel@tonic-gate } 17750Sstevel@tonic-gate 17760Sstevel@tonic-gate #else /* NCA_COUNTER_TRACE */ 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate #define NCA_COUNTER(p, v) atomic_add_long((p), (v)) 17790Sstevel@tonic-gate 17800Sstevel@tonic-gate #endif /* NCA_COUNTER_TRACE */ 17810Sstevel@tonic-gate 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate /* 17840Sstevel@tonic-gate * This is the buf used in upcall to httpd. 17850Sstevel@tonic-gate */ 17860Sstevel@tonic-gate typedef struct { 17870Sstevel@tonic-gate uintptr_t tid; 17880Sstevel@tonic-gate char *buf; 17890Sstevel@tonic-gate } http_buf_table_t; 17900Sstevel@tonic-gate 17910Sstevel@tonic-gate /* 17920Sstevel@tonic-gate * URI and filename hash, a simple static hash bucket array of singly 17930Sstevel@tonic-gate * linked grounded lists is used with a hashing algorithm which has 17940Sstevel@tonic-gate * proven to have good distribution properities for strings of ... 17950Sstevel@tonic-gate * 17960Sstevel@tonic-gate * Note: NCA_HASH_SZ must be a prime number. 17970Sstevel@tonic-gate */ 17980Sstevel@tonic-gate 17990Sstevel@tonic-gate #define NCA_HASH_SZ 8053 18000Sstevel@tonic-gate #define NCA_HASH_MASK 0xFFFFFF 18010Sstevel@tonic-gate #define HASH_IX(s, l, hix, hsz) { \ 18020Sstevel@tonic-gate char *cp = (s); \ 18030Sstevel@tonic-gate int len = (l); \ 18040Sstevel@tonic-gate \ 18050Sstevel@tonic-gate (hix) = 0; \ 18060Sstevel@tonic-gate while (len-- > 0) { \ 18070Sstevel@tonic-gate (hix) = (hix) * 33 + *cp++; \ 18080Sstevel@tonic-gate (hix) &= NCA_HASH_MASK; \ 18090Sstevel@tonic-gate } \ 18100Sstevel@tonic-gate (hix) %= (hsz); \ 18110Sstevel@tonic-gate } 18120Sstevel@tonic-gate 18130Sstevel@tonic-gate /* 18140Sstevel@tonic-gate * CTAG hash. 18150Sstevel@tonic-gate */ 18160Sstevel@tonic-gate #define NCA_CTAGHASH_SZ 4096 18170Sstevel@tonic-gate #define CTAGHASH_IX(t, ix) ((ix) = (t) % NCA_CTAGHASH_SZ) 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate /* 18200Sstevel@tonic-gate * VNODE hash. 18210Sstevel@tonic-gate * 18220Sstevel@tonic-gate * Note: NCA_VNODEHASH_SZ must be a P2Ps() value. 18230Sstevel@tonic-gate */ 18240Sstevel@tonic-gate #define NCA_VNODEHASH_SZ 12281 18250Sstevel@tonic-gate #define VNODEHASH_IX(p, ix) ((ix) = (((uintptr_t)p >> 27) ^ \ 18260Sstevel@tonic-gate ((uintptr_t)p >> 17) ^ ((uintptr_t)p >> 11) ^ (uintptr_t)p) % \ 18270Sstevel@tonic-gate ncavnodehash_sz) 18280Sstevel@tonic-gate 18290Sstevel@tonic-gate extern pgcnt_t nca_ppmax; 18300Sstevel@tonic-gate extern pgcnt_t nca_vpmax; 18310Sstevel@tonic-gate extern pgcnt_t nca_pplim; 18320Sstevel@tonic-gate extern pgcnt_t nca_vplim; 18330Sstevel@tonic-gate extern pgcnt_t nca_ppmem; 18340Sstevel@tonic-gate extern pgcnt_t nca_vpmem; 18350Sstevel@tonic-gate extern ssize_t nca_kbmem; 18360Sstevel@tonic-gate extern ssize_t nca_spmem; 18370Sstevel@tonic-gate extern ssize_t nca_ckmem; 18380Sstevel@tonic-gate extern ssize_t nca_mbmem; 18390Sstevel@tonic-gate extern ssize_t nca_cbmem; 18400Sstevel@tonic-gate extern ssize_t nca_lbmem; 18410Sstevel@tonic-gate extern size_t nca_maxkmem; 18420Sstevel@tonic-gate extern uint32_t nca_use_segmap; 18430Sstevel@tonic-gate 18440Sstevel@tonic-gate extern ulong_t nca_hits; 18450Sstevel@tonic-gate extern ulong_t nca_file; 18460Sstevel@tonic-gate extern ulong_t nca_ctag; 18470Sstevel@tonic-gate extern ulong_t nca_miss; 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate extern ulong_t nca_hit304; 18500Sstevel@tonic-gate extern ulong_t nca_hitnoV; 18510Sstevel@tonic-gate extern ulong_t nca_hitnoVfast; 18520Sstevel@tonic-gate extern ulong_t nca_hitnoVtemp; 18530Sstevel@tonic-gate 18540Sstevel@tonic-gate extern ulong_t nca_filehits; 18550Sstevel@tonic-gate extern ulong_t nca_filenoV; 18560Sstevel@tonic-gate extern ulong_t nca_filenoVfast; 18570Sstevel@tonic-gate extern ulong_t nca_filemiss; 18580Sstevel@tonic-gate 18590Sstevel@tonic-gate extern ulong_t nca_missURI; 18600Sstevel@tonic-gate extern ulong_t nca_missQ; 18610Sstevel@tonic-gate extern ulong_t nca_missSAFE; 18620Sstevel@tonic-gate extern ulong_t nca_missnoV; 18630Sstevel@tonic-gate extern ulong_t nca_missnotcp; 18640Sstevel@tonic-gate extern ulong_t nca_missfail; 18650Sstevel@tonic-gate extern ulong_t nca_misstemp; 18660Sstevel@tonic-gate extern ulong_t nca_missnohash; 18670Sstevel@tonic-gate extern ulong_t nca_missclean; 18680Sstevel@tonic-gate extern ulong_t nca_missadvisory; 18690Sstevel@tonic-gate extern ulong_t nca_missadvNoA; 18700Sstevel@tonic-gate extern ulong_t nca_missERROR; 18710Sstevel@tonic-gate 18720Sstevel@tonic-gate extern ulong_t nca_ERROR; 18730Sstevel@tonic-gate extern ulong_t nca_flushnode; 18740Sstevel@tonic-gate extern ulong_t nca_replacenode; 18750Sstevel@tonic-gate extern ulong_t nca_tempnode; 18760Sstevel@tonic-gate 18770Sstevel@tonic-gate extern ulong_t nca_fail304; 18780Sstevel@tonic-gate 18790Sstevel@tonic-gate extern ulong_t nca_nocache1; 18800Sstevel@tonic-gate extern ulong_t nca_nocache2; 18810Sstevel@tonic-gate extern ulong_t nca_nocache3; 18820Sstevel@tonic-gate extern ulong_t nca_nocache4; 18830Sstevel@tonic-gate extern ulong_t nca_nocache5; 18840Sstevel@tonic-gate extern ulong_t nca_nocache6; 18850Sstevel@tonic-gate extern ulong_t nca_nocache6nomp; 18860Sstevel@tonic-gate extern ulong_t nca_nocache7; 18870Sstevel@tonic-gate extern ulong_t nca_nocache8; 18880Sstevel@tonic-gate extern ulong_t nca_nocache9; 18890Sstevel@tonic-gate extern ulong_t nca_nocache10; 18900Sstevel@tonic-gate extern ulong_t nca_nocache11; 18910Sstevel@tonic-gate extern ulong_t nca_nocache12; 18920Sstevel@tonic-gate extern ulong_t nca_nocache13; 18930Sstevel@tonic-gate extern ulong_t nca_nocache14; 18940Sstevel@tonic-gate extern ulong_t nca_nocache15; 18950Sstevel@tonic-gate extern ulong_t nca_nodes; 18960Sstevel@tonic-gate extern ulong_t nca_desballoc; 18970Sstevel@tonic-gate 18980Sstevel@tonic-gate extern ulong_t nca_plrucnt; 18990Sstevel@tonic-gate extern ulong_t nca_vlrucnt; 19000Sstevel@tonic-gate extern ulong_t nca_rpcall; 19010Sstevel@tonic-gate extern ulong_t nca_rvcall; 19020Sstevel@tonic-gate extern ulong_t nca_rpbusy; 19030Sstevel@tonic-gate extern ulong_t nca_rvbusy; 19040Sstevel@tonic-gate extern ulong_t nca_rpfail; 19050Sstevel@tonic-gate extern ulong_t nca_rpempty; 19060Sstevel@tonic-gate extern ulong_t nca_rvempty; 19070Sstevel@tonic-gate extern ulong_t nca_rpdone; 19080Sstevel@tonic-gate extern ulong_t nca_rvdone; 19090Sstevel@tonic-gate extern ulong_t nca_rmdone; 19100Sstevel@tonic-gate extern ulong_t nca_rkdone; 19110Sstevel@tonic-gate extern ulong_t nca_rsdone; 19120Sstevel@tonic-gate extern ulong_t nca_rndone; 19130Sstevel@tonic-gate extern ulong_t nca_rpnone; 19140Sstevel@tonic-gate extern ulong_t nca_rvnone; 19150Sstevel@tonic-gate extern ulong_t nca_rmnone; 19160Sstevel@tonic-gate extern ulong_t nca_rknone; 19170Sstevel@tonic-gate extern ulong_t nca_rsnone; 19180Sstevel@tonic-gate extern ulong_t nca_rnh; 19190Sstevel@tonic-gate extern ulong_t nca_ref[]; 19200Sstevel@tonic-gate extern ulong_t nca_vmap_rpcall; 19210Sstevel@tonic-gate 19220Sstevel@tonic-gate extern ulong_t nca_node_kmem_fail1; 19230Sstevel@tonic-gate extern ulong_t nca_node_kmem_fail2; 19240Sstevel@tonic-gate 19250Sstevel@tonic-gate extern ulong_t doorsrv_nopreempt; 19260Sstevel@tonic-gate extern ulong_t doorsrv_badconnect; 19270Sstevel@tonic-gate extern ulong_t doorsrv_invaladvise; 19280Sstevel@tonic-gate extern ulong_t doorsrv_notupcall; 19290Sstevel@tonic-gate extern ulong_t doorsrv_badadvise; 19300Sstevel@tonic-gate extern ulong_t doorsrv_cksum; 19310Sstevel@tonic-gate extern ulong_t doorsrv_error; 19320Sstevel@tonic-gate extern ulong_t doorsrv_op; 19330Sstevel@tonic-gate extern ulong_t doorsrv_badtee; 19340Sstevel@tonic-gate extern ulong_t doorsrv_badio; 19350Sstevel@tonic-gate extern ulong_t doorsrv_sz; 19360Sstevel@tonic-gate 19370Sstevel@tonic-gate extern ulong_t nca_allocfail; 19380Sstevel@tonic-gate extern ulong_t nca_mapinfail; 19390Sstevel@tonic-gate extern ulong_t nca_mapinfail1; 19400Sstevel@tonic-gate extern ulong_t nca_mapinfail2; 19410Sstevel@tonic-gate extern ulong_t nca_mapinfail3; 19420Sstevel@tonic-gate 19430Sstevel@tonic-gate extern ulong_t nca_httpd_http; 19440Sstevel@tonic-gate extern ulong_t nca_httpd_badsz; 19450Sstevel@tonic-gate extern ulong_t nca_httpd_nosz; 19460Sstevel@tonic-gate extern ulong_t nca_httpd_filename; 19470Sstevel@tonic-gate extern ulong_t nca_httpd_filename1; 19480Sstevel@tonic-gate extern ulong_t nca_httpd_filename2; 19490Sstevel@tonic-gate extern ulong_t nca_httpd_trailer; 19500Sstevel@tonic-gate extern ulong_t nca_httpd_preempt; 19510Sstevel@tonic-gate extern ulong_t nca_httpd_downcall; 19520Sstevel@tonic-gate extern ulong_t nca_early_downcall; 19530Sstevel@tonic-gate extern ulong_t nca_httpd_more; 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate ulong_t nca_logit_noupcall; 19560Sstevel@tonic-gate 19570Sstevel@tonic-gate ulong_t nca_logit; 19580Sstevel@tonic-gate ulong_t nca_logit_nomp; 19590Sstevel@tonic-gate ulong_t nca_logit_no; 19600Sstevel@tonic-gate ulong_t nca_logit_NULL; 19610Sstevel@tonic-gate ulong_t nca_logit_fail; 19620Sstevel@tonic-gate 19630Sstevel@tonic-gate ulong_t nca_logit_flush_NULL1; 19640Sstevel@tonic-gate ulong_t nca_logit_flush_NULL2; 19650Sstevel@tonic-gate 19660Sstevel@tonic-gate ulong_t nca_logger_NULL1; 19670Sstevel@tonic-gate ulong_t nca_logger_NULL2; 19680Sstevel@tonic-gate 19690Sstevel@tonic-gate ulong_t nca_log_buf_alloc_NULL; 19700Sstevel@tonic-gate ulong_t nca_log_buf_alloc_fail; 19710Sstevel@tonic-gate ulong_t nca_log_buf_alloc_part; 19720Sstevel@tonic-gate 19730Sstevel@tonic-gate ulong_t nca_log_buf_dup; 19740Sstevel@tonic-gate 19750Sstevel@tonic-gate extern ulong_t nca_upcalls; 19760Sstevel@tonic-gate extern ulong_t nca_ncafs_upcalls; 19770Sstevel@tonic-gate 19780Sstevel@tonic-gate extern ulong_t nca_conn_count; 19790Sstevel@tonic-gate extern ulong_t nca_conn_kmem; 19800Sstevel@tonic-gate extern ulong_t nca_conn_kmem_fail; 19810Sstevel@tonic-gate extern ulong_t nca_conn_allocb_fail; 19820Sstevel@tonic-gate extern ulong_t nca_conn_tw; 19830Sstevel@tonic-gate extern ulong_t nca_conn_tw1; 19840Sstevel@tonic-gate extern ulong_t nca_conn_tw2; 19850Sstevel@tonic-gate extern ulong_t nca_conn_reinit_cnt; 19860Sstevel@tonic-gate extern ulong_t nca_conn_NULL1; 19870Sstevel@tonic-gate extern ulong_t nca_conn_Q0; 19880Sstevel@tonic-gate extern ulong_t nca_conn_FLAGS; 19890Sstevel@tonic-gate 19900Sstevel@tonic-gate extern ulong_t tcpwronginq; 19910Sstevel@tonic-gate extern ulong_t ipsendup; 19920Sstevel@tonic-gate extern ulong_t ipwrongcpu; 19930Sstevel@tonic-gate extern ulong_t iponcpu; 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate extern ulong_t nca_tcp_xmit_null; 19960Sstevel@tonic-gate extern ulong_t nca_tcp_xmit_null1; 19970Sstevel@tonic-gate 19980Sstevel@tonic-gate extern ulong_t tw_on; 19990Sstevel@tonic-gate extern ulong_t tw_fire; 20000Sstevel@tonic-gate extern ulong_t tw_fire1; 20010Sstevel@tonic-gate extern ulong_t tw_fire2; 20020Sstevel@tonic-gate extern ulong_t tw_fire3; 20030Sstevel@tonic-gate extern ulong_t tw_add; 20040Sstevel@tonic-gate extern ulong_t tw_add1; 20050Sstevel@tonic-gate extern ulong_t tw_delete; 20060Sstevel@tonic-gate extern ulong_t tw_reclaim; 20070Sstevel@tonic-gate extern ulong_t tw_reap; 20080Sstevel@tonic-gate extern ulong_t tw_reap1; 20090Sstevel@tonic-gate extern ulong_t tw_reap2; 20100Sstevel@tonic-gate extern ulong_t tw_reap3; 20110Sstevel@tonic-gate extern ulong_t tw_reap4; 20120Sstevel@tonic-gate extern ulong_t tw_reap5; 20130Sstevel@tonic-gate extern ulong_t tw_timer; 20140Sstevel@tonic-gate extern ulong_t tw_timer1; 20150Sstevel@tonic-gate extern ulong_t tw_timer2; 20160Sstevel@tonic-gate extern ulong_t tw_timer3; 20170Sstevel@tonic-gate extern ulong_t tw_timer4; 20180Sstevel@tonic-gate extern ulong_t tw_timer5; 20190Sstevel@tonic-gate 20200Sstevel@tonic-gate extern ulong_t ti_on; 20210Sstevel@tonic-gate extern ulong_t ti_fire; 20220Sstevel@tonic-gate extern ulong_t ti_fire1; 20230Sstevel@tonic-gate extern ulong_t ti_fire2; 20240Sstevel@tonic-gate extern ulong_t ti_fire3; 20250Sstevel@tonic-gate extern ulong_t ti_fire4; 20260Sstevel@tonic-gate extern ulong_t ti_add; 20270Sstevel@tonic-gate extern ulong_t ti_add1; 20280Sstevel@tonic-gate extern ulong_t ti_add2; 20290Sstevel@tonic-gate extern ulong_t ti_add3; 20300Sstevel@tonic-gate extern ulong_t ti_add4; 20310Sstevel@tonic-gate extern ulong_t ti_add5; 20320Sstevel@tonic-gate extern ulong_t ti_add_reuse; 20330Sstevel@tonic-gate extern ulong_t ti_delete; 20340Sstevel@tonic-gate extern ulong_t ti_delete1; 20350Sstevel@tonic-gate extern ulong_t ti_delete2; 20360Sstevel@tonic-gate extern ulong_t ti_reap; 20370Sstevel@tonic-gate extern ulong_t ti_reap1; 20380Sstevel@tonic-gate extern ulong_t ti_reap2; 20390Sstevel@tonic-gate extern ulong_t ti_reap3; 20400Sstevel@tonic-gate extern ulong_t ti_reap4; 20410Sstevel@tonic-gate extern ulong_t ti_reap5; 20420Sstevel@tonic-gate extern ulong_t ti_timer; 20430Sstevel@tonic-gate extern ulong_t ti_timer1; 20440Sstevel@tonic-gate extern ulong_t ti_timer2; 20450Sstevel@tonic-gate extern ulong_t ti_timer3; 20460Sstevel@tonic-gate extern ulong_t ti_timer4; 20470Sstevel@tonic-gate extern ulong_t ti_timer5; 20480Sstevel@tonic-gate extern ulong_t ti_timer6; 20490Sstevel@tonic-gate 20500Sstevel@tonic-gate extern uint32_t nca_conn_q; 20510Sstevel@tonic-gate extern uint32_t nca_conn_q0; 20520Sstevel@tonic-gate extern uint32_t nca_conn_req_max_q; 20530Sstevel@tonic-gate extern uint32_t nca_conn_req_max_q0; 20540Sstevel@tonic-gate 20550Sstevel@tonic-gate extern char nca_resp_500[]; 20560Sstevel@tonic-gate extern ssize_t nca_resp_500_sz; 20570Sstevel@tonic-gate 20580Sstevel@tonic-gate extern uint32_t ncaurihash_sz; 20590Sstevel@tonic-gate extern uint32_t ncafilehash_sz; 20600Sstevel@tonic-gate extern uint32_t ncactaghash_sz; 20610Sstevel@tonic-gate extern uint32_t ncavnodehash_sz; 20620Sstevel@tonic-gate extern nodef_t *ncaurihash; 20630Sstevel@tonic-gate extern nodef_t *ncafilehash; 20640Sstevel@tonic-gate extern nodef_t *ncavnodehash; 20650Sstevel@tonic-gate extern nodef_t *ncactaghash; 20660Sstevel@tonic-gate extern char nca_httpd_door_path[]; 20670Sstevel@tonic-gate extern char nca_httpd_downdoor_path[]; 20680Sstevel@tonic-gate extern door_handle_t nca_downcall_door_hand; 20690Sstevel@tonic-gate extern uint32_t n_http_buf_size; 20700Sstevel@tonic-gate extern door_handle_t nca_httpd_door_hand; 20710Sstevel@tonic-gate extern sqfan_t nca_miss_fanout1; 20720Sstevel@tonic-gate extern sqfan_t nca_miss_fanout2; 20730Sstevel@tonic-gate extern nca_door_t nca_httpd_door; 20740Sstevel@tonic-gate extern int nca_downdoor_created; 20750Sstevel@tonic-gate extern int n_http_buf_table; 20760Sstevel@tonic-gate extern http_buf_table_t *g_http_buf_table; 20770Sstevel@tonic-gate extern struct kmem_cache *node_cache; 20780Sstevel@tonic-gate #ifdef DEBUG 20790Sstevel@tonic-gate extern node_t *nca_http_response(nca_conn_t *, const char *, int, char *, int, 20800Sstevel@tonic-gate uint_t, const char *); 20810Sstevel@tonic-gate extern node_t *nca_http_response_node(nca_conn_t *, const char *, int, node_t *, 20820Sstevel@tonic-gate const char *); 20830Sstevel@tonic-gate #else 20840Sstevel@tonic-gate extern node_t *nca_http_response(nca_conn_t *, const char *, int, char *, int, 20850Sstevel@tonic-gate uint_t); 20860Sstevel@tonic-gate extern node_t *nca_http_response_node(nca_conn_t *, const char *, int, 20870Sstevel@tonic-gate node_t *); 20880Sstevel@tonic-gate #endif 20890Sstevel@tonic-gate extern void nca_node_del(node_t *); 20900Sstevel@tonic-gate extern void nca_node_uncache(node_t *); 20910Sstevel@tonic-gate extern node_t *nca_node_add(char *, int, nodef_t *, int); 20920Sstevel@tonic-gate extern node_t *node_create(int, boolean_t, char *, int); 20930Sstevel@tonic-gate extern void nca_reclaim_phys(node_t *, boolean_t, boolean_t); 20940Sstevel@tonic-gate extern boolean_t nca_http_pmap(node_t *); 20950Sstevel@tonic-gate extern boolean_t nca_http_vmap(node_t *, int); 20960Sstevel@tonic-gate extern time_t nca_http_date(char *); 20970Sstevel@tonic-gate extern node_t *nca_httpd_data(node_t *, nca_conn_t *, nca_io2_t *, int); 20980Sstevel@tonic-gate extern void nca_missed(node_t *, mblk_t *, nca_squeue_t *); 20990Sstevel@tonic-gate extern void nca_miss_conn_mv(node_t *, nca_conn_t *); 21000Sstevel@tonic-gate extern void nca_miss_conn_fr(node_t *, nca_conn_t *); 21010Sstevel@tonic-gate extern void nca_http_logit(nca_conn_t *); 21020Sstevel@tonic-gate extern void nca_http_error(nca_conn_t *); 21030Sstevel@tonic-gate extern void nca_node_xmit(node_t *, nca_conn_t *); 21040Sstevel@tonic-gate 21050Sstevel@tonic-gate /* 21060Sstevel@tonic-gate * It contains data for forwarding data to application programs. 21070Sstevel@tonic-gate * For door case, doorhandle is the upcall door handle and listenerq 21080Sstevel@tonic-gate * is NULL; for ncafs, listenerq is the upcall listener queue and 21090Sstevel@tonic-gate * doorhandle is NULL. listenning is always B_TRUE for door and it is 21100Sstevel@tonic-gate * B_TRUE for ncafs only after the listen system call has been issued. 21110Sstevel@tonic-gate */ 21120Sstevel@tonic-gate typedef struct nca_listener_s { 21130Sstevel@tonic-gate boolean_t listenning; /* is ready for accepting connection */ 21140Sstevel@tonic-gate door_handle_t doorhandle; /* door handle or NULL for ncafs */ 21150Sstevel@tonic-gate queue_t *listenerq; /* upcall queue or NULL for door */ 21160Sstevel@tonic-gate } nca_listener_t; 21170Sstevel@tonic-gate 21180Sstevel@tonic-gate /* 21190Sstevel@tonic-gate * Returned values of nca_isnca_data. 21200Sstevel@tonic-gate * NOT_NCA_DATA: not NCA data. 21210Sstevel@tonic-gate * NCA_DATA_ANY_ADDR: NCA data, matches INADDR_ANY. 21220Sstevel@tonic-gate * NCA_DATA_ADDR: NCA data, match an IP address. 21230Sstevel@tonic-gate */ 21240Sstevel@tonic-gate #define NOT_NCA_DATA 0 21250Sstevel@tonic-gate #define NCA_DATA_ANY_ADDR 1 21260Sstevel@tonic-gate #define NCA_DATA_ADDR 2 21270Sstevel@tonic-gate 21280Sstevel@tonic-gate extern uint32_t ipportrehashcount1; 21290Sstevel@tonic-gate extern uint32_t ipportrehashcount2; 21300Sstevel@tonic-gate extern uint32_t ipportbucketcnt; 21310Sstevel@tonic-gate extern uint32_t ipporttablesize; 21320Sstevel@tonic-gate extern uint32_t ncafscount; 21330Sstevel@tonic-gate extern uint32_t doorcount; 21340Sstevel@tonic-gate extern int ip_virtual_hosting; 21350Sstevel@tonic-gate 21360Sstevel@tonic-gate extern nca_listener_t *nca_listener_find(ipaddr_t, uint16_t); 21370Sstevel@tonic-gate extern nca_listener_t *nca_listener_find2(ipaddr_t, uint16_t); 21380Sstevel@tonic-gate extern int nca_isnca_data(ipaddr_t, uint16_t); 21390Sstevel@tonic-gate extern int nca_listener_add(ipaddr_t, uint16_t, void *, boolean_t); 21400Sstevel@tonic-gate extern int nca_listener_del(ipaddr_t, uint16_t); 21410Sstevel@tonic-gate extern void nca_listener_report(mblk_t *); 21420Sstevel@tonic-gate 21430Sstevel@tonic-gate #ifdef __cplusplus 21440Sstevel@tonic-gate } 21450Sstevel@tonic-gate #endif 21460Sstevel@tonic-gate 21470Sstevel@tonic-gate #endif /* _INET_NCA_H */ 2148