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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2022 Garrett D'Amore 26 * Copyright 2025 Oxide Computer Company 27 */ 28 29 #ifndef _SYS_SOFTMAC_IMPL_H 30 #define _SYS_SOFTMAC_IMPL_H 31 32 #include <sys/types.h> 33 #include <sys/ethernet.h> 34 #include <sys/taskq.h> 35 #include <sys/sunddi.h> 36 #include <sys/sunldi.h> 37 #include <sys/strsun.h> 38 #include <sys/stream.h> 39 #include <sys/dlpi.h> 40 #include <sys/mac.h> 41 #include <sys/mac_provider.h> 42 #include <sys/mac_client.h> 43 #include <sys/mac_client_priv.h> 44 #include <sys/mac_ether.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 typedef void (*softmac_rx_t)(void *, mac_resource_handle_t, mblk_t *, 51 mac_header_info_t *); 52 53 typedef struct softmac_lower_rxinfo_s { 54 softmac_rx_t slr_rx; 55 void *slr_arg; 56 } softmac_lower_rxinfo_t; 57 58 typedef struct softmac_lower_s { 59 ldi_handle_t sl_lh; 60 struct softmac *sl_softmac; 61 queue_t *sl_wq; 62 struct softmac_upper_s *sl_sup; 63 softmac_lower_rxinfo_t *sl_rxinfo; 64 65 /* 66 * When a control message is processed, either sl_pending_prim or 67 * sl_pending_ioctl will be set. They will be cleared when the 68 * acknowledgement of the specific control message is received 69 * from the underlying legacy driver. 70 */ 71 kmutex_t sl_mutex; 72 kcondvar_t sl_cv; 73 t_uscalar_t sl_pending_prim; 74 boolean_t sl_pending_ioctl; 75 mblk_t *sl_ack_mp; 76 } softmac_lower_t; 77 78 typedef enum { 79 SOFTMAC_UNINIT, 80 SOFTMAC_ATTACH_INPROG, 81 SOFTMAC_ATTACH_DONE, 82 SOFTMAC_DETACH_INPROG, 83 } softmac_state_t; 84 85 typedef struct softmac_dev_s { 86 dev_t sd_dev; 87 } softmac_dev_t; 88 89 /* 90 * smac_flag values. 91 */ 92 #define SOFTMAC_GLDV3 0x01 93 #define SOFTMAC_NOSUPP 0x02 94 #define SOFTMAC_NEED_RECREATE 0x04 95 #define SOFTMAC_NOTIFY_QUIT 0x08 96 #define SOFTMAC_NOTIFY_DONE 0x10 97 98 #define SMAC_NONZERO_NODECNT(softmac) \ 99 ((softmac->smac_softmac[0] != NULL) + \ 100 (softmac->smac_softmac[1] != NULL)) 101 102 /* 103 * The softmac structure allows all minor nodes (at most two, style-1 and 104 * style-2) for the same device to be processed. A softmac_dev_t will be 105 * created for each minor node. 106 * 107 * We try to "register" the mac after all the softmac_dev_t's are processed so 108 * that even if DLPI operations fail (because of driver bugs) for one minor 109 * node, the other minor node can still be used to register the mac. 110 * (Specifically, an incorrect xxx_getinfo() implementation will cause style-2 111 * minor node mac registration to fail.) 112 * 113 * Locking description: 114 * WO: write once, valid the life time. 115 */ 116 typedef struct softmac { 117 char smac_devname[MAXNAMELEN]; /* WO */ 118 major_t smac_umajor; /* WO */ 119 int smac_uppa; /* WO */ 120 uint32_t smac_cnt; /* WO, # of minor nodes */ 121 122 kmutex_t smac_mutex; 123 kcondvar_t smac_cv; 124 softmac_state_t smac_state; /* smac_mutex */ 125 /* 126 * The smac_hold_cnt field increases when softmac_hold_device() is 127 * called to force the dls_vlan_t of the device to be created. The 128 * device pre-detach fails if this counter is not 0. 129 */ 130 uint32_t smac_hold_cnt; /* smac_mutex */ 131 uint32_t smac_flags; /* smac_mutex */ 132 int smac_attacherr; /* smac_mutex */ 133 mac_handle_t smac_mh; 134 softmac_dev_t *smac_softmac[2]; /* smac_mutex */ 135 136 /* 137 * Number of minor nodes whose post-attach routine has succeeded. 138 * This should be the same as the numbers of softmac_dev_t. 139 * Note that it does not imply SOFTMAC_ATTACH_DONE as the taskq might 140 * be still ongoing. 141 */ 142 uint32_t smac_attachok_cnt; /* smac_mutex */ 143 /* 144 * Number of softmac_dev_t left when pre-detach fails. This is used 145 * to indicate whether postattach is called because of a failed 146 * pre-detach. 147 */ 148 uint32_t smac_attached_left; /* smac_mutex */ 149 150 /* 151 * Thread handles the DL_NOTIFY_IND message from the lower stream. 152 */ 153 kthread_t *smac_notify_thread; /* smac_mutex */ 154 /* 155 * Head and tail of the DL_NOTIFY_IND messsages. 156 */ 157 mblk_t *smac_notify_head; /* smac_mutex */ 158 mblk_t *smac_notify_tail; /* smac_mutex */ 159 160 /* 161 * The remaining fields are used to register the MAC for a legacy 162 * device. They are set in softmac_mac_register() and do not change. 163 * One can access them when mac_register() is done without locks. 164 */ 165 166 /* 167 * media type is needed for create <link name, linkid> mapping, so 168 * it is set for GLDv3 device as well 169 */ 170 uint_t smac_media; 171 /* DLPI style of the underlying device */ 172 int smac_style; 173 dev_t smac_dev; 174 size_t smac_saplen; 175 size_t smac_addrlen; 176 uchar_t smac_unicst_addr[MAXMACADDRLEN]; 177 uint_t smac_min_sdu; 178 uint_t smac_max_sdu; 179 uint32_t smac_margin; 180 181 /* Notifications the underlying driver can support. */ 182 uint32_t smac_notifications; 183 184 /* 185 * Capabilities of the underlying driver. 186 */ 187 uint32_t smac_capab_flags; 188 uint32_t smac_hcksum_txflags; 189 boolean_t smac_no_capability_req; 190 191 /* 192 * Lower stream structure, accessed by the MAC provider API. The GLDv3 193 * framework assures it's validity. 194 */ 195 softmac_lower_t *smac_lower; 196 197 kmutex_t smac_active_mutex; 198 /* 199 * Set by xxx_active_set() when aggregation is created. 200 */ 201 boolean_t smac_active; /* smac_active_mutex */ 202 /* 203 * Numbers of the bounded streams in the fast-path mode. 204 */ 205 uint32_t smac_nactive; /* smac_active_mutex */ 206 207 kmutex_t smac_fp_mutex; 208 kcondvar_t smac_fp_cv; 209 /* 210 * numbers of clients that request to disable fastpath. 211 */ 212 uint32_t smac_fp_disable_clients; /* smac_fp_mutex */ 213 boolean_t smac_fastpath_admin_disabled; /* smac_fp_mutex */ 214 215 /* 216 * stream list over this softmac. 217 */ 218 list_t smac_sup_list; /* smac_fp_mutex */ 219 } softmac_t; 220 221 typedef struct smac_ioc_start_s { 222 softmac_lower_t *si_slp; 223 } smac_ioc_start_t; 224 225 #define SMAC_IOC ('S' << 24 | 'M' << 16 | 'C' << 8) 226 #define SMAC_IOC_START (SMAC_IOC | 0x01) 227 228 /* 229 * The su_mode of a non-IP/ARP stream is UNKNOWN, and the su_mode of an IP/ARP 230 * stream is either SLOWPATH or FASTPATH. 231 */ 232 #define SOFTMAC_UNKNOWN 0x00 233 #define SOFTMAC_SLOWPATH 0x01 234 #define SOFTMAC_FASTPATH 0x02 235 236 typedef struct softmac_switch_req_s { 237 list_node_t ssq_req_list_node; 238 uint32_t ssq_expected_mode; 239 } softmac_switch_req_t; 240 241 #define DATAPATH_MODE(softmac) \ 242 ((((softmac)->smac_fp_disable_clients != 0) || \ 243 (softmac)->smac_fastpath_admin_disabled) ? SOFTMAC_SLOWPATH : \ 244 SOFTMAC_FASTPATH) 245 246 247 /* 248 * Locking description: 249 * 250 * WO: Set once and valid for life; 251 * SL: Serialized by the control path (softmac_wput_nondata_task()) 252 */ 253 typedef struct softmac_upper_s { 254 softmac_t *su_softmac; /* WO */ 255 queue_t *su_rq; /* WO */ 256 queue_t *su_wq; /* WO */ 257 258 /* 259 * List of upper streams that has pending DLPI messages to be processed. 260 */ 261 list_node_t su_taskq_list_node; /* softmac_taskq_lock */ 262 263 /* 264 * non-NULL for IP/ARP streams in the fast-path mode 265 */ 266 softmac_lower_t *su_slp; /* SL & su_mutex */ 267 268 /* 269 * List of all IP/ARP upperstreams on the same softmac (including 270 * the ones in both data-path modes). 271 */ 272 list_node_t su_list_node; /* smac_fp_mutex */ 273 274 /* 275 * List of datapath switch requests. 276 */ 277 list_t su_req_list; /* smac_fp_mutex */ 278 279 /* 280 * Place holder of RX callbacks used to handles data messages comes 281 * from the dedicated-lower-stream associated with the IP/ARP stream. 282 * Another RX callback is softmac_drop_rxinfo, which is a global 283 * variable. 284 */ 285 softmac_lower_rxinfo_t su_rxinfo; /* WO */ 286 softmac_lower_rxinfo_t su_direct_rxinfo; /* WO */ 287 288 /* 289 * Used to serialize the DLPI operation and fastpath<->slowpath 290 * switching over operation. 291 */ 292 kmutex_t su_disp_mutex; 293 kcondvar_t su_disp_cv; 294 mblk_t *su_pending_head; /* su_disp_mutex */ 295 mblk_t *su_pending_tail; /* su_disp_mutex */ 296 boolean_t su_dlpi_pending; /* su_disp_mutex */ 297 boolean_t su_closing; /* su_disp_mutex */ 298 299 uint32_t su_bound : 1, /* SL */ 300 su_active : 1, /* SL */ 301 su_direct : 1, /* SL */ 302 su_is_arp : 1, 303 su_pad_to_32:28; 304 305 /* 306 * Used for fastpath data path. 307 */ 308 kmutex_t su_mutex; 309 kcondvar_t su_cv; 310 mblk_t *su_tx_flow_mp; /* su_mutex */ 311 boolean_t su_tx_busy; /* su_mutex */ 312 /* 313 * Number of softmac_srv() operation in fastpath processing. 314 */ 315 uint32_t su_tx_inprocess; /* su_mutex */ 316 /* 317 * SOFTMAC_SLOWPATH or SOFTMAC_FASTPATH 318 */ 319 uint32_t su_mode; /* SL & su_mutex */ 320 321 /* 322 * Whether this stream is already scheduled in softmac_taskq_list. 323 */ 324 boolean_t su_taskq_scheduled; /* softmac_taskq_lock */ 325 326 /* 327 * The DLD_CAPAB_DIRECT related notify callback. 328 */ 329 mac_tx_notify_t su_tx_notify_func; /* su_mutex */ 330 void *su_tx_notify_arg; /* su_mutex */ 331 } softmac_upper_t; 332 333 #define SOFTMAC_EQ_PENDING(sup, mp) { \ 334 if ((sup)->su_pending_head == NULL) { \ 335 (sup)->su_pending_head = (sup)->su_pending_tail = (mp); \ 336 } else { \ 337 (sup)->su_pending_tail->b_next = (mp); \ 338 (sup)->su_pending_tail = (mp); \ 339 } \ 340 } 341 342 #define SOFTMAC_DQ_PENDING(sup, mpp) { \ 343 if ((sup)->su_pending_head == NULL) { \ 344 *(mpp) = NULL; \ 345 } else { \ 346 *(mpp) = (sup)->su_pending_head; \ 347 if (((sup)->su_pending_head = (*(mpp))->b_next) == NULL)\ 348 (sup)->su_pending_tail = NULL; \ 349 (*(mpp))->b_next = NULL; \ 350 } \ 351 } 352 353 /* 354 * A macro to check whether the write-queue of the lower stream is full 355 * and packets need to be enqueued. 356 * 357 * Because softmac is pushed right above the underlying device and 358 * _I_INSERT/_I_REMOVE is not processed in the lower stream, it is 359 * safe to directly access the q_next pointer. 360 */ 361 #define SOFTMAC_CANPUTNEXT(q) \ 362 (!((q)->q_next->q_nfsrv->q_flag & QFULL) || canput((q)->q_next)) 363 364 365 extern dev_info_t *softmac_dip; 366 #define SOFTMAC_DEV_NAME "softmac" 367 368 extern int softmac_send_bind_req(softmac_lower_t *, uint_t); 369 extern int softmac_send_unbind_req(softmac_lower_t *); 370 extern int softmac_send_notify_req(softmac_lower_t *, uint32_t); 371 extern int softmac_send_promisc_req(softmac_lower_t *, t_uscalar_t, 372 boolean_t); 373 extern void softmac_init(); 374 extern void softmac_fini(); 375 extern void softmac_fp_init(); 376 extern void softmac_fp_fini(); 377 extern boolean_t softmac_busy(); 378 extern int softmac_fill_capab(ldi_handle_t, softmac_t *); 379 extern int softmac_capab_enable(softmac_lower_t *); 380 extern void softmac_rput_process_notdata(queue_t *, softmac_upper_t *, 381 mblk_t *); 382 extern void softmac_rput_process_data(softmac_lower_t *, mblk_t *); 383 extern int softmac_output(softmac_lower_t *, mblk_t *, t_uscalar_t, 384 t_uscalar_t, mblk_t **); 385 extern int softmac_mexchange_error_ack(mblk_t **, t_uscalar_t, 386 t_uscalar_t, t_uscalar_t); 387 388 extern int softmac_m_promisc(void *, boolean_t); 389 extern int softmac_m_multicst(void *, boolean_t, const uint8_t *); 390 extern int softmac_m_unicst(void *, const uint8_t *); 391 extern void softmac_m_ioctl(void *, queue_t *, mblk_t *); 392 extern int softmac_m_stat(void *, uint_t, uint64_t *); 393 extern mblk_t *softmac_m_tx(void *, mblk_t *); 394 extern int softmac_proto_tx(softmac_lower_t *, mblk_t *, mblk_t **); 395 extern void softmac_ioctl_tx(softmac_lower_t *, mblk_t *, mblk_t **); 396 extern void softmac_notify_thread(void *); 397 398 extern int softmac_hold(dev_t, softmac_t **); 399 extern void softmac_rele(softmac_t *); 400 extern int softmac_lower_setup(softmac_t *, softmac_upper_t *, 401 softmac_lower_t **); 402 extern boolean_t softmac_active_set(void *); 403 extern void softmac_active_clear(void *); 404 extern int softmac_fastpath_disable(void *); 405 extern void softmac_fastpath_enable(void *); 406 extern int softmac_datapath_switch(softmac_t *, boolean_t, boolean_t); 407 408 extern void softmac_wput_data(softmac_upper_t *, mblk_t *); 409 extern void softmac_wput_nondata(softmac_upper_t *, mblk_t *); 410 extern void softmac_upperstream_close(softmac_upper_t *); 411 412 #ifdef __cplusplus 413 } 414 #endif 415 416 #endif /* _SYS_SOFTMAC_IMPL_H */ 417