1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _DS_IMPL_H 28 #define _DS_IMPL_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /* 37 * The Domain Services Protocol 38 * 39 * The DS protocol is divided into two parts. The first is fixed and 40 * must remain exactly the same for *all* versions of the DS protocol. 41 * The only messages supported by the fixed portion of the protocol are 42 * to negotiate a version to use for the rest of the protocol. 43 */ 44 45 /* 46 * Domain Services Header 47 */ 48 typedef struct ds_hdr { 49 uint32_t msg_type; /* message type */ 50 uint32_t payload_len; /* payload length */ 51 } ds_hdr_t; 52 53 #define DS_HDR_SZ (sizeof (ds_hdr_t)) 54 55 /* 56 * DS Fixed Message Types 57 */ 58 #define DS_INIT_REQ 0x0 /* initiate DS connection */ 59 #define DS_INIT_ACK 0x1 /* initiation acknowledgment */ 60 #define DS_INIT_NACK 0x2 /* initiation negative acknowledgment */ 61 62 /* 63 * DS Fixed Initialization Messages 64 */ 65 typedef struct ds_init_req { 66 uint16_t major_vers; /* requested major version */ 67 uint16_t minor_vers; /* requested minor version */ 68 } ds_init_req_t; 69 70 typedef struct ds_init_ack { 71 uint16_t minor_vers; /* highest supported minor version */ 72 } ds_init_ack_t; 73 74 typedef struct ds_init_nack { 75 uint16_t major_vers; /* alternate supported major version */ 76 } ds_init_nack_t; 77 78 /* 79 * DS Message Types for Version 1.0 80 */ 81 #define DS_REG_REQ 0x3 /* register a service */ 82 #define DS_REG_ACK 0x4 /* register acknowledgment */ 83 #define DS_REG_NACK 0x5 /* register failed */ 84 #define DS_UNREG 0x6 /* unregister a service */ 85 #define DS_UNREG_ACK 0x7 /* unregister acknowledgment */ 86 #define DS_UNREG_NACK 0x8 /* unregister failed */ 87 #define DS_DATA 0x9 /* data message */ 88 #define DS_NACK 0xa /* data error */ 89 90 /* result codes */ 91 #define DS_OK 0x0 /* success */ 92 #define DS_REG_VER_NACK 0x1 /* unsupported major version */ 93 #define DS_REG_DUP 0x2 /* duplicate registration attempted */ 94 #define DS_INV_HDL 0x3 /* service handle not valid */ 95 #define DS_TYPE_UNKNOWN 0x4 /* unknown message type received */ 96 97 /* 98 * Service Register Messages 99 */ 100 typedef struct ds_reg_req { 101 uint64_t svc_handle; /* service handle to register */ 102 uint16_t major_vers; /* requested major version */ 103 uint16_t minor_vers; /* requested minor version */ 104 char svc_id[1]; /* service identifier string */ 105 } ds_reg_req_t; 106 107 typedef struct ds_reg_ack { 108 uint64_t svc_handle; /* service handle sent in register */ 109 uint16_t minor_vers; /* highest supported minor version */ 110 } ds_reg_ack_t; 111 112 typedef struct ds_reg_nack { 113 uint64_t svc_handle; /* service handle sent in register */ 114 uint64_t result; /* reason for the failure */ 115 uint16_t major_vers; /* alternate supported major version */ 116 } ds_reg_nack_t; 117 118 /* 119 * Service Unregister Messages 120 */ 121 typedef struct ds_unreg_req { 122 uint64_t svc_handle; /* service handle to unregister */ 123 } ds_unreg_req_t; 124 125 typedef struct ds_unreg_ack { 126 uint64_t svc_handle; /* service handle sent in unregister */ 127 } ds_unreg_ack_t; 128 129 typedef struct ds_unreg_nack { 130 uint64_t svc_handle; /* service handle sent in unregister */ 131 } ds_unreg_nack_t; 132 133 /* 134 * Data Transfer Messages 135 */ 136 typedef struct ds_data_handle { 137 uint64_t svc_handle; /* service handle for data */ 138 } ds_data_handle_t; 139 140 typedef struct ds_data_nack { 141 uint64_t svc_handle; /* service handle sent in data msg */ 142 uint64_t result; /* reason for failure */ 143 } ds_data_nack_t; 144 145 /* 146 * Message Processing Utilities 147 */ 148 #define DS_MSG_TYPE_VALID(type) ((type) <= DS_NACK) 149 #define DS_MSG_LEN(ds_type) (sizeof (ds_hdr_t) + sizeof (ds_type)) 150 151 152 /* 153 * Domain Service Port 154 * 155 * A DS port is a logical representation of an LDC dedicated to 156 * communication between DS endpoints. The ds_port_t maintains state 157 * associated with a connection to a remote endpoint. This includes 158 * the state of the port, the LDC state, the current version of the 159 * DS protocol in use on the port, and other port properties. 160 * 161 * Locking: The port is protected by a single mutex. It must be held 162 * while the port structure is being accessed and also when data is 163 * being read or written using the port 164 */ 165 typedef enum { 166 DS_PORT_FREE, /* port structure not in use */ 167 DS_PORT_INIT, /* port structure created */ 168 DS_PORT_LDC_INIT, /* ldc successfully initialized */ 169 DS_PORT_INIT_REQ, /* initialization handshake sent */ 170 DS_PORT_READY /* init handshake completed */ 171 } ds_port_state_t; 172 173 typedef struct ds_ldc { 174 uint64_t id; /* LDC id */ 175 ldc_handle_t hdl; /* LDC handle */ 176 ldc_status_t state; /* current LDC state */ 177 } ds_ldc_t; 178 179 typedef struct ds_port { 180 kmutex_t lock; /* port lock */ 181 uint64_t id; /* port id from MD */ 182 ds_port_state_t state; /* state of the port */ 183 ds_ver_t ver; /* DS protocol version in use */ 184 uint32_t ver_idx; /* index of version during handshake */ 185 ds_ldc_t ldc; /* LDC for this port */ 186 } ds_port_t; 187 188 /* 189 * A DS portset is a bitmap that represents a collection of DS 190 * ports. Each bit represent a particular port id. The current 191 * implementation constrains the maximum number of ports to 64. 192 */ 193 typedef uint64_t ds_portset_t; 194 195 #define DS_MAX_PORTS ((sizeof (ds_portset_t)) * 8) 196 #define DS_MAX_PORT_ID (DS_MAX_PORTS - 1) 197 198 #define DS_PORT_SET(port) (1UL << (port)) 199 #define DS_PORT_IN_SET(set, port) ((set) & DS_PORT_SET(port)) 200 #define DS_PORTSET_ADD(set, port) ((void)((set) |= DS_PORT_SET(port))) 201 #define DS_PORTSET_DEL(set, port) ((void)((set) &= ~DS_PORT_SET(port))) 202 #define DS_PORTSET_ISNULL(set) ((set) == 0) 203 #define DS_PORTSET_DUP(set1, set2) ((void)((set1) = (set2))) 204 205 /* 206 * LDC Information 207 */ 208 #define DS_STREAM_MTU 4096 209 210 /* 211 * Machine Description Constants 212 */ 213 #define DS_MD_ROOT_NAME "domain-services" 214 #define DS_MD_PORT_NAME "domain-services-port" 215 #define DS_MD_CHAN_NAME "channel-endpoint" 216 217 /* 218 * DS Services 219 * 220 * A DS Service is a mapping between a DS capability and a client 221 * of the DS framework that provides that capability. It includes 222 * information on the state of the service, the currently negotiated 223 * version of the capability specific protocol, the port that is 224 * currently in use by the capability, etc. 225 */ 226 227 typedef enum { 228 DS_SVC_INVAL, /* svc structure uninitialized */ 229 DS_SVC_FREE, /* svc structure not in use */ 230 DS_SVC_INACTIVE, /* svc not registered */ 231 DS_SVC_REG_PENDING, /* register message sent */ 232 DS_SVC_ACTIVE /* register message acknowledged */ 233 } ds_svc_state_t; 234 235 typedef struct ds_svc { 236 ds_capability_t cap; /* capability information */ 237 ds_clnt_ops_t ops; /* client ops vector */ 238 ds_svc_hdl_t hdl; /* handle assigned by DS */ 239 ds_svc_state_t state; /* current service state */ 240 ds_ver_t ver; /* svc protocol version in use */ 241 uint_t ver_idx; /* index into client version array */ 242 ds_port_t *port; /* port for this service */ 243 ds_portset_t avail; /* ports available to this service */ 244 } ds_svc_t; 245 246 #define DS_SVC_ISFREE(svc) ((svc == NULL) || (svc->state == DS_SVC_FREE)) 247 248 /* 249 * A service handle is a 64 bit value with two pieces of information 250 * encoded in it. The upper 32 bits is the index into the table of 251 * a particular service structure. The lower 32 bits is a counter 252 * that is incremented each time a service structure is reused. 253 */ 254 #define DS_IDX_SHIFT 32 255 #define DS_COUNT_MASK 0xfffffffful 256 257 #define DS_ALLOC_HDL(_idx, _count) (((uint64_t)_idx << DS_IDX_SHIFT) | \ 258 ((uint64_t)(_count + 1) & \ 259 DS_COUNT_MASK)) 260 #define DS_HDL2IDX(hdl) (hdl >> DS_IDX_SHIFT) 261 #define DS_HDL2COUNT(hdl) (hdl & DS_COUNT_MASK) 262 263 /* 264 * DS Message Logging 265 * 266 * The DS framework logs all incoming and outgoing messages to a 267 * ring buffer. This provides the ability to reconstruct a trace 268 * of DS activity for use in debugging. In addition to the message 269 * data, each log entry contains a timestamp and the destination 270 * of the message. The destination is based on the port number the 271 * message passed through (port number + 1). The sign of the dest 272 * field distinguishes incoming messages from outgoing messages. 273 * Incoming messages have a negative destination field. 274 */ 275 276 typedef struct ds_log_entry { 277 struct ds_log_entry *next; /* next in log or free list */ 278 struct ds_log_entry *prev; /* previous in log */ 279 time_t timestamp; /* time message added to log */ 280 size_t datasz; /* size of the data */ 281 void *data; /* the data itself */ 282 int32_t dest; /* message destination */ 283 } ds_log_entry_t; 284 285 #define DS_LOG_IN(pid) (-(pid + 1)) 286 #define DS_LOG_OUT(pid) (pid + 1) 287 288 /* 289 * DS Log Limits: 290 * 291 * The size of the log is controlled by two limits. The first is 292 * a soft limit that is configurable by the user (via the global 293 * variable ds_log_sz). When this limit is exceeded, each new 294 * message that is added to the log replaces the oldest message. 295 * 296 * The second is a hard limit that is calculated based on the soft 297 * limit (DS_LOG_LIMIT). It is defined to be ~3% above the soft limit. 298 * Once this limit is exceeded, a thread is scheduled to delete old 299 * messages until the size of the log is below the soft limit. 300 */ 301 #define DS_LOG_DEFAULT_SZ (4 * 1024 * 1024) /* 4 MB */ 302 303 #define DS_LOG_LIMIT (ds_log_sz + (ds_log_sz >> 5)) 304 305 #define DS_LOG_ENTRY_SZ(ep) (sizeof (ds_log_entry_t) + (ep)->datasz) 306 307 /* 308 * DS Log Memory Usage: 309 * 310 * The log free list is initialized from a pre-allocated pool of entry 311 * structures (the global ds_log_entry_pool). The number of entries 312 * in the pool (DS_LOG_NPOOL) is the number of entries that would 313 * take up half the default size of the log. 314 * 315 * As messages are added to the log, entry structures are pulled from 316 * the free list. If the free list is empty, memory is allocated for 317 * the entry. When entries are removed from the log, they are placed 318 * on the free list. Allocated memory is only deallocated when the 319 * entire log is destroyed. 320 */ 321 #define DS_LOG_NPOOL ((DS_LOG_DEFAULT_SZ >> 1) / \ 322 sizeof (ds_log_entry_t)) 323 324 #define DS_LOG_POOL_END (ds_log_entry_pool + DS_LOG_NPOOL) 325 326 #define DS_IS_POOL_ENTRY(ep) (((ep) >= ds_log_entry_pool) && \ 327 ((ep) <= &(ds_log_entry_pool[DS_LOG_NPOOL]))) 328 329 #ifdef __cplusplus 330 } 331 #endif 332 333 #endif /* _DS_IMPL_H */ 334