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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/errno.h> 28 #include <sys/sysmacros.h> 29 #include <sys/param.h> 30 #include <sys/machsystm.h> 31 #include <sys/stream.h> 32 #include <sys/strsubr.h> 33 #include <sys/kmem.h> 34 #include <sys/conf.h> 35 #include <sys/devops.h> 36 #include <sys/ksynch.h> 37 #include <sys/stat.h> 38 #include <sys/modctl.h> 39 #include <sys/debug.h> 40 #include <sys/ethernet.h> 41 #include <sys/ddi.h> 42 #include <sys/sunddi.h> 43 #include <sys/strsun.h> 44 #include <sys/note.h> 45 #include <sys/mac_provider.h> 46 #include <sys/mac_ether.h> 47 #include <sys/ldc.h> 48 #include <sys/mach_descrip.h> 49 #include <sys/mdeg.h> 50 #include <net/if.h> 51 #include <sys/vnet.h> 52 #include <sys/vio_mailbox.h> 53 #include <sys/vio_common.h> 54 #include <sys/vnet_common.h> 55 #include <sys/vnet_mailbox.h> 56 #include <sys/vio_util.h> 57 #include <sys/vnet_gen.h> 58 #include <sys/atomic.h> 59 #include <sys/callb.h> 60 #include <sys/sdt.h> 61 #include <sys/intr.h> 62 #include <sys/pattr.h> 63 #include <sys/vlan.h> 64 65 /* 66 * Implementation of the mac provider functionality for vnet using the 67 * generic(default) transport layer of sun4v Logical Domain Channels(LDC). 68 */ 69 70 /* Entry Points */ 71 int vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip, 72 const uint8_t *macaddr, void **vgenhdl); 73 int vgen_init_mdeg(void *arg); 74 void vgen_uninit(void *arg); 75 int vgen_dds_tx(void *arg, void *dmsg); 76 int vgen_enable_intr(void *arg); 77 int vgen_disable_intr(void *arg); 78 mblk_t *vgen_rx_poll(void *arg, int bytes_to_pickup); 79 static int vgen_start(void *arg); 80 static void vgen_stop(void *arg); 81 static mblk_t *vgen_tx(void *arg, mblk_t *mp); 82 static int vgen_multicst(void *arg, boolean_t add, 83 const uint8_t *mca); 84 static int vgen_promisc(void *arg, boolean_t on); 85 static int vgen_unicst(void *arg, const uint8_t *mca); 86 static int vgen_stat(void *arg, uint_t stat, uint64_t *val); 87 static void vgen_ioctl(void *arg, queue_t *q, mblk_t *mp); 88 #ifdef VNET_IOC_DEBUG 89 static int vgen_force_link_state(vgen_port_t *portp, int link_state); 90 #endif 91 92 /* Port/LDC Configuration */ 93 static int vgen_read_mdprops(vgen_t *vgenp); 94 static void vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 95 static void vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, 96 mde_cookie_t node); 97 static void vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 98 uint32_t *mtu); 99 static void vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 100 boolean_t *pls); 101 static void vgen_detach_ports(vgen_t *vgenp); 102 static void vgen_port_detach(vgen_port_t *portp); 103 static void vgen_port_list_insert(vgen_port_t *portp); 104 static void vgen_port_list_remove(vgen_port_t *portp); 105 static vgen_port_t *vgen_port_lookup(vgen_portlist_t *plistp, 106 int port_num); 107 static int vgen_mdeg_reg(vgen_t *vgenp); 108 static void vgen_mdeg_unreg(vgen_t *vgenp); 109 static int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp); 110 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp); 111 static int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 112 static int vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp, 113 mde_cookie_t mdex); 114 static int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex); 115 static int vgen_port_attach(vgen_port_t *portp); 116 static void vgen_port_detach_mdeg(vgen_port_t *portp); 117 static int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, 118 mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex); 119 static uint64_t vgen_port_stat(vgen_port_t *portp, uint_t stat); 120 static void vgen_port_reset(vgen_port_t *portp); 121 static void vgen_reset_vsw_port(vgen_t *vgenp); 122 static int vgen_ldc_reset(vgen_ldc_t *ldcp, vgen_caller_t caller); 123 static void vgen_ldc_up(vgen_ldc_t *ldcp); 124 static int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id); 125 static void vgen_ldc_detach(vgen_ldc_t *ldcp); 126 static void vgen_port_init(vgen_port_t *portp); 127 static void vgen_port_uninit(vgen_port_t *portp); 128 static int vgen_ldc_init(vgen_ldc_t *ldcp); 129 static void vgen_ldc_uninit(vgen_ldc_t *ldcp); 130 static uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat); 131 132 /* I/O Processing */ 133 static int vgen_portsend(vgen_port_t *portp, mblk_t *mp); 134 static int vgen_ldcsend(void *arg, mblk_t *mp); 135 static void vgen_ldcsend_pkt(void *arg, mblk_t *mp); 136 static uint_t vgen_ldc_cb(uint64_t event, caddr_t arg); 137 static void vgen_tx_watchdog(void *arg); 138 139 /* Dring Configuration */ 140 static int vgen_create_dring(vgen_ldc_t *ldcp); 141 static void vgen_destroy_dring(vgen_ldc_t *ldcp); 142 static int vgen_map_dring(vgen_ldc_t *ldcp, void *pkt); 143 static void vgen_unmap_dring(vgen_ldc_t *ldcp); 144 145 /* VIO Message Processing */ 146 static int vgen_handshake(vgen_ldc_t *ldcp); 147 static int vgen_handshake_done(vgen_ldc_t *ldcp); 148 static vgen_ldc_t *vh_nextphase(vgen_ldc_t *ldcp); 149 static int vgen_handshake_phase2(vgen_ldc_t *ldcp); 150 static int vgen_handshake_phase3(vgen_ldc_t *ldcp); 151 static void vgen_setup_handshake_params(vgen_ldc_t *ldcp); 152 static int vgen_send_version_negotiate(vgen_ldc_t *ldcp); 153 static int vgen_send_attr_info(vgen_ldc_t *ldcp); 154 static int vgen_send_rx_dring_reg(vgen_ldc_t *ldcp); 155 static int vgen_send_tx_dring_reg(vgen_ldc_t *ldcp); 156 static void vgen_init_dring_reg_msg(vgen_ldc_t *ldcp, vio_dring_reg_msg_t *msg, 157 uint8_t option); 158 static int vgen_send_rdx_info(vgen_ldc_t *ldcp); 159 static int vgen_send_dringdata(vgen_ldc_t *ldcp, uint32_t start, int32_t end); 160 static int vgen_send_mcast_info(vgen_ldc_t *ldcp); 161 static int vgen_handle_version_negotiate(vgen_ldc_t *ldcp, 162 vio_msg_tag_t *tagp); 163 static int vgen_handle_attr_msg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 164 static int vgen_handle_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg); 165 static int vgen_handle_attr_ack(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg); 166 static int vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 167 static int vgen_handle_dring_reg_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 168 static int vgen_handle_dring_reg_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 169 static int vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 170 static int vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 171 static int vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 172 static void vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen); 173 static int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, 174 uint32_t msglen); 175 static void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 176 static int vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 177 static void vgen_handle_evt_up(vgen_ldc_t *ldcp); 178 static int vgen_process_reset(vgen_ldc_t *ldcp, int flags); 179 static int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 180 static void vgen_hwatchdog(void *arg); 181 static void vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp); 182 static void vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp); 183 static void vgen_link_update(vgen_t *vgenp, link_state_t link_state); 184 185 /* VLANs */ 186 static void vgen_vlan_read_ids(void *arg, int type, md_t *mdp, 187 mde_cookie_t node, uint16_t *pvidp, uint16_t **vidspp, 188 uint16_t *nvidsp, uint16_t *default_idp); 189 static void vgen_vlan_create_hash(vgen_port_t *portp); 190 static void vgen_vlan_destroy_hash(vgen_port_t *portp); 191 static void vgen_vlan_add_ids(vgen_port_t *portp); 192 static void vgen_vlan_remove_ids(vgen_port_t *portp); 193 static boolean_t vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid); 194 static boolean_t vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, 195 uint16_t *vidp); 196 static mblk_t *vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, 197 boolean_t is_tagged, uint16_t vid); 198 static void vgen_vlan_unaware_port_reset(vgen_port_t *portp); 199 static void vgen_reset_vlan_unaware_ports(vgen_t *vgenp); 200 201 /* Exported functions */ 202 int vgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller); 203 int vgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller); 204 void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen); 205 void vgen_destroy_rxpools(void *arg); 206 207 /* Externs */ 208 extern void vnet_dds_rx(void *arg, void *dmsg); 209 extern void vnet_dds_cleanup_hio(vnet_t *vnetp); 210 extern int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu); 211 extern void vnet_link_update(vnet_t *vnetp, link_state_t link_state); 212 extern int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen, 213 boolean_t caller_holds_lock); 214 extern void vgen_stop_msg_thread(vgen_ldc_t *ldcp); 215 extern int vgen_create_tx_dring(vgen_ldc_t *ldcp); 216 extern void vgen_destroy_tx_dring(vgen_ldc_t *ldcp); 217 extern int vgen_map_rx_dring(vgen_ldc_t *ldcp, void *pkt); 218 extern void vgen_unmap_rx_dring(vgen_ldc_t *ldcp); 219 extern int vgen_create_rx_dring(vgen_ldc_t *ldcp); 220 extern void vgen_destroy_rx_dring(vgen_ldc_t *ldcp); 221 extern int vgen_map_tx_dring(vgen_ldc_t *ldcp, void *pkt); 222 extern void vgen_unmap_tx_dring(vgen_ldc_t *ldcp); 223 extern int vgen_map_data(vgen_ldc_t *ldcp, void *pkt); 224 extern int vgen_handle_dringdata_shm(void *arg1, void *arg2); 225 extern int vgen_handle_dringdata(void *arg1, void *arg2); 226 extern int vgen_dringsend_shm(void *arg, mblk_t *mp); 227 extern int vgen_dringsend(void *arg, mblk_t *mp); 228 extern void vgen_ldc_msg_worker(void *arg); 229 extern int vgen_send_dringack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, 230 uint32_t start, int32_t end, uint8_t pstate); 231 extern mblk_t *vgen_poll_rcv_shm(vgen_ldc_t *ldcp, int bytes_to_pickup); 232 extern mblk_t *vgen_poll_rcv(vgen_ldc_t *ldcp, int bytes_to_pickup); 233 extern int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp); 234 235 #define VGEN_PRI_ETH_DEFINED(vgenp) ((vgenp)->pri_num_types != 0) 236 237 #define LDC_LOCK(ldcp) \ 238 mutex_enter(&((ldcp)->cblock));\ 239 mutex_enter(&((ldcp)->rxlock));\ 240 mutex_enter(&((ldcp)->wrlock));\ 241 mutex_enter(&((ldcp)->txlock));\ 242 mutex_enter(&((ldcp)->tclock)); 243 #define LDC_UNLOCK(ldcp) \ 244 mutex_exit(&((ldcp)->tclock));\ 245 mutex_exit(&((ldcp)->txlock));\ 246 mutex_exit(&((ldcp)->wrlock));\ 247 mutex_exit(&((ldcp)->rxlock));\ 248 mutex_exit(&((ldcp)->cblock)); 249 250 #define VGEN_VER_EQ(ldcp, major, minor) \ 251 ((ldcp)->local_hparams.ver_major == (major) && \ 252 (ldcp)->local_hparams.ver_minor == (minor)) 253 254 #define VGEN_VER_LT(ldcp, major, minor) \ 255 (((ldcp)->local_hparams.ver_major < (major)) || \ 256 ((ldcp)->local_hparams.ver_major == (major) && \ 257 (ldcp)->local_hparams.ver_minor < (minor))) 258 259 #define VGEN_VER_GTEQ(ldcp, major, minor) \ 260 (((ldcp)->local_hparams.ver_major > (major)) || \ 261 ((ldcp)->local_hparams.ver_major == (major) && \ 262 (ldcp)->local_hparams.ver_minor >= (minor))) 263 264 /* 265 * Property names 266 */ 267 static char macaddr_propname[] = "mac-address"; 268 static char rmacaddr_propname[] = "remote-mac-address"; 269 static char channel_propname[] = "channel-endpoint"; 270 static char reg_propname[] = "reg"; 271 static char port_propname[] = "port"; 272 static char swport_propname[] = "switch-port"; 273 static char id_propname[] = "id"; 274 static char vdev_propname[] = "virtual-device"; 275 static char vnet_propname[] = "network"; 276 static char pri_types_propname[] = "priority-ether-types"; 277 static char vgen_pvid_propname[] = "port-vlan-id"; 278 static char vgen_vid_propname[] = "vlan-id"; 279 static char vgen_dvid_propname[] = "default-vlan-id"; 280 static char port_pvid_propname[] = "remote-port-vlan-id"; 281 static char port_vid_propname[] = "remote-vlan-id"; 282 static char vgen_mtu_propname[] = "mtu"; 283 static char vgen_linkprop_propname[] = "linkprop"; 284 285 /* 286 * VIO Protocol Version Info: 287 * 288 * The version specified below represents the version of protocol currently 289 * supported in the driver. It means the driver can negotiate with peers with 290 * versions <= this version. Here is a summary of the feature(s) that are 291 * supported at each version of the protocol: 292 * 293 * 1.0 Basic VIO protocol. 294 * 1.1 vDisk protocol update (no virtual network update). 295 * 1.2 Support for priority frames (priority-ether-types). 296 * 1.3 VLAN and HybridIO support. 297 * 1.4 Jumbo Frame support. 298 * 1.5 Link State Notification support with optional support 299 * for Physical Link information. 300 * 1.6 Support for RxDringData mode. 301 */ 302 static vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 6} }; 303 304 /* Tunables */ 305 uint32_t vgen_hwd_interval = 5; /* handshake watchdog freq in sec */ 306 uint32_t vgen_ldcwr_retries = 10; /* max # of ldc_write() retries */ 307 uint32_t vgen_ldcup_retries = 5; /* max # of ldc_up() retries */ 308 uint32_t vgen_ldccl_retries = 5; /* max # of ldc_close() retries */ 309 uint32_t vgen_tx_delay = 0x30; /* delay when tx descr not available */ 310 uint32_t vgen_ldc_mtu = VGEN_LDC_MTU; /* ldc mtu */ 311 uint32_t vgen_txwd_interval = VGEN_TXWD_INTERVAL; /* watchdog freq in msec */ 312 uint32_t vgen_txwd_timeout = VGEN_TXWD_TIMEOUT; /* tx timeout in msec */ 313 314 /* 315 * Max # of channel resets allowed during handshake. 316 */ 317 uint32_t vgen_ldc_max_resets = 5; 318 319 /* 320 * We provide a tunable to enable RxDringData mode for versions >= 1.6. By 321 * default, this tunable is set to 1 (VIO_TX_DRING). To enable RxDringData mode 322 * set this tunable to 4 (VIO_RX_DRING_DATA). 323 * See comments in vsw.c for details on the dring modes supported. 324 */ 325 uint8_t vgen_dring_mode = VIO_TX_DRING; 326 327 /* 328 * In RxDringData mode, # of buffers is determined by multiplying the # of 329 * descriptors with the factor below. Note that the factor must be > 1; i.e, 330 * the # of buffers must always be > # of descriptors. This is needed because, 331 * while the shared memory buffers are sent up the stack on the receiver, the 332 * sender needs additional buffers that can be used for further transmits. 333 * See vgen_create_rx_dring() for details. 334 */ 335 uint32_t vgen_nrbufs_factor = 2; 336 337 /* 338 * Retry delay used while destroying rx mblk pools. Used in both Dring modes. 339 */ 340 int vgen_rxpool_cleanup_delay = 100000; /* 100ms */ 341 342 /* 343 * Delay when rx descr not ready; used in TxDring mode only. 344 */ 345 uint32_t vgen_recv_delay = 1; 346 347 /* 348 * Retry when rx descr not ready; used in TxDring mode only. 349 */ 350 uint32_t vgen_recv_retries = 10; 351 352 /* 353 * Max # of packets accumulated prior to sending them up. It is best 354 * to keep this at 60% of the number of receive buffers. Used in TxDring mode 355 * by the msg worker thread. Used in RxDringData mode while in interrupt mode 356 * (not used in polled mode). 357 */ 358 uint32_t vgen_chain_len = (VGEN_NRBUFS * 0.6); 359 360 /* 361 * Internal tunables for receive buffer pools, that is, the size and number of 362 * mblks for each pool. At least 3 sizes must be specified if these are used. 363 * The sizes must be specified in increasing order. Non-zero value of the first 364 * size will be used as a hint to use these values instead of the algorithm 365 * that determines the sizes based on MTU. Used in TxDring mode only. 366 */ 367 uint32_t vgen_rbufsz1 = 0; 368 uint32_t vgen_rbufsz2 = 0; 369 uint32_t vgen_rbufsz3 = 0; 370 uint32_t vgen_rbufsz4 = 0; 371 372 uint32_t vgen_nrbufs1 = VGEN_NRBUFS; 373 uint32_t vgen_nrbufs2 = VGEN_NRBUFS; 374 uint32_t vgen_nrbufs3 = VGEN_NRBUFS; 375 uint32_t vgen_nrbufs4 = VGEN_NRBUFS; 376 377 /* 378 * In the absence of "priority-ether-types" property in MD, the following 379 * internal tunable can be set to specify a single priority ethertype. 380 */ 381 uint64_t vgen_pri_eth_type = 0; 382 383 /* 384 * Number of transmit priority buffers that are preallocated per device. 385 * This number is chosen to be a small value to throttle transmission 386 * of priority packets. Note: Must be a power of 2 for vio_create_mblks(). 387 */ 388 uint32_t vgen_pri_tx_nmblks = 64; 389 390 uint32_t vgen_vlan_nchains = 4; /* # of chains in vlan id hash table */ 391 392 /* 393 * Matching criteria passed to the MDEG to register interest 394 * in changes to 'virtual-device' nodes (i.e. vnet nodes) identified 395 * by their 'name' and 'cfg-handle' properties. 396 */ 397 static md_prop_match_t vdev_prop_match[] = { 398 { MDET_PROP_STR, "name" }, 399 { MDET_PROP_VAL, "cfg-handle" }, 400 { MDET_LIST_END, NULL } 401 }; 402 403 static mdeg_node_match_t vdev_match = { "virtual-device", 404 vdev_prop_match }; 405 406 /* MD update matching structure */ 407 static md_prop_match_t vport_prop_match[] = { 408 { MDET_PROP_VAL, "id" }, 409 { MDET_LIST_END, NULL } 410 }; 411 412 static mdeg_node_match_t vport_match = { "virtual-device-port", 413 vport_prop_match }; 414 415 /* Template for matching a particular vnet instance */ 416 static mdeg_prop_spec_t vgen_prop_template[] = { 417 { MDET_PROP_STR, "name", "network" }, 418 { MDET_PROP_VAL, "cfg-handle", NULL }, 419 { MDET_LIST_END, NULL, NULL } 420 }; 421 422 #define VGEN_SET_MDEG_PROP_INST(specp, val) (specp)[1].ps_val = (val) 423 424 static int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp); 425 426 #ifdef VNET_IOC_DEBUG 427 #define VGEN_M_CALLBACK_FLAGS (MC_IOCTL) 428 #else 429 #define VGEN_M_CALLBACK_FLAGS (0) 430 #endif 431 432 static mac_callbacks_t vgen_m_callbacks = { 433 VGEN_M_CALLBACK_FLAGS, 434 vgen_stat, 435 vgen_start, 436 vgen_stop, 437 vgen_promisc, 438 vgen_multicst, 439 vgen_unicst, 440 vgen_tx, 441 NULL, 442 vgen_ioctl, 443 NULL, 444 NULL 445 }; 446 447 /* Externs */ 448 extern pri_t maxclsyspri; 449 extern proc_t p0; 450 extern uint32_t vnet_ethermtu; 451 extern uint16_t vnet_default_vlan_id; 452 453 #ifdef DEBUG 454 455 #define DEBUG_PRINTF vgen_debug_printf 456 457 extern int vnet_dbglevel; 458 459 void vgen_debug_printf(const char *fname, vgen_t *vgenp, 460 vgen_ldc_t *ldcp, const char *fmt, ...); 461 462 /* -1 for all LDCs info, or ldc_id for a specific LDC info */ 463 int vgendbg_ldcid = -1; 464 465 /* Flags to simulate error conditions for debugging */ 466 int vgen_inject_err_flag = 0; 467 468 469 boolean_t 470 vgen_inject_error(vgen_ldc_t *ldcp, int error) 471 { 472 if ((vgendbg_ldcid == ldcp->ldc_id) && 473 (vgen_inject_err_flag & error)) { 474 return (B_TRUE); 475 } 476 return (B_FALSE); 477 } 478 479 #endif 480 481 /* 482 * vgen_init() is called by an instance of vnet driver to initialize the 483 * corresponding generic transport layer. This layer uses Logical Domain 484 * Channels (LDCs) to communicate with the virtual switch in the service domain 485 * and also with peer vnets in other guest domains in the system. 486 * 487 * Arguments: 488 * vnetp: an opaque pointer to the vnet instance 489 * regprop: frame to be transmitted 490 * vnetdip: dip of the vnet device 491 * macaddr: mac address of the vnet device 492 * 493 * Returns: 494 * Sucess: a handle to the vgen instance (vgen_t) 495 * Failure: NULL 496 */ 497 int 498 vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip, 499 const uint8_t *macaddr, void **vgenhdl) 500 { 501 vgen_t *vgenp; 502 int instance; 503 int rv; 504 char qname[TASKQ_NAMELEN]; 505 506 if ((vnetp == NULL) || (vnetdip == NULL)) 507 return (DDI_FAILURE); 508 509 instance = ddi_get_instance(vnetdip); 510 511 DBG1(NULL, NULL, "vnet(%d): enter\n", instance); 512 513 vgenp = kmem_zalloc(sizeof (vgen_t), KM_SLEEP); 514 515 vgenp->vnetp = vnetp; 516 vgenp->instance = instance; 517 vgenp->regprop = regprop; 518 vgenp->vnetdip = vnetdip; 519 bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL); 520 vgenp->phys_link_state = LINK_STATE_UNKNOWN; 521 522 /* allocate multicast table */ 523 vgenp->mctab = kmem_zalloc(VGEN_INIT_MCTAB_SIZE * 524 sizeof (struct ether_addr), KM_SLEEP); 525 vgenp->mccount = 0; 526 vgenp->mcsize = VGEN_INIT_MCTAB_SIZE; 527 528 mutex_init(&vgenp->lock, NULL, MUTEX_DRIVER, NULL); 529 rw_init(&vgenp->vgenports.rwlock, NULL, RW_DRIVER, NULL); 530 531 (void) snprintf(qname, TASKQ_NAMELEN, "rxpool_taskq%d", 532 instance); 533 if ((vgenp->rxp_taskq = ddi_taskq_create(vnetdip, qname, 1, 534 TASKQ_DEFAULTPRI, 0)) == NULL) { 535 cmn_err(CE_WARN, "!vnet%d: Unable to create rx pool task queue", 536 instance); 537 goto vgen_init_fail; 538 } 539 540 rv = vgen_read_mdprops(vgenp); 541 if (rv != 0) { 542 goto vgen_init_fail; 543 } 544 *vgenhdl = (void *)vgenp; 545 546 DBG1(NULL, NULL, "vnet(%d): exit\n", instance); 547 return (DDI_SUCCESS); 548 549 vgen_init_fail: 550 rw_destroy(&vgenp->vgenports.rwlock); 551 mutex_destroy(&vgenp->lock); 552 kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE * 553 sizeof (struct ether_addr)); 554 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 555 kmem_free(vgenp->pri_types, 556 sizeof (uint16_t) * vgenp->pri_num_types); 557 (void) vio_destroy_mblks(vgenp->pri_tx_vmp); 558 } 559 if (vgenp->rxp_taskq != NULL) { 560 ddi_taskq_destroy(vgenp->rxp_taskq); 561 vgenp->rxp_taskq = NULL; 562 } 563 KMEM_FREE(vgenp); 564 return (DDI_FAILURE); 565 } 566 567 int 568 vgen_init_mdeg(void *arg) 569 { 570 vgen_t *vgenp = (vgen_t *)arg; 571 572 /* register with MD event generator */ 573 return (vgen_mdeg_reg(vgenp)); 574 } 575 576 /* 577 * Called by vnet to undo the initializations done by vgen_init(). 578 * The handle provided by generic transport during vgen_init() is the argument. 579 */ 580 void 581 vgen_uninit(void *arg) 582 { 583 vgen_t *vgenp = (vgen_t *)arg; 584 585 if (vgenp == NULL) { 586 return; 587 } 588 589 DBG1(vgenp, NULL, "enter\n"); 590 591 /* Unregister with MD event generator */ 592 vgen_mdeg_unreg(vgenp); 593 594 mutex_enter(&vgenp->lock); 595 596 /* 597 * Detach all ports from the device; note that the device should have 598 * been unplumbed by this time (See vnet_unattach() for the sequence) 599 * and thus vgen_stop() has already been invoked on all the ports. 600 */ 601 vgen_detach_ports(vgenp); 602 603 /* 604 * We now destroy the taskq used to clean up rx mblk pools that 605 * couldn't be destroyed when the ports/channels were detached. 606 * We implicitly wait for those tasks to complete in 607 * ddi_taskq_destroy(). 608 */ 609 if (vgenp->rxp_taskq != NULL) { 610 ddi_taskq_destroy(vgenp->rxp_taskq); 611 vgenp->rxp_taskq = NULL; 612 } 613 614 /* Free multicast table */ 615 kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr)); 616 617 /* Free pri_types table */ 618 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 619 kmem_free(vgenp->pri_types, 620 sizeof (uint16_t) * vgenp->pri_num_types); 621 (void) vio_destroy_mblks(vgenp->pri_tx_vmp); 622 } 623 624 mutex_exit(&vgenp->lock); 625 rw_destroy(&vgenp->vgenports.rwlock); 626 mutex_destroy(&vgenp->lock); 627 628 DBG1(vgenp, NULL, "exit\n"); 629 KMEM_FREE(vgenp); 630 } 631 632 /* enable transmit/receive for the device */ 633 int 634 vgen_start(void *arg) 635 { 636 vgen_port_t *portp = (vgen_port_t *)arg; 637 vgen_t *vgenp = portp->vgenp; 638 639 DBG1(vgenp, NULL, "enter\n"); 640 mutex_enter(&portp->lock); 641 vgen_port_init(portp); 642 portp->flags |= VGEN_STARTED; 643 mutex_exit(&portp->lock); 644 DBG1(vgenp, NULL, "exit\n"); 645 646 return (DDI_SUCCESS); 647 } 648 649 /* stop transmit/receive */ 650 void 651 vgen_stop(void *arg) 652 { 653 vgen_port_t *portp = (vgen_port_t *)arg; 654 vgen_t *vgenp = portp->vgenp; 655 656 DBG1(vgenp, NULL, "enter\n"); 657 658 mutex_enter(&portp->lock); 659 if (portp->flags & VGEN_STARTED) { 660 vgen_port_uninit(portp); 661 portp->flags &= ~(VGEN_STARTED); 662 } 663 mutex_exit(&portp->lock); 664 DBG1(vgenp, NULL, "exit\n"); 665 666 } 667 668 /* vgen transmit function */ 669 static mblk_t * 670 vgen_tx(void *arg, mblk_t *mp) 671 { 672 vgen_port_t *portp; 673 int status; 674 675 portp = (vgen_port_t *)arg; 676 status = vgen_portsend(portp, mp); 677 if (status != VGEN_SUCCESS) { 678 /* failure */ 679 return (mp); 680 } 681 /* success */ 682 return (NULL); 683 } 684 685 /* 686 * This function provides any necessary tagging/untagging of the frames 687 * that are being transmitted over the port. It first verifies the vlan 688 * membership of the destination(port) and drops the packet if the 689 * destination doesn't belong to the given vlan. 690 * 691 * Arguments: 692 * portp: port over which the frames should be transmitted 693 * mp: frame to be transmitted 694 * is_tagged: 695 * B_TRUE: indicates frame header contains the vlan tag already. 696 * B_FALSE: indicates frame is untagged. 697 * vid: vlan in which the frame should be transmitted. 698 * 699 * Returns: 700 * Sucess: frame(mblk_t *) after doing the necessary tag/untag. 701 * Failure: NULL 702 */ 703 static mblk_t * 704 vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, boolean_t is_tagged, 705 uint16_t vid) 706 { 707 vgen_t *vgenp; 708 boolean_t dst_tagged; 709 int rv; 710 711 vgenp = portp->vgenp; 712 713 /* 714 * If the packet is going to a vnet: 715 * Check if the destination vnet is in the same vlan. 716 * Check the frame header if tag or untag is needed. 717 * 718 * We do not check the above conditions if the packet is going to vsw: 719 * vsw must be present implicitly in all the vlans that a vnet device 720 * is configured into; even if vsw itself is not assigned to those 721 * vlans as an interface. For instance, the packet might be destined 722 * to another vnet(indirectly through vsw) or to an external host 723 * which is in the same vlan as this vnet and vsw itself may not be 724 * present in that vlan. Similarly packets going to vsw must be 725 * always tagged(unless in the default-vlan) if not already tagged, 726 * as we do not know the final destination. This is needed because 727 * vsw must always invoke its switching function only after tagging 728 * the packet; otherwise after switching function determines the 729 * destination we cannot figure out if the destination belongs to the 730 * the same vlan that the frame originated from and if it needs tag/ 731 * untag. Note that vsw will tag the packet itself when it receives 732 * it over the channel from a client if needed. However, that is 733 * needed only in the case of vlan unaware clients such as obp or 734 * earlier versions of vnet. 735 * 736 */ 737 if (portp != vgenp->vsw_portp) { 738 /* 739 * Packet going to a vnet. Check if the destination vnet is in 740 * the same vlan. Then check the frame header if tag/untag is 741 * needed. 742 */ 743 rv = vgen_vlan_lookup(portp->vlan_hashp, vid); 744 if (rv == B_FALSE) { 745 /* drop the packet */ 746 freemsg(mp); 747 return (NULL); 748 } 749 750 /* is the destination tagged or untagged in this vlan? */ 751 (vid == portp->pvid) ? (dst_tagged = B_FALSE) : 752 (dst_tagged = B_TRUE); 753 754 if (is_tagged == dst_tagged) { 755 /* no tagging/untagging needed */ 756 return (mp); 757 } 758 759 if (is_tagged == B_TRUE) { 760 /* frame is tagged; destination needs untagged */ 761 mp = vnet_vlan_remove_tag(mp); 762 return (mp); 763 } 764 765 /* (is_tagged == B_FALSE): fallthru to tag tx packet: */ 766 } 767 768 /* 769 * Packet going to a vnet needs tagging. 770 * OR 771 * If the packet is going to vsw, then it must be tagged in all cases: 772 * unknown unicast, broadcast/multicast or to vsw interface. 773 */ 774 775 if (is_tagged == B_FALSE) { 776 mp = vnet_vlan_insert_tag(mp, vid); 777 } 778 779 return (mp); 780 } 781 782 /* transmit packets over the given port */ 783 static int 784 vgen_portsend(vgen_port_t *portp, mblk_t *mp) 785 { 786 vgen_ldc_t *ldcp; 787 int status; 788 int rv = VGEN_SUCCESS; 789 vgen_t *vgenp = portp->vgenp; 790 vnet_t *vnetp = vgenp->vnetp; 791 boolean_t is_tagged; 792 boolean_t dec_refcnt = B_FALSE; 793 uint16_t vlan_id; 794 struct ether_header *ehp; 795 796 if (portp == NULL) { 797 return (VGEN_FAILURE); 798 } 799 800 if (portp->use_vsw_port) { 801 (void) atomic_inc_32(&vgenp->vsw_port_refcnt); 802 portp = portp->vgenp->vsw_portp; 803 ASSERT(portp != NULL); 804 dec_refcnt = B_TRUE; 805 } 806 807 /* 808 * Determine the vlan id that the frame belongs to. 809 */ 810 ehp = (struct ether_header *)mp->b_rptr; 811 is_tagged = vgen_frame_lookup_vid(vnetp, ehp, &vlan_id); 812 813 if (vlan_id == vnetp->default_vlan_id) { 814 815 /* Frames in default vlan must be untagged */ 816 ASSERT(is_tagged == B_FALSE); 817 818 /* 819 * If the destination is a vnet-port verify it belongs to the 820 * default vlan; otherwise drop the packet. We do not need 821 * this check for vsw-port, as it should implicitly belong to 822 * this vlan; see comments in vgen_vlan_frame_fixtag(). 823 */ 824 if (portp != vgenp->vsw_portp && 825 portp->pvid != vnetp->default_vlan_id) { 826 freemsg(mp); 827 goto portsend_ret; 828 } 829 830 } else { /* frame not in default-vlan */ 831 832 mp = vgen_vlan_frame_fixtag(portp, mp, is_tagged, vlan_id); 833 if (mp == NULL) { 834 goto portsend_ret; 835 } 836 837 } 838 839 ldcp = portp->ldcp; 840 status = ldcp->tx(ldcp, mp); 841 842 if (status != VGEN_TX_SUCCESS) { 843 rv = VGEN_FAILURE; 844 } 845 846 portsend_ret: 847 if (dec_refcnt == B_TRUE) { 848 (void) atomic_dec_32(&vgenp->vsw_port_refcnt); 849 } 850 return (rv); 851 } 852 853 /* 854 * Wrapper function to transmit normal and/or priority frames over the channel. 855 */ 856 static int 857 vgen_ldcsend(void *arg, mblk_t *mp) 858 { 859 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 860 int status; 861 struct ether_header *ehp; 862 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 863 uint32_t num_types; 864 uint16_t *types; 865 int i; 866 867 ASSERT(VGEN_PRI_ETH_DEFINED(vgenp)); 868 869 num_types = vgenp->pri_num_types; 870 types = vgenp->pri_types; 871 ehp = (struct ether_header *)mp->b_rptr; 872 873 for (i = 0; i < num_types; i++) { 874 875 if (ehp->ether_type == types[i]) { 876 /* priority frame, use pri tx function */ 877 vgen_ldcsend_pkt(ldcp, mp); 878 return (VGEN_SUCCESS); 879 } 880 881 } 882 883 if (ldcp->tx_dringdata == NULL) { 884 freemsg(mp); 885 return (VGEN_SUCCESS); 886 } 887 888 status = ldcp->tx_dringdata(ldcp, mp); 889 return (status); 890 } 891 892 /* 893 * This function transmits the frame in the payload of a raw data 894 * (VIO_PKT_DATA) message. Thus, it provides an Out-Of-Band path to 895 * send special frames with high priorities, without going through 896 * the normal data path which uses descriptor ring mechanism. 897 */ 898 static void 899 vgen_ldcsend_pkt(void *arg, mblk_t *mp) 900 { 901 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 902 vio_raw_data_msg_t *pkt; 903 mblk_t *bp; 904 mblk_t *nmp = NULL; 905 vio_mblk_t *vmp; 906 caddr_t dst; 907 uint32_t mblksz; 908 uint32_t size; 909 uint32_t nbytes; 910 int rv; 911 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 912 vgen_stats_t *statsp = &ldcp->stats; 913 914 /* drop the packet if ldc is not up or handshake is not done */ 915 if (ldcp->ldc_status != LDC_UP) { 916 (void) atomic_inc_32(&statsp->tx_pri_fail); 917 DWARN(vgenp, ldcp, "status(%d), dropping packet\n", 918 ldcp->ldc_status); 919 goto send_pkt_exit; 920 } 921 922 if (ldcp->hphase != VH_DONE) { 923 (void) atomic_inc_32(&statsp->tx_pri_fail); 924 DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n", 925 ldcp->hphase); 926 goto send_pkt_exit; 927 } 928 929 size = msgsize(mp); 930 931 /* frame size bigger than available payload len of raw data msg ? */ 932 if (size > (size_t)(ldcp->msglen - VIO_PKT_DATA_HDRSIZE)) { 933 (void) atomic_inc_32(&statsp->tx_pri_fail); 934 DWARN(vgenp, ldcp, "invalid size(%d)\n", size); 935 goto send_pkt_exit; 936 } 937 938 if (size < ETHERMIN) 939 size = ETHERMIN; 940 941 /* alloc space for a raw data message */ 942 vmp = vio_allocb(vgenp->pri_tx_vmp); 943 if (vmp == NULL) { 944 (void) atomic_inc_32(&statsp->tx_pri_fail); 945 DWARN(vgenp, ldcp, "vio_allocb failed\n"); 946 goto send_pkt_exit; 947 } else { 948 nmp = vmp->mp; 949 } 950 pkt = (vio_raw_data_msg_t *)nmp->b_rptr; 951 952 /* copy frame into the payload of raw data message */ 953 dst = (caddr_t)pkt->data; 954 for (bp = mp; bp != NULL; bp = bp->b_cont) { 955 mblksz = MBLKL(bp); 956 bcopy(bp->b_rptr, dst, mblksz); 957 dst += mblksz; 958 } 959 960 vmp->state = VIO_MBLK_HAS_DATA; 961 962 /* setup the raw data msg */ 963 pkt->tag.vio_msgtype = VIO_TYPE_DATA; 964 pkt->tag.vio_subtype = VIO_SUBTYPE_INFO; 965 pkt->tag.vio_subtype_env = VIO_PKT_DATA; 966 pkt->tag.vio_sid = ldcp->local_sid; 967 nbytes = VIO_PKT_DATA_HDRSIZE + size; 968 969 /* send the msg over ldc */ 970 rv = vgen_sendmsg(ldcp, (caddr_t)pkt, nbytes, B_FALSE); 971 if (rv != VGEN_SUCCESS) { 972 (void) atomic_inc_32(&statsp->tx_pri_fail); 973 DWARN(vgenp, ldcp, "Error sending priority frame\n"); 974 if (rv == ECONNRESET) { 975 (void) vgen_handle_evt_reset(ldcp, VGEN_OTHER); 976 } 977 goto send_pkt_exit; 978 } 979 980 /* update stats */ 981 (void) atomic_inc_64(&statsp->tx_pri_packets); 982 (void) atomic_add_64(&statsp->tx_pri_bytes, size); 983 984 send_pkt_exit: 985 if (nmp != NULL) 986 freemsg(nmp); 987 freemsg(mp); 988 } 989 990 /* 991 * enable/disable a multicast address 992 * note that the cblock of the ldc channel connected to the vsw is used for 993 * synchronization of the mctab. 994 */ 995 int 996 vgen_multicst(void *arg, boolean_t add, const uint8_t *mca) 997 { 998 vgen_t *vgenp; 999 vnet_mcast_msg_t mcastmsg; 1000 vio_msg_tag_t *tagp; 1001 vgen_port_t *portp; 1002 vgen_ldc_t *ldcp; 1003 struct ether_addr *addrp; 1004 int rv = DDI_FAILURE; 1005 uint32_t i; 1006 1007 portp = (vgen_port_t *)arg; 1008 vgenp = portp->vgenp; 1009 1010 if (portp->is_vsw_port != B_TRUE) { 1011 return (DDI_SUCCESS); 1012 } 1013 1014 addrp = (struct ether_addr *)mca; 1015 tagp = &mcastmsg.tag; 1016 bzero(&mcastmsg, sizeof (mcastmsg)); 1017 1018 ldcp = portp->ldcp; 1019 if (ldcp == NULL) { 1020 return (DDI_FAILURE); 1021 } 1022 1023 mutex_enter(&ldcp->cblock); 1024 1025 if (ldcp->hphase == VH_DONE) { 1026 /* 1027 * If handshake is done, send a msg to vsw to add/remove 1028 * the multicast address. Otherwise, we just update this 1029 * mcast address in our table and the table will be sync'd 1030 * with vsw when handshake completes. 1031 */ 1032 tagp->vio_msgtype = VIO_TYPE_CTRL; 1033 tagp->vio_subtype = VIO_SUBTYPE_INFO; 1034 tagp->vio_subtype_env = VNET_MCAST_INFO; 1035 tagp->vio_sid = ldcp->local_sid; 1036 bcopy(mca, &(mcastmsg.mca), ETHERADDRL); 1037 mcastmsg.set = add; 1038 mcastmsg.count = 1; 1039 if (vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (mcastmsg), 1040 B_FALSE) != VGEN_SUCCESS) { 1041 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 1042 rv = DDI_FAILURE; 1043 goto vgen_mcast_exit; 1044 } 1045 } 1046 1047 if (add) { 1048 1049 /* expand multicast table if necessary */ 1050 if (vgenp->mccount >= vgenp->mcsize) { 1051 struct ether_addr *newtab; 1052 uint32_t newsize; 1053 1054 1055 newsize = vgenp->mcsize * 2; 1056 1057 newtab = kmem_zalloc(newsize * 1058 sizeof (struct ether_addr), KM_NOSLEEP); 1059 if (newtab == NULL) 1060 goto vgen_mcast_exit; 1061 bcopy(vgenp->mctab, newtab, vgenp->mcsize * 1062 sizeof (struct ether_addr)); 1063 kmem_free(vgenp->mctab, 1064 vgenp->mcsize * sizeof (struct ether_addr)); 1065 1066 vgenp->mctab = newtab; 1067 vgenp->mcsize = newsize; 1068 } 1069 1070 /* add address to the table */ 1071 vgenp->mctab[vgenp->mccount++] = *addrp; 1072 1073 } else { 1074 1075 /* delete address from the table */ 1076 for (i = 0; i < vgenp->mccount; i++) { 1077 if (ether_cmp(addrp, &(vgenp->mctab[i])) == 0) { 1078 1079 /* 1080 * If there's more than one address in this 1081 * table, delete the unwanted one by moving 1082 * the last one in the list over top of it; 1083 * otherwise, just remove it. 1084 */ 1085 if (vgenp->mccount > 1) { 1086 vgenp->mctab[i] = 1087 vgenp->mctab[vgenp->mccount-1]; 1088 } 1089 vgenp->mccount--; 1090 break; 1091 } 1092 } 1093 } 1094 1095 rv = DDI_SUCCESS; 1096 1097 vgen_mcast_exit: 1098 1099 mutex_exit(&ldcp->cblock); 1100 return (rv); 1101 } 1102 1103 /* set or clear promiscuous mode on the device */ 1104 static int 1105 vgen_promisc(void *arg, boolean_t on) 1106 { 1107 _NOTE(ARGUNUSED(arg, on)) 1108 return (DDI_SUCCESS); 1109 } 1110 1111 /* set the unicast mac address of the device */ 1112 static int 1113 vgen_unicst(void *arg, const uint8_t *mca) 1114 { 1115 _NOTE(ARGUNUSED(arg, mca)) 1116 return (DDI_SUCCESS); 1117 } 1118 1119 /* get device statistics */ 1120 int 1121 vgen_stat(void *arg, uint_t stat, uint64_t *val) 1122 { 1123 vgen_port_t *portp = (vgen_port_t *)arg; 1124 1125 *val = vgen_port_stat(portp, stat); 1126 return (0); 1127 } 1128 1129 /* vgen internal functions */ 1130 /* detach all ports from the device */ 1131 static void 1132 vgen_detach_ports(vgen_t *vgenp) 1133 { 1134 vgen_port_t *portp; 1135 vgen_portlist_t *plistp; 1136 1137 plistp = &(vgenp->vgenports); 1138 WRITE_ENTER(&plistp->rwlock); 1139 while ((portp = plistp->headp) != NULL) { 1140 vgen_port_detach(portp); 1141 } 1142 RW_EXIT(&plistp->rwlock); 1143 } 1144 1145 /* 1146 * detach the given port. 1147 */ 1148 static void 1149 vgen_port_detach(vgen_port_t *portp) 1150 { 1151 vgen_t *vgenp; 1152 int port_num; 1153 1154 vgenp = portp->vgenp; 1155 port_num = portp->port_num; 1156 1157 DBG1(vgenp, NULL, "port(%d):enter\n", port_num); 1158 1159 /* 1160 * If this port is connected to the vswitch, then 1161 * potentially there could be ports that may be using 1162 * this port to transmit packets. To address this do 1163 * the following: 1164 * - First set vgenp->vsw_portp to NULL, so that 1165 * its not used after that. 1166 * - Then wait for the refcnt to go down to 0. 1167 * - Now we can safely detach this port. 1168 */ 1169 if (vgenp->vsw_portp == portp) { 1170 vgenp->vsw_portp = NULL; 1171 while (vgenp->vsw_port_refcnt > 0) { 1172 delay(drv_usectohz(vgen_tx_delay)); 1173 } 1174 (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0); 1175 } 1176 1177 if (portp->vhp != NULL) { 1178 vio_net_resource_unreg(portp->vhp); 1179 portp->vhp = NULL; 1180 } 1181 1182 vgen_vlan_destroy_hash(portp); 1183 1184 /* remove it from port list */ 1185 vgen_port_list_remove(portp); 1186 1187 /* detach channels from this port */ 1188 vgen_ldc_detach(portp->ldcp); 1189 1190 if (portp->num_ldcs != 0) { 1191 kmem_free(portp->ldc_ids, portp->num_ldcs * sizeof (uint64_t)); 1192 portp->num_ldcs = 0; 1193 } 1194 1195 mutex_destroy(&portp->lock); 1196 KMEM_FREE(portp); 1197 1198 DBG1(vgenp, NULL, "port(%d):exit\n", port_num); 1199 } 1200 1201 /* add a port to port list */ 1202 static void 1203 vgen_port_list_insert(vgen_port_t *portp) 1204 { 1205 vgen_portlist_t *plistp; 1206 vgen_t *vgenp; 1207 1208 vgenp = portp->vgenp; 1209 plistp = &(vgenp->vgenports); 1210 1211 if (plistp->headp == NULL) { 1212 plistp->headp = portp; 1213 } else { 1214 plistp->tailp->nextp = portp; 1215 } 1216 plistp->tailp = portp; 1217 portp->nextp = NULL; 1218 } 1219 1220 /* remove a port from port list */ 1221 static void 1222 vgen_port_list_remove(vgen_port_t *portp) 1223 { 1224 vgen_port_t *prevp; 1225 vgen_port_t *nextp; 1226 vgen_portlist_t *plistp; 1227 vgen_t *vgenp; 1228 1229 vgenp = portp->vgenp; 1230 1231 plistp = &(vgenp->vgenports); 1232 1233 if (plistp->headp == NULL) 1234 return; 1235 1236 if (portp == plistp->headp) { 1237 plistp->headp = portp->nextp; 1238 if (portp == plistp->tailp) 1239 plistp->tailp = plistp->headp; 1240 } else { 1241 for (prevp = plistp->headp; 1242 ((nextp = prevp->nextp) != NULL) && (nextp != portp); 1243 prevp = nextp) 1244 ; 1245 if (nextp == portp) { 1246 prevp->nextp = portp->nextp; 1247 } 1248 if (portp == plistp->tailp) 1249 plistp->tailp = prevp; 1250 } 1251 } 1252 1253 /* lookup a port in the list based on port_num */ 1254 static vgen_port_t * 1255 vgen_port_lookup(vgen_portlist_t *plistp, int port_num) 1256 { 1257 vgen_port_t *portp = NULL; 1258 1259 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 1260 if (portp->port_num == port_num) { 1261 break; 1262 } 1263 } 1264 1265 return (portp); 1266 } 1267 1268 static void 1269 vgen_port_init(vgen_port_t *portp) 1270 { 1271 /* Add the port to the specified vlans */ 1272 vgen_vlan_add_ids(portp); 1273 1274 /* Bring up the channel */ 1275 (void) vgen_ldc_init(portp->ldcp); 1276 } 1277 1278 static void 1279 vgen_port_uninit(vgen_port_t *portp) 1280 { 1281 vgen_ldc_uninit(portp->ldcp); 1282 1283 /* remove the port from vlans it has been assigned to */ 1284 vgen_vlan_remove_ids(portp); 1285 } 1286 1287 /* 1288 * Scan the machine description for this instance of vnet 1289 * and read its properties. Called only from vgen_init(). 1290 * Returns: 0 on success, 1 on failure. 1291 */ 1292 static int 1293 vgen_read_mdprops(vgen_t *vgenp) 1294 { 1295 vnet_t *vnetp = vgenp->vnetp; 1296 md_t *mdp = NULL; 1297 mde_cookie_t rootnode; 1298 mde_cookie_t *listp = NULL; 1299 uint64_t cfgh; 1300 char *name; 1301 int rv = 1; 1302 int num_nodes = 0; 1303 int num_devs = 0; 1304 int listsz = 0; 1305 int i; 1306 1307 if ((mdp = md_get_handle()) == NULL) { 1308 return (rv); 1309 } 1310 1311 num_nodes = md_node_count(mdp); 1312 ASSERT(num_nodes > 0); 1313 1314 listsz = num_nodes * sizeof (mde_cookie_t); 1315 listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP); 1316 1317 rootnode = md_root_node(mdp); 1318 1319 /* search for all "virtual_device" nodes */ 1320 num_devs = md_scan_dag(mdp, rootnode, 1321 md_find_name(mdp, vdev_propname), 1322 md_find_name(mdp, "fwd"), listp); 1323 if (num_devs <= 0) { 1324 goto vgen_readmd_exit; 1325 } 1326 1327 /* 1328 * Now loop through the list of virtual-devices looking for 1329 * devices with name "network" and for each such device compare 1330 * its instance with what we have from the 'reg' property to 1331 * find the right node in MD and then read all its properties. 1332 */ 1333 for (i = 0; i < num_devs; i++) { 1334 1335 if (md_get_prop_str(mdp, listp[i], "name", &name) != 0) { 1336 goto vgen_readmd_exit; 1337 } 1338 1339 /* is this a "network" device? */ 1340 if (strcmp(name, vnet_propname) != 0) 1341 continue; 1342 1343 if (md_get_prop_val(mdp, listp[i], "cfg-handle", &cfgh) != 0) { 1344 goto vgen_readmd_exit; 1345 } 1346 1347 /* is this the required instance of vnet? */ 1348 if (vgenp->regprop != cfgh) 1349 continue; 1350 1351 /* 1352 * Read the 'linkprop' property to know if this vnet 1353 * device should get physical link updates from vswitch. 1354 */ 1355 vgen_linkprop_read(vgenp, mdp, listp[i], 1356 &vnetp->pls_update); 1357 1358 /* 1359 * Read the mtu. Note that we set the mtu of vnet device within 1360 * this routine itself, after validating the range. 1361 */ 1362 vgen_mtu_read(vgenp, mdp, listp[i], &vnetp->mtu); 1363 if (vnetp->mtu < ETHERMTU || vnetp->mtu > VNET_MAX_MTU) { 1364 vnetp->mtu = ETHERMTU; 1365 } 1366 vgenp->max_frame_size = vnetp->mtu + 1367 sizeof (struct ether_header) + VLAN_TAGSZ; 1368 1369 /* read priority ether types */ 1370 vgen_read_pri_eth_types(vgenp, mdp, listp[i]); 1371 1372 /* read vlan id properties of this vnet instance */ 1373 vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, listp[i], 1374 &vnetp->pvid, &vnetp->vids, &vnetp->nvids, 1375 &vnetp->default_vlan_id); 1376 1377 rv = 0; 1378 break; 1379 } 1380 1381 vgen_readmd_exit: 1382 1383 kmem_free(listp, listsz); 1384 (void) md_fini_handle(mdp); 1385 return (rv); 1386 } 1387 1388 /* 1389 * Read vlan id properties of the given MD node. 1390 * Arguments: 1391 * arg: device argument(vnet device or a port) 1392 * type: type of arg; VGEN_LOCAL(vnet device) or VGEN_PEER(port) 1393 * mdp: machine description 1394 * node: md node cookie 1395 * 1396 * Returns: 1397 * pvidp: port-vlan-id of the node 1398 * vidspp: list of vlan-ids of the node 1399 * nvidsp: # of vlan-ids in the list 1400 * default_idp: default-vlan-id of the node(if node is vnet device) 1401 */ 1402 static void 1403 vgen_vlan_read_ids(void *arg, int type, md_t *mdp, mde_cookie_t node, 1404 uint16_t *pvidp, uint16_t **vidspp, uint16_t *nvidsp, 1405 uint16_t *default_idp) 1406 { 1407 vgen_t *vgenp; 1408 vnet_t *vnetp; 1409 vgen_port_t *portp; 1410 char *pvid_propname; 1411 char *vid_propname; 1412 uint_t nvids; 1413 uint32_t vids_size; 1414 int rv; 1415 int i; 1416 uint64_t *data; 1417 uint64_t val; 1418 int size; 1419 int inst; 1420 1421 if (type == VGEN_LOCAL) { 1422 1423 vgenp = (vgen_t *)arg; 1424 vnetp = vgenp->vnetp; 1425 pvid_propname = vgen_pvid_propname; 1426 vid_propname = vgen_vid_propname; 1427 inst = vnetp->instance; 1428 1429 } else if (type == VGEN_PEER) { 1430 1431 portp = (vgen_port_t *)arg; 1432 vgenp = portp->vgenp; 1433 vnetp = vgenp->vnetp; 1434 pvid_propname = port_pvid_propname; 1435 vid_propname = port_vid_propname; 1436 inst = portp->port_num; 1437 1438 } else { 1439 return; 1440 } 1441 1442 if (type == VGEN_LOCAL && default_idp != NULL) { 1443 rv = md_get_prop_val(mdp, node, vgen_dvid_propname, &val); 1444 if (rv != 0) { 1445 DWARN(vgenp, NULL, "prop(%s) not found", 1446 vgen_dvid_propname); 1447 1448 *default_idp = vnet_default_vlan_id; 1449 } else { 1450 *default_idp = val & 0xFFF; 1451 DBG2(vgenp, NULL, "%s(%d): (%d)\n", vgen_dvid_propname, 1452 inst, *default_idp); 1453 } 1454 } 1455 1456 rv = md_get_prop_val(mdp, node, pvid_propname, &val); 1457 if (rv != 0) { 1458 DWARN(vgenp, NULL, "prop(%s) not found", pvid_propname); 1459 *pvidp = vnet_default_vlan_id; 1460 } else { 1461 1462 *pvidp = val & 0xFFF; 1463 DBG2(vgenp, NULL, "%s(%d): (%d)\n", 1464 pvid_propname, inst, *pvidp); 1465 } 1466 1467 rv = md_get_prop_data(mdp, node, vid_propname, (uint8_t **)&data, 1468 &size); 1469 if (rv != 0) { 1470 DBG2(vgenp, NULL, "prop(%s) not found", vid_propname); 1471 size = 0; 1472 } else { 1473 size /= sizeof (uint64_t); 1474 } 1475 nvids = size; 1476 1477 if (nvids != 0) { 1478 DBG2(vgenp, NULL, "%s(%d): ", vid_propname, inst); 1479 vids_size = sizeof (uint16_t) * nvids; 1480 *vidspp = kmem_zalloc(vids_size, KM_SLEEP); 1481 for (i = 0; i < nvids; i++) { 1482 (*vidspp)[i] = data[i] & 0xFFFF; 1483 DBG2(vgenp, NULL, " %d ", (*vidspp)[i]); 1484 } 1485 DBG2(vgenp, NULL, "\n"); 1486 } 1487 1488 *nvidsp = nvids; 1489 } 1490 1491 /* 1492 * Create a vlan id hash table for the given port. 1493 */ 1494 static void 1495 vgen_vlan_create_hash(vgen_port_t *portp) 1496 { 1497 char hashname[MAXNAMELEN]; 1498 1499 (void) snprintf(hashname, MAXNAMELEN, "port%d-vlan-hash", 1500 portp->port_num); 1501 1502 portp->vlan_nchains = vgen_vlan_nchains; 1503 portp->vlan_hashp = mod_hash_create_idhash(hashname, 1504 portp->vlan_nchains, mod_hash_null_valdtor); 1505 } 1506 1507 /* 1508 * Destroy the vlan id hash table in the given port. 1509 */ 1510 static void 1511 vgen_vlan_destroy_hash(vgen_port_t *portp) 1512 { 1513 if (portp->vlan_hashp != NULL) { 1514 mod_hash_destroy_hash(portp->vlan_hashp); 1515 portp->vlan_hashp = NULL; 1516 portp->vlan_nchains = 0; 1517 } 1518 } 1519 1520 /* 1521 * Add a port to the vlans specified in its port properites. 1522 */ 1523 static void 1524 vgen_vlan_add_ids(vgen_port_t *portp) 1525 { 1526 int rv; 1527 int i; 1528 1529 rv = mod_hash_insert(portp->vlan_hashp, 1530 (mod_hash_key_t)VLAN_ID_KEY(portp->pvid), 1531 (mod_hash_val_t)B_TRUE); 1532 ASSERT(rv == 0); 1533 1534 for (i = 0; i < portp->nvids; i++) { 1535 rv = mod_hash_insert(portp->vlan_hashp, 1536 (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]), 1537 (mod_hash_val_t)B_TRUE); 1538 ASSERT(rv == 0); 1539 } 1540 } 1541 1542 /* 1543 * Remove a port from the vlans it has been assigned to. 1544 */ 1545 static void 1546 vgen_vlan_remove_ids(vgen_port_t *portp) 1547 { 1548 int rv; 1549 int i; 1550 mod_hash_val_t vp; 1551 1552 rv = mod_hash_remove(portp->vlan_hashp, 1553 (mod_hash_key_t)VLAN_ID_KEY(portp->pvid), 1554 (mod_hash_val_t *)&vp); 1555 ASSERT(rv == 0); 1556 1557 for (i = 0; i < portp->nvids; i++) { 1558 rv = mod_hash_remove(portp->vlan_hashp, 1559 (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]), 1560 (mod_hash_val_t *)&vp); 1561 ASSERT(rv == 0); 1562 } 1563 } 1564 1565 /* 1566 * Lookup the vlan id of the given tx frame. If it is a vlan-tagged frame, 1567 * then the vlan-id is available in the tag; otherwise, its vlan id is 1568 * implicitly obtained from the port-vlan-id of the vnet device. 1569 * The vlan id determined is returned in vidp. 1570 * Returns: B_TRUE if it is a tagged frame; B_FALSE if it is untagged. 1571 */ 1572 static boolean_t 1573 vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, uint16_t *vidp) 1574 { 1575 struct ether_vlan_header *evhp; 1576 1577 /* If it's a tagged frame, get the vlan id from vlan header */ 1578 if (ehp->ether_type == ETHERTYPE_VLAN) { 1579 1580 evhp = (struct ether_vlan_header *)ehp; 1581 *vidp = VLAN_ID(ntohs(evhp->ether_tci)); 1582 return (B_TRUE); 1583 } 1584 1585 /* Untagged frame, vlan-id is the pvid of vnet device */ 1586 *vidp = vnetp->pvid; 1587 return (B_FALSE); 1588 } 1589 1590 /* 1591 * Find the given vlan id in the hash table. 1592 * Return: B_TRUE if the id is found; B_FALSE if not found. 1593 */ 1594 static boolean_t 1595 vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid) 1596 { 1597 int rv; 1598 mod_hash_val_t vp; 1599 1600 rv = mod_hash_find(vlan_hashp, VLAN_ID_KEY(vid), (mod_hash_val_t *)&vp); 1601 1602 if (rv != 0) 1603 return (B_FALSE); 1604 1605 return (B_TRUE); 1606 } 1607 1608 /* 1609 * This function reads "priority-ether-types" property from md. This property 1610 * is used to enable support for priority frames. Applications which need 1611 * guaranteed and timely delivery of certain high priority frames to/from 1612 * a vnet or vsw within ldoms, should configure this property by providing 1613 * the ether type(s) for which the priority facility is needed. 1614 * Normal data frames are delivered over a ldc channel using the descriptor 1615 * ring mechanism which is constrained by factors such as descriptor ring size, 1616 * the rate at which the ring is processed at the peer ldc end point, etc. 1617 * The priority mechanism provides an Out-Of-Band path to send/receive frames 1618 * as raw pkt data (VIO_PKT_DATA) messages over the channel, avoiding the 1619 * descriptor ring path and enables a more reliable and timely delivery of 1620 * frames to the peer. 1621 */ 1622 static void 1623 vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, mde_cookie_t node) 1624 { 1625 int rv; 1626 uint16_t *types; 1627 uint64_t *data; 1628 int size; 1629 int i; 1630 size_t mblk_sz; 1631 1632 rv = md_get_prop_data(mdp, node, pri_types_propname, 1633 (uint8_t **)&data, &size); 1634 if (rv != 0) { 1635 /* 1636 * Property may not exist if we are running pre-ldoms1.1 f/w. 1637 * Check if 'vgen_pri_eth_type' has been set in that case. 1638 */ 1639 if (vgen_pri_eth_type != 0) { 1640 size = sizeof (vgen_pri_eth_type); 1641 data = &vgen_pri_eth_type; 1642 } else { 1643 DBG2(vgenp, NULL, 1644 "prop(%s) not found", pri_types_propname); 1645 size = 0; 1646 } 1647 } 1648 1649 if (size == 0) { 1650 vgenp->pri_num_types = 0; 1651 return; 1652 } 1653 1654 /* 1655 * we have some priority-ether-types defined; 1656 * allocate a table of these types and also 1657 * allocate a pool of mblks to transmit these 1658 * priority packets. 1659 */ 1660 size /= sizeof (uint64_t); 1661 vgenp->pri_num_types = size; 1662 vgenp->pri_types = kmem_zalloc(size * sizeof (uint16_t), KM_SLEEP); 1663 for (i = 0, types = vgenp->pri_types; i < size; i++) { 1664 types[i] = data[i] & 0xFFFF; 1665 } 1666 mblk_sz = (VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size + 7) & ~7; 1667 (void) vio_create_mblks(vgen_pri_tx_nmblks, mblk_sz, NULL, 1668 &vgenp->pri_tx_vmp); 1669 } 1670 1671 static void 1672 vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, uint32_t *mtu) 1673 { 1674 int rv; 1675 uint64_t val; 1676 char *mtu_propname; 1677 1678 mtu_propname = vgen_mtu_propname; 1679 1680 rv = md_get_prop_val(mdp, node, mtu_propname, &val); 1681 if (rv != 0) { 1682 DWARN(vgenp, NULL, "prop(%s) not found", mtu_propname); 1683 *mtu = vnet_ethermtu; 1684 } else { 1685 1686 *mtu = val & 0xFFFF; 1687 DBG2(vgenp, NULL, "%s(%d): (%d)\n", mtu_propname, 1688 vgenp->instance, *mtu); 1689 } 1690 } 1691 1692 static void 1693 vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, 1694 boolean_t *pls) 1695 { 1696 int rv; 1697 uint64_t val; 1698 char *linkpropname; 1699 1700 linkpropname = vgen_linkprop_propname; 1701 1702 rv = md_get_prop_val(mdp, node, linkpropname, &val); 1703 if (rv != 0) { 1704 DWARN(vgenp, NULL, "prop(%s) not found", linkpropname); 1705 *pls = B_FALSE; 1706 } else { 1707 1708 *pls = (val & 0x1) ? B_TRUE : B_FALSE; 1709 DBG2(vgenp, NULL, "%s(%d): (%d)\n", linkpropname, 1710 vgenp->instance, *pls); 1711 } 1712 } 1713 1714 /* register with MD event generator */ 1715 static int 1716 vgen_mdeg_reg(vgen_t *vgenp) 1717 { 1718 mdeg_prop_spec_t *pspecp; 1719 mdeg_node_spec_t *parentp; 1720 uint_t templatesz; 1721 int rv; 1722 mdeg_handle_t dev_hdl = NULL; 1723 mdeg_handle_t port_hdl = NULL; 1724 1725 templatesz = sizeof (vgen_prop_template); 1726 pspecp = kmem_zalloc(templatesz, KM_NOSLEEP); 1727 if (pspecp == NULL) { 1728 return (DDI_FAILURE); 1729 } 1730 parentp = kmem_zalloc(sizeof (mdeg_node_spec_t), KM_NOSLEEP); 1731 if (parentp == NULL) { 1732 kmem_free(pspecp, templatesz); 1733 return (DDI_FAILURE); 1734 } 1735 1736 bcopy(vgen_prop_template, pspecp, templatesz); 1737 1738 /* 1739 * NOTE: The instance here refers to the value of "reg" property and 1740 * not the dev_info instance (ddi_get_instance()) of vnet. 1741 */ 1742 VGEN_SET_MDEG_PROP_INST(pspecp, vgenp->regprop); 1743 1744 parentp->namep = "virtual-device"; 1745 parentp->specp = pspecp; 1746 1747 /* save parentp in vgen_t */ 1748 vgenp->mdeg_parentp = parentp; 1749 1750 /* 1751 * Register an interest in 'virtual-device' nodes with a 1752 * 'name' property of 'network' 1753 */ 1754 rv = mdeg_register(parentp, &vdev_match, vgen_mdeg_cb, vgenp, &dev_hdl); 1755 if (rv != MDEG_SUCCESS) { 1756 DERR(vgenp, NULL, "mdeg_register failed\n"); 1757 goto mdeg_reg_fail; 1758 } 1759 1760 /* Register an interest in 'port' nodes */ 1761 rv = mdeg_register(parentp, &vport_match, vgen_mdeg_port_cb, vgenp, 1762 &port_hdl); 1763 if (rv != MDEG_SUCCESS) { 1764 DERR(vgenp, NULL, "mdeg_register failed\n"); 1765 goto mdeg_reg_fail; 1766 } 1767 1768 /* save mdeg handle in vgen_t */ 1769 vgenp->mdeg_dev_hdl = dev_hdl; 1770 vgenp->mdeg_port_hdl = port_hdl; 1771 1772 return (DDI_SUCCESS); 1773 1774 mdeg_reg_fail: 1775 if (dev_hdl != NULL) { 1776 (void) mdeg_unregister(dev_hdl); 1777 } 1778 KMEM_FREE(parentp); 1779 kmem_free(pspecp, templatesz); 1780 vgenp->mdeg_parentp = NULL; 1781 return (DDI_FAILURE); 1782 } 1783 1784 /* unregister with MD event generator */ 1785 static void 1786 vgen_mdeg_unreg(vgen_t *vgenp) 1787 { 1788 if (vgenp->mdeg_dev_hdl != NULL) { 1789 (void) mdeg_unregister(vgenp->mdeg_dev_hdl); 1790 vgenp->mdeg_dev_hdl = NULL; 1791 } 1792 if (vgenp->mdeg_port_hdl != NULL) { 1793 (void) mdeg_unregister(vgenp->mdeg_port_hdl); 1794 vgenp->mdeg_port_hdl = NULL; 1795 } 1796 1797 if (vgenp->mdeg_parentp != NULL) { 1798 kmem_free(vgenp->mdeg_parentp->specp, 1799 sizeof (vgen_prop_template)); 1800 KMEM_FREE(vgenp->mdeg_parentp); 1801 vgenp->mdeg_parentp = NULL; 1802 } 1803 } 1804 1805 /* mdeg callback function for the port node */ 1806 static int 1807 vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp) 1808 { 1809 int idx; 1810 int vsw_idx = -1; 1811 uint64_t val; 1812 vgen_t *vgenp; 1813 1814 if ((resp == NULL) || (cb_argp == NULL)) { 1815 return (MDEG_FAILURE); 1816 } 1817 1818 vgenp = (vgen_t *)cb_argp; 1819 DBG1(vgenp, NULL, "enter\n"); 1820 1821 mutex_enter(&vgenp->lock); 1822 1823 DBG1(vgenp, NULL, "ports: removed(%x), " 1824 "added(%x), updated(%x)\n", resp->removed.nelem, 1825 resp->added.nelem, resp->match_curr.nelem); 1826 1827 for (idx = 0; idx < resp->removed.nelem; idx++) { 1828 (void) vgen_remove_port(vgenp, resp->removed.mdp, 1829 resp->removed.mdep[idx]); 1830 } 1831 1832 if (vgenp->vsw_portp == NULL) { 1833 /* 1834 * find vsw_port and add it first, because other ports need 1835 * this when adding fdb entry (see vgen_port_init()). 1836 */ 1837 for (idx = 0; idx < resp->added.nelem; idx++) { 1838 if (!(md_get_prop_val(resp->added.mdp, 1839 resp->added.mdep[idx], swport_propname, &val))) { 1840 if (val == 0) { 1841 /* 1842 * This port is connected to the 1843 * vsw on service domain. 1844 */ 1845 vsw_idx = idx; 1846 if (vgen_add_port(vgenp, 1847 resp->added.mdp, 1848 resp->added.mdep[idx]) != 1849 DDI_SUCCESS) { 1850 cmn_err(CE_NOTE, "vnet%d Could " 1851 "not initialize virtual " 1852 "switch port.", 1853 vgenp->instance); 1854 mutex_exit(&vgenp->lock); 1855 return (MDEG_FAILURE); 1856 } 1857 break; 1858 } 1859 } 1860 } 1861 if (vsw_idx == -1) { 1862 DWARN(vgenp, NULL, "can't find vsw_port\n"); 1863 mutex_exit(&vgenp->lock); 1864 return (MDEG_FAILURE); 1865 } 1866 } 1867 1868 for (idx = 0; idx < resp->added.nelem; idx++) { 1869 if ((vsw_idx != -1) && (vsw_idx == idx)) /* skip vsw_port */ 1870 continue; 1871 1872 /* If this port can't be added just skip it. */ 1873 (void) vgen_add_port(vgenp, resp->added.mdp, 1874 resp->added.mdep[idx]); 1875 } 1876 1877 for (idx = 0; idx < resp->match_curr.nelem; idx++) { 1878 (void) vgen_update_port(vgenp, resp->match_curr.mdp, 1879 resp->match_curr.mdep[idx], 1880 resp->match_prev.mdp, 1881 resp->match_prev.mdep[idx]); 1882 } 1883 1884 mutex_exit(&vgenp->lock); 1885 DBG1(vgenp, NULL, "exit\n"); 1886 return (MDEG_SUCCESS); 1887 } 1888 1889 /* mdeg callback function for the vnet node */ 1890 static int 1891 vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp) 1892 { 1893 vgen_t *vgenp; 1894 vnet_t *vnetp; 1895 md_t *mdp; 1896 mde_cookie_t node; 1897 uint64_t inst; 1898 char *node_name = NULL; 1899 1900 if ((resp == NULL) || (cb_argp == NULL)) { 1901 return (MDEG_FAILURE); 1902 } 1903 1904 vgenp = (vgen_t *)cb_argp; 1905 vnetp = vgenp->vnetp; 1906 1907 DBG1(vgenp, NULL, "added %d : removed %d : curr matched %d" 1908 " : prev matched %d", resp->added.nelem, resp->removed.nelem, 1909 resp->match_curr.nelem, resp->match_prev.nelem); 1910 1911 mutex_enter(&vgenp->lock); 1912 1913 /* 1914 * We get an initial callback for this node as 'added' after 1915 * registering with mdeg. Note that we would have already gathered 1916 * information about this vnet node by walking MD earlier during attach 1917 * (in vgen_read_mdprops()). So, there is a window where the properties 1918 * of this node might have changed when we get this initial 'added' 1919 * callback. We handle this as if an update occured and invoke the same 1920 * function which handles updates to the properties of this vnet-node 1921 * if any. A non-zero 'match' value indicates that the MD has been 1922 * updated and that a 'network' node is present which may or may not 1923 * have been updated. It is up to the clients to examine their own 1924 * nodes and determine if they have changed. 1925 */ 1926 if (resp->added.nelem != 0) { 1927 1928 if (resp->added.nelem != 1) { 1929 cmn_err(CE_NOTE, "!vnet%d: number of nodes added " 1930 "invalid: %d\n", vnetp->instance, 1931 resp->added.nelem); 1932 goto vgen_mdeg_cb_err; 1933 } 1934 1935 mdp = resp->added.mdp; 1936 node = resp->added.mdep[0]; 1937 1938 } else if (resp->match_curr.nelem != 0) { 1939 1940 if (resp->match_curr.nelem != 1) { 1941 cmn_err(CE_NOTE, "!vnet%d: number of nodes updated " 1942 "invalid: %d\n", vnetp->instance, 1943 resp->match_curr.nelem); 1944 goto vgen_mdeg_cb_err; 1945 } 1946 1947 mdp = resp->match_curr.mdp; 1948 node = resp->match_curr.mdep[0]; 1949 1950 } else { 1951 goto vgen_mdeg_cb_err; 1952 } 1953 1954 /* Validate name and instance */ 1955 if (md_get_prop_str(mdp, node, "name", &node_name) != 0) { 1956 DERR(vgenp, NULL, "unable to get node name\n"); 1957 goto vgen_mdeg_cb_err; 1958 } 1959 1960 /* is this a virtual-network device? */ 1961 if (strcmp(node_name, vnet_propname) != 0) { 1962 DERR(vgenp, NULL, "%s: Invalid node name: %s\n", node_name); 1963 goto vgen_mdeg_cb_err; 1964 } 1965 1966 if (md_get_prop_val(mdp, node, "cfg-handle", &inst)) { 1967 DERR(vgenp, NULL, "prop(cfg-handle) not found\n"); 1968 goto vgen_mdeg_cb_err; 1969 } 1970 1971 /* is this the right instance of vnet? */ 1972 if (inst != vgenp->regprop) { 1973 DERR(vgenp, NULL, "Invalid cfg-handle: %lx\n", inst); 1974 goto vgen_mdeg_cb_err; 1975 } 1976 1977 vgen_update_md_prop(vgenp, mdp, node); 1978 1979 mutex_exit(&vgenp->lock); 1980 return (MDEG_SUCCESS); 1981 1982 vgen_mdeg_cb_err: 1983 mutex_exit(&vgenp->lock); 1984 return (MDEG_FAILURE); 1985 } 1986 1987 /* 1988 * Check to see if the relevant properties in the specified node have 1989 * changed, and if so take the appropriate action. 1990 */ 1991 static void 1992 vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 1993 { 1994 uint16_t pvid; 1995 uint16_t *vids; 1996 uint16_t nvids; 1997 vnet_t *vnetp = vgenp->vnetp; 1998 uint32_t mtu; 1999 boolean_t pls_update; 2000 enum { MD_init = 0x1, 2001 MD_vlans = 0x2, 2002 MD_mtu = 0x4, 2003 MD_pls = 0x8 } updated; 2004 int rv; 2005 2006 updated = MD_init; 2007 2008 /* Read the vlan ids */ 2009 vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, mdex, &pvid, &vids, 2010 &nvids, NULL); 2011 2012 /* Determine if there are any vlan id updates */ 2013 if ((pvid != vnetp->pvid) || /* pvid changed? */ 2014 (nvids != vnetp->nvids) || /* # of vids changed? */ 2015 ((nvids != 0) && (vnetp->nvids != 0) && /* vids changed? */ 2016 bcmp(vids, vnetp->vids, sizeof (uint16_t) * nvids))) { 2017 updated |= MD_vlans; 2018 } 2019 2020 /* Read mtu */ 2021 vgen_mtu_read(vgenp, mdp, mdex, &mtu); 2022 if (mtu != vnetp->mtu) { 2023 if (mtu >= ETHERMTU && mtu <= VNET_MAX_MTU) { 2024 updated |= MD_mtu; 2025 } else { 2026 cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu update" 2027 " as the specified value:%d is invalid\n", 2028 vnetp->instance, mtu); 2029 } 2030 } 2031 2032 /* 2033 * Read the 'linkprop' property. 2034 */ 2035 vgen_linkprop_read(vgenp, mdp, mdex, &pls_update); 2036 if (pls_update != vnetp->pls_update) { 2037 updated |= MD_pls; 2038 } 2039 2040 /* Now process the updated props */ 2041 2042 if (updated & MD_vlans) { 2043 2044 /* save the new vlan ids */ 2045 vnetp->pvid = pvid; 2046 if (vnetp->nvids != 0) { 2047 kmem_free(vnetp->vids, 2048 sizeof (uint16_t) * vnetp->nvids); 2049 vnetp->nvids = 0; 2050 } 2051 if (nvids != 0) { 2052 vnetp->nvids = nvids; 2053 vnetp->vids = vids; 2054 } 2055 2056 /* reset vlan-unaware peers (ver < 1.3) and restart handshake */ 2057 vgen_reset_vlan_unaware_ports(vgenp); 2058 2059 } else { 2060 2061 if (nvids != 0) { 2062 kmem_free(vids, sizeof (uint16_t) * nvids); 2063 } 2064 } 2065 2066 if (updated & MD_mtu) { 2067 2068 DBG2(vgenp, NULL, "curr_mtu(%d) new_mtu(%d)\n", 2069 vnetp->mtu, mtu); 2070 2071 rv = vnet_mtu_update(vnetp, mtu); 2072 if (rv == 0) { 2073 vgenp->max_frame_size = mtu + 2074 sizeof (struct ether_header) + VLAN_TAGSZ; 2075 } 2076 } 2077 2078 if (updated & MD_pls) { 2079 /* enable/disable physical link state updates */ 2080 vnetp->pls_update = pls_update; 2081 mutex_exit(&vgenp->lock); 2082 2083 /* reset vsw-port to re-negotiate with the updated prop. */ 2084 vgen_reset_vsw_port(vgenp); 2085 2086 mutex_enter(&vgenp->lock); 2087 } 2088 } 2089 2090 /* add a new port to the device */ 2091 static int 2092 vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 2093 { 2094 vgen_port_t *portp; 2095 int rv; 2096 2097 portp = kmem_zalloc(sizeof (vgen_port_t), KM_SLEEP); 2098 2099 rv = vgen_port_read_props(portp, vgenp, mdp, mdex); 2100 if (rv != DDI_SUCCESS) { 2101 KMEM_FREE(portp); 2102 return (DDI_FAILURE); 2103 } 2104 2105 rv = vgen_port_attach(portp); 2106 if (rv != DDI_SUCCESS) { 2107 return (DDI_FAILURE); 2108 } 2109 2110 return (DDI_SUCCESS); 2111 } 2112 2113 /* read properties of the port from its md node */ 2114 static int 2115 vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp, 2116 mde_cookie_t mdex) 2117 { 2118 uint64_t port_num; 2119 uint64_t *ldc_ids; 2120 uint64_t macaddr; 2121 uint64_t val; 2122 int num_ldcs; 2123 int i; 2124 int addrsz; 2125 int num_nodes = 0; 2126 int listsz = 0; 2127 mde_cookie_t *listp = NULL; 2128 uint8_t *addrp; 2129 struct ether_addr ea; 2130 2131 /* read "id" property to get the port number */ 2132 if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) { 2133 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2134 return (DDI_FAILURE); 2135 } 2136 2137 /* 2138 * Find the channel endpoint node(s) under this port node. 2139 */ 2140 if ((num_nodes = md_node_count(mdp)) <= 0) { 2141 DWARN(vgenp, NULL, "invalid number of nodes found (%d)", 2142 num_nodes); 2143 return (DDI_FAILURE); 2144 } 2145 2146 /* allocate space for node list */ 2147 listsz = num_nodes * sizeof (mde_cookie_t); 2148 listp = kmem_zalloc(listsz, KM_NOSLEEP); 2149 if (listp == NULL) 2150 return (DDI_FAILURE); 2151 2152 num_ldcs = md_scan_dag(mdp, mdex, 2153 md_find_name(mdp, channel_propname), 2154 md_find_name(mdp, "fwd"), listp); 2155 2156 if (num_ldcs <= 0) { 2157 DWARN(vgenp, NULL, "can't find %s nodes", channel_propname); 2158 kmem_free(listp, listsz); 2159 return (DDI_FAILURE); 2160 } 2161 2162 if (num_ldcs > 1) { 2163 DWARN(vgenp, NULL, "Port %d: Number of channels %d > 1\n", 2164 port_num, num_ldcs); 2165 } 2166 2167 ldc_ids = kmem_zalloc(num_ldcs * sizeof (uint64_t), KM_NOSLEEP); 2168 if (ldc_ids == NULL) { 2169 kmem_free(listp, listsz); 2170 return (DDI_FAILURE); 2171 } 2172 2173 for (i = 0; i < num_ldcs; i++) { 2174 /* read channel ids */ 2175 if (md_get_prop_val(mdp, listp[i], id_propname, &ldc_ids[i])) { 2176 DWARN(vgenp, NULL, "prop(%s) not found\n", 2177 id_propname); 2178 kmem_free(listp, listsz); 2179 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2180 return (DDI_FAILURE); 2181 } 2182 DBG2(vgenp, NULL, "ldc_id 0x%llx", ldc_ids[i]); 2183 } 2184 2185 kmem_free(listp, listsz); 2186 2187 if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp, 2188 &addrsz)) { 2189 DWARN(vgenp, NULL, "prop(%s) not found\n", rmacaddr_propname); 2190 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2191 return (DDI_FAILURE); 2192 } 2193 2194 if (addrsz < ETHERADDRL) { 2195 DWARN(vgenp, NULL, "invalid address size (%d)\n", addrsz); 2196 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2197 return (DDI_FAILURE); 2198 } 2199 2200 macaddr = *((uint64_t *)addrp); 2201 2202 DBG2(vgenp, NULL, "remote mac address 0x%llx\n", macaddr); 2203 2204 for (i = ETHERADDRL - 1; i >= 0; i--) { 2205 ea.ether_addr_octet[i] = macaddr & 0xFF; 2206 macaddr >>= 8; 2207 } 2208 2209 if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) { 2210 if (val == 0) { 2211 /* This port is connected to the vswitch */ 2212 portp->is_vsw_port = B_TRUE; 2213 } else { 2214 portp->is_vsw_port = B_FALSE; 2215 } 2216 } 2217 2218 /* now update all properties into the port */ 2219 portp->vgenp = vgenp; 2220 portp->port_num = port_num; 2221 ether_copy(&ea, &portp->macaddr); 2222 portp->ldc_ids = kmem_zalloc(sizeof (uint64_t) * num_ldcs, KM_SLEEP); 2223 bcopy(ldc_ids, portp->ldc_ids, sizeof (uint64_t) * num_ldcs); 2224 portp->num_ldcs = num_ldcs; 2225 2226 /* read vlan id properties of this port node */ 2227 vgen_vlan_read_ids(portp, VGEN_PEER, mdp, mdex, &portp->pvid, 2228 &portp->vids, &portp->nvids, NULL); 2229 2230 kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t)); 2231 2232 return (DDI_SUCCESS); 2233 } 2234 2235 /* remove a port from the device */ 2236 static int 2237 vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex) 2238 { 2239 uint64_t port_num; 2240 vgen_port_t *portp; 2241 vgen_portlist_t *plistp; 2242 2243 /* read "id" property to get the port number */ 2244 if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) { 2245 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2246 return (DDI_FAILURE); 2247 } 2248 2249 plistp = &(vgenp->vgenports); 2250 2251 WRITE_ENTER(&plistp->rwlock); 2252 portp = vgen_port_lookup(plistp, (int)port_num); 2253 if (portp == NULL) { 2254 DWARN(vgenp, NULL, "can't find port(%lx)\n", port_num); 2255 RW_EXIT(&plistp->rwlock); 2256 return (DDI_FAILURE); 2257 } 2258 2259 vgen_port_detach_mdeg(portp); 2260 RW_EXIT(&plistp->rwlock); 2261 2262 return (DDI_SUCCESS); 2263 } 2264 2265 /* attach a port to the device based on mdeg data */ 2266 static int 2267 vgen_port_attach(vgen_port_t *portp) 2268 { 2269 vgen_portlist_t *plistp; 2270 vgen_t *vgenp; 2271 uint64_t *ldcids; 2272 mac_register_t *macp; 2273 vio_net_res_type_t type; 2274 int rv; 2275 2276 ASSERT(portp != NULL); 2277 vgenp = portp->vgenp; 2278 ldcids = portp->ldc_ids; 2279 2280 DBG2(vgenp, NULL, "port_num(%d), ldcid(%lx)\n", 2281 portp->port_num, ldcids[0]); 2282 2283 mutex_init(&portp->lock, NULL, MUTEX_DRIVER, NULL); 2284 2285 /* 2286 * attach the channel under the port using its channel id; 2287 * note that we only support one channel per port for now. 2288 */ 2289 if (vgen_ldc_attach(portp, ldcids[0]) == DDI_FAILURE) { 2290 vgen_port_detach(portp); 2291 return (DDI_FAILURE); 2292 } 2293 2294 /* create vlan id hash table */ 2295 vgen_vlan_create_hash(portp); 2296 2297 if (portp->is_vsw_port == B_TRUE) { 2298 /* This port is connected to the switch port */ 2299 (void) atomic_swap_32(&portp->use_vsw_port, B_FALSE); 2300 type = VIO_NET_RES_LDC_SERVICE; 2301 } else { 2302 (void) atomic_swap_32(&portp->use_vsw_port, B_TRUE); 2303 type = VIO_NET_RES_LDC_GUEST; 2304 } 2305 2306 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 2307 vgen_port_detach(portp); 2308 return (DDI_FAILURE); 2309 } 2310 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2311 macp->m_driver = portp; 2312 macp->m_dip = vgenp->vnetdip; 2313 macp->m_src_addr = (uint8_t *)&(vgenp->macaddr); 2314 macp->m_callbacks = &vgen_m_callbacks; 2315 macp->m_min_sdu = 0; 2316 macp->m_max_sdu = ETHERMTU; 2317 2318 mutex_enter(&portp->lock); 2319 rv = vio_net_resource_reg(macp, type, vgenp->macaddr, 2320 portp->macaddr, &portp->vhp, &portp->vcb); 2321 mutex_exit(&portp->lock); 2322 mac_free(macp); 2323 2324 if (rv == 0) { 2325 /* link it into the list of ports */ 2326 plistp = &(vgenp->vgenports); 2327 WRITE_ENTER(&plistp->rwlock); 2328 vgen_port_list_insert(portp); 2329 RW_EXIT(&plistp->rwlock); 2330 2331 if (portp->is_vsw_port == B_TRUE) { 2332 /* We now have the vswitch port attached */ 2333 vgenp->vsw_portp = portp; 2334 (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0); 2335 } 2336 } else { 2337 DERR(vgenp, NULL, "vio_net_resource_reg failed for portp=0x%p", 2338 portp); 2339 vgen_port_detach(portp); 2340 } 2341 2342 DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num); 2343 return (DDI_SUCCESS); 2344 } 2345 2346 /* detach a port from the device based on mdeg data */ 2347 static void 2348 vgen_port_detach_mdeg(vgen_port_t *portp) 2349 { 2350 vgen_t *vgenp = portp->vgenp; 2351 2352 DBG1(vgenp, NULL, "enter: port_num(%d)\n", portp->port_num); 2353 2354 mutex_enter(&portp->lock); 2355 2356 /* stop the port if needed */ 2357 if (portp->flags & VGEN_STARTED) { 2358 vgen_port_uninit(portp); 2359 portp->flags &= ~(VGEN_STARTED); 2360 } 2361 2362 mutex_exit(&portp->lock); 2363 vgen_port_detach(portp); 2364 2365 DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num); 2366 } 2367 2368 static int 2369 vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex, 2370 md_t *prev_mdp, mde_cookie_t prev_mdex) 2371 { 2372 uint64_t cport_num; 2373 uint64_t pport_num; 2374 vgen_portlist_t *plistp; 2375 vgen_port_t *portp; 2376 boolean_t updated_vlans = B_FALSE; 2377 uint16_t pvid; 2378 uint16_t *vids; 2379 uint16_t nvids; 2380 2381 /* 2382 * For now, we get port updates only if vlan ids changed. 2383 * We read the port num and do some sanity check. 2384 */ 2385 if (md_get_prop_val(curr_mdp, curr_mdex, id_propname, &cport_num)) { 2386 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2387 return (DDI_FAILURE); 2388 } 2389 2390 if (md_get_prop_val(prev_mdp, prev_mdex, id_propname, &pport_num)) { 2391 DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname); 2392 return (DDI_FAILURE); 2393 } 2394 if (cport_num != pport_num) 2395 return (DDI_FAILURE); 2396 2397 plistp = &(vgenp->vgenports); 2398 2399 READ_ENTER(&plistp->rwlock); 2400 2401 portp = vgen_port_lookup(plistp, (int)cport_num); 2402 if (portp == NULL) { 2403 DWARN(vgenp, NULL, "can't find port(%lx)\n", cport_num); 2404 RW_EXIT(&plistp->rwlock); 2405 return (DDI_FAILURE); 2406 } 2407 2408 /* Read the vlan ids */ 2409 vgen_vlan_read_ids(portp, VGEN_PEER, curr_mdp, curr_mdex, &pvid, &vids, 2410 &nvids, NULL); 2411 2412 /* Determine if there are any vlan id updates */ 2413 if ((pvid != portp->pvid) || /* pvid changed? */ 2414 (nvids != portp->nvids) || /* # of vids changed? */ 2415 ((nvids != 0) && (portp->nvids != 0) && /* vids changed? */ 2416 bcmp(vids, portp->vids, sizeof (uint16_t) * nvids))) { 2417 updated_vlans = B_TRUE; 2418 } 2419 2420 if (updated_vlans == B_FALSE) { 2421 RW_EXIT(&plistp->rwlock); 2422 return (DDI_FAILURE); 2423 } 2424 2425 /* remove the port from vlans it has been assigned to */ 2426 vgen_vlan_remove_ids(portp); 2427 2428 /* save the new vlan ids */ 2429 portp->pvid = pvid; 2430 if (portp->nvids != 0) { 2431 kmem_free(portp->vids, sizeof (uint16_t) * portp->nvids); 2432 portp->nvids = 0; 2433 } 2434 if (nvids != 0) { 2435 portp->vids = kmem_zalloc(sizeof (uint16_t) * nvids, KM_SLEEP); 2436 bcopy(vids, portp->vids, sizeof (uint16_t) * nvids); 2437 portp->nvids = nvids; 2438 kmem_free(vids, sizeof (uint16_t) * nvids); 2439 } 2440 2441 /* add port to the new vlans */ 2442 vgen_vlan_add_ids(portp); 2443 2444 /* reset the port if it is vlan unaware (ver < 1.3) */ 2445 vgen_vlan_unaware_port_reset(portp); 2446 2447 RW_EXIT(&plistp->rwlock); 2448 2449 return (DDI_SUCCESS); 2450 } 2451 2452 static uint64_t 2453 vgen_port_stat(vgen_port_t *portp, uint_t stat) 2454 { 2455 return (vgen_ldc_stat(portp->ldcp, stat)); 2456 } 2457 2458 /* attach the channel corresponding to the given ldc_id to the port */ 2459 static int 2460 vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id) 2461 { 2462 vgen_t *vgenp; 2463 vgen_ldc_t *ldcp; 2464 ldc_attr_t attr; 2465 int status; 2466 ldc_status_t istatus; 2467 char kname[MAXNAMELEN]; 2468 int instance; 2469 enum {AST_init = 0x0, AST_ldc_alloc = 0x1, 2470 AST_mutex_init = 0x2, AST_ldc_init = 0x4, 2471 AST_ldc_reg_cb = 0x8 } attach_state; 2472 2473 attach_state = AST_init; 2474 vgenp = portp->vgenp; 2475 2476 ldcp = kmem_zalloc(sizeof (vgen_ldc_t), KM_NOSLEEP); 2477 if (ldcp == NULL) { 2478 goto ldc_attach_failed; 2479 } 2480 ldcp->ldc_id = ldc_id; 2481 ldcp->portp = portp; 2482 2483 attach_state |= AST_ldc_alloc; 2484 2485 mutex_init(&ldcp->txlock, NULL, MUTEX_DRIVER, NULL); 2486 mutex_init(&ldcp->cblock, NULL, MUTEX_DRIVER, NULL); 2487 mutex_init(&ldcp->tclock, NULL, MUTEX_DRIVER, NULL); 2488 mutex_init(&ldcp->wrlock, NULL, MUTEX_DRIVER, NULL); 2489 mutex_init(&ldcp->rxlock, NULL, MUTEX_DRIVER, NULL); 2490 mutex_init(&ldcp->pollq_lock, NULL, MUTEX_DRIVER, NULL); 2491 mutex_init(&ldcp->msg_thr_lock, NULL, MUTEX_DRIVER, NULL); 2492 cv_init(&ldcp->msg_thr_cv, NULL, CV_DRIVER, NULL); 2493 2494 attach_state |= AST_mutex_init; 2495 2496 attr.devclass = LDC_DEV_NT; 2497 attr.instance = vgenp->instance; 2498 attr.mode = LDC_MODE_UNRELIABLE; 2499 attr.mtu = vgen_ldc_mtu; 2500 status = ldc_init(ldc_id, &attr, &ldcp->ldc_handle); 2501 if (status != 0) { 2502 DWARN(vgenp, ldcp, "ldc_init failed,rv (%d)\n", status); 2503 goto ldc_attach_failed; 2504 } 2505 attach_state |= AST_ldc_init; 2506 2507 status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp); 2508 if (status != 0) { 2509 DWARN(vgenp, ldcp, "ldc_reg_callback failed, rv (%d)\n", 2510 status); 2511 goto ldc_attach_failed; 2512 } 2513 /* 2514 * allocate a message for ldc_read()s, big enough to hold ctrl and 2515 * data msgs, including raw data msgs used to recv priority frames. 2516 */ 2517 ldcp->msglen = VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size; 2518 ldcp->ldcmsg = kmem_alloc(ldcp->msglen, KM_SLEEP); 2519 attach_state |= AST_ldc_reg_cb; 2520 2521 (void) ldc_status(ldcp->ldc_handle, &istatus); 2522 ASSERT(istatus == LDC_INIT); 2523 ldcp->ldc_status = istatus; 2524 2525 /* Setup kstats for the channel */ 2526 instance = vgenp->instance; 2527 (void) sprintf(kname, "vnetldc0x%lx", ldcp->ldc_id); 2528 ldcp->ksp = vgen_setup_kstats("vnet", instance, kname, &ldcp->stats); 2529 if (ldcp->ksp == NULL) { 2530 goto ldc_attach_failed; 2531 } 2532 2533 /* initialize vgen_versions supported */ 2534 bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions)); 2535 vgen_reset_vnet_proto_ops(ldcp); 2536 2537 /* Link this channel to the port */ 2538 portp->ldcp = ldcp; 2539 2540 ldcp->link_state = LINK_STATE_UNKNOWN; 2541 #ifdef VNET_IOC_DEBUG 2542 ldcp->link_down_forced = B_FALSE; 2543 #endif 2544 ldcp->flags |= CHANNEL_ATTACHED; 2545 return (DDI_SUCCESS); 2546 2547 ldc_attach_failed: 2548 if (attach_state & AST_ldc_reg_cb) { 2549 (void) ldc_unreg_callback(ldcp->ldc_handle); 2550 kmem_free(ldcp->ldcmsg, ldcp->msglen); 2551 } 2552 2553 if (attach_state & AST_ldc_init) { 2554 (void) ldc_fini(ldcp->ldc_handle); 2555 } 2556 if (attach_state & AST_mutex_init) { 2557 mutex_destroy(&ldcp->tclock); 2558 mutex_destroy(&ldcp->txlock); 2559 mutex_destroy(&ldcp->cblock); 2560 mutex_destroy(&ldcp->wrlock); 2561 mutex_destroy(&ldcp->rxlock); 2562 mutex_destroy(&ldcp->pollq_lock); 2563 } 2564 if (attach_state & AST_ldc_alloc) { 2565 KMEM_FREE(ldcp); 2566 } 2567 return (DDI_FAILURE); 2568 } 2569 2570 /* detach a channel from the port */ 2571 static void 2572 vgen_ldc_detach(vgen_ldc_t *ldcp) 2573 { 2574 vgen_port_t *portp; 2575 vgen_t *vgenp; 2576 2577 ASSERT(ldcp != NULL); 2578 2579 portp = ldcp->portp; 2580 vgenp = portp->vgenp; 2581 2582 if (ldcp->ldc_status != LDC_INIT) { 2583 DWARN(vgenp, ldcp, "ldc_status is not INIT\n"); 2584 } 2585 2586 if (ldcp->flags & CHANNEL_ATTACHED) { 2587 ldcp->flags &= ~(CHANNEL_ATTACHED); 2588 2589 (void) ldc_unreg_callback(ldcp->ldc_handle); 2590 (void) ldc_fini(ldcp->ldc_handle); 2591 2592 kmem_free(ldcp->ldcmsg, ldcp->msglen); 2593 vgen_destroy_kstats(ldcp->ksp); 2594 ldcp->ksp = NULL; 2595 mutex_destroy(&ldcp->tclock); 2596 mutex_destroy(&ldcp->txlock); 2597 mutex_destroy(&ldcp->cblock); 2598 mutex_destroy(&ldcp->wrlock); 2599 mutex_destroy(&ldcp->rxlock); 2600 mutex_destroy(&ldcp->pollq_lock); 2601 mutex_destroy(&ldcp->msg_thr_lock); 2602 cv_destroy(&ldcp->msg_thr_cv); 2603 2604 KMEM_FREE(ldcp); 2605 } 2606 } 2607 2608 /* enable transmit/receive on the channel */ 2609 static int 2610 vgen_ldc_init(vgen_ldc_t *ldcp) 2611 { 2612 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 2613 ldc_status_t istatus; 2614 int rv; 2615 enum { ST_init = 0x0, ST_ldc_open = 0x1, 2616 ST_cb_enable = 0x2} init_state; 2617 int flag = 0; 2618 2619 init_state = ST_init; 2620 2621 DBG1(vgenp, ldcp, "enter\n"); 2622 LDC_LOCK(ldcp); 2623 2624 rv = ldc_open(ldcp->ldc_handle); 2625 if (rv != 0) { 2626 DWARN(vgenp, ldcp, "ldc_open failed: rv(%d)\n", rv); 2627 goto ldcinit_failed; 2628 } 2629 init_state |= ST_ldc_open; 2630 2631 (void) ldc_status(ldcp->ldc_handle, &istatus); 2632 if (istatus != LDC_OPEN && istatus != LDC_READY) { 2633 DWARN(vgenp, ldcp, "status(%d) is not OPEN/READY\n", istatus); 2634 goto ldcinit_failed; 2635 } 2636 ldcp->ldc_status = istatus; 2637 2638 rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_ENABLE); 2639 if (rv != 0) { 2640 DWARN(vgenp, ldcp, "ldc_set_cb_mode failed: rv(%d)\n", rv); 2641 goto ldcinit_failed; 2642 } 2643 2644 init_state |= ST_cb_enable; 2645 2646 vgen_ldc_up(ldcp); 2647 2648 (void) ldc_status(ldcp->ldc_handle, &istatus); 2649 if (istatus == LDC_UP) { 2650 DWARN(vgenp, ldcp, "status(%d) is UP\n", istatus); 2651 } 2652 2653 ldcp->ldc_status = istatus; 2654 2655 ldcp->hphase = VH_PHASE0; 2656 ldcp->hstate = 0; 2657 ldcp->flags |= CHANNEL_STARTED; 2658 2659 vgen_setup_handshake_params(ldcp); 2660 2661 /* if channel is already UP - start handshake */ 2662 if (istatus == LDC_UP) { 2663 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 2664 if (ldcp->portp != vgenp->vsw_portp) { 2665 /* 2666 * As the channel is up, use this port from now on. 2667 */ 2668 (void) atomic_swap_32( 2669 &ldcp->portp->use_vsw_port, B_FALSE); 2670 } 2671 2672 /* Initialize local session id */ 2673 ldcp->local_sid = ddi_get_lbolt(); 2674 2675 /* clear peer session id */ 2676 ldcp->peer_sid = 0; 2677 2678 mutex_exit(&ldcp->tclock); 2679 mutex_exit(&ldcp->txlock); 2680 mutex_exit(&ldcp->wrlock); 2681 mutex_exit(&ldcp->rxlock); 2682 rv = vgen_handshake(vh_nextphase(ldcp)); 2683 mutex_exit(&ldcp->cblock); 2684 if (rv != 0) { 2685 flag = (rv == ECONNRESET) ? VGEN_FLAG_EVT_RESET : 2686 VGEN_FLAG_NEED_LDCRESET; 2687 (void) vgen_process_reset(ldcp, flag); 2688 } 2689 } else { 2690 LDC_UNLOCK(ldcp); 2691 } 2692 2693 return (DDI_SUCCESS); 2694 2695 ldcinit_failed: 2696 if (init_state & ST_cb_enable) { 2697 (void) ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE); 2698 } 2699 if (init_state & ST_ldc_open) { 2700 (void) ldc_close(ldcp->ldc_handle); 2701 } 2702 LDC_UNLOCK(ldcp); 2703 DBG1(vgenp, ldcp, "exit\n"); 2704 return (DDI_FAILURE); 2705 } 2706 2707 /* stop transmit/receive on the channel */ 2708 static void 2709 vgen_ldc_uninit(vgen_ldc_t *ldcp) 2710 { 2711 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 2712 2713 DBG1(vgenp, ldcp, "enter\n"); 2714 2715 LDC_LOCK(ldcp); 2716 2717 if ((ldcp->flags & CHANNEL_STARTED) == 0) { 2718 LDC_UNLOCK(ldcp); 2719 DWARN(vgenp, ldcp, "CHANNEL_STARTED flag is not set\n"); 2720 return; 2721 } 2722 2723 LDC_UNLOCK(ldcp); 2724 2725 while (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) { 2726 delay(drv_usectohz(VGEN_LDC_UNINIT_DELAY)); 2727 } 2728 2729 (void) vgen_process_reset(ldcp, VGEN_FLAG_UNINIT); 2730 2731 DBG1(vgenp, ldcp, "exit\n"); 2732 } 2733 2734 /* 2735 * Create a descriptor ring, that will be exported to the peer for mapping. 2736 */ 2737 static int 2738 vgen_create_dring(vgen_ldc_t *ldcp) 2739 { 2740 vgen_hparams_t *lp = &ldcp->local_hparams; 2741 int rv; 2742 2743 if (lp->dring_mode == VIO_RX_DRING_DATA) { 2744 rv = vgen_create_rx_dring(ldcp); 2745 } else { 2746 rv = vgen_create_tx_dring(ldcp); 2747 } 2748 2749 return (rv); 2750 } 2751 2752 /* 2753 * Destroy the descriptor ring. 2754 */ 2755 static void 2756 vgen_destroy_dring(vgen_ldc_t *ldcp) 2757 { 2758 vgen_hparams_t *lp = &ldcp->local_hparams; 2759 2760 if (lp->dring_mode == VIO_RX_DRING_DATA) { 2761 vgen_destroy_rx_dring(ldcp); 2762 } else { 2763 vgen_destroy_tx_dring(ldcp); 2764 } 2765 } 2766 2767 /* 2768 * Map the descriptor ring exported by the peer. 2769 */ 2770 static int 2771 vgen_map_dring(vgen_ldc_t *ldcp, void *pkt) 2772 { 2773 int rv; 2774 vgen_hparams_t *lp = &ldcp->local_hparams; 2775 2776 if (lp->dring_mode == VIO_RX_DRING_DATA) { 2777 /* 2778 * In RxDringData mode, dring that we map in 2779 * becomes our transmit descriptor ring. 2780 */ 2781 rv = vgen_map_tx_dring(ldcp, pkt); 2782 } else { 2783 2784 /* 2785 * In TxDring mode, dring that we map in 2786 * becomes our receive descriptor ring. 2787 */ 2788 rv = vgen_map_rx_dring(ldcp, pkt); 2789 } 2790 2791 return (rv); 2792 } 2793 2794 /* 2795 * Unmap the descriptor ring exported by the peer. 2796 */ 2797 static void 2798 vgen_unmap_dring(vgen_ldc_t *ldcp) 2799 { 2800 vgen_hparams_t *lp = &ldcp->local_hparams; 2801 2802 if (lp->dring_mode == VIO_RX_DRING_DATA) { 2803 vgen_unmap_tx_dring(ldcp); 2804 } else { 2805 vgen_unmap_rx_dring(ldcp); 2806 } 2807 } 2808 2809 void 2810 vgen_destroy_rxpools(void *arg) 2811 { 2812 vio_mblk_pool_t *poolp = (vio_mblk_pool_t *)arg; 2813 vio_mblk_pool_t *npoolp; 2814 2815 while (poolp != NULL) { 2816 npoolp = poolp->nextp; 2817 while (vio_destroy_mblks(poolp) != 0) { 2818 delay(drv_usectohz(vgen_rxpool_cleanup_delay)); 2819 } 2820 poolp = npoolp; 2821 } 2822 } 2823 2824 /* get channel statistics */ 2825 static uint64_t 2826 vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat) 2827 { 2828 vgen_stats_t *statsp; 2829 uint64_t val; 2830 2831 val = 0; 2832 statsp = &ldcp->stats; 2833 switch (stat) { 2834 2835 case MAC_STAT_MULTIRCV: 2836 val = statsp->multircv; 2837 break; 2838 2839 case MAC_STAT_BRDCSTRCV: 2840 val = statsp->brdcstrcv; 2841 break; 2842 2843 case MAC_STAT_MULTIXMT: 2844 val = statsp->multixmt; 2845 break; 2846 2847 case MAC_STAT_BRDCSTXMT: 2848 val = statsp->brdcstxmt; 2849 break; 2850 2851 case MAC_STAT_NORCVBUF: 2852 val = statsp->norcvbuf; 2853 break; 2854 2855 case MAC_STAT_IERRORS: 2856 val = statsp->ierrors; 2857 break; 2858 2859 case MAC_STAT_NOXMTBUF: 2860 val = statsp->noxmtbuf; 2861 break; 2862 2863 case MAC_STAT_OERRORS: 2864 val = statsp->oerrors; 2865 break; 2866 2867 case MAC_STAT_COLLISIONS: 2868 break; 2869 2870 case MAC_STAT_RBYTES: 2871 val = statsp->rbytes; 2872 break; 2873 2874 case MAC_STAT_IPACKETS: 2875 val = statsp->ipackets; 2876 break; 2877 2878 case MAC_STAT_OBYTES: 2879 val = statsp->obytes; 2880 break; 2881 2882 case MAC_STAT_OPACKETS: 2883 val = statsp->opackets; 2884 break; 2885 2886 /* stats not relevant to ldc, return 0 */ 2887 case MAC_STAT_IFSPEED: 2888 case ETHER_STAT_ALIGN_ERRORS: 2889 case ETHER_STAT_FCS_ERRORS: 2890 case ETHER_STAT_FIRST_COLLISIONS: 2891 case ETHER_STAT_MULTI_COLLISIONS: 2892 case ETHER_STAT_DEFER_XMTS: 2893 case ETHER_STAT_TX_LATE_COLLISIONS: 2894 case ETHER_STAT_EX_COLLISIONS: 2895 case ETHER_STAT_MACXMT_ERRORS: 2896 case ETHER_STAT_CARRIER_ERRORS: 2897 case ETHER_STAT_TOOLONG_ERRORS: 2898 case ETHER_STAT_XCVR_ADDR: 2899 case ETHER_STAT_XCVR_ID: 2900 case ETHER_STAT_XCVR_INUSE: 2901 case ETHER_STAT_CAP_1000FDX: 2902 case ETHER_STAT_CAP_1000HDX: 2903 case ETHER_STAT_CAP_100FDX: 2904 case ETHER_STAT_CAP_100HDX: 2905 case ETHER_STAT_CAP_10FDX: 2906 case ETHER_STAT_CAP_10HDX: 2907 case ETHER_STAT_CAP_ASMPAUSE: 2908 case ETHER_STAT_CAP_PAUSE: 2909 case ETHER_STAT_CAP_AUTONEG: 2910 case ETHER_STAT_ADV_CAP_1000FDX: 2911 case ETHER_STAT_ADV_CAP_1000HDX: 2912 case ETHER_STAT_ADV_CAP_100FDX: 2913 case ETHER_STAT_ADV_CAP_100HDX: 2914 case ETHER_STAT_ADV_CAP_10FDX: 2915 case ETHER_STAT_ADV_CAP_10HDX: 2916 case ETHER_STAT_ADV_CAP_ASMPAUSE: 2917 case ETHER_STAT_ADV_CAP_PAUSE: 2918 case ETHER_STAT_ADV_CAP_AUTONEG: 2919 case ETHER_STAT_LP_CAP_1000FDX: 2920 case ETHER_STAT_LP_CAP_1000HDX: 2921 case ETHER_STAT_LP_CAP_100FDX: 2922 case ETHER_STAT_LP_CAP_100HDX: 2923 case ETHER_STAT_LP_CAP_10FDX: 2924 case ETHER_STAT_LP_CAP_10HDX: 2925 case ETHER_STAT_LP_CAP_ASMPAUSE: 2926 case ETHER_STAT_LP_CAP_PAUSE: 2927 case ETHER_STAT_LP_CAP_AUTONEG: 2928 case ETHER_STAT_LINK_ASMPAUSE: 2929 case ETHER_STAT_LINK_PAUSE: 2930 case ETHER_STAT_LINK_AUTONEG: 2931 case ETHER_STAT_LINK_DUPLEX: 2932 default: 2933 val = 0; 2934 break; 2935 2936 } 2937 return (val); 2938 } 2939 2940 /* 2941 * LDC channel is UP, start handshake process with peer. 2942 */ 2943 static void 2944 vgen_handle_evt_up(vgen_ldc_t *ldcp) 2945 { 2946 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 2947 2948 DBG1(vgenp, ldcp, "enter\n"); 2949 2950 ASSERT(MUTEX_HELD(&ldcp->cblock)); 2951 2952 if (ldcp->portp != vgenp->vsw_portp) { 2953 /* 2954 * As the channel is up, use this port from now on. 2955 */ 2956 (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_FALSE); 2957 } 2958 2959 /* Initialize local session id */ 2960 ldcp->local_sid = ddi_get_lbolt(); 2961 2962 /* clear peer session id */ 2963 ldcp->peer_sid = 0; 2964 2965 /* Initiate Handshake process with peer ldc endpoint */ 2966 (void) vgen_handshake(vh_nextphase(ldcp)); 2967 2968 DBG1(vgenp, ldcp, "exit\n"); 2969 } 2970 2971 /* 2972 * LDC channel is Reset, terminate connection with peer and try to 2973 * bring the channel up again. 2974 */ 2975 int 2976 vgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller) 2977 { 2978 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 2979 ASSERT(MUTEX_HELD(&ldcp->cblock)); 2980 } 2981 2982 /* Set the flag to indicate reset is in progress */ 2983 if (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) { 2984 /* another thread is already in the process of resetting */ 2985 return (EBUSY); 2986 } 2987 2988 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 2989 mutex_exit(&ldcp->cblock); 2990 } 2991 2992 (void) vgen_process_reset(ldcp, VGEN_FLAG_EVT_RESET); 2993 2994 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 2995 mutex_enter(&ldcp->cblock); 2996 } 2997 2998 return (0); 2999 } 3000 3001 /* Interrupt handler for the channel */ 3002 static uint_t 3003 vgen_ldc_cb(uint64_t event, caddr_t arg) 3004 { 3005 _NOTE(ARGUNUSED(event)) 3006 vgen_ldc_t *ldcp; 3007 vgen_t *vgenp; 3008 ldc_status_t istatus; 3009 vgen_stats_t *statsp; 3010 uint_t ret = LDC_SUCCESS; 3011 3012 ldcp = (vgen_ldc_t *)arg; 3013 vgenp = LDC_TO_VGEN(ldcp); 3014 statsp = &ldcp->stats; 3015 3016 DBG1(vgenp, ldcp, "enter\n"); 3017 3018 mutex_enter(&ldcp->cblock); 3019 statsp->callbacks++; 3020 if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) { 3021 DWARN(vgenp, ldcp, "status(%d) is LDC_INIT\n", 3022 ldcp->ldc_status); 3023 mutex_exit(&ldcp->cblock); 3024 return (LDC_SUCCESS); 3025 } 3026 3027 /* 3028 * NOTE: not using switch() as event could be triggered by 3029 * a state change and a read request. Also the ordering of the 3030 * check for the event types is deliberate. 3031 */ 3032 if (event & LDC_EVT_UP) { 3033 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3034 DWARN(vgenp, ldcp, "ldc_status err\n"); 3035 /* status couldn't be determined */ 3036 ret = LDC_FAILURE; 3037 goto ldc_cb_ret; 3038 } 3039 ldcp->ldc_status = istatus; 3040 if (ldcp->ldc_status != LDC_UP) { 3041 DWARN(vgenp, ldcp, "LDC_EVT_UP received " 3042 " but ldc status is not UP(0x%x)\n", 3043 ldcp->ldc_status); 3044 /* spurious interrupt, return success */ 3045 goto ldc_cb_ret; 3046 } 3047 DWARN(vgenp, ldcp, "event(%lx) UP, status(%d)\n", 3048 event, ldcp->ldc_status); 3049 3050 vgen_handle_evt_up(ldcp); 3051 3052 ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 3053 } 3054 3055 /* Handle RESET/DOWN before READ event */ 3056 if (event & (LDC_EVT_RESET | LDC_EVT_DOWN)) { 3057 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3058 DWARN(vgenp, ldcp, "ldc_status error\n"); 3059 /* status couldn't be determined */ 3060 ret = LDC_FAILURE; 3061 goto ldc_cb_ret; 3062 } 3063 ldcp->ldc_status = istatus; 3064 DWARN(vgenp, ldcp, "event(%lx) RESET/DOWN, status(%d)\n", 3065 event, ldcp->ldc_status); 3066 3067 (void) vgen_handle_evt_reset(ldcp, VGEN_LDC_CB); 3068 3069 /* 3070 * As the channel is down/reset, ignore READ event 3071 * but print a debug warning message. 3072 */ 3073 if (event & LDC_EVT_READ) { 3074 DWARN(vgenp, ldcp, 3075 "LDC_EVT_READ set along with RESET/DOWN\n"); 3076 event &= ~LDC_EVT_READ; 3077 } 3078 } 3079 3080 if (event & LDC_EVT_READ) { 3081 DBG2(vgenp, ldcp, "event(%lx) READ, status(%d)\n", 3082 event, ldcp->ldc_status); 3083 3084 ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0); 3085 3086 if (ldcp->msg_thread != NULL) { 3087 /* 3088 * If the receive thread is enabled, then 3089 * wakeup the receive thread to process the 3090 * LDC messages. 3091 */ 3092 mutex_exit(&ldcp->cblock); 3093 mutex_enter(&ldcp->msg_thr_lock); 3094 if (!(ldcp->msg_thr_flags & VGEN_WTHR_DATARCVD)) { 3095 ldcp->msg_thr_flags |= VGEN_WTHR_DATARCVD; 3096 cv_signal(&ldcp->msg_thr_cv); 3097 } 3098 mutex_exit(&ldcp->msg_thr_lock); 3099 mutex_enter(&ldcp->cblock); 3100 } else { 3101 (void) vgen_handle_evt_read(ldcp, VGEN_LDC_CB); 3102 } 3103 } 3104 3105 ldc_cb_ret: 3106 mutex_exit(&ldcp->cblock); 3107 DBG1(vgenp, ldcp, "exit\n"); 3108 return (ret); 3109 } 3110 3111 int 3112 vgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller) 3113 { 3114 int rv; 3115 uint64_t *ldcmsg; 3116 size_t msglen; 3117 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3118 vio_msg_tag_t *tagp; 3119 ldc_status_t istatus; 3120 boolean_t has_data; 3121 3122 DBG1(vgenp, ldcp, "enter\n"); 3123 3124 if (caller == VGEN_LDC_CB) { 3125 ASSERT(MUTEX_HELD(&ldcp->cblock)); 3126 } else if (caller == VGEN_MSG_THR) { 3127 mutex_enter(&ldcp->cblock); 3128 } else { 3129 return (EINVAL); 3130 } 3131 3132 ldcmsg = ldcp->ldcmsg; 3133 3134 vgen_evtread: 3135 do { 3136 msglen = ldcp->msglen; 3137 rv = ldc_read(ldcp->ldc_handle, (caddr_t)ldcmsg, &msglen); 3138 3139 if (rv != 0) { 3140 DWARN(vgenp, ldcp, "ldc_read() failed " 3141 "rv(%d) len(%d)\n", rv, msglen); 3142 if (rv == ECONNRESET) 3143 goto vgen_evtread_error; 3144 break; 3145 } 3146 if (msglen == 0) { 3147 DBG2(vgenp, ldcp, "ldc_read NODATA"); 3148 break; 3149 } 3150 DBG2(vgenp, ldcp, "ldc_read msglen(%d)", msglen); 3151 3152 tagp = (vio_msg_tag_t *)ldcmsg; 3153 3154 if (ldcp->peer_sid) { 3155 /* 3156 * check sid only after we have received peer's sid 3157 * in the version negotiate msg. 3158 */ 3159 #ifdef DEBUG 3160 if (vgen_inject_error(ldcp, VGEN_ERR_HSID)) { 3161 /* simulate bad sid condition */ 3162 tagp->vio_sid = 0; 3163 vgen_inject_err_flag &= ~(VGEN_ERR_HSID); 3164 } 3165 #endif 3166 rv = vgen_check_sid(ldcp, tagp); 3167 if (rv != VGEN_SUCCESS) { 3168 /* 3169 * If sid mismatch is detected, 3170 * reset the channel. 3171 */ 3172 DWARN(vgenp, ldcp, "vgen_check_sid() failed\n"); 3173 goto vgen_evtread_error; 3174 } 3175 } 3176 3177 switch (tagp->vio_msgtype) { 3178 case VIO_TYPE_CTRL: 3179 rv = vgen_handle_ctrlmsg(ldcp, tagp); 3180 if (rv != 0) { 3181 DWARN(vgenp, ldcp, "vgen_handle_ctrlmsg()" 3182 " failed rv(%d)\n", rv); 3183 } 3184 break; 3185 3186 case VIO_TYPE_DATA: 3187 rv = vgen_handle_datamsg(ldcp, tagp, msglen); 3188 if (rv != 0) { 3189 DWARN(vgenp, ldcp, "vgen_handle_datamsg()" 3190 " failed rv(%d)\n", rv); 3191 } 3192 break; 3193 3194 case VIO_TYPE_ERR: 3195 vgen_handle_errmsg(ldcp, tagp); 3196 break; 3197 3198 default: 3199 DWARN(vgenp, ldcp, "Unknown VIO_TYPE(%x)\n", 3200 tagp->vio_msgtype); 3201 break; 3202 } 3203 3204 /* 3205 * If an error is encountered, stop processing and 3206 * handle the error. 3207 */ 3208 if (rv != 0) { 3209 goto vgen_evtread_error; 3210 } 3211 3212 } while (msglen); 3213 3214 /* check once more before exiting */ 3215 rv = ldc_chkq(ldcp->ldc_handle, &has_data); 3216 if ((rv == 0) && (has_data == B_TRUE)) { 3217 DTRACE_PROBE1(vgen_chkq, vgen_ldc_t *, ldcp); 3218 goto vgen_evtread; 3219 } 3220 3221 vgen_evtread_error: 3222 if (rv != 0) { 3223 /* 3224 * We handle the error and then return the error value. If we 3225 * are running in the context of the msg worker, the error 3226 * tells the worker thread to exit, as the channel would have 3227 * been reset. 3228 */ 3229 if (rv == ECONNRESET) { 3230 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 3231 DWARN(vgenp, ldcp, "ldc_status err\n"); 3232 } else { 3233 ldcp->ldc_status = istatus; 3234 } 3235 (void) vgen_handle_evt_reset(ldcp, caller); 3236 } else { 3237 DWARN(vgenp, ldcp, "Calling vgen_ldc_reset()...\n"); 3238 (void) vgen_ldc_reset(ldcp, caller); 3239 } 3240 } 3241 3242 if (caller == VGEN_MSG_THR) { 3243 mutex_exit(&ldcp->cblock); 3244 } 3245 3246 DBG1(vgenp, ldcp, "exit\n"); 3247 return (rv); 3248 } 3249 3250 /* vgen handshake functions */ 3251 3252 /* change the hphase for the channel to the next phase */ 3253 static vgen_ldc_t * 3254 vh_nextphase(vgen_ldc_t *ldcp) 3255 { 3256 if (ldcp->hphase == VH_PHASE4) { 3257 ldcp->hphase = VH_DONE; 3258 } else { 3259 ldcp->hphase++; 3260 } 3261 return (ldcp); 3262 } 3263 3264 /* send version negotiate message to the peer over ldc */ 3265 static int 3266 vgen_send_version_negotiate(vgen_ldc_t *ldcp) 3267 { 3268 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3269 vio_ver_msg_t vermsg; 3270 vio_msg_tag_t *tagp = &vermsg.tag; 3271 int rv; 3272 3273 bzero(&vermsg, sizeof (vermsg)); 3274 3275 tagp->vio_msgtype = VIO_TYPE_CTRL; 3276 tagp->vio_subtype = VIO_SUBTYPE_INFO; 3277 tagp->vio_subtype_env = VIO_VER_INFO; 3278 tagp->vio_sid = ldcp->local_sid; 3279 3280 /* get version msg payload from ldcp->local */ 3281 vermsg.ver_major = ldcp->local_hparams.ver_major; 3282 vermsg.ver_minor = ldcp->local_hparams.ver_minor; 3283 vermsg.dev_class = ldcp->local_hparams.dev_class; 3284 3285 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vermsg), B_FALSE); 3286 if (rv != VGEN_SUCCESS) { 3287 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 3288 return (rv); 3289 } 3290 3291 ldcp->hstate |= VER_INFO_SENT; 3292 DBG2(vgenp, ldcp, "VER_INFO_SENT ver(%d,%d)\n", 3293 vermsg.ver_major, vermsg.ver_minor); 3294 3295 return (VGEN_SUCCESS); 3296 } 3297 3298 /* send attr info message to the peer over ldc */ 3299 static int 3300 vgen_send_attr_info(vgen_ldc_t *ldcp) 3301 { 3302 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3303 vnet_attr_msg_t attrmsg; 3304 vio_msg_tag_t *tagp = &attrmsg.tag; 3305 int rv; 3306 3307 bzero(&attrmsg, sizeof (attrmsg)); 3308 3309 tagp->vio_msgtype = VIO_TYPE_CTRL; 3310 tagp->vio_subtype = VIO_SUBTYPE_INFO; 3311 tagp->vio_subtype_env = VIO_ATTR_INFO; 3312 tagp->vio_sid = ldcp->local_sid; 3313 3314 /* get attr msg payload from ldcp->local */ 3315 attrmsg.mtu = ldcp->local_hparams.mtu; 3316 attrmsg.addr = ldcp->local_hparams.addr; 3317 attrmsg.addr_type = ldcp->local_hparams.addr_type; 3318 attrmsg.xfer_mode = ldcp->local_hparams.xfer_mode; 3319 attrmsg.ack_freq = ldcp->local_hparams.ack_freq; 3320 attrmsg.physlink_update = ldcp->local_hparams.physlink_update; 3321 attrmsg.options = ldcp->local_hparams.dring_mode; 3322 3323 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE); 3324 if (rv != VGEN_SUCCESS) { 3325 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 3326 return (rv); 3327 } 3328 3329 ldcp->hstate |= ATTR_INFO_SENT; 3330 DBG2(vgenp, ldcp, "ATTR_INFO_SENT\n"); 3331 3332 return (VGEN_SUCCESS); 3333 } 3334 3335 /* 3336 * Send descriptor ring register message to the peer over ldc. 3337 * Invoked in RxDringData mode. 3338 */ 3339 static int 3340 vgen_send_rx_dring_reg(vgen_ldc_t *ldcp) 3341 { 3342 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3343 vio_dring_reg_msg_t *msg; 3344 vio_dring_reg_ext_msg_t *emsg; 3345 int rv; 3346 uint8_t *buf; 3347 uint_t msgsize; 3348 3349 msgsize = VNET_DRING_REG_EXT_MSG_SIZE(ldcp->rx_data_ncookies); 3350 msg = kmem_zalloc(msgsize, KM_SLEEP); 3351 3352 /* Initialize the common part of dring reg msg */ 3353 vgen_init_dring_reg_msg(ldcp, msg, VIO_RX_DRING_DATA); 3354 3355 /* skip over dring cookies at the tail of common section */ 3356 buf = (uint8_t *)msg->cookie; 3357 ASSERT(msg->ncookies == 1); 3358 buf += (msg->ncookies * sizeof (ldc_mem_cookie_t)); 3359 3360 /* Now setup the extended part, specific to RxDringData mode */ 3361 emsg = (vio_dring_reg_ext_msg_t *)buf; 3362 3363 /* copy data_ncookies in the msg */ 3364 emsg->data_ncookies = ldcp->rx_data_ncookies; 3365 3366 /* copy data area size in the msg */ 3367 emsg->data_area_size = ldcp->rx_data_sz; 3368 3369 /* copy data area cookies in the msg */ 3370 bcopy(ldcp->rx_data_cookie, (ldc_mem_cookie_t *)emsg->data_cookie, 3371 sizeof (ldc_mem_cookie_t) * ldcp->rx_data_ncookies); 3372 3373 rv = vgen_sendmsg(ldcp, (caddr_t)msg, msgsize, B_FALSE); 3374 if (rv != VGEN_SUCCESS) { 3375 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 3376 kmem_free(msg, msgsize); 3377 return (rv); 3378 } 3379 3380 ldcp->hstate |= DRING_INFO_SENT; 3381 DBG2(vgenp, ldcp, "DRING_INFO_SENT \n"); 3382 3383 kmem_free(msg, msgsize); 3384 return (VGEN_SUCCESS); 3385 } 3386 3387 /* 3388 * Send descriptor ring register message to the peer over ldc. 3389 * Invoked in TxDring mode. 3390 */ 3391 static int 3392 vgen_send_tx_dring_reg(vgen_ldc_t *ldcp) 3393 { 3394 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3395 vio_dring_reg_msg_t msg; 3396 int rv; 3397 3398 bzero(&msg, sizeof (msg)); 3399 3400 /* 3401 * Initialize only the common part of dring reg msg in TxDring mode. 3402 */ 3403 vgen_init_dring_reg_msg(ldcp, &msg, VIO_TX_DRING); 3404 3405 rv = vgen_sendmsg(ldcp, (caddr_t)&msg, sizeof (msg), B_FALSE); 3406 if (rv != VGEN_SUCCESS) { 3407 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 3408 return (rv); 3409 } 3410 3411 ldcp->hstate |= DRING_INFO_SENT; 3412 DBG2(vgenp, ldcp, "DRING_INFO_SENT \n"); 3413 3414 return (VGEN_SUCCESS); 3415 } 3416 3417 static int 3418 vgen_send_rdx_info(vgen_ldc_t *ldcp) 3419 { 3420 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3421 vio_rdx_msg_t rdxmsg; 3422 vio_msg_tag_t *tagp = &rdxmsg.tag; 3423 int rv; 3424 3425 bzero(&rdxmsg, sizeof (rdxmsg)); 3426 3427 tagp->vio_msgtype = VIO_TYPE_CTRL; 3428 tagp->vio_subtype = VIO_SUBTYPE_INFO; 3429 tagp->vio_subtype_env = VIO_RDX; 3430 tagp->vio_sid = ldcp->local_sid; 3431 3432 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (rdxmsg), B_FALSE); 3433 if (rv != VGEN_SUCCESS) { 3434 DWARN(vgenp, ldcp, "vgen_sendmsg failed\n"); 3435 return (rv); 3436 } 3437 3438 ldcp->hstate |= RDX_INFO_SENT; 3439 DBG2(vgenp, ldcp, "RDX_INFO_SENT\n"); 3440 3441 return (VGEN_SUCCESS); 3442 } 3443 3444 /* send multicast addr info message to vsw */ 3445 static int 3446 vgen_send_mcast_info(vgen_ldc_t *ldcp) 3447 { 3448 vnet_mcast_msg_t mcastmsg; 3449 vnet_mcast_msg_t *msgp; 3450 vio_msg_tag_t *tagp; 3451 vgen_t *vgenp; 3452 struct ether_addr *mca; 3453 int rv; 3454 int i; 3455 uint32_t size; 3456 uint32_t mccount; 3457 uint32_t n; 3458 3459 msgp = &mcastmsg; 3460 tagp = &msgp->tag; 3461 vgenp = LDC_TO_VGEN(ldcp); 3462 3463 mccount = vgenp->mccount; 3464 i = 0; 3465 3466 do { 3467 tagp->vio_msgtype = VIO_TYPE_CTRL; 3468 tagp->vio_subtype = VIO_SUBTYPE_INFO; 3469 tagp->vio_subtype_env = VNET_MCAST_INFO; 3470 tagp->vio_sid = ldcp->local_sid; 3471 3472 n = ((mccount >= VNET_NUM_MCAST) ? VNET_NUM_MCAST : mccount); 3473 size = n * sizeof (struct ether_addr); 3474 3475 mca = &(vgenp->mctab[i]); 3476 bcopy(mca, (msgp->mca), size); 3477 msgp->set = B_TRUE; 3478 msgp->count = n; 3479 3480 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), 3481 B_FALSE); 3482 if (rv != VGEN_SUCCESS) { 3483 DWARN(vgenp, ldcp, "vgen_sendmsg err(%d)\n", rv); 3484 return (rv); 3485 } 3486 3487 mccount -= n; 3488 i += n; 3489 3490 } while (mccount); 3491 3492 return (VGEN_SUCCESS); 3493 } 3494 3495 /* 3496 * vgen_dds_rx -- post DDS messages to vnet. 3497 */ 3498 static int 3499 vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 3500 { 3501 vio_dds_msg_t *dmsg = (vio_dds_msg_t *)tagp; 3502 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3503 3504 if (dmsg->dds_class != DDS_VNET_NIU) { 3505 DWARN(vgenp, ldcp, "Unknown DDS class, dropping"); 3506 return (EBADMSG); 3507 } 3508 vnet_dds_rx(vgenp->vnetp, dmsg); 3509 return (0); 3510 } 3511 3512 /* 3513 * vgen_dds_tx -- an interface called by vnet to send DDS messages. 3514 */ 3515 int 3516 vgen_dds_tx(void *arg, void *msg) 3517 { 3518 vgen_t *vgenp = arg; 3519 vio_dds_msg_t *dmsg = msg; 3520 vgen_portlist_t *plistp = &vgenp->vgenports; 3521 vgen_ldc_t *ldcp; 3522 int rv = EIO; 3523 3524 READ_ENTER(&plistp->rwlock); 3525 ldcp = vgenp->vsw_portp->ldcp; 3526 if ((ldcp == NULL) || (ldcp->hphase != VH_DONE)) { 3527 goto vgen_dsend_exit; 3528 } 3529 3530 dmsg->tag.vio_sid = ldcp->local_sid; 3531 rv = vgen_sendmsg(ldcp, (caddr_t)dmsg, sizeof (vio_dds_msg_t), B_FALSE); 3532 if (rv != VGEN_SUCCESS) { 3533 rv = EIO; 3534 } else { 3535 rv = 0; 3536 } 3537 3538 vgen_dsend_exit: 3539 RW_EXIT(&plistp->rwlock); 3540 return (rv); 3541 3542 } 3543 3544 /* Initiate Phase 2 of handshake */ 3545 static int 3546 vgen_handshake_phase2(vgen_ldc_t *ldcp) 3547 { 3548 int rv; 3549 3550 #ifdef DEBUG 3551 if (vgen_inject_error(ldcp, VGEN_ERR_HSTATE)) { 3552 /* simulate out of state condition */ 3553 vgen_inject_err_flag &= ~(VGEN_ERR_HSTATE); 3554 rv = vgen_send_rdx_info(ldcp); 3555 return (rv); 3556 } 3557 if (vgen_inject_error(ldcp, VGEN_ERR_HTIMEOUT)) { 3558 /* simulate timeout condition */ 3559 vgen_inject_err_flag &= ~(VGEN_ERR_HTIMEOUT); 3560 return (VGEN_SUCCESS); 3561 } 3562 #endif 3563 rv = vgen_send_attr_info(ldcp); 3564 if (rv != VGEN_SUCCESS) { 3565 return (rv); 3566 } 3567 3568 return (VGEN_SUCCESS); 3569 } 3570 3571 static int 3572 vgen_handshake_phase3(vgen_ldc_t *ldcp) 3573 { 3574 int rv; 3575 vgen_hparams_t *lp = &ldcp->local_hparams; 3576 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3577 vgen_stats_t *statsp = &ldcp->stats; 3578 3579 /* dring mode has been negotiated in attr phase; save in stats */ 3580 statsp->dring_mode = lp->dring_mode; 3581 3582 if (lp->dring_mode == VIO_RX_DRING_DATA) { /* RxDringData mode */ 3583 ldcp->rx_dringdata = vgen_handle_dringdata_shm; 3584 ldcp->tx_dringdata = vgen_dringsend_shm; 3585 if (!VGEN_PRI_ETH_DEFINED(vgenp)) { 3586 /* 3587 * If priority frames are not in use, we don't need a 3588 * separate wrapper function for 'tx', so we set it to 3589 * 'tx_dringdata'. If priority frames are configured, 3590 * we leave the 'tx' pointer as is (initialized in 3591 * vgen_set_vnet_proto_ops()). 3592 */ 3593 ldcp->tx = ldcp->tx_dringdata; 3594 } 3595 } else { /* TxDring mode */ 3596 ldcp->msg_thread = thread_create(NULL, 3597 2 * DEFAULTSTKSZ, vgen_ldc_msg_worker, ldcp, 0, 3598 &p0, TS_RUN, maxclsyspri); 3599 } 3600 3601 rv = vgen_create_dring(ldcp); 3602 if (rv != VGEN_SUCCESS) { 3603 return (rv); 3604 } 3605 3606 /* update local dring_info params */ 3607 if (lp->dring_mode == VIO_RX_DRING_DATA) { 3608 bcopy(&(ldcp->rx_dring_cookie), 3609 &(ldcp->local_hparams.dring_cookie), 3610 sizeof (ldc_mem_cookie_t)); 3611 ldcp->local_hparams.dring_ncookies = ldcp->rx_dring_ncookies; 3612 ldcp->local_hparams.num_desc = ldcp->num_rxds; 3613 ldcp->local_hparams.desc_size = 3614 sizeof (vnet_rx_dringdata_desc_t); 3615 rv = vgen_send_rx_dring_reg(ldcp); 3616 } else { 3617 bcopy(&(ldcp->tx_dring_cookie), 3618 &(ldcp->local_hparams.dring_cookie), 3619 sizeof (ldc_mem_cookie_t)); 3620 ldcp->local_hparams.dring_ncookies = ldcp->tx_dring_ncookies; 3621 ldcp->local_hparams.num_desc = ldcp->num_txds; 3622 ldcp->local_hparams.desc_size = sizeof (vnet_public_desc_t); 3623 rv = vgen_send_tx_dring_reg(ldcp); 3624 } 3625 3626 if (rv != VGEN_SUCCESS) { 3627 return (rv); 3628 } 3629 3630 return (VGEN_SUCCESS); 3631 } 3632 3633 /* 3634 * Set vnet-protocol-version dependent functions based on version. 3635 */ 3636 static void 3637 vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp) 3638 { 3639 vgen_hparams_t *lp = &ldcp->local_hparams; 3640 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3641 3642 /* 3643 * Setup the appropriate dring data processing routine and any 3644 * associated thread based on the version. 3645 * 3646 * In versions < 1.6, we only support TxDring mode. In this mode, the 3647 * msg worker thread processes all types of VIO msgs (ctrl and data). 3648 * 3649 * In versions >= 1.6, we also support RxDringData mode. In this mode, 3650 * all msgs including dring data messages are handled directly by the 3651 * callback (intr) thread. The dring data msgs (msgtype: VIO_TYPE_DATA, 3652 * subtype: VIO_SUBTYPE_INFO, subtype_env: VIO_DRING_DATA) can also be 3653 * disabled while the polling thread is active, in which case the 3654 * polling thread processes the rcv descriptor ring. 3655 * 3656 * However, for versions >= 1.6, we can force to only use TxDring mode. 3657 * This could happen if RxDringData mode has been disabled (see 3658 * vgen_dring_mode) on this guest or on the peer guest. This info is 3659 * determined as part of attr exchange phase of handshake. Hence, we 3660 * setup these pointers for v1.6 after attr msg phase completes during 3661 * handshake. 3662 */ 3663 if (VGEN_VER_GTEQ(ldcp, 1, 6)) { /* Ver >= 1.6 */ 3664 /* 3665 * Set data dring mode for vgen_send_attr_info(). 3666 */ 3667 if (vgen_dring_mode == VIO_RX_DRING_DATA) { 3668 lp->dring_mode = (VIO_RX_DRING_DATA | VIO_TX_DRING); 3669 } else { 3670 lp->dring_mode = VIO_TX_DRING; 3671 } 3672 } else { /* Ver <= 1.5 */ 3673 lp->dring_mode = VIO_TX_DRING; 3674 } 3675 3676 if (VGEN_VER_GTEQ(ldcp, 1, 5)) { 3677 vgen_port_t *portp = ldcp->portp; 3678 vnet_t *vnetp = vgenp->vnetp; 3679 /* 3680 * If the version negotiated with vswitch is >= 1.5 (link 3681 * status update support), set the required bits in our 3682 * attributes if this vnet device has been configured to get 3683 * physical link state updates. 3684 */ 3685 if (portp == vgenp->vsw_portp && vnetp->pls_update == B_TRUE) { 3686 lp->physlink_update = PHYSLINK_UPDATE_STATE; 3687 } else { 3688 lp->physlink_update = PHYSLINK_UPDATE_NONE; 3689 } 3690 } 3691 3692 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 3693 /* 3694 * If the version negotiated with peer is >= 1.4(Jumbo Frame 3695 * Support), set the mtu in our attributes to max_frame_size. 3696 */ 3697 lp->mtu = vgenp->max_frame_size; 3698 } else if (VGEN_VER_EQ(ldcp, 1, 3)) { 3699 /* 3700 * If the version negotiated with peer is == 1.3 (Vlan Tag 3701 * Support) set the attr.mtu to ETHERMAX + VLAN_TAGSZ. 3702 */ 3703 lp->mtu = ETHERMAX + VLAN_TAGSZ; 3704 } else { 3705 vgen_port_t *portp = ldcp->portp; 3706 vnet_t *vnetp = vgenp->vnetp; 3707 /* 3708 * Pre-1.3 peers expect max frame size of ETHERMAX. 3709 * We can negotiate that size with those peers provided the 3710 * following conditions are true: 3711 * - Only pvid is defined for our peer and there are no vids. 3712 * - pvids are equal. 3713 * If the above conditions are true, then we can send/recv only 3714 * untagged frames of max size ETHERMAX. 3715 */ 3716 if (portp->nvids == 0 && portp->pvid == vnetp->pvid) { 3717 lp->mtu = ETHERMAX; 3718 } 3719 } 3720 3721 if (VGEN_VER_GTEQ(ldcp, 1, 2)) { /* Versions >= 1.2 */ 3722 /* 3723 * Starting v1.2 we support priority frames; so set the 3724 * dring processing routines and xfer modes based on the 3725 * version. Note that the dring routines could be changed after 3726 * attribute handshake phase for versions >= 1.6 (See 3727 * vgen_handshake_phase3()) 3728 */ 3729 ldcp->tx_dringdata = vgen_dringsend; 3730 ldcp->rx_dringdata = vgen_handle_dringdata; 3731 3732 if (VGEN_PRI_ETH_DEFINED(vgenp)) { 3733 /* 3734 * Enable priority routines and pkt mode only if 3735 * at least one pri-eth-type is specified in MD. 3736 */ 3737 ldcp->tx = vgen_ldcsend; 3738 ldcp->rx_pktdata = vgen_handle_pkt_data; 3739 3740 /* set xfer mode for vgen_send_attr_info() */ 3741 lp->xfer_mode = VIO_PKT_MODE | VIO_DRING_MODE_V1_2; 3742 } else { 3743 /* No priority eth types defined in MD */ 3744 ldcp->tx = ldcp->tx_dringdata; 3745 ldcp->rx_pktdata = vgen_handle_pkt_data_nop; 3746 3747 /* Set xfer mode for vgen_send_attr_info() */ 3748 lp->xfer_mode = VIO_DRING_MODE_V1_2; 3749 } 3750 } else { /* Versions prior to 1.2 */ 3751 vgen_reset_vnet_proto_ops(ldcp); 3752 } 3753 } 3754 3755 /* 3756 * Reset vnet-protocol-version dependent functions to pre-v1.2. 3757 */ 3758 static void 3759 vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp) 3760 { 3761 vgen_hparams_t *lp = &ldcp->local_hparams; 3762 3763 ldcp->tx = ldcp->tx_dringdata = vgen_dringsend; 3764 ldcp->rx_dringdata = vgen_handle_dringdata; 3765 ldcp->rx_pktdata = vgen_handle_pkt_data_nop; 3766 3767 /* set xfer mode for vgen_send_attr_info() */ 3768 lp->xfer_mode = VIO_DRING_MODE_V1_0; 3769 } 3770 3771 static void 3772 vgen_vlan_unaware_port_reset(vgen_port_t *portp) 3773 { 3774 vgen_ldc_t *ldcp = portp->ldcp; 3775 vgen_t *vgenp = portp->vgenp; 3776 vnet_t *vnetp = vgenp->vnetp; 3777 boolean_t need_reset = B_FALSE; 3778 3779 mutex_enter(&ldcp->cblock); 3780 3781 /* 3782 * If the peer is vlan_unaware(ver < 1.3), reset channel and terminate 3783 * the connection. See comments in vgen_set_vnet_proto_ops(). 3784 */ 3785 if (ldcp->hphase == VH_DONE && VGEN_VER_LT(ldcp, 1, 3) && 3786 (portp->nvids != 0 || portp->pvid != vnetp->pvid)) { 3787 need_reset = B_TRUE; 3788 } 3789 mutex_exit(&ldcp->cblock); 3790 3791 if (need_reset == B_TRUE) { 3792 (void) vgen_ldc_reset(ldcp, VGEN_OTHER); 3793 } 3794 } 3795 3796 static void 3797 vgen_port_reset(vgen_port_t *portp) 3798 { 3799 (void) vgen_ldc_reset(portp->ldcp, VGEN_OTHER); 3800 } 3801 3802 static void 3803 vgen_reset_vlan_unaware_ports(vgen_t *vgenp) 3804 { 3805 vgen_port_t *portp; 3806 vgen_portlist_t *plistp; 3807 3808 plistp = &(vgenp->vgenports); 3809 READ_ENTER(&plistp->rwlock); 3810 3811 for (portp = plistp->headp; portp != NULL; portp = portp->nextp) { 3812 3813 vgen_vlan_unaware_port_reset(portp); 3814 3815 } 3816 3817 RW_EXIT(&plistp->rwlock); 3818 } 3819 3820 static void 3821 vgen_reset_vsw_port(vgen_t *vgenp) 3822 { 3823 vgen_port_t *portp; 3824 3825 if ((portp = vgenp->vsw_portp) != NULL) { 3826 vgen_port_reset(portp); 3827 } 3828 } 3829 3830 static void 3831 vgen_setup_handshake_params(vgen_ldc_t *ldcp) 3832 { 3833 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3834 3835 /* 3836 * clear local handshake params and initialize. 3837 */ 3838 bzero(&(ldcp->local_hparams), sizeof (ldcp->local_hparams)); 3839 3840 /* set version to the highest version supported */ 3841 ldcp->local_hparams.ver_major = 3842 ldcp->vgen_versions[0].ver_major; 3843 ldcp->local_hparams.ver_minor = 3844 ldcp->vgen_versions[0].ver_minor; 3845 ldcp->local_hparams.dev_class = VDEV_NETWORK; 3846 3847 /* set attr_info params */ 3848 ldcp->local_hparams.mtu = vgenp->max_frame_size; 3849 ldcp->local_hparams.addr = 3850 vnet_macaddr_strtoul(vgenp->macaddr); 3851 ldcp->local_hparams.addr_type = ADDR_TYPE_MAC; 3852 ldcp->local_hparams.xfer_mode = VIO_DRING_MODE_V1_0; 3853 ldcp->local_hparams.ack_freq = 0; /* don't need acks */ 3854 ldcp->local_hparams.physlink_update = PHYSLINK_UPDATE_NONE; 3855 3856 /* reset protocol version specific function pointers */ 3857 vgen_reset_vnet_proto_ops(ldcp); 3858 ldcp->local_hparams.dring_ident = 0; 3859 ldcp->local_hparams.dring_ready = B_FALSE; 3860 3861 /* clear peer_hparams */ 3862 bzero(&(ldcp->peer_hparams), sizeof (ldcp->peer_hparams)); 3863 ldcp->peer_hparams.dring_ready = B_FALSE; 3864 } 3865 3866 /* 3867 * Process Channel Reset. We tear down the resources (timers, threads, 3868 * descriptor rings etc) associated with the channel and reinitialize the 3869 * channel based on the flags. 3870 * 3871 * Arguments: 3872 * ldcp: The channel being processed. 3873 * 3874 * flags: 3875 * VGEN_FLAG_EVT_RESET: 3876 * A ECONNRESET error occured while doing ldc operations such as 3877 * ldc_read() or ldc_write(); the channel is already reset and it 3878 * needs to be handled. 3879 * VGEN_FLAG_NEED_LDCRESET: 3880 * Some other errors occured and the error handling code needs to 3881 * explicitly reset the channel and restart handshake with the 3882 * peer. The error could be either in ldc operations or other 3883 * parts of the code such as timeouts or mdeg events etc. 3884 * VGEN_FLAG_UNINIT: 3885 * The channel is being torn down; no need to bring up the channel 3886 * after resetting. 3887 */ 3888 static int 3889 vgen_process_reset(vgen_ldc_t *ldcp, int flags) 3890 { 3891 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 3892 vgen_port_t *portp = ldcp->portp; 3893 vgen_hparams_t *lp = &ldcp->local_hparams; 3894 boolean_t is_vsw_port = B_FALSE; 3895 boolean_t link_update = B_FALSE; 3896 ldc_status_t istatus; 3897 int rv; 3898 uint_t retries = 0; 3899 timeout_id_t htid = 0; 3900 timeout_id_t wd_tid = 0; 3901 3902 if (portp == vgenp->vsw_portp) { /* vswitch port ? */ 3903 is_vsw_port = B_TRUE; 3904 } 3905 3906 /* 3907 * Report that the channel is being reset; it ensures that any HybridIO 3908 * configuration is torn down before we reset the channel if it is not 3909 * already reset (flags == VGEN_FLAG_NEED_LDCRESET). 3910 */ 3911 if (is_vsw_port == B_TRUE) { 3912 vio_net_report_err_t rep_err = portp->vcb.vio_net_report_err; 3913 rep_err(portp->vhp, VIO_NET_RES_DOWN); 3914 } 3915 3916 again: 3917 mutex_enter(&ldcp->cblock); 3918 3919 /* Clear hstate and hphase */ 3920 ldcp->hstate = 0; 3921 ldcp->hphase = VH_PHASE0; 3922 if (flags == VGEN_FLAG_NEED_LDCRESET || flags == VGEN_FLAG_UNINIT) { 3923 DWARN(vgenp, ldcp, "Doing Channel Reset...\n"); 3924 (void) ldc_down(ldcp->ldc_handle); 3925 (void) ldc_status(ldcp->ldc_handle, &istatus); 3926 DWARN(vgenp, ldcp, "Reset Done, ldc_status(%d)\n", istatus); 3927 ldcp->ldc_status = istatus; 3928 3929 if (flags == VGEN_FLAG_UNINIT) { 3930 /* disable further callbacks */ 3931 rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE); 3932 if (rv != 0) { 3933 DWARN(vgenp, ldcp, "ldc_set_cb_mode failed\n"); 3934 } 3935 } 3936 3937 } else { 3938 /* flags == VGEN_FLAG_EVT_RESET */ 3939 DWARN(vgenp, ldcp, "ldc status(%d)\n", ldcp->ldc_status); 3940 } 3941 3942 /* 3943 * As the connection is now reset, mark the channel 3944 * link_state as 'down' and notify the stack if needed. 3945 */ 3946 if (ldcp->link_state != LINK_STATE_DOWN) { 3947 ldcp->link_state = LINK_STATE_DOWN; 3948 3949 if (is_vsw_port == B_TRUE) { /* vswitch port ? */ 3950 /* 3951 * As the channel link is down, mark physical link also 3952 * as down. After the channel comes back up and 3953 * handshake completes, we will get an update on the 3954 * physlink state from vswitch (if this device has been 3955 * configured to get phys link updates). 3956 */ 3957 vgenp->phys_link_state = LINK_STATE_DOWN; 3958 link_update = B_TRUE; 3959 3960 } 3961 } 3962 3963 if (ldcp->htid != 0) { 3964 htid = ldcp->htid; 3965 ldcp->htid = 0; 3966 } 3967 3968 if (ldcp->wd_tid != 0) { 3969 wd_tid = ldcp->wd_tid; 3970 ldcp->wd_tid = 0; 3971 } 3972 3973 mutex_exit(&ldcp->cblock); 3974 3975 /* Update link state to the stack */ 3976 if (link_update == B_TRUE) { 3977 vgen_link_update(vgenp, ldcp->link_state); 3978 } 3979 3980 /* 3981 * As the channel is being reset, redirect traffic to the peer through 3982 * vswitch, until the channel becomes ready to be used again. 3983 */ 3984 if (is_vsw_port == B_FALSE && vgenp->vsw_portp != NULL) { 3985 (void) atomic_swap_32(&portp->use_vsw_port, B_TRUE); 3986 } 3987 3988 /* Cancel handshake watchdog timeout */ 3989 if (htid) { 3990 (void) untimeout(htid); 3991 } 3992 3993 /* Cancel transmit watchdog timeout */ 3994 if (wd_tid) { 3995 (void) untimeout(wd_tid); 3996 } 3997 3998 /* Stop the msg worker thread */ 3999 if (lp->dring_mode == VIO_TX_DRING && curthread != ldcp->msg_thread) { 4000 vgen_stop_msg_thread(ldcp); 4001 } 4002 4003 /* Grab all locks while we tear down tx/rx resources */ 4004 LDC_LOCK(ldcp); 4005 4006 /* Destroy the local dring which is exported to the peer */ 4007 vgen_destroy_dring(ldcp); 4008 4009 /* Unmap the remote dring which is imported from the peer */ 4010 vgen_unmap_dring(ldcp); 4011 4012 /* 4013 * Bring up the channel and restart handshake 4014 * only if the channel is not being torn down. 4015 */ 4016 if (flags != VGEN_FLAG_UNINIT) { 4017 4018 /* Setup handshake parameters to restart a new handshake */ 4019 vgen_setup_handshake_params(ldcp); 4020 4021 /* Bring the channel up */ 4022 vgen_ldc_up(ldcp); 4023 4024 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 4025 DWARN(vgenp, ldcp, "ldc_status err\n"); 4026 } else { 4027 ldcp->ldc_status = istatus; 4028 } 4029 4030 /* If the channel is UP, start handshake */ 4031 if (ldcp->ldc_status == LDC_UP) { 4032 4033 if (is_vsw_port == B_FALSE) { 4034 /* 4035 * Channel is up; use this port from now on. 4036 */ 4037 (void) atomic_swap_32(&portp->use_vsw_port, 4038 B_FALSE); 4039 } 4040 4041 /* Initialize local session id */ 4042 ldcp->local_sid = ddi_get_lbolt(); 4043 4044 /* clear peer session id */ 4045 ldcp->peer_sid = 0; 4046 4047 /* 4048 * Initiate Handshake process with peer ldc endpoint by 4049 * sending version info vio message. If that fails we 4050 * go back to the top of this function to process the 4051 * error again. Note that we can be in this loop for 4052 * 'vgen_ldc_max_resets' times, after which the channel 4053 * is not brought up. 4054 */ 4055 mutex_exit(&ldcp->tclock); 4056 mutex_exit(&ldcp->txlock); 4057 mutex_exit(&ldcp->wrlock); 4058 mutex_exit(&ldcp->rxlock); 4059 rv = vgen_handshake(vh_nextphase(ldcp)); 4060 mutex_exit(&ldcp->cblock); 4061 if (rv != 0) { 4062 if (rv == ECONNRESET) { 4063 flags = VGEN_FLAG_EVT_RESET; 4064 } else { 4065 flags = VGEN_FLAG_NEED_LDCRESET; 4066 } 4067 4068 /* 4069 * We still hold 'reset_in_progress'; so we can 4070 * just loop back to the top to restart error 4071 * processing. 4072 */ 4073 goto again; 4074 } 4075 } else { 4076 LDC_UNLOCK(ldcp); 4077 } 4078 4079 } else { /* flags == VGEN_FLAG_UNINIT */ 4080 4081 /* Close the channel - retry on EAGAIN */ 4082 while ((rv = ldc_close(ldcp->ldc_handle)) == EAGAIN) { 4083 if (++retries > vgen_ldccl_retries) { 4084 break; 4085 } 4086 drv_usecwait(VGEN_LDC_CLOSE_DELAY); 4087 } 4088 if (rv != 0) { 4089 cmn_err(CE_NOTE, 4090 "!vnet%d: Error(%d) closing the channel(0x%lx)\n", 4091 vgenp->instance, rv, ldcp->ldc_id); 4092 } 4093 4094 ldcp->ldc_reset_count = 0; 4095 ldcp->ldc_status = LDC_INIT; 4096 ldcp->flags &= ~(CHANNEL_STARTED); 4097 4098 LDC_UNLOCK(ldcp); 4099 } 4100 4101 /* Done processing channel reset; clear the atomic flag */ 4102 ldcp->reset_in_progress = 0; 4103 return (0); 4104 } 4105 4106 /* 4107 * Initiate handshake with the peer by sending various messages 4108 * based on the handshake-phase that the channel is currently in. 4109 */ 4110 static int 4111 vgen_handshake(vgen_ldc_t *ldcp) 4112 { 4113 uint32_t hphase = ldcp->hphase; 4114 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4115 int rv = 0; 4116 timeout_id_t htid; 4117 4118 switch (hphase) { 4119 4120 case VH_PHASE1: 4121 4122 /* 4123 * start timer, for entire handshake process, turn this timer 4124 * off if all phases of handshake complete successfully and 4125 * hphase goes to VH_DONE(below) or channel is reset due to 4126 * errors or vgen_ldc_uninit() is invoked(vgen_stop). 4127 */ 4128 ASSERT(ldcp->htid == 0); 4129 ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp, 4130 drv_usectohz(vgen_hwd_interval * MICROSEC)); 4131 4132 /* Phase 1 involves negotiating the version */ 4133 rv = vgen_send_version_negotiate(ldcp); 4134 break; 4135 4136 case VH_PHASE2: 4137 rv = vgen_handshake_phase2(ldcp); 4138 break; 4139 4140 case VH_PHASE3: 4141 rv = vgen_handshake_phase3(ldcp); 4142 break; 4143 4144 case VH_PHASE4: 4145 rv = vgen_send_rdx_info(ldcp); 4146 break; 4147 4148 case VH_DONE: 4149 4150 ldcp->ldc_reset_count = 0; 4151 4152 DBG1(vgenp, ldcp, "Handshake Done\n"); 4153 4154 /* 4155 * The channel is up and handshake is done successfully. Now we 4156 * can mark the channel link_state as 'up'. We also notify the 4157 * stack if the channel is connected to vswitch. 4158 */ 4159 ldcp->link_state = LINK_STATE_UP; 4160 4161 if (ldcp->portp == vgenp->vsw_portp) { 4162 /* 4163 * If this channel(port) is connected to vsw, 4164 * need to sync multicast table with vsw. 4165 */ 4166 rv = vgen_send_mcast_info(ldcp); 4167 if (rv != VGEN_SUCCESS) 4168 break; 4169 4170 if (vgenp->pls_negotiated == B_FALSE) { 4171 /* 4172 * We haven't negotiated with vswitch to get 4173 * physical link state updates. We can update 4174 * update the stack at this point as the 4175 * channel to vswitch is up and the handshake 4176 * is done successfully. 4177 * 4178 * If we have negotiated to get physical link 4179 * state updates, then we won't notify the 4180 * the stack here; we do that as soon as 4181 * vswitch sends us the initial phys link state 4182 * (see vgen_handle_physlink_info()). 4183 */ 4184 mutex_exit(&ldcp->cblock); 4185 vgen_link_update(vgenp, ldcp->link_state); 4186 mutex_enter(&ldcp->cblock); 4187 } 4188 } 4189 4190 if (ldcp->htid != 0) { 4191 htid = ldcp->htid; 4192 ldcp->htid = 0; 4193 4194 mutex_exit(&ldcp->cblock); 4195 (void) untimeout(htid); 4196 mutex_enter(&ldcp->cblock); 4197 } 4198 4199 /* 4200 * Check if mac layer should be notified to restart 4201 * transmissions. This can happen if the channel got 4202 * reset and while tx_blocked is set. 4203 */ 4204 mutex_enter(&ldcp->tclock); 4205 if (ldcp->tx_blocked) { 4206 vio_net_tx_update_t vtx_update = 4207 ldcp->portp->vcb.vio_net_tx_update; 4208 4209 ldcp->tx_blocked = B_FALSE; 4210 vtx_update(ldcp->portp->vhp); 4211 } 4212 mutex_exit(&ldcp->tclock); 4213 4214 /* start transmit watchdog timer */ 4215 ldcp->wd_tid = timeout(vgen_tx_watchdog, (caddr_t)ldcp, 4216 drv_usectohz(vgen_txwd_interval * 1000)); 4217 4218 break; 4219 4220 default: 4221 break; 4222 } 4223 4224 return (rv); 4225 } 4226 4227 /* 4228 * Check if the current handshake phase has completed successfully and 4229 * return the status. 4230 */ 4231 static int 4232 vgen_handshake_done(vgen_ldc_t *ldcp) 4233 { 4234 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4235 uint32_t hphase = ldcp->hphase; 4236 int status = 0; 4237 4238 switch (hphase) { 4239 4240 case VH_PHASE1: 4241 /* 4242 * Phase1 is done, if version negotiation 4243 * completed successfully. 4244 */ 4245 status = ((ldcp->hstate & VER_NEGOTIATED) == 4246 VER_NEGOTIATED); 4247 break; 4248 4249 case VH_PHASE2: 4250 /* 4251 * Phase 2 is done, if attr info 4252 * has been exchanged successfully. 4253 */ 4254 status = ((ldcp->hstate & ATTR_INFO_EXCHANGED) == 4255 ATTR_INFO_EXCHANGED); 4256 break; 4257 4258 case VH_PHASE3: 4259 /* 4260 * Phase 3 is done, if dring registration 4261 * has been exchanged successfully. 4262 */ 4263 status = ((ldcp->hstate & DRING_INFO_EXCHANGED) == 4264 DRING_INFO_EXCHANGED); 4265 break; 4266 4267 case VH_PHASE4: 4268 /* Phase 4 is done, if rdx msg has been exchanged */ 4269 status = ((ldcp->hstate & RDX_EXCHANGED) == 4270 RDX_EXCHANGED); 4271 break; 4272 4273 default: 4274 break; 4275 } 4276 4277 if (status == 0) { 4278 return (VGEN_FAILURE); 4279 } 4280 DBG2(vgenp, ldcp, "PHASE(%d)\n", hphase); 4281 return (VGEN_SUCCESS); 4282 } 4283 4284 /* 4285 * Link State Update Notes: 4286 * The link state of the channel connected to vswitch is reported as the link 4287 * state of the vnet device, by default. If the channel is down or reset, then 4288 * the link state is marked 'down'. If the channel is 'up' *and* handshake 4289 * between the vnet and vswitch is successful, then the link state is marked 4290 * 'up'. If physical network link state is desired, then the vnet device must 4291 * be configured to get physical link updates and the 'linkprop' property 4292 * in the virtual-device MD node indicates this. As part of attribute exchange 4293 * the vnet device negotiates with the vswitch to obtain physical link state 4294 * updates. If it successfully negotiates, vswitch sends an initial physlink 4295 * msg once the handshake is done and further whenever the physical link state 4296 * changes. Currently we don't have mac layer interfaces to report two distinct 4297 * link states - virtual and physical. Thus, if the vnet has been configured to 4298 * get physical link updates, then the link status will be reported as 'up' 4299 * only when both the virtual and physical links are up. 4300 */ 4301 static void 4302 vgen_link_update(vgen_t *vgenp, link_state_t link_state) 4303 { 4304 vnet_link_update(vgenp->vnetp, link_state); 4305 } 4306 4307 /* 4308 * Handle a version info msg from the peer or an ACK/NACK from the peer 4309 * to a version info msg that we sent. 4310 */ 4311 static int 4312 vgen_handle_version_negotiate(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 4313 { 4314 vgen_t *vgenp; 4315 vio_ver_msg_t *vermsg = (vio_ver_msg_t *)tagp; 4316 int ack = 0; 4317 int failed = 0; 4318 int idx; 4319 vgen_ver_t *versions = ldcp->vgen_versions; 4320 int rv = 0; 4321 4322 vgenp = LDC_TO_VGEN(ldcp); 4323 DBG1(vgenp, ldcp, "enter\n"); 4324 switch (tagp->vio_subtype) { 4325 case VIO_SUBTYPE_INFO: 4326 4327 /* Cache sid of peer if this is the first time */ 4328 if (ldcp->peer_sid == 0) { 4329 DBG2(vgenp, ldcp, "Caching peer_sid(%x)\n", 4330 tagp->vio_sid); 4331 ldcp->peer_sid = tagp->vio_sid; 4332 } 4333 4334 if (ldcp->hphase != VH_PHASE1) { 4335 /* 4336 * If we are not already in VH_PHASE1, reset to 4337 * pre-handshake state, and initiate handshake 4338 * to the peer too. 4339 */ 4340 return (EINVAL); 4341 } 4342 4343 ldcp->hstate |= VER_INFO_RCVD; 4344 4345 /* save peer's requested values */ 4346 ldcp->peer_hparams.ver_major = vermsg->ver_major; 4347 ldcp->peer_hparams.ver_minor = vermsg->ver_minor; 4348 ldcp->peer_hparams.dev_class = vermsg->dev_class; 4349 4350 if ((vermsg->dev_class != VDEV_NETWORK) && 4351 (vermsg->dev_class != VDEV_NETWORK_SWITCH)) { 4352 /* unsupported dev_class, send NACK */ 4353 4354 DWARN(vgenp, ldcp, "Version Negotiation Failed\n"); 4355 4356 tagp->vio_subtype = VIO_SUBTYPE_NACK; 4357 tagp->vio_sid = ldcp->local_sid; 4358 /* send reply msg back to peer */ 4359 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, 4360 sizeof (*vermsg), B_FALSE); 4361 if (rv != VGEN_SUCCESS) { 4362 return (rv); 4363 } 4364 return (VGEN_FAILURE); 4365 } 4366 4367 DBG2(vgenp, ldcp, "VER_INFO_RCVD, ver(%d,%d)\n", 4368 vermsg->ver_major, vermsg->ver_minor); 4369 4370 idx = 0; 4371 4372 for (;;) { 4373 4374 if (vermsg->ver_major > versions[idx].ver_major) { 4375 4376 /* nack with next lower version */ 4377 tagp->vio_subtype = VIO_SUBTYPE_NACK; 4378 vermsg->ver_major = versions[idx].ver_major; 4379 vermsg->ver_minor = versions[idx].ver_minor; 4380 break; 4381 } 4382 4383 if (vermsg->ver_major == versions[idx].ver_major) { 4384 4385 /* major version match - ACK version */ 4386 tagp->vio_subtype = VIO_SUBTYPE_ACK; 4387 ack = 1; 4388 4389 /* 4390 * lower minor version to the one this endpt 4391 * supports, if necessary 4392 */ 4393 if (vermsg->ver_minor > 4394 versions[idx].ver_minor) { 4395 vermsg->ver_minor = 4396 versions[idx].ver_minor; 4397 ldcp->peer_hparams.ver_minor = 4398 versions[idx].ver_minor; 4399 } 4400 break; 4401 } 4402 4403 idx++; 4404 4405 if (idx == VGEN_NUM_VER) { 4406 4407 /* no version match - send NACK */ 4408 tagp->vio_subtype = VIO_SUBTYPE_NACK; 4409 vermsg->ver_major = 0; 4410 vermsg->ver_minor = 0; 4411 failed = 1; 4412 break; 4413 } 4414 4415 } 4416 4417 tagp->vio_sid = ldcp->local_sid; 4418 4419 /* send reply msg back to peer */ 4420 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*vermsg), 4421 B_FALSE); 4422 if (rv != VGEN_SUCCESS) { 4423 return (rv); 4424 } 4425 4426 if (ack) { 4427 ldcp->hstate |= VER_ACK_SENT; 4428 DBG2(vgenp, ldcp, "VER_ACK_SENT, ver(%d,%d) \n", 4429 vermsg->ver_major, vermsg->ver_minor); 4430 } 4431 if (failed) { 4432 DWARN(vgenp, ldcp, "Negotiation Failed\n"); 4433 return (VGEN_FAILURE); 4434 } 4435 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 4436 4437 /* VER_ACK_SENT and VER_ACK_RCVD */ 4438 4439 /* local and peer versions match? */ 4440 ASSERT((ldcp->local_hparams.ver_major == 4441 ldcp->peer_hparams.ver_major) && 4442 (ldcp->local_hparams.ver_minor == 4443 ldcp->peer_hparams.ver_minor)); 4444 4445 vgen_set_vnet_proto_ops(ldcp); 4446 4447 /* move to the next phase */ 4448 rv = vgen_handshake(vh_nextphase(ldcp)); 4449 if (rv != 0) { 4450 return (rv); 4451 } 4452 } 4453 4454 break; 4455 4456 case VIO_SUBTYPE_ACK: 4457 4458 if (ldcp->hphase != VH_PHASE1) { 4459 /* This should not happen. */ 4460 DWARN(vgenp, ldcp, "Invalid Phase(%u)\n", ldcp->hphase); 4461 return (VGEN_FAILURE); 4462 } 4463 4464 /* SUCCESS - we have agreed on a version */ 4465 ldcp->local_hparams.ver_major = vermsg->ver_major; 4466 ldcp->local_hparams.ver_minor = vermsg->ver_minor; 4467 ldcp->hstate |= VER_ACK_RCVD; 4468 4469 DBG2(vgenp, ldcp, "VER_ACK_RCVD, ver(%d,%d) \n", 4470 vermsg->ver_major, vermsg->ver_minor); 4471 4472 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 4473 4474 /* VER_ACK_SENT and VER_ACK_RCVD */ 4475 4476 /* local and peer versions match? */ 4477 ASSERT((ldcp->local_hparams.ver_major == 4478 ldcp->peer_hparams.ver_major) && 4479 (ldcp->local_hparams.ver_minor == 4480 ldcp->peer_hparams.ver_minor)); 4481 4482 vgen_set_vnet_proto_ops(ldcp); 4483 4484 /* move to the next phase */ 4485 rv = vgen_handshake(vh_nextphase(ldcp)); 4486 if (rv != 0) { 4487 return (rv); 4488 } 4489 } 4490 break; 4491 4492 case VIO_SUBTYPE_NACK: 4493 4494 if (ldcp->hphase != VH_PHASE1) { 4495 /* This should not happen. */ 4496 DWARN(vgenp, ldcp, "VER_NACK_RCVD Invalid " 4497 "Phase(%u)\n", ldcp->hphase); 4498 return (VGEN_FAILURE); 4499 } 4500 4501 DBG2(vgenp, ldcp, "VER_NACK_RCVD next ver(%d,%d)\n", 4502 vermsg->ver_major, vermsg->ver_minor); 4503 4504 /* check if version in NACK is zero */ 4505 if (vermsg->ver_major == 0 && vermsg->ver_minor == 0) { 4506 /* 4507 * Version Negotiation has failed. 4508 */ 4509 DWARN(vgenp, ldcp, "Version Negotiation Failed\n"); 4510 return (VGEN_FAILURE); 4511 } 4512 4513 idx = 0; 4514 4515 for (;;) { 4516 4517 if (vermsg->ver_major > versions[idx].ver_major) { 4518 /* select next lower version */ 4519 4520 ldcp->local_hparams.ver_major = 4521 versions[idx].ver_major; 4522 ldcp->local_hparams.ver_minor = 4523 versions[idx].ver_minor; 4524 break; 4525 } 4526 4527 if (vermsg->ver_major == versions[idx].ver_major) { 4528 /* major version match */ 4529 4530 ldcp->local_hparams.ver_major = 4531 versions[idx].ver_major; 4532 4533 ldcp->local_hparams.ver_minor = 4534 versions[idx].ver_minor; 4535 break; 4536 } 4537 4538 idx++; 4539 4540 if (idx == VGEN_NUM_VER) { 4541 /* 4542 * no version match. 4543 * Version Negotiation has failed. 4544 */ 4545 DWARN(vgenp, ldcp, 4546 "Version Negotiation Failed\n"); 4547 return (VGEN_FAILURE); 4548 } 4549 4550 } 4551 4552 rv = vgen_send_version_negotiate(ldcp); 4553 if (rv != VGEN_SUCCESS) { 4554 return (rv); 4555 } 4556 4557 break; 4558 } 4559 4560 DBG1(vgenp, ldcp, "exit\n"); 4561 return (VGEN_SUCCESS); 4562 } 4563 4564 static int 4565 vgen_handle_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg) 4566 { 4567 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4568 vgen_hparams_t *lp = &ldcp->local_hparams; 4569 vgen_hparams_t *rp = &ldcp->peer_hparams; 4570 uint32_t mtu; 4571 uint8_t dring_mode; 4572 4573 ldcp->hstate |= ATTR_INFO_RCVD; 4574 4575 /* save peer's values */ 4576 rp->mtu = msg->mtu; 4577 rp->addr = msg->addr; 4578 rp->addr_type = msg->addr_type; 4579 rp->xfer_mode = msg->xfer_mode; 4580 rp->ack_freq = msg->ack_freq; 4581 rp->dring_mode = msg->options; 4582 4583 /* 4584 * Process address type, ack frequency and transfer mode attributes. 4585 */ 4586 if ((msg->addr_type != ADDR_TYPE_MAC) || 4587 (msg->ack_freq > 64) || 4588 (msg->xfer_mode != lp->xfer_mode)) { 4589 return (VGEN_FAILURE); 4590 } 4591 4592 /* 4593 * Process dring mode attribute. 4594 */ 4595 if (VGEN_VER_GTEQ(ldcp, 1, 6)) { 4596 /* 4597 * Versions >= 1.6: 4598 * Though we are operating in v1.6 mode, it is possible that 4599 * RxDringData mode has been disabled either on this guest or 4600 * on the peer guest. If so, we revert to pre v1.6 behavior of 4601 * TxDring mode. But this must be agreed upon in both 4602 * directions of attr exchange. We first determine the mode 4603 * that can be negotiated. 4604 */ 4605 if ((msg->options & VIO_RX_DRING_DATA) != 0 && 4606 vgen_dring_mode == VIO_RX_DRING_DATA) { 4607 /* 4608 * We are capable of handling RxDringData AND the peer 4609 * is also capable of it; we enable RxDringData mode on 4610 * this channel. 4611 */ 4612 dring_mode = VIO_RX_DRING_DATA; 4613 } else if ((msg->options & VIO_TX_DRING) != 0) { 4614 /* 4615 * If the peer is capable of TxDring mode, we 4616 * negotiate TxDring mode on this channel. 4617 */ 4618 dring_mode = VIO_TX_DRING; 4619 } else { 4620 /* 4621 * We support only VIO_TX_DRING and VIO_RX_DRING_DATA 4622 * modes. We don't support VIO_RX_DRING mode. 4623 */ 4624 return (VGEN_FAILURE); 4625 } 4626 4627 /* 4628 * If we have received an ack for the attr info that we sent, 4629 * then check if the dring mode matches what the peer had ack'd 4630 * (saved in local hparams). If they don't match, we fail the 4631 * handshake. 4632 */ 4633 if (ldcp->hstate & ATTR_ACK_RCVD) { 4634 if (msg->options != lp->dring_mode) { 4635 /* send NACK */ 4636 return (VGEN_FAILURE); 4637 } 4638 } else { 4639 /* 4640 * Save the negotiated dring mode in our attr 4641 * parameters, so it gets sent in the attr info from us 4642 * to the peer. 4643 */ 4644 lp->dring_mode = dring_mode; 4645 } 4646 4647 /* save the negotiated dring mode in the msg to be replied */ 4648 msg->options = dring_mode; 4649 } 4650 4651 /* 4652 * Process MTU attribute. 4653 */ 4654 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 4655 /* 4656 * Versions >= 1.4: 4657 * Validate mtu of the peer is at least ETHERMAX. Then, the mtu 4658 * is negotiated down to the minimum of our mtu and peer's mtu. 4659 */ 4660 if (msg->mtu < ETHERMAX) { 4661 return (VGEN_FAILURE); 4662 } 4663 4664 mtu = MIN(msg->mtu, vgenp->max_frame_size); 4665 4666 /* 4667 * If we have received an ack for the attr info 4668 * that we sent, then check if the mtu computed 4669 * above matches the mtu that the peer had ack'd 4670 * (saved in local hparams). If they don't 4671 * match, we fail the handshake. 4672 */ 4673 if (ldcp->hstate & ATTR_ACK_RCVD) { 4674 if (mtu != lp->mtu) { 4675 /* send NACK */ 4676 return (VGEN_FAILURE); 4677 } 4678 } else { 4679 /* 4680 * Save the mtu computed above in our 4681 * attr parameters, so it gets sent in 4682 * the attr info from us to the peer. 4683 */ 4684 lp->mtu = mtu; 4685 } 4686 4687 /* save the MIN mtu in the msg to be replied */ 4688 msg->mtu = mtu; 4689 4690 } else { 4691 /* versions < 1.4, mtu must match */ 4692 if (msg->mtu != lp->mtu) { 4693 return (VGEN_FAILURE); 4694 } 4695 } 4696 4697 return (VGEN_SUCCESS); 4698 } 4699 4700 static int 4701 vgen_handle_attr_ack(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg) 4702 { 4703 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4704 vgen_hparams_t *lp = &ldcp->local_hparams; 4705 4706 /* 4707 * Process dring mode attribute. 4708 */ 4709 if (VGEN_VER_GTEQ(ldcp, 1, 6)) { 4710 /* 4711 * Versions >= 1.6: 4712 * The ack msg sent by the peer contains the negotiated dring 4713 * mode between our capability (that we had sent in our attr 4714 * info) and the peer's capability. 4715 */ 4716 if (ldcp->hstate & ATTR_ACK_SENT) { 4717 /* 4718 * If we have sent an ack for the attr info msg from 4719 * the peer, check if the dring mode that was 4720 * negotiated then (saved in local hparams) matches the 4721 * mode that the peer has ack'd. If they don't match, 4722 * we fail the handshake. 4723 */ 4724 if (lp->dring_mode != msg->options) { 4725 return (VGEN_FAILURE); 4726 } 4727 } else { 4728 if ((msg->options & lp->dring_mode) == 0) { 4729 /* 4730 * Peer ack'd with a mode that we don't 4731 * support; we fail the handshake. 4732 */ 4733 return (VGEN_FAILURE); 4734 } 4735 if ((msg->options & (VIO_TX_DRING|VIO_RX_DRING_DATA)) 4736 == (VIO_TX_DRING|VIO_RX_DRING_DATA)) { 4737 /* 4738 * Peer must ack with only one negotiated mode. 4739 * Otherwise fail handshake. 4740 */ 4741 return (VGEN_FAILURE); 4742 } 4743 4744 /* 4745 * Save the negotiated mode, so we can validate it when 4746 * we receive attr info from the peer. 4747 */ 4748 lp->dring_mode = msg->options; 4749 } 4750 } 4751 4752 /* 4753 * Process Physical Link Update attribute. 4754 */ 4755 if (VGEN_VER_GTEQ(ldcp, 1, 5) && 4756 ldcp->portp == vgenp->vsw_portp) { 4757 /* 4758 * Versions >= 1.5: 4759 * If the vnet device has been configured to get 4760 * physical link state updates, check the corresponding 4761 * bits in the ack msg, if the peer is vswitch. 4762 */ 4763 if (((lp->physlink_update & PHYSLINK_UPDATE_STATE_MASK) == 4764 PHYSLINK_UPDATE_STATE) && 4765 ((msg->physlink_update & PHYSLINK_UPDATE_STATE_MASK) == 4766 PHYSLINK_UPDATE_STATE_ACK)) { 4767 vgenp->pls_negotiated = B_TRUE; 4768 } else { 4769 vgenp->pls_negotiated = B_FALSE; 4770 } 4771 } 4772 4773 /* 4774 * Process MTU attribute. 4775 */ 4776 if (VGEN_VER_GTEQ(ldcp, 1, 4)) { 4777 /* 4778 * Versions >= 1.4: 4779 * The ack msg sent by the peer contains the minimum of 4780 * our mtu (that we had sent in our attr info) and the 4781 * peer's mtu. 4782 * 4783 * If we have sent an ack for the attr info msg from 4784 * the peer, check if the mtu that was computed then 4785 * (saved in local hparams) matches the mtu that the 4786 * peer has ack'd. If they don't match, we fail the 4787 * handshake. 4788 */ 4789 if (ldcp->hstate & ATTR_ACK_SENT) { 4790 if (lp->mtu != msg->mtu) { 4791 return (VGEN_FAILURE); 4792 } 4793 } else { 4794 /* 4795 * If the mtu ack'd by the peer is > our mtu 4796 * fail handshake. Otherwise, save the mtu, so 4797 * we can validate it when we receive attr info 4798 * from our peer. 4799 */ 4800 if (msg->mtu > lp->mtu) { 4801 return (VGEN_FAILURE); 4802 } 4803 if (msg->mtu <= lp->mtu) { 4804 lp->mtu = msg->mtu; 4805 } 4806 } 4807 } 4808 4809 return (VGEN_SUCCESS); 4810 } 4811 4812 4813 /* 4814 * Handle an attribute info msg from the peer or an ACK/NACK from the peer 4815 * to an attr info msg that we sent. 4816 */ 4817 static int 4818 vgen_handle_attr_msg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 4819 { 4820 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4821 vnet_attr_msg_t *msg = (vnet_attr_msg_t *)tagp; 4822 int rv = 0; 4823 4824 DBG1(vgenp, ldcp, "enter\n"); 4825 if (ldcp->hphase != VH_PHASE2) { 4826 DWARN(vgenp, ldcp, "Rcvd ATTR_INFO subtype(%d)," 4827 " Invalid Phase(%u)\n", 4828 tagp->vio_subtype, ldcp->hphase); 4829 return (VGEN_FAILURE); 4830 } 4831 switch (tagp->vio_subtype) { 4832 case VIO_SUBTYPE_INFO: 4833 4834 rv = vgen_handle_attr_info(ldcp, msg); 4835 if (rv == VGEN_SUCCESS) { 4836 tagp->vio_subtype = VIO_SUBTYPE_ACK; 4837 } else { 4838 tagp->vio_subtype = VIO_SUBTYPE_NACK; 4839 } 4840 tagp->vio_sid = ldcp->local_sid; 4841 4842 /* send reply msg back to peer */ 4843 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg), 4844 B_FALSE); 4845 if (rv != VGEN_SUCCESS) { 4846 return (rv); 4847 } 4848 4849 if (tagp->vio_subtype == VIO_SUBTYPE_NACK) { 4850 DWARN(vgenp, ldcp, "ATTR_NACK_SENT"); 4851 break; 4852 } 4853 4854 ldcp->hstate |= ATTR_ACK_SENT; 4855 DBG2(vgenp, ldcp, "ATTR_ACK_SENT \n"); 4856 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 4857 rv = vgen_handshake(vh_nextphase(ldcp)); 4858 if (rv != 0) { 4859 return (rv); 4860 } 4861 } 4862 4863 break; 4864 4865 case VIO_SUBTYPE_ACK: 4866 4867 rv = vgen_handle_attr_ack(ldcp, msg); 4868 if (rv == VGEN_FAILURE) { 4869 break; 4870 } 4871 4872 ldcp->hstate |= ATTR_ACK_RCVD; 4873 DBG2(vgenp, ldcp, "ATTR_ACK_RCVD \n"); 4874 4875 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 4876 rv = vgen_handshake(vh_nextphase(ldcp)); 4877 if (rv != 0) { 4878 return (rv); 4879 } 4880 } 4881 break; 4882 4883 case VIO_SUBTYPE_NACK: 4884 4885 DBG2(vgenp, ldcp, "ATTR_NACK_RCVD \n"); 4886 return (VGEN_FAILURE); 4887 } 4888 DBG1(vgenp, ldcp, "exit\n"); 4889 return (VGEN_SUCCESS); 4890 } 4891 4892 static int 4893 vgen_handle_dring_reg_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 4894 { 4895 int rv = 0; 4896 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4897 vgen_hparams_t *lp = &ldcp->local_hparams; 4898 4899 DBG2(vgenp, ldcp, "DRING_INFO_RCVD"); 4900 ldcp->hstate |= DRING_INFO_RCVD; 4901 4902 if (VGEN_VER_GTEQ(ldcp, 1, 6) && 4903 (lp->dring_mode != ((vio_dring_reg_msg_t *)tagp)->options)) { 4904 /* 4905 * The earlier version of Solaris vnet driver doesn't set the 4906 * option (VIO_TX_DRING in its case) correctly in its dring reg 4907 * message. We workaround that here by doing the check only 4908 * for versions >= v1.6. 4909 */ 4910 DWARN(vgenp, ldcp, 4911 "Rcvd dring reg option (%d), negotiated mode (%d)\n", 4912 ((vio_dring_reg_msg_t *)tagp)->options, lp->dring_mode); 4913 return (VGEN_FAILURE); 4914 } 4915 4916 /* 4917 * Map dring exported by the peer. 4918 */ 4919 rv = vgen_map_dring(ldcp, (void *)tagp); 4920 if (rv != VGEN_SUCCESS) { 4921 return (rv); 4922 } 4923 4924 /* 4925 * Map data buffers exported by the peer if we are in RxDringData mode. 4926 */ 4927 if (lp->dring_mode == VIO_RX_DRING_DATA) { 4928 rv = vgen_map_data(ldcp, (void *)tagp); 4929 if (rv != VGEN_SUCCESS) { 4930 vgen_unmap_dring(ldcp); 4931 return (rv); 4932 } 4933 } 4934 4935 if (ldcp->peer_hparams.dring_ready == B_FALSE) { 4936 ldcp->peer_hparams.dring_ready = B_TRUE; 4937 } 4938 4939 return (VGEN_SUCCESS); 4940 } 4941 4942 static int 4943 vgen_handle_dring_reg_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 4944 { 4945 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4946 vgen_hparams_t *lp = &ldcp->local_hparams; 4947 4948 DBG2(vgenp, ldcp, "DRING_ACK_RCVD"); 4949 ldcp->hstate |= DRING_ACK_RCVD; 4950 4951 if (lp->dring_ready) { 4952 return (VGEN_SUCCESS); 4953 } 4954 4955 /* save dring_ident acked by peer */ 4956 lp->dring_ident = ((vio_dring_reg_msg_t *)tagp)->dring_ident; 4957 4958 /* local dring is now ready */ 4959 lp->dring_ready = B_TRUE; 4960 4961 return (VGEN_SUCCESS); 4962 } 4963 4964 /* 4965 * Handle a descriptor ring register msg from the peer or an ACK/NACK from 4966 * the peer to a dring register msg that we sent. 4967 */ 4968 static int 4969 vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 4970 { 4971 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 4972 int rv = 0; 4973 int msgsize; 4974 vgen_hparams_t *lp = &ldcp->local_hparams; 4975 4976 DBG1(vgenp, ldcp, "enter\n"); 4977 if (ldcp->hphase < VH_PHASE2) { 4978 /* dring_info can be rcvd in any of the phases after Phase1 */ 4979 DWARN(vgenp, ldcp, 4980 "Rcvd DRING_INFO Subtype (%d), Invalid Phase(%u)\n", 4981 tagp->vio_subtype, ldcp->hphase); 4982 return (VGEN_FAILURE); 4983 } 4984 4985 switch (tagp->vio_subtype) { 4986 case VIO_SUBTYPE_INFO: 4987 4988 rv = vgen_handle_dring_reg_info(ldcp, tagp); 4989 if (rv == VGEN_SUCCESS) { 4990 tagp->vio_subtype = VIO_SUBTYPE_ACK; 4991 } else { 4992 tagp->vio_subtype = VIO_SUBTYPE_NACK; 4993 } 4994 4995 tagp->vio_sid = ldcp->local_sid; 4996 4997 if (lp->dring_mode == VIO_RX_DRING_DATA) { 4998 msgsize = 4999 VNET_DRING_REG_EXT_MSG_SIZE(ldcp->tx_data_ncookies); 5000 } else { 5001 msgsize = sizeof (vio_dring_reg_msg_t); 5002 } 5003 5004 /* send reply msg back to peer */ 5005 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, msgsize, 5006 B_FALSE); 5007 if (rv != VGEN_SUCCESS) { 5008 return (rv); 5009 } 5010 5011 if (tagp->vio_subtype == VIO_SUBTYPE_NACK) { 5012 DWARN(vgenp, ldcp, "DRING_NACK_SENT"); 5013 return (VGEN_FAILURE); 5014 } 5015 5016 ldcp->hstate |= DRING_ACK_SENT; 5017 DBG2(vgenp, ldcp, "DRING_ACK_SENT"); 5018 5019 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5020 rv = vgen_handshake(vh_nextphase(ldcp)); 5021 if (rv != 0) { 5022 return (rv); 5023 } 5024 } 5025 break; 5026 5027 case VIO_SUBTYPE_ACK: 5028 5029 rv = vgen_handle_dring_reg_ack(ldcp, tagp); 5030 if (rv == VGEN_FAILURE) { 5031 return (rv); 5032 } 5033 5034 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5035 rv = vgen_handshake(vh_nextphase(ldcp)); 5036 if (rv != 0) { 5037 return (rv); 5038 } 5039 } 5040 5041 break; 5042 5043 case VIO_SUBTYPE_NACK: 5044 5045 DWARN(vgenp, ldcp, "DRING_NACK_RCVD"); 5046 return (VGEN_FAILURE); 5047 } 5048 DBG1(vgenp, ldcp, "exit\n"); 5049 return (VGEN_SUCCESS); 5050 } 5051 5052 /* 5053 * Handle a rdx info msg from the peer or an ACK/NACK 5054 * from the peer to a rdx info msg that we sent. 5055 */ 5056 static int 5057 vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5058 { 5059 int rv = 0; 5060 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5061 5062 DBG1(vgenp, ldcp, "enter\n"); 5063 if (ldcp->hphase != VH_PHASE4) { 5064 DWARN(vgenp, ldcp, 5065 "Rcvd RDX_INFO Subtype (%d), Invalid Phase(%u)\n", 5066 tagp->vio_subtype, ldcp->hphase); 5067 return (VGEN_FAILURE); 5068 } 5069 switch (tagp->vio_subtype) { 5070 case VIO_SUBTYPE_INFO: 5071 5072 DBG2(vgenp, ldcp, "RDX_INFO_RCVD \n"); 5073 ldcp->hstate |= RDX_INFO_RCVD; 5074 5075 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5076 tagp->vio_sid = ldcp->local_sid; 5077 /* send reply msg back to peer */ 5078 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vio_rdx_msg_t), 5079 B_FALSE); 5080 if (rv != VGEN_SUCCESS) { 5081 return (rv); 5082 } 5083 5084 ldcp->hstate |= RDX_ACK_SENT; 5085 DBG2(vgenp, ldcp, "RDX_ACK_SENT \n"); 5086 5087 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5088 rv = vgen_handshake(vh_nextphase(ldcp)); 5089 if (rv != 0) { 5090 return (rv); 5091 } 5092 } 5093 5094 break; 5095 5096 case VIO_SUBTYPE_ACK: 5097 5098 ldcp->hstate |= RDX_ACK_RCVD; 5099 5100 DBG2(vgenp, ldcp, "RDX_ACK_RCVD \n"); 5101 5102 if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) { 5103 rv = vgen_handshake(vh_nextphase(ldcp)); 5104 if (rv != 0) { 5105 return (rv); 5106 } 5107 } 5108 break; 5109 5110 case VIO_SUBTYPE_NACK: 5111 5112 DBG2(vgenp, ldcp, "RDX_NACK_RCVD \n"); 5113 return (VGEN_FAILURE); 5114 } 5115 DBG1(vgenp, ldcp, "exit\n"); 5116 return (VGEN_SUCCESS); 5117 } 5118 5119 /* Handle ACK/NACK from vsw to a set multicast msg that we sent */ 5120 static int 5121 vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5122 { 5123 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5124 vnet_mcast_msg_t *msgp = (vnet_mcast_msg_t *)tagp; 5125 struct ether_addr *addrp; 5126 int count; 5127 int i; 5128 5129 DBG1(vgenp, ldcp, "enter\n"); 5130 switch (tagp->vio_subtype) { 5131 5132 case VIO_SUBTYPE_INFO: 5133 5134 /* vnet shouldn't recv set mcast msg, only vsw handles it */ 5135 DWARN(vgenp, ldcp, "rcvd SET_MCAST_INFO \n"); 5136 break; 5137 5138 case VIO_SUBTYPE_ACK: 5139 5140 /* success adding/removing multicast addr */ 5141 DBG1(vgenp, ldcp, "rcvd SET_MCAST_ACK \n"); 5142 break; 5143 5144 case VIO_SUBTYPE_NACK: 5145 5146 DWARN(vgenp, ldcp, "rcvd SET_MCAST_NACK \n"); 5147 if (!(msgp->set)) { 5148 /* multicast remove request failed */ 5149 break; 5150 } 5151 5152 /* multicast add request failed */ 5153 for (count = 0; count < msgp->count; count++) { 5154 addrp = &(msgp->mca[count]); 5155 5156 /* delete address from the table */ 5157 for (i = 0; i < vgenp->mccount; i++) { 5158 if (ether_cmp(addrp, 5159 &(vgenp->mctab[i])) == 0) { 5160 if (vgenp->mccount > 1) { 5161 int t = vgenp->mccount - 1; 5162 vgenp->mctab[i] = 5163 vgenp->mctab[t]; 5164 } 5165 vgenp->mccount--; 5166 break; 5167 } 5168 } 5169 } 5170 break; 5171 5172 } 5173 DBG1(vgenp, ldcp, "exit\n"); 5174 5175 return (VGEN_SUCCESS); 5176 } 5177 5178 /* 5179 * Physical link information message from the peer. Only vswitch should send 5180 * us this message; if the vnet device has been configured to get physical link 5181 * state updates. Note that we must have already negotiated this with the 5182 * vswitch during attribute exchange phase of handshake. 5183 */ 5184 static int 5185 vgen_handle_physlink_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5186 { 5187 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5188 vnet_physlink_msg_t *msgp = (vnet_physlink_msg_t *)tagp; 5189 link_state_t link_state; 5190 int rv; 5191 5192 if (ldcp->portp != vgenp->vsw_portp) { 5193 /* 5194 * drop the message and don't process; as we should 5195 * receive physlink_info message from only vswitch. 5196 */ 5197 return (VGEN_SUCCESS); 5198 } 5199 5200 if (vgenp->pls_negotiated == B_FALSE) { 5201 /* 5202 * drop the message and don't process; as we should receive 5203 * physlink_info message only if physlink update is enabled for 5204 * the device and negotiated with vswitch. 5205 */ 5206 return (VGEN_SUCCESS); 5207 } 5208 5209 switch (tagp->vio_subtype) { 5210 5211 case VIO_SUBTYPE_INFO: 5212 5213 if ((msgp->physlink_info & VNET_PHYSLINK_STATE_MASK) == 5214 VNET_PHYSLINK_STATE_UP) { 5215 link_state = LINK_STATE_UP; 5216 } else { 5217 link_state = LINK_STATE_DOWN; 5218 } 5219 5220 if (vgenp->phys_link_state != link_state) { 5221 vgenp->phys_link_state = link_state; 5222 mutex_exit(&ldcp->cblock); 5223 5224 /* Now update the stack */ 5225 vgen_link_update(vgenp, link_state); 5226 5227 mutex_enter(&ldcp->cblock); 5228 } 5229 5230 tagp->vio_subtype = VIO_SUBTYPE_ACK; 5231 tagp->vio_sid = ldcp->local_sid; 5232 5233 /* send reply msg back to peer */ 5234 rv = vgen_sendmsg(ldcp, (caddr_t)tagp, 5235 sizeof (vnet_physlink_msg_t), B_FALSE); 5236 if (rv != VGEN_SUCCESS) { 5237 return (rv); 5238 } 5239 break; 5240 5241 case VIO_SUBTYPE_ACK: 5242 5243 /* vnet shouldn't recv physlink acks */ 5244 DWARN(vgenp, ldcp, "rcvd PHYSLINK_ACK \n"); 5245 break; 5246 5247 case VIO_SUBTYPE_NACK: 5248 5249 /* vnet shouldn't recv physlink nacks */ 5250 DWARN(vgenp, ldcp, "rcvd PHYSLINK_NACK \n"); 5251 break; 5252 5253 } 5254 DBG1(vgenp, ldcp, "exit\n"); 5255 5256 return (VGEN_SUCCESS); 5257 } 5258 5259 /* handler for control messages received from the peer ldc end-point */ 5260 static int 5261 vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5262 { 5263 int rv = 0; 5264 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5265 5266 DBG1(vgenp, ldcp, "enter\n"); 5267 switch (tagp->vio_subtype_env) { 5268 5269 case VIO_VER_INFO: 5270 rv = vgen_handle_version_negotiate(ldcp, tagp); 5271 break; 5272 5273 case VIO_ATTR_INFO: 5274 rv = vgen_handle_attr_msg(ldcp, tagp); 5275 break; 5276 5277 case VIO_DRING_REG: 5278 rv = vgen_handle_dring_reg(ldcp, tagp); 5279 break; 5280 5281 case VIO_RDX: 5282 rv = vgen_handle_rdx_info(ldcp, tagp); 5283 break; 5284 5285 case VNET_MCAST_INFO: 5286 rv = vgen_handle_mcast_info(ldcp, tagp); 5287 break; 5288 5289 case VIO_DDS_INFO: 5290 /* 5291 * If we are in the process of resetting the vswitch channel, 5292 * drop the dds message. A new handshake will be initiated 5293 * when the channel comes back up after the reset and dds 5294 * negotiation can then continue. 5295 */ 5296 if (ldcp->reset_in_progress == 1) { 5297 break; 5298 } 5299 rv = vgen_dds_rx(ldcp, tagp); 5300 break; 5301 5302 case VNET_PHYSLINK_INFO: 5303 rv = vgen_handle_physlink_info(ldcp, tagp); 5304 break; 5305 } 5306 5307 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 5308 return (rv); 5309 } 5310 5311 /* handler for error messages received from the peer ldc end-point */ 5312 static void 5313 vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5314 { 5315 _NOTE(ARGUNUSED(ldcp, tagp)) 5316 } 5317 5318 /* 5319 * This function handles raw pkt data messages received over the channel. 5320 * Currently, only priority-eth-type frames are received through this mechanism. 5321 * In this case, the frame(data) is present within the message itself which 5322 * is copied into an mblk before sending it up the stack. 5323 */ 5324 void 5325 vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen) 5326 { 5327 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg1; 5328 vio_raw_data_msg_t *pkt = (vio_raw_data_msg_t *)arg2; 5329 uint32_t size; 5330 mblk_t *mp; 5331 vio_mblk_t *vmp; 5332 vio_net_rx_cb_t vrx_cb = NULL; 5333 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5334 vgen_stats_t *statsp = &ldcp->stats; 5335 vgen_hparams_t *lp = &ldcp->local_hparams; 5336 uint_t dring_mode = lp->dring_mode; 5337 5338 ASSERT(MUTEX_HELD(&ldcp->cblock)); 5339 5340 mutex_exit(&ldcp->cblock); 5341 5342 size = msglen - VIO_PKT_DATA_HDRSIZE; 5343 if (size < ETHERMIN || size > lp->mtu) { 5344 (void) atomic_inc_32(&statsp->rx_pri_fail); 5345 mutex_enter(&ldcp->cblock); 5346 return; 5347 } 5348 5349 vmp = vio_multipool_allocb(&ldcp->vmp, size); 5350 if (vmp == NULL) { 5351 mp = allocb(size, BPRI_MED); 5352 if (mp == NULL) { 5353 (void) atomic_inc_32(&statsp->rx_pri_fail); 5354 DWARN(vgenp, ldcp, "allocb failure, " 5355 "unable to process priority frame\n"); 5356 mutex_enter(&ldcp->cblock); 5357 return; 5358 } 5359 } else { 5360 mp = vmp->mp; 5361 } 5362 5363 /* copy the frame from the payload of raw data msg into the mblk */ 5364 bcopy(pkt->data, mp->b_rptr, size); 5365 mp->b_wptr = mp->b_rptr + size; 5366 5367 if (vmp != NULL) { 5368 vmp->state = VIO_MBLK_HAS_DATA; 5369 } 5370 5371 /* update stats */ 5372 (void) atomic_inc_64(&statsp->rx_pri_packets); 5373 (void) atomic_add_64(&statsp->rx_pri_bytes, size); 5374 5375 /* 5376 * If polling is currently enabled, add the packet to the priority 5377 * packets list and return. It will be picked up by the polling thread. 5378 */ 5379 if (dring_mode == VIO_RX_DRING_DATA) { 5380 mutex_enter(&ldcp->rxlock); 5381 } else { 5382 mutex_enter(&ldcp->pollq_lock); 5383 } 5384 5385 if (ldcp->polling_on == B_TRUE) { 5386 if (ldcp->rx_pri_tail != NULL) { 5387 ldcp->rx_pri_tail->b_next = mp; 5388 } else { 5389 ldcp->rx_pri_head = ldcp->rx_pri_tail = mp; 5390 } 5391 } else { 5392 vrx_cb = ldcp->portp->vcb.vio_net_rx_cb; 5393 } 5394 5395 if (dring_mode == VIO_RX_DRING_DATA) { 5396 mutex_exit(&ldcp->rxlock); 5397 } else { 5398 mutex_exit(&ldcp->pollq_lock); 5399 } 5400 5401 if (vrx_cb != NULL) { 5402 vrx_cb(ldcp->portp->vhp, mp); 5403 } 5404 5405 mutex_enter(&ldcp->cblock); 5406 } 5407 5408 /* 5409 * dummy pkt data handler function for vnet protocol version 1.0 5410 */ 5411 static void 5412 vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen) 5413 { 5414 _NOTE(ARGUNUSED(arg1, arg2, msglen)) 5415 } 5416 5417 /* handler for data messages received from the peer ldc end-point */ 5418 static int 5419 vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t msglen) 5420 { 5421 int rv = 0; 5422 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5423 vgen_hparams_t *lp = &ldcp->local_hparams; 5424 5425 DBG1(vgenp, ldcp, "enter\n"); 5426 5427 if (ldcp->hphase != VH_DONE) { 5428 return (0); 5429 } 5430 5431 /* 5432 * We check the data msg seqnum. This is needed only in TxDring mode. 5433 */ 5434 if (lp->dring_mode == VIO_TX_DRING && 5435 tagp->vio_subtype == VIO_SUBTYPE_INFO) { 5436 rv = vgen_check_datamsg_seq(ldcp, tagp); 5437 if (rv != 0) { 5438 return (rv); 5439 } 5440 } 5441 5442 switch (tagp->vio_subtype_env) { 5443 case VIO_DRING_DATA: 5444 rv = ldcp->rx_dringdata((void *)ldcp, (void *)tagp); 5445 break; 5446 5447 case VIO_PKT_DATA: 5448 ldcp->rx_pktdata((void *)ldcp, (void *)tagp, msglen); 5449 break; 5450 default: 5451 break; 5452 } 5453 5454 DBG1(vgenp, ldcp, "exit rv(%d)\n", rv); 5455 return (rv); 5456 } 5457 5458 5459 static int 5460 vgen_ldc_reset(vgen_ldc_t *ldcp, vgen_caller_t caller) 5461 { 5462 int rv; 5463 5464 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 5465 ASSERT(MUTEX_HELD(&ldcp->cblock)); 5466 } 5467 5468 /* Set the flag to indicate reset is in progress */ 5469 if (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) { 5470 /* another thread is already in the process of resetting */ 5471 return (EBUSY); 5472 } 5473 5474 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 5475 mutex_exit(&ldcp->cblock); 5476 } 5477 5478 rv = vgen_process_reset(ldcp, VGEN_FLAG_NEED_LDCRESET); 5479 5480 if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) { 5481 mutex_enter(&ldcp->cblock); 5482 } 5483 5484 return (rv); 5485 } 5486 5487 static void 5488 vgen_ldc_up(vgen_ldc_t *ldcp) 5489 { 5490 int rv; 5491 uint32_t retries = 0; 5492 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5493 5494 ASSERT(MUTEX_HELD(&ldcp->cblock)); 5495 5496 /* 5497 * If the channel has been reset max # of times, without successfully 5498 * completing handshake, stop and do not bring the channel up. 5499 */ 5500 if (ldcp->ldc_reset_count == vgen_ldc_max_resets) { 5501 cmn_err(CE_WARN, "!vnet%d: exceeded number of permitted" 5502 " handshake attempts (%d) on channel %ld", 5503 vgenp->instance, vgen_ldc_max_resets, ldcp->ldc_id); 5504 return; 5505 } 5506 ldcp->ldc_reset_count++; 5507 5508 do { 5509 rv = ldc_up(ldcp->ldc_handle); 5510 if ((rv != 0) && (rv == EWOULDBLOCK)) { 5511 drv_usecwait(VGEN_LDC_UP_DELAY); 5512 } 5513 if (retries++ >= vgen_ldcup_retries) 5514 break; 5515 } while (rv == EWOULDBLOCK); 5516 5517 if (rv != 0) { 5518 DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv); 5519 } 5520 } 5521 5522 int 5523 vgen_enable_intr(void *arg) 5524 { 5525 uint32_t end_ix; 5526 vio_dring_msg_t msg; 5527 vgen_port_t *portp = (vgen_port_t *)arg; 5528 vgen_ldc_t *ldcp = portp->ldcp; 5529 vgen_hparams_t *lp = &ldcp->local_hparams; 5530 5531 if (lp->dring_mode == VIO_RX_DRING_DATA) { 5532 mutex_enter(&ldcp->rxlock); 5533 5534 ldcp->polling_on = B_FALSE; 5535 /* 5536 * We send a stopped message to peer (sender) as we are turning 5537 * off polled mode. This effectively restarts data interrupts 5538 * by allowing the peer to send further dring data msgs to us. 5539 */ 5540 end_ix = ldcp->next_rxi; 5541 DECR_RXI(end_ix, ldcp); 5542 msg.dring_ident = ldcp->peer_hparams.dring_ident; 5543 (void) vgen_send_dringack_shm(ldcp, (vio_msg_tag_t *)&msg, 5544 VNET_START_IDX_UNSPEC, end_ix, VIO_DP_STOPPED); 5545 5546 mutex_exit(&ldcp->rxlock); 5547 } else { 5548 mutex_enter(&ldcp->pollq_lock); 5549 ldcp->polling_on = B_FALSE; 5550 mutex_exit(&ldcp->pollq_lock); 5551 } 5552 5553 return (0); 5554 } 5555 5556 int 5557 vgen_disable_intr(void *arg) 5558 { 5559 vgen_port_t *portp = (vgen_port_t *)arg; 5560 vgen_ldc_t *ldcp = portp->ldcp; 5561 vgen_hparams_t *lp = &ldcp->local_hparams; 5562 5563 if (lp->dring_mode == VIO_RX_DRING_DATA) { 5564 mutex_enter(&ldcp->rxlock); 5565 ldcp->polling_on = B_TRUE; 5566 mutex_exit(&ldcp->rxlock); 5567 } else { 5568 mutex_enter(&ldcp->pollq_lock); 5569 ldcp->polling_on = B_TRUE; 5570 mutex_exit(&ldcp->pollq_lock); 5571 } 5572 5573 return (0); 5574 } 5575 5576 mblk_t * 5577 vgen_rx_poll(void *arg, int bytes_to_pickup) 5578 { 5579 vgen_port_t *portp = (vgen_port_t *)arg; 5580 vgen_ldc_t *ldcp = portp->ldcp; 5581 vgen_hparams_t *lp = &ldcp->local_hparams; 5582 mblk_t *mp = NULL; 5583 5584 if (lp->dring_mode == VIO_RX_DRING_DATA) { 5585 mp = vgen_poll_rcv_shm(ldcp, bytes_to_pickup); 5586 } else { 5587 mp = vgen_poll_rcv(ldcp, bytes_to_pickup); 5588 } 5589 5590 return (mp); 5591 } 5592 5593 /* transmit watchdog timeout handler */ 5594 static void 5595 vgen_tx_watchdog(void *arg) 5596 { 5597 vgen_ldc_t *ldcp; 5598 vgen_t *vgenp; 5599 int rv; 5600 boolean_t tx_blocked; 5601 clock_t tx_blocked_lbolt; 5602 5603 ldcp = (vgen_ldc_t *)arg; 5604 vgenp = LDC_TO_VGEN(ldcp); 5605 5606 tx_blocked = ldcp->tx_blocked; 5607 tx_blocked_lbolt = ldcp->tx_blocked_lbolt; 5608 5609 if (vgen_txwd_timeout && 5610 (tx_blocked == B_TRUE) && 5611 ((ddi_get_lbolt() - tx_blocked_lbolt) > 5612 drv_usectohz(vgen_txwd_timeout * 1000))) { 5613 /* 5614 * Something is wrong; the peer is not picking up the packets 5615 * in the transmit dring. We now go ahead and reset the channel 5616 * to break out of this condition. 5617 */ 5618 DWARN(vgenp, ldcp, "transmit timeout lbolt(%lx), " 5619 "tx_blocked_lbolt(%lx)\n", 5620 ddi_get_lbolt(), tx_blocked_lbolt); 5621 5622 #ifdef DEBUG 5623 if (vgen_inject_error(ldcp, VGEN_ERR_TXTIMEOUT)) { 5624 /* tx timeout triggered for debugging */ 5625 vgen_inject_err_flag &= ~(VGEN_ERR_TXTIMEOUT); 5626 } 5627 #endif 5628 5629 /* 5630 * Clear tid before invoking vgen_ldc_reset(). Otherwise, 5631 * it will result in a deadlock when vgen_process_reset() tries 5632 * to untimeout() on seeing a non-zero tid, but it is being 5633 * invoked by the timer itself in this case. 5634 */ 5635 mutex_enter(&ldcp->cblock); 5636 if (ldcp->wd_tid == 0) { 5637 /* Cancelled by vgen_process_reset() */ 5638 mutex_exit(&ldcp->cblock); 5639 return; 5640 } 5641 ldcp->wd_tid = 0; 5642 mutex_exit(&ldcp->cblock); 5643 5644 /* 5645 * Now reset the channel. 5646 */ 5647 rv = vgen_ldc_reset(ldcp, VGEN_OTHER); 5648 if (rv == 0) { 5649 /* 5650 * We have successfully reset the channel. If we are 5651 * in tx flow controlled state, clear it now and enable 5652 * transmit in the upper layer. 5653 */ 5654 if (ldcp->tx_blocked) { 5655 vio_net_tx_update_t vtx_update = 5656 ldcp->portp->vcb.vio_net_tx_update; 5657 5658 ldcp->tx_blocked = B_FALSE; 5659 vtx_update(ldcp->portp->vhp); 5660 } 5661 } 5662 5663 /* 5664 * Channel has been reset by us or some other thread is already 5665 * in the process of resetting. In either case, we return 5666 * without restarting the timer. When handshake completes and 5667 * the channel is ready for data transmit/receive we start a 5668 * new watchdog timer. 5669 */ 5670 return; 5671 } 5672 5673 restart_timer: 5674 /* Restart the timer */ 5675 mutex_enter(&ldcp->cblock); 5676 if (ldcp->wd_tid == 0) { 5677 /* Cancelled by vgen_process_reset() */ 5678 mutex_exit(&ldcp->cblock); 5679 return; 5680 } 5681 ldcp->wd_tid = timeout(vgen_tx_watchdog, (caddr_t)ldcp, 5682 drv_usectohz(vgen_txwd_interval * 1000)); 5683 mutex_exit(&ldcp->cblock); 5684 } 5685 5686 /* Handshake watchdog timeout handler */ 5687 static void 5688 vgen_hwatchdog(void *arg) 5689 { 5690 vgen_ldc_t *ldcp = (vgen_ldc_t *)arg; 5691 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5692 5693 DWARN(vgenp, ldcp, "handshake timeout phase(%x) state(%x)\n", 5694 ldcp->hphase, ldcp->hstate); 5695 5696 mutex_enter(&ldcp->cblock); 5697 if (ldcp->htid == 0) { 5698 /* Cancelled by vgen_process_reset() */ 5699 mutex_exit(&ldcp->cblock); 5700 return; 5701 } 5702 ldcp->htid = 0; 5703 mutex_exit(&ldcp->cblock); 5704 5705 /* 5706 * Something is wrong; handshake with the peer seems to be hung. We now 5707 * go ahead and reset the channel to break out of this condition. 5708 */ 5709 (void) vgen_ldc_reset(ldcp, VGEN_OTHER); 5710 } 5711 5712 /* Check if the session id in the received message is valid */ 5713 static int 5714 vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp) 5715 { 5716 vgen_t *vgenp = LDC_TO_VGEN(ldcp); 5717 5718 if (tagp->vio_sid != ldcp->peer_sid) { 5719 DWARN(vgenp, ldcp, "sid mismatch: expected(%x), rcvd(%x)\n", 5720 ldcp->peer_sid, tagp->vio_sid); 5721 return (VGEN_FAILURE); 5722 } 5723 else 5724 return (VGEN_SUCCESS); 5725 } 5726 5727 /* 5728 * Initialize the common part of dring registration 5729 * message; used in both TxDring and RxDringData modes. 5730 */ 5731 static void 5732 vgen_init_dring_reg_msg(vgen_ldc_t *ldcp, vio_dring_reg_msg_t *msg, 5733 uint8_t option) 5734 { 5735 vio_msg_tag_t *tagp; 5736 5737 tagp = &msg->tag; 5738 tagp->vio_msgtype = VIO_TYPE_CTRL; 5739 tagp->vio_subtype = VIO_SUBTYPE_INFO; 5740 tagp->vio_subtype_env = VIO_DRING_REG; 5741 tagp->vio_sid = ldcp->local_sid; 5742 5743 /* get dring info msg payload from ldcp->local */ 5744 bcopy(&(ldcp->local_hparams.dring_cookie), &(msg->cookie[0]), 5745 sizeof (ldc_mem_cookie_t)); 5746 msg->ncookies = ldcp->local_hparams.dring_ncookies; 5747 msg->num_descriptors = ldcp->local_hparams.num_desc; 5748 msg->descriptor_size = ldcp->local_hparams.desc_size; 5749 5750 msg->options = option; 5751 5752 /* 5753 * dring_ident is set to 0. After mapping the dring, peer sets this 5754 * value and sends it in the ack, which is saved in 5755 * vgen_handle_dring_reg(). 5756 */ 5757 msg->dring_ident = 0; 5758 } 5759 5760 #if DEBUG 5761 5762 /* 5763 * Print debug messages - set to 0xf to enable all msgs 5764 */ 5765 void 5766 vgen_debug_printf(const char *fname, vgen_t *vgenp, 5767 vgen_ldc_t *ldcp, const char *fmt, ...) 5768 { 5769 char buf[256]; 5770 char *bufp = buf; 5771 va_list ap; 5772 5773 if ((vgenp != NULL) && (vgenp->vnetp != NULL)) { 5774 (void) sprintf(bufp, "vnet%d:", 5775 ((vnet_t *)(vgenp->vnetp))->instance); 5776 bufp += strlen(bufp); 5777 } 5778 if (ldcp != NULL) { 5779 (void) sprintf(bufp, "ldc(%ld):", ldcp->ldc_id); 5780 bufp += strlen(bufp); 5781 } 5782 (void) sprintf(bufp, "%s: ", fname); 5783 bufp += strlen(bufp); 5784 5785 va_start(ap, fmt); 5786 (void) vsprintf(bufp, fmt, ap); 5787 va_end(ap); 5788 5789 if ((ldcp == NULL) ||(vgendbg_ldcid == -1) || 5790 (vgendbg_ldcid == ldcp->ldc_id)) { 5791 cmn_err(CE_CONT, "%s\n", buf); 5792 } 5793 } 5794 #endif 5795 5796 #ifdef VNET_IOC_DEBUG 5797 5798 static void 5799 vgen_ioctl(void *arg, queue_t *q, mblk_t *mp) 5800 { 5801 struct iocblk *iocp; 5802 vgen_port_t *portp; 5803 enum ioc_reply { 5804 IOC_INVAL = -1, /* bad, NAK with EINVAL */ 5805 IOC_ACK /* OK, just send ACK */ 5806 } status; 5807 int rv; 5808 5809 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 5810 iocp->ioc_error = 0; 5811 portp = (vgen_port_t *)arg; 5812 5813 if (portp == NULL) { 5814 status = IOC_INVAL; 5815 goto vgen_ioc_exit; 5816 } 5817 5818 mutex_enter(&portp->lock); 5819 5820 switch (iocp->ioc_cmd) { 5821 5822 case VNET_FORCE_LINK_DOWN: 5823 case VNET_FORCE_LINK_UP: 5824 rv = vgen_force_link_state(portp, iocp->ioc_cmd); 5825 (rv == 0) ? (status = IOC_ACK) : (status = IOC_INVAL); 5826 break; 5827 5828 default: 5829 status = IOC_INVAL; 5830 break; 5831 5832 } 5833 5834 mutex_exit(&portp->lock); 5835 5836 vgen_ioc_exit: 5837 5838 switch (status) { 5839 default: 5840 case IOC_INVAL: 5841 /* Error, reply with a NAK and EINVAL error */ 5842 miocnak(q, mp, 0, EINVAL); 5843 break; 5844 case IOC_ACK: 5845 /* OK, reply with an ACK */ 5846 miocack(q, mp, 0, 0); 5847 break; 5848 } 5849 } 5850 5851 static int 5852 vgen_force_link_state(vgen_port_t *portp, int cmd) 5853 { 5854 ldc_status_t istatus; 5855 int rv; 5856 vgen_ldc_t *ldcp = portp->ldcp; 5857 vgen_t *vgenp = portp->vgenp; 5858 5859 mutex_enter(&ldcp->cblock); 5860 5861 switch (cmd) { 5862 5863 case VNET_FORCE_LINK_DOWN: 5864 (void) ldc_down(ldcp->ldc_handle); 5865 ldcp->link_down_forced = B_TRUE; 5866 break; 5867 5868 case VNET_FORCE_LINK_UP: 5869 vgen_ldc_up(ldcp); 5870 ldcp->link_down_forced = B_FALSE; 5871 5872 if (ldc_status(ldcp->ldc_handle, &istatus) != 0) { 5873 DWARN(vgenp, ldcp, "ldc_status err\n"); 5874 } else { 5875 ldcp->ldc_status = istatus; 5876 } 5877 5878 /* if channel is already UP - restart handshake */ 5879 if (ldcp->ldc_status == LDC_UP) { 5880 vgen_handle_evt_up(ldcp); 5881 } 5882 break; 5883 5884 } 5885 5886 mutex_exit(&ldcp->cblock); 5887 5888 return (0); 5889 } 5890 5891 #else 5892 5893 static void 5894 vgen_ioctl(void *arg, queue_t *q, mblk_t *mp) 5895 { 5896 vgen_port_t *portp; 5897 5898 portp = (vgen_port_t *)arg; 5899 5900 if (portp == NULL) { 5901 miocnak(q, mp, 0, EINVAL); 5902 return; 5903 } 5904 5905 miocnak(q, mp, 0, ENOTSUP); 5906 } 5907 5908 #endif 5909