1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER START
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The contents of this file are subject to the terms of the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Common Development and Distribution License (the "License").
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You may not use this file except in compliance with the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * See the License for the specific language governing permissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and limitations under the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * When distributing Covered Code, include this CDDL HEADER in each
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If applicable, add the following below this CDDL HEADER, with the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fields enclosed by brackets "[]" replaced with your own identifying
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * information: Portions Copyright [yyyy] [name of copyright owner]
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER END
a862df29af145cac620492c4ebe1f42c1906c66eSriharsha Basavapatna * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Implementation of the mac provider functionality for vnet using the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * generic(default) transport layer of sun4v Logical Domain Channels(LDC).
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Entry Points */
678453a8ed49104d8adad58f3ba591bdc39883e8speerint vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnamblk_t *vgen_rx_poll(void *arg, int bytes_to_pickup);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int vgen_stat(void *arg, uint_t stat, uint64_t *val);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_ioctl(void *arg, queue_t *q, mblk_t *mp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic int vgen_force_link_state(vgen_port_t *portp, int link_state);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Port/LDC Configuration */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic void vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_port_t *vgen_port_lookup(vgen_portlist_t *plistp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic uint64_t vgen_port_stat(vgen_port_t *portp, uint_t stat);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_port_reset(vgen_port_t *portp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_reset_vsw_port(vgen_t *vgenp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_ldc_reset(vgen_ldc_t *ldcp, vgen_caller_t caller);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_ldc_up(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* I/O Processing */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_portsend(vgen_port_t *portp, mblk_t *mp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic uint_t vgen_ldc_cb(uint64_t event, caddr_t arg);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_tx_watchdog(void *arg);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Dring Configuration */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_create_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_destroy_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_map_dring(vgen_ldc_t *ldcp, void *pkt);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_unmap_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* VIO Message Processing */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handshake(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handshake_done(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handshake_phase2(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handshake_phase3(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_setup_handshake_params(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_version_negotiate(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_send_rx_dring_reg(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_send_tx_dring_reg(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic void vgen_init_dring_reg_msg(vgen_ldc_t *ldcp, vio_dring_reg_msg_t *msg,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_send_dringdata(vgen_ldc_t *ldcp, uint32_t start, int32_t end);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_version_negotiate(vgen_ldc_t *ldcp,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handle_attr_msg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handle_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handle_attr_ack(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handle_dring_reg_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_handle_dring_reg_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic int vgen_process_reset(vgen_ldc_t *ldcp, int flags);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_link_update(vgen_t *vgenp, link_state_t link_state);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_read_ids(void *arg, int type, md_t *mdp,
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp,
c1c61f44e88f4c8c155272ee56d868043146096asbstatic mblk_t *vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp,
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_unaware_port_reset(vgen_port_t *portp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Exported functions */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaint vgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaint vgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavoid vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnaextern int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnaextern void vnet_link_update(vnet_t *vnetp, link_state_t link_state);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_stop_msg_thread(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_create_tx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_destroy_tx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_map_rx_dring(vgen_ldc_t *ldcp, void *pkt);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_unmap_rx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_create_rx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_destroy_rx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_map_tx_dring(vgen_ldc_t *ldcp, void *pkt);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_unmap_tx_dring(vgen_ldc_t *ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_map_data(vgen_ldc_t *ldcp, void *pkt);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_handle_dringdata_shm(void *arg1, void *arg2);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_handle_dringdata(void *arg1, void *arg2);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_dringsend_shm(void *arg, mblk_t *mp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_dringsend(void *arg, mblk_t *mp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern void vgen_ldc_msg_worker(void *arg);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_send_dringack_shm(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna uint32_t start, int32_t end, uint8_t pstate);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern mblk_t *vgen_poll_rcv_shm(vgen_ldc_t *ldcp, int bytes_to_pickup);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern mblk_t *vgen_poll_rcv(vgen_ldc_t *ldcp, int bytes_to_pickup);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaextern int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb#define VGEN_PRI_ETH_DEFINED(vgenp) ((vgenp)->pri_num_types != 0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Property names
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char rmacaddr_propname[] = "remote-mac-address";
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic char pri_types_propname[] = "priority-ether-types";
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic char vgen_mtu_propname[] = "mtu";
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic char vgen_linkprop_propname[] = "linkprop";
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * VIO Protocol Version Info:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * The version specified below represents the version of protocol currently
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * supported in the driver. It means the driver can negotiate with peers with
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * versions <= this version. Here is a summary of the feature(s) that are
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * supported at each version of the protocol:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.0 Basic VIO protocol.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.1 vDisk protocol update (no virtual network update).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.2 Support for priority frames (priority-ether-types).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.3 VLAN and HybridIO support.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.4 Jumbo Frame support.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.5 Link State Notification support with optional support
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * for Physical Link information.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * 1.6 Support for RxDringData mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnastatic vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 6} };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Tunables */
19b65a69adc64b3289ccb2fc32b805782e3f4540sbuint32_t vgen_hwd_interval = 5; /* handshake watchdog freq in sec */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint32_t vgen_ldcwr_retries = 10; /* max # of ldc_write() retries */
8e6a2a040587479821d1e682a28bcef7e75f19a6lmuint32_t vgen_ldcup_retries = 5; /* max # of ldc_up() retries */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatnauint32_t vgen_ldccl_retries = 5; /* max # of ldc_close() retries */
61a70d81555b002d961400e93b444d97fc467f13raghuramuint32_t vgen_tx_delay = 0x30; /* delay when tx descr not available */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnauint32_t vgen_ldc_mtu = VGEN_LDC_MTU; /* ldc mtu */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnauint32_t vgen_txwd_interval = VGEN_TXWD_INTERVAL; /* watchdog freq in msec */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnauint32_t vgen_txwd_timeout = VGEN_TXWD_TIMEOUT; /* tx timeout in msec */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Max # of channel resets allowed during handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * See comments in vsw.c for details on the dring modes supported.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * In RxDringData mode, # of buffers is determined by multiplying the # of
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * descriptors with the factor below. Note that the factor must be > 1; i.e,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * the # of buffers must always be > # of descriptors. This is needed because,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * while the shared memory buffers are sent up the stack on the receiver, the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * sender needs additional buffers that can be used for further transmits.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * See vgen_create_rx_dring() for details.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Retry delay used while destroying rx mblk pools. Used in both Dring modes.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnaint vgen_rxpool_cleanup_delay = 100000; /* 100ms */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Delay when rx descr not ready; used in TxDring mode only.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Retry when rx descr not ready; used in TxDring mode only.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Max # of packets accumulated prior to sending them up. It is best
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * to keep this at 60% of the number of receive buffers. Used in TxDring mode
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * by the msg worker thread. Used in RxDringData mode while in interrupt mode
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * (not used in polled mode).
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Internal tunables for receive buffer pools, that is, the size and number of
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * mblks for each pool. At least 3 sizes must be specified if these are used.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * The sizes must be specified in increasing order. Non-zero value of the first
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * size will be used as a hint to use these values instead of the algorithm
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * that determines the sizes based on MTU. Used in TxDring mode only.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * In the absence of "priority-ether-types" property in MD, the following
f0ca1d9a12d54d304791bc74525e2010ca924726sb * internal tunable can be set to specify a single priority ethertype.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Number of transmit priority buffers that are preallocated per device.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This number is chosen to be a small value to throttle transmission
f0ca1d9a12d54d304791bc74525e2010ca924726sb * of priority packets. Note: Must be a power of 2 for vio_create_mblks().
c1c61f44e88f4c8c155272ee56d868043146096asbuint32_t vgen_vlan_nchains = 4; /* # of chains in vlan id hash table */
c1c61f44e88f4c8c155272ee56d868043146096asb * Matching criteria passed to the MDEG to register interest
c1c61f44e88f4c8c155272ee56d868043146096asb * in changes to 'virtual-device' nodes (i.e. vnet nodes) identified
c1c61f44e88f4c8c155272ee56d868043146096asb * by their 'name' and 'cfg-handle' properties.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* MD update matching structure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mdeg_node_match_t vport_match = { "virtual-device-port",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Template for matching a particular vnet instance */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define VGEN_SET_MDEG_PROP_INST(specp, val) (specp)[1].ps_val = (val)
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#define VGEN_M_CALLBACK_FLAGS (MC_IOCTL)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavoid vgen_debug_printf(const char *fname, vgen_t *vgenp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* -1 for all LDCs info, or ldc_id for a specific LDC info */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Flags to simulate error conditions for debugging */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_inject_error(vgen_ldc_t *ldcp, int error)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((vgendbg_ldcid == ldcp->ldc_id) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_init() is called by an instance of vnet driver to initialize the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * corresponding generic transport layer. This layer uses Logical Domain
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Channels (LDCs) to communicate with the virtual switch in the service domain
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * and also with peer vnets in other guest domains in the system.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vnetp: an opaque pointer to the vnet instance
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * regprop: frame to be transmitted
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vnetdip: dip of the vnet device
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * macaddr: mac address of the vnet device
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Sucess: a handle to the vgen instance (vgen_t)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Failure: NULL
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->phys_link_state = LINK_STATE_UNKNOWN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate multicast table */
93b13a42237cddf986044511610fa8eddef1bd09wentaoy rw_init(&vgenp->vgenports.rwlock, NULL, RW_DRIVER, NULL);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) snprintf(qname, TASKQ_NAMELEN, "rxpool_taskq%d",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((vgenp->rxp_taskq = ddi_taskq_create(vnetdip, qname, 1,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna cmn_err(CE_WARN, "!vnet%d: Unable to create rx pool task queue",
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb sizeof (struct ether_addr));
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* register with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Called by vnet to undo the initializations done by vgen_init().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The handle provided by generic transport during vgen_init() is the argument.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Unregister with MD event generator */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Detach all ports from the device; note that the device should have
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * been unplumbed by this time (See vnet_unattach() for the sequence)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * and thus vgen_stop() has already been invoked on all the ports.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We now destroy the taskq used to clean up rx mblk pools that
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * couldn't be destroyed when the ports/channels were detached.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We implicitly wait for those tasks to complete in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * ddi_taskq_destroy().
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Free multicast table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Free pri_types table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive for the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen transmit function */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success */
c1c61f44e88f4c8c155272ee56d868043146096asb * This function provides any necessary tagging/untagging of the frames
c1c61f44e88f4c8c155272ee56d868043146096asb * that are being transmitted over the port. It first verifies the vlan
c1c61f44e88f4c8c155272ee56d868043146096asb * membership of the destination(port) and drops the packet if the
c1c61f44e88f4c8c155272ee56d868043146096asb * destination doesn't belong to the given vlan.
c1c61f44e88f4c8c155272ee56d868043146096asb * Arguments:
c1c61f44e88f4c8c155272ee56d868043146096asb * portp: port over which the frames should be transmitted
c1c61f44e88f4c8c155272ee56d868043146096asb * mp: frame to be transmitted
c1c61f44e88f4c8c155272ee56d868043146096asb * is_tagged:
c1c61f44e88f4c8c155272ee56d868043146096asb * B_TRUE: indicates frame header contains the vlan tag already.
c1c61f44e88f4c8c155272ee56d868043146096asb * B_FALSE: indicates frame is untagged.
c1c61f44e88f4c8c155272ee56d868043146096asb * vid: vlan in which the frame should be transmitted.
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns:
c1c61f44e88f4c8c155272ee56d868043146096asb * Sucess: frame(mblk_t *) after doing the necessary tag/untag.
c1c61f44e88f4c8c155272ee56d868043146096asb * Failure: NULL
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, boolean_t is_tagged,
c1c61f44e88f4c8c155272ee56d868043146096asb * If the packet is going to a vnet:
c1c61f44e88f4c8c155272ee56d868043146096asb * Check if the destination vnet is in the same vlan.
c1c61f44e88f4c8c155272ee56d868043146096asb * Check the frame header if tag or untag is needed.
c1c61f44e88f4c8c155272ee56d868043146096asb * We do not check the above conditions if the packet is going to vsw:
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw must be present implicitly in all the vlans that a vnet device
c1c61f44e88f4c8c155272ee56d868043146096asb * is configured into; even if vsw itself is not assigned to those
c1c61f44e88f4c8c155272ee56d868043146096asb * vlans as an interface. For instance, the packet might be destined
c1c61f44e88f4c8c155272ee56d868043146096asb * to another vnet(indirectly through vsw) or to an external host
c1c61f44e88f4c8c155272ee56d868043146096asb * which is in the same vlan as this vnet and vsw itself may not be
c1c61f44e88f4c8c155272ee56d868043146096asb * present in that vlan. Similarly packets going to vsw must be
c1c61f44e88f4c8c155272ee56d868043146096asb * always tagged(unless in the default-vlan) if not already tagged,
c1c61f44e88f4c8c155272ee56d868043146096asb * as we do not know the final destination. This is needed because
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw must always invoke its switching function only after tagging
c1c61f44e88f4c8c155272ee56d868043146096asb * the packet; otherwise after switching function determines the
c1c61f44e88f4c8c155272ee56d868043146096asb * destination we cannot figure out if the destination belongs to the
c1c61f44e88f4c8c155272ee56d868043146096asb * the same vlan that the frame originated from and if it needs tag/
c1c61f44e88f4c8c155272ee56d868043146096asb * untag. Note that vsw will tag the packet itself when it receives
c1c61f44e88f4c8c155272ee56d868043146096asb * it over the channel from a client if needed. However, that is
c1c61f44e88f4c8c155272ee56d868043146096asb * needed only in the case of vlan unaware clients such as obp or
c1c61f44e88f4c8c155272ee56d868043146096asb * earlier versions of vnet.
c1c61f44e88f4c8c155272ee56d868043146096asb * Packet going to a vnet. Check if the destination vnet is in
c1c61f44e88f4c8c155272ee56d868043146096asb * the same vlan. Then check the frame header if tag/untag is
c1c61f44e88f4c8c155272ee56d868043146096asb /* drop the packet */
c1c61f44e88f4c8c155272ee56d868043146096asb /* is the destination tagged or untagged in this vlan? */
c1c61f44e88f4c8c155272ee56d868043146096asb /* no tagging/untagging needed */
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb /* frame is tagged; destination needs untagged */
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb /* (is_tagged == B_FALSE): fallthru to tag tx packet: */
c1c61f44e88f4c8c155272ee56d868043146096asb * Packet going to a vnet needs tagging.
c1c61f44e88f4c8c155272ee56d868043146096asb * If the packet is going to vsw, then it must be tagged in all cases:
c1c61f44e88f4c8c155272ee56d868043146096asb * unknown unicast, broadcast/multicast or to vsw interface.
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* transmit packets over the given port */
c1c61f44e88f4c8c155272ee56d868043146096asb * Determine the vlan id that the frame belongs to.
c1c61f44e88f4c8c155272ee56d868043146096asb /* Frames in default vlan must be untagged */
c1c61f44e88f4c8c155272ee56d868043146096asb * If the destination is a vnet-port verify it belongs to the
c1c61f44e88f4c8c155272ee56d868043146096asb * default vlan; otherwise drop the packet. We do not need
c1c61f44e88f4c8c155272ee56d868043146096asb * this check for vsw-port, as it should implicitly belong to
c1c61f44e88f4c8c155272ee56d868043146096asb * this vlan; see comments in vgen_vlan_frame_fixtag().
c1c61f44e88f4c8c155272ee56d868043146096asb } else { /* frame not in default-vlan */
c1c61f44e88f4c8c155272ee56d868043146096asb mp = vgen_vlan_frame_fixtag(portp, mp, is_tagged, vlan_id);
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Wrapper function to transmit normal and/or priority frames over the channel.
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (i = 0; i < num_types; i++) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* priority frame, use pri tx function */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna status = ldcp->tx_dringdata(ldcp, mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function transmits the frame in the payload of a raw data
f0ca1d9a12d54d304791bc74525e2010ca924726sb * (VIO_PKT_DATA) message. Thus, it provides an Out-Of-Band path to
f0ca1d9a12d54d304791bc74525e2010ca924726sb * send special frames with high priorities, without going through
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the normal data path which uses descriptor ring mechanism.
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* drop the packet if ldc is not up or handshake is not done */
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* frame size bigger than available payload len of raw data msg ? */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (size > (size_t)(ldcp->msglen - VIO_PKT_DATA_HDRSIZE)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* alloc space for a raw data message */
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* copy frame into the payload of raw data message */
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* setup the raw data msg */
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* send the msg over ldc */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_handle_evt_reset(ldcp, VGEN_OTHER);
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* update stats */
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * enable/disable a multicast address
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * note that the cblock of the ldc channel connected to the vsw is used for
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * synchronization of the mctab.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_multicst(void *arg, boolean_t add, const uint8_t *mca)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If handshake is done, send a msg to vsw to add/remove
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * the multicast address. Otherwise, we just update this
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * mcast address in our table and the table will be sync'd
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * with vsw when handshake completes.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (mcastmsg),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* expand multicast table if necessary */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (struct ether_addr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* add address to the table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* delete address from the table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If there's more than one address in this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * table, delete the unwanted one by moving
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the last one in the list over top of it;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * otherwise, just remove it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* set or clear promiscuous mode on the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* set the unicast mac address of the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* get device statistics */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen internal functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach all ports from the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * detach the given port.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * If this port is connected to the vswitch, then
678453a8ed49104d8adad58f3ba591bdc39883e8speer * potentially there could be ports that may be using
678453a8ed49104d8adad58f3ba591bdc39883e8speer * this port to transmit packets. To address this do
678453a8ed49104d8adad58f3ba591bdc39883e8speer * the following:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - First set vgenp->vsw_portp to NULL, so that
678453a8ed49104d8adad58f3ba591bdc39883e8speer * its not used after that.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - Then wait for the refcnt to go down to 0.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - Now we can safely detach this port.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* remove it from port list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* detach channels from this port */
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(portp->ldc_ids, portp->num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a port to port list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* remove a port from port list */
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ((nextp = prevp->nextp) != NULL) && (nextp != portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* lookup a port in the list based on port_num */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_lookup(vgen_portlist_t *plistp, int port_num)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* Add the port to the specified vlans */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Bring up the channel */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* remove the port from vlans it has been assigned to */
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Scan the machine description for this instance of vnet
f0ca1d9a12d54d304791bc74525e2010ca924726sb * and read its properties. Called only from vgen_init().
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Returns: 0 on success, 1 on failure.
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (rv);
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* search for all "virtual_device" nodes */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (num_devs <= 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Now loop through the list of virtual-devices looking for
f0ca1d9a12d54d304791bc74525e2010ca924726sb * devices with name "network" and for each such device compare
f0ca1d9a12d54d304791bc74525e2010ca924726sb * its instance with what we have from the 'reg' property to
f0ca1d9a12d54d304791bc74525e2010ca924726sb * find the right node in MD and then read all its properties.
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (i = 0; i < num_devs; i++) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (md_get_prop_str(mdp, listp[i], "name", &name) != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* is this a "network" device? */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (md_get_prop_val(mdp, listp[i], "cfg-handle", &cfgh) != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* is this the required instance of vnet? */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Read the 'linkprop' property to know if this vnet
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * device should get physical link updates from vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_linkprop_read(vgenp, mdp, listp[i],
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Read the mtu. Note that we set the mtu of vnet device within
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * this routine itself, after validating the range.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_mtu_read(vgenp, mdp, listp[i], &vnetp->mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (vnetp->mtu < ETHERMTU || vnetp->mtu > VNET_MAX_MTU) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sizeof (struct ether_header) + VLAN_TAGSZ;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* read priority ether types */
c1c61f44e88f4c8c155272ee56d868043146096asb /* read vlan id properties of this vnet instance */
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (rv);
c1c61f44e88f4c8c155272ee56d868043146096asb * Read vlan id properties of the given MD node.
c1c61f44e88f4c8c155272ee56d868043146096asb * Arguments:
c1c61f44e88f4c8c155272ee56d868043146096asb * arg: device argument(vnet device or a port)
c1c61f44e88f4c8c155272ee56d868043146096asb * type: type of arg; VGEN_LOCAL(vnet device) or VGEN_PEER(port)
c1c61f44e88f4c8c155272ee56d868043146096asb * mdp: machine description
c1c61f44e88f4c8c155272ee56d868043146096asb * node: md node cookie
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns:
c1c61f44e88f4c8c155272ee56d868043146096asb * pvidp: port-vlan-id of the node
c1c61f44e88f4c8c155272ee56d868043146096asb * vidspp: list of vlan-ids of the node
c1c61f44e88f4c8c155272ee56d868043146096asb * nvidsp: # of vlan-ids in the list
c1c61f44e88f4c8c155272ee56d868043146096asb * default_idp: default-vlan-id of the node(if node is vnet device)
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_read_ids(void *arg, int type, md_t *mdp, mde_cookie_t node,
c1c61f44e88f4c8c155272ee56d868043146096asb rv = md_get_prop_val(mdp, node, vgen_dvid_propname, &val);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb rv = md_get_prop_data(mdp, node, vid_propname, (uint8_t **)&data,
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb for (i = 0; i < nvids; i++) {
c1c61f44e88f4c8c155272ee56d868043146096asb * Create a vlan id hash table for the given port.
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb (void) snprintf(hashname, MAXNAMELEN, "port%d-vlan-hash",
c1c61f44e88f4c8c155272ee56d868043146096asb * Destroy the vlan id hash table in the given port.
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb * Add a port to the vlans specified in its port properites.
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb * Remove a port from the vlans it has been assigned to.
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb * Lookup the vlan id of the given tx frame. If it is a vlan-tagged frame,
c1c61f44e88f4c8c155272ee56d868043146096asb * then the vlan-id is available in the tag; otherwise, its vlan id is
c1c61f44e88f4c8c155272ee56d868043146096asb * implicitly obtained from the port-vlan-id of the vnet device.
c1c61f44e88f4c8c155272ee56d868043146096asb * The vlan id determined is returned in vidp.
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns: B_TRUE if it is a tagged frame; B_FALSE if it is untagged.
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, uint16_t *vidp)
c1c61f44e88f4c8c155272ee56d868043146096asb /* If it's a tagged frame, get the vlan id from vlan header */
c1c61f44e88f4c8c155272ee56d868043146096asb /* Untagged frame, vlan-id is the pvid of vnet device */
c1c61f44e88f4c8c155272ee56d868043146096asb * Find the given vlan id in the hash table.
c1c61f44e88f4c8c155272ee56d868043146096asb * Return: B_TRUE if the id is found; B_FALSE if not found.
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_find(vlan_hashp, VLAN_ID_KEY(vid), (mod_hash_val_t *)&vp);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0)
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function reads "priority-ether-types" property from md. This property
f0ca1d9a12d54d304791bc74525e2010ca924726sb * is used to enable support for priority frames. Applications which need
f0ca1d9a12d54d304791bc74525e2010ca924726sb * guaranteed and timely delivery of certain high priority frames to/from
f0ca1d9a12d54d304791bc74525e2010ca924726sb * a vnet or vsw within ldoms, should configure this property by providing
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the ether type(s) for which the priority facility is needed.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Normal data frames are delivered over a ldc channel using the descriptor
f0ca1d9a12d54d304791bc74525e2010ca924726sb * ring mechanism which is constrained by factors such as descriptor ring size,
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the rate at which the ring is processed at the peer ldc end point, etc.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * The priority mechanism provides an Out-Of-Band path to send/receive frames
f0ca1d9a12d54d304791bc74525e2010ca924726sb * as raw pkt data (VIO_PKT_DATA) messages over the channel, avoiding the
f0ca1d9a12d54d304791bc74525e2010ca924726sb * descriptor ring path and enables a more reliable and timely delivery of
f0ca1d9a12d54d304791bc74525e2010ca924726sb * frames to the peer.
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, mde_cookie_t node)
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Property may not exist if we are running pre-ldoms1.1 f/w.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Check if 'vgen_pri_eth_type' has been set in that case.
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (size == 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb * we have some priority-ether-types defined;
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a table of these types and also
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a pool of mblks to transmit these
f0ca1d9a12d54d304791bc74525e2010ca924726sb * priority packets.
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgenp->pri_types = kmem_zalloc(size * sizeof (uint16_t), KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb mblk_sz = (VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size + 7) & ~7;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vio_create_mblks(vgen_pri_tx_nmblks, mblk_sz, NULL,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnavgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, uint32_t *mtu)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = md_get_prop_val(mdp, node, mtu_propname, &val);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DWARN(vgenp, NULL, "prop(%s) not found", mtu_propname);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DBG2(vgenp, NULL, "%s(%d): (%d)\n", mtu_propname,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna linkpropname = vgen_linkprop_propname;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = md_get_prop_val(mdp, node, linkpropname, &val);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, NULL, "prop(%s) not found", linkpropname);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *pls = (val & 0x1) ? B_TRUE : B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DBG2(vgenp, NULL, "%s(%d): (%d)\n", linkpropname,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* register with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp = kmem_zalloc(sizeof (mdeg_node_spec_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * NOTE: The instance here refers to the value of "reg" property and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * not the dev_info instance (ddi_get_instance()) of vnet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save parentp in vgen_t */
c1c61f44e88f4c8c155272ee56d868043146096asb * Register an interest in 'virtual-device' nodes with a
c1c61f44e88f4c8c155272ee56d868043146096asb * 'name' property of 'network'
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mdeg_register(parentp, &vdev_match, vgen_mdeg_cb, vgenp, &dev_hdl);
c1c61f44e88f4c8c155272ee56d868043146096asb /* Register an interest in 'port' nodes */
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mdeg_register(parentp, &vport_match, vgen_mdeg_port_cb, vgenp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save mdeg handle in vgen_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* unregister with MD event generator */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna (void) mdeg_unregister(vgenp->mdeg_dev_hdl);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna (void) mdeg_unregister(vgenp->mdeg_port_hdl);
c1c61f44e88f4c8c155272ee56d868043146096asb/* mdeg callback function for the port node */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * find vsw_port and add it first, because other ports need
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * this when adding fdb entry (see vgen_port_init()).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (val == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This port is connected to the
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw on service domain.
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk "not initialize virtual "
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk "switch port.",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((vsw_idx != -1) && (vsw_idx == idx)) /* skip vsw_port */
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk /* If this port can't be added just skip it. */
c1c61f44e88f4c8c155272ee56d868043146096asb/* mdeg callback function for the vnet node */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG DBG1(vgenp, NULL, "added %d : removed %d : curr matched %d"
c1c61f44e88f4c8c155272ee56d868043146096asb " : prev matched %d", resp->added.nelem, resp->removed.nelem,
c1c61f44e88f4c8c155272ee56d868043146096asb * We get an initial callback for this node as 'added' after
c1c61f44e88f4c8c155272ee56d868043146096asb * registering with mdeg. Note that we would have already gathered
c1c61f44e88f4c8c155272ee56d868043146096asb * information about this vnet node by walking MD earlier during attach
c1c61f44e88f4c8c155272ee56d868043146096asb * (in vgen_read_mdprops()). So, there is a window where the properties
c1c61f44e88f4c8c155272ee56d868043146096asb * of this node might have changed when we get this initial 'added'
c1c61f44e88f4c8c155272ee56d868043146096asb * callback. We handle this as if an update occured and invoke the same
c1c61f44e88f4c8c155272ee56d868043146096asb * function which handles updates to the properties of this vnet-node
c1c61f44e88f4c8c155272ee56d868043146096asb * if any. A non-zero 'match' value indicates that the MD has been
c1c61f44e88f4c8c155272ee56d868043146096asb * updated and that a 'network' node is present which may or may not
c1c61f44e88f4c8c155272ee56d868043146096asb * have been updated. It is up to the clients to examine their own
c1c61f44e88f4c8c155272ee56d868043146096asb * nodes and determine if they have changed.
c1c61f44e88f4c8c155272ee56d868043146096asb /* Validate name and instance */
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_str(mdp, node, "name", &node_name) != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* is this a virtual-network device? */
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "%s: Invalid node name: %s\n", node_name);
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* is this the right instance of vnet? */
c1c61f44e88f4c8c155272ee56d868043146096asb * Check to see if the relevant properties in the specified node have
c1c61f44e88f4c8c155272ee56d868043146096asb * changed, and if so take the appropriate action.
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
c1c61f44e88f4c8c155272ee56d868043146096asb /* Read the vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, mdex, &pvid, &vids,
c1c61f44e88f4c8c155272ee56d868043146096asb /* Determine if there are any vlan id updates */
c1c61f44e88f4c8c155272ee56d868043146096asb ((nvids != 0) && (vnetp->nvids != 0) && /* vids changed? */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_mtu_read(vgenp, mdp, mdex, &mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (mtu >= ETHERMTU && mtu <= VNET_MAX_MTU) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu update"
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna " as the specified value:%d is invalid\n",
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Read the 'linkprop' property.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_linkprop_read(vgenp, mdp, mdex, &pls_update);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (pls_update != vnetp->pls_update) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* Now process the updated props */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* save the new vlan ids */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* reset vlan-unaware peers (ver < 1.3) and restart handshake */
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DBG2(vgenp, NULL, "curr_mtu(%d) new_mtu(%d)\n",
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sizeof (struct ether_header) + VLAN_TAGSZ;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* enable/disable physical link state updates */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* reset vsw-port to re-negotiate with the updated prop. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a new port to the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
c1c61f44e88f4c8c155272ee56d868043146096asb/* read properties of the port from its md node */
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read "id" property to get the port number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Find the channel endpoint node(s) under this port node.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "invalid number of nodes found (%d)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate space for node list */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "can't find %s nodes", channel_propname);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, NULL, "Port %d: Number of channels %d > 1\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_ids = kmem_zalloc(num_ldcs * sizeof (uint64_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < num_ldcs; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read channel ids */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, listp[i], id_propname, &ldc_ids[i])) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", rmacaddr_propname);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "invalid address size (%d)\n", addrsz);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, NULL, "remote mac address 0x%llx\n", macaddr);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* This port is connected to the vswitch */
c1c61f44e88f4c8c155272ee56d868043146096asb /* now update all properties into the port */
c1c61f44e88f4c8c155272ee56d868043146096asb portp->ldc_ids = kmem_zalloc(sizeof (uint64_t) * num_ldcs, KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(ldc_ids, portp->ldc_ids, sizeof (uint64_t) * num_ldcs);
c1c61f44e88f4c8c155272ee56d868043146096asb /* read vlan id properties of this port node */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(portp, VGEN_PEER, mdp, mdex, &portp->pvid,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* remove a port from the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read "id" property to get the port number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "can't find port(%lx)\n", port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* attach a port to the device based on mdeg data */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DBG2(vgenp, NULL, "port_num(%d), ldcid(%lx)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * attach the channel under the port using its channel id;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * note that we only support one channel per port for now.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgen_ldc_attach(portp, ldcids[0]) == DDI_FAILURE) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* create vlan id hash table */
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* This port is connected to the switch port */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (rv == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* link it into the list of ports */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* We now have the vswitch port attached */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer DERR(vgenp, NULL, "vio_net_resource_reg failed for portp=0x%p",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach a port from the device based on mdeg data */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter: port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* stop the port if needed */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex,
c1c61f44e88f4c8c155272ee56d868043146096asb * For now, we get port updates only if vlan ids changed.
c1c61f44e88f4c8c155272ee56d868043146096asb * We read the port num and do some sanity check.
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_val(curr_mdp, curr_mdex, id_propname, &cport_num)) {
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_val(prev_mdp, prev_mdex, id_propname, &pport_num)) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* Read the vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(portp, VGEN_PEER, curr_mdp, curr_mdex, &pvid, &vids,
c1c61f44e88f4c8c155272ee56d868043146096asb /* Determine if there are any vlan id updates */
c1c61f44e88f4c8c155272ee56d868043146096asb ((nvids != 0) && (portp->nvids != 0) && /* vids changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb /* remove the port from vlans it has been assigned to */
c1c61f44e88f4c8c155272ee56d868043146096asb /* save the new vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(portp->vids, sizeof (uint16_t) * portp->nvids);
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vids = kmem_zalloc(sizeof (uint16_t) * nvids, KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb /* add port to the new vlans */
c1c61f44e88f4c8c155272ee56d868043146096asb /* reset the port if it is vlan unaware (ver < 1.3) */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna return (vgen_ldc_stat(portp->ldcp, stat));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* attach the channel corresponding to the given ldc_id to the port */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_init(&ldcp->wrlock, NULL, MUTEX_DRIVER, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_init(&ldcp->rxlock, NULL, MUTEX_DRIVER, NULL);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_init(&ldcp->pollq_lock, NULL, MUTEX_DRIVER, NULL);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna mutex_init(&ldcp->msg_thr_lock, NULL, MUTEX_DRIVER, NULL);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna cv_init(&ldcp->msg_thr_cv, NULL, CV_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_init failed,rv (%d)\n", status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_reg_callback failed, rv (%d)\n",
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a message for ldc_read()s, big enough to hold ctrl and
f0ca1d9a12d54d304791bc74525e2010ca924726sb * data msgs, including raw data msgs used to recv priority frames.
c1c61f44e88f4c8c155272ee56d868043146096asb ldcp->msglen = VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Setup kstats for the channel */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) sprintf(kname, "vnetldc0x%lx", ldcp->ldc_id);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ldcp->ksp = vgen_setup_kstats("vnet", instance, kname, &ldcp->stats);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize vgen_versions supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Link this channel to the port */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_state = LINK_STATE_UNKNOWN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach a channel from the port */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna kmem_free(ldcp->ldcmsg, ldcp->msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive on the channel */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna enum { ST_init = 0x0, ST_ldc_open = 0x1,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_open failed: rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "status(%d) is not OPEN/READY\n", istatus);
7636cb21f250f0485ca6052ffadc80ace93e6358lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_set_cb_mode failed: rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm /* if channel is already UP - start handshake */
678453a8ed49104d8adad58f3ba591bdc39883e8speer * As the channel is up, use this port from now on.
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initialize local session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* clear peer session id */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna flag = (rv == ECONNRESET) ? VGEN_FLAG_EVT_RESET :
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_process_reset(ldcp, flag);
7636cb21f250f0485ca6052ffadc80ace93e6358lm (void) ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive on the channel */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "CHANNEL_STARTED flag is not set\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna while (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna delay(drv_usectohz(VGEN_LDC_UNINIT_DELAY));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_process_reset(ldcp, VGEN_FLAG_UNINIT);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Create a descriptor ring, that will be exported to the peer for mapping.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Destroy the descriptor ring.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Map the descriptor ring exported by the peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_map_dring(vgen_ldc_t *ldcp, void *pkt)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * In RxDringData mode, dring that we map in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * becomes our transmit descriptor ring.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * In TxDring mode, dring that we map in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * becomes our receive descriptor ring.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Unmap the descriptor ring exported by the peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vio_mblk_pool_t *poolp = (vio_mblk_pool_t *)arg;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna while (vio_destroy_mblks(poolp) != 0) {
a862df29af145cac620492c4ebe1f42c1906c66eSriharsha Basavapatna delay(drv_usectohz(vgen_rxpool_cleanup_delay));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* get channel statistics */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* stats not relevant to ldc, return 0 */
678453a8ed49104d8adad58f3ba591bdc39883e8speer * LDC channel is UP, start handshake process with peer.
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
678453a8ed49104d8adad58f3ba591bdc39883e8speer * As the channel is up, use this port from now on.
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initialize local session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* clear peer session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initiate Handshake process with peer ldc endpoint */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_handshake(vh_nextphase(ldcp));
3af08d828975d7e2581b6829e0eecff14d87a483lm * LDC channel is Reset, terminate connection with peer and try to
3af08d828975d7e2581b6829e0eecff14d87a483lm * bring the channel up again.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_evt_reset(vgen_ldc_t *ldcp, vgen_caller_t caller)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Set the flag to indicate reset is in progress */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* another thread is already in the process of resetting */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_process_reset(ldcp, VGEN_FLAG_EVT_RESET);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Interrupt handler for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) {
3af08d828975d7e2581b6829e0eecff14d87a483lm * NOTE: not using switch() as event could be triggered by
3af08d828975d7e2581b6829e0eecff14d87a483lm * a state change and a read request. Also the ordering of the
3af08d828975d7e2581b6829e0eecff14d87a483lm * check for the event types is deliberate.
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* status couldn't be determined */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram " but ldc status is not UP(0x%x)\n",
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* spurious interrupt, return success */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* Handle RESET/DOWN before READ event */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* status couldn't be determined */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram DWARN(vgenp, ldcp, "event(%lx) RESET/DOWN, status(%d)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_handle_evt_reset(ldcp, VGEN_LDC_CB);
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram * As the channel is down/reset, ignore READ event
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram * but print a debug warning message.
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram "LDC_EVT_READ set along with RESET/DOWN\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the receive thread is enabled, then
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * wakeup the receive thread to process the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * LDC messages.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (!(ldcp->msg_thr_flags & VGEN_WTHR_DATARCVD)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->msg_thr_flags |= VGEN_WTHR_DATARCVD;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_handle_evt_read(ldcp, VGEN_LDC_CB);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_evt_read(vgen_ldc_t *ldcp, vgen_caller_t caller)
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = ldc_read(ldcp->ldc_handle, (caddr_t)ldcmsg, &msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_read() failed "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (msglen == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * check sid only after we have received peer's sid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in the version negotiate msg.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgen_inject_error(ldcp, VGEN_ERR_HSID)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* simulate bad sid condition */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_inject_err_flag &= ~(VGEN_ERR_HSID);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If sid mismatch is detected,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * reset the channel.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "vgen_check_sid() failed\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "vgen_handle_ctrlmsg()"
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "vgen_handle_datamsg()"
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If an error is encountered, stop processing and
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * handle the error.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* check once more before exiting */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DTRACE_PROBE1(vgen_chkq, vgen_ldc_t *, ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We handle the error and then return the error value. If we
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * are running in the context of the msg worker, the error
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * tells the worker thread to exit, as the channel would have
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_status err\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_handle_evt_reset(ldcp, caller);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "Calling vgen_ldc_reset()...\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen handshake functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* change the hphase for the channel to the next phase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send version negotiate message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get version msg payload from ldcp->local */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vermsg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send attr info message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get attr msg payload from ldcp->local */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna attrmsg.physlink_update = ldcp->local_hparams.physlink_update;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna attrmsg.options = ldcp->local_hparams.dring_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Send descriptor ring register message to the peer over ldc.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Invoked in RxDringData mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_send_rx_dring_reg(vgen_ldc_t *ldcp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msgsize = VNET_DRING_REG_EXT_MSG_SIZE(ldcp->rx_data_ncookies);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Initialize the common part of dring reg msg */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_init_dring_reg_msg(ldcp, msg, VIO_RX_DRING_DATA);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* skip over dring cookies at the tail of common section */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna buf += (msg->ncookies * sizeof (ldc_mem_cookie_t));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Now setup the extended part, specific to RxDringData mode */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna emsg = (vio_dring_reg_ext_msg_t *)buf;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* copy data_ncookies in the msg */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna emsg->data_ncookies = ldcp->rx_data_ncookies;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* copy data area size in the msg */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna emsg->data_area_size = ldcp->rx_data_sz;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* copy data area cookies in the msg */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna bcopy(ldcp->rx_data_cookie, (ldc_mem_cookie_t *)emsg->data_cookie,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna sizeof (ldc_mem_cookie_t) * ldcp->rx_data_ncookies);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)msg, msgsize, B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Send descriptor ring register message to the peer over ldc.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Invoked in TxDring mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_send_tx_dring_reg(vgen_ldc_t *ldcp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Initialize only the common part of dring reg msg in TxDring mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_init_dring_reg_msg(ldcp, &msg, VIO_TX_DRING);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)&msg, sizeof (msg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DBG2(vgenp, ldcp, "DRING_INFO_SENT \n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (rdxmsg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send multicast addr info message to vsw */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = ((mccount >= VNET_NUM_MCAST) ? VNET_NUM_MCAST : mccount);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp),
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vgen_dds_rx -- post DDS messages to vnet.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vio_dds_msg_t *dmsg = (vio_dds_msg_t *)tagp;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (dmsg->dds_class != DDS_VNET_NIU) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "Unknown DDS class, dropping");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vgen_dds_tx -- an interface called by vnet to send DDS messages.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_portlist_t *plistp = &vgenp->vgenports;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((ldcp == NULL) || (ldcp->hphase != VH_DONE)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)dmsg, sizeof (vio_dds_msg_t), B_FALSE);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Initiate Phase 2 of handshake */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handshake_phase2(vgen_ldc_t *ldcp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgen_inject_error(ldcp, VGEN_ERR_HSTATE)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* simulate out of state condition */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_inject_err_flag &= ~(VGEN_ERR_HSTATE);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgen_inject_error(ldcp, VGEN_ERR_HTIMEOUT)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* simulate timeout condition */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_inject_err_flag &= ~(VGEN_ERR_HTIMEOUT);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handshake_phase3(vgen_ldc_t *ldcp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* dring mode has been negotiated in attr phase; save in stats */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) { /* RxDringData mode */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->rx_dringdata = vgen_handle_dringdata_shm;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->tx_dringdata = vgen_dringsend_shm;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If priority frames are not in use, we don't need a
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * separate wrapper function for 'tx', so we set it to
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * 'tx_dringdata'. If priority frames are configured,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * we leave the 'tx' pointer as is (initialized in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vgen_set_vnet_proto_ops()).
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna } else { /* TxDring mode */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->msg_thread = thread_create(NULL,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna 2 * DEFAULTSTKSZ, vgen_ldc_msg_worker, ldcp, 0,
3af08d828975d7e2581b6829e0eecff14d87a483lm /* update local dring_info params */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.dring_ncookies = ldcp->rx_dring_ncookies;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.num_desc = ldcp->num_rxds;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.dring_ncookies = ldcp->tx_dring_ncookies;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.num_desc = ldcp->num_txds;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.desc_size = sizeof (vnet_public_desc_t);
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Set vnet-protocol-version dependent functions based on version.
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Setup the appropriate dring data processing routine and any
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * associated thread based on the version.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * In versions < 1.6, we only support TxDring mode. In this mode, the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * msg worker thread processes all types of VIO msgs (ctrl and data).
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * In versions >= 1.6, we also support RxDringData mode. In this mode,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * all msgs including dring data messages are handled directly by the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * callback (intr) thread. The dring data msgs (msgtype: VIO_TYPE_DATA,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * subtype: VIO_SUBTYPE_INFO, subtype_env: VIO_DRING_DATA) can also be
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * disabled while the polling thread is active, in which case the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * polling thread processes the rcv descriptor ring.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * However, for versions >= 1.6, we can force to only use TxDring mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * This could happen if RxDringData mode has been disabled (see
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG * below) on this guest or on the peer guest. This info is determined
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG * as part of attr exchange phase of handshake. Hence, we setup these
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG * pointers for v1.6 after attr msg phase completes during handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 6)) { /* Ver >= 1.6 */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Set data dring mode for vgen_send_attr_info().
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna lp->dring_mode = (VIO_RX_DRING_DATA | VIO_TX_DRING);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna } else { /* Ver <= 1.5 */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * If the version negotiated with vswitch is >= 1.5 (link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * status update support), set the required bits in our
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * attributes if this vnet device has been configured to get
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physical link state updates.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp == vgenp->vsw_portp && vnetp->pls_update == B_TRUE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna lp->physlink_update = PHYSLINK_UPDATE_STATE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna lp->physlink_update = PHYSLINK_UPDATE_NONE;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If the version negotiated with peer is >= 1.4(Jumbo Frame
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Support), set the mtu in our attributes to max_frame_size.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If the version negotiated with peer is == 1.3 (Vlan Tag
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Support) set the attr.mtu to ETHERMAX + VLAN_TAGSZ.
c1c61f44e88f4c8c155272ee56d868043146096asb * Pre-1.3 peers expect max frame size of ETHERMAX.
c1c61f44e88f4c8c155272ee56d868043146096asb * We can negotiate that size with those peers provided the
c1c61f44e88f4c8c155272ee56d868043146096asb * following conditions are true:
c1c61f44e88f4c8c155272ee56d868043146096asb * - Only pvid is defined for our peer and there are no vids.
c1c61f44e88f4c8c155272ee56d868043146096asb * - pvids are equal.
c1c61f44e88f4c8c155272ee56d868043146096asb * If the above conditions are true, then we can send/recv only
c1c61f44e88f4c8c155272ee56d868043146096asb * untagged frames of max size ETHERMAX.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (portp->nvids == 0 && portp->pvid == vnetp->pvid) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 2)) { /* Versions >= 1.2 */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Starting v1.2 we support priority frames; so set the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * dring processing routines and xfer modes based on the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * version. Note that the dring routines could be changed after
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * attribute handshake phase for versions >= 1.6 (See
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vgen_handshake_phase3())
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->rx_dringdata = vgen_handle_dringdata;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Enable priority routines and pkt mode only if
f0ca1d9a12d54d304791bc74525e2010ca924726sb * at least one pri-eth-type is specified in MD.
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* set xfer mode for vgen_send_attr_info() */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* No priority eth types defined in MD */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Set xfer mode for vgen_send_attr_info() */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna } else { /* Versions prior to 1.2 */
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Reset vnet-protocol-version dependent functions to pre-v1.2.
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->tx = ldcp->tx_dringdata = vgen_dringsend;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->rx_dringdata = vgen_handle_dringdata;
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* set xfer mode for vgen_send_attr_info() */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb * If the peer is vlan_unaware(ver < 1.3), reset channel and terminate
c1c61f44e88f4c8c155272ee56d868043146096asb * the connection. See comments in vgen_set_vnet_proto_ops().
c1c61f44e88f4c8c155272ee56d868043146096asb if (ldcp->hphase == VH_DONE && VGEN_VER_LT(ldcp, 1, 3) &&
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_ldc_reset(ldcp, VGEN_OTHER);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_ldc_reset(portp->ldcp, VGEN_OTHER);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asb for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if ((portp = vgenp->vsw_portp) != NULL) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_setup_handshake_params(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * clear local handshake params and initialize.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&(ldcp->local_hparams), sizeof (ldcp->local_hparams));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set version to the highest version supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set attr_info params */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ack_freq = 0; /* don't need acks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->local_hparams.physlink_update = PHYSLINK_UPDATE_NONE;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* reset protocol version specific function pointers */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->local_hparams.dring_ready = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* clear peer_hparams */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&(ldcp->peer_hparams), sizeof (ldcp->peer_hparams));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->peer_hparams.dring_ready = B_FALSE;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process Channel Reset. We tear down the resources (timers, threads,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * descriptor rings etc) associated with the channel and reinitialize the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * channel based on the flags.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * ldcp: The channel being processed.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * VGEN_FLAG_EVT_RESET:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * A ECONNRESET error occured while doing ldc operations such as
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * ldc_read() or ldc_write(); the channel is already reset and it
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * needs to be handled.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * VGEN_FLAG_NEED_LDCRESET:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Some other errors occured and the error handling code needs to
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * explicitly reset the channel and restart handshake with the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * peer. The error could be either in ldc operations or other
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * parts of the code such as timeouts or mdeg events etc.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * VGEN_FLAG_UNINIT:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * The channel is being torn down; no need to bring up the channel
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * after resetting.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_process_reset(vgen_ldc_t *ldcp, int flags)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (portp == vgenp->vsw_portp) { /* vswitch port ? */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Report that the channel is being reset; it ensures that any HybridIO
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * configuration is torn down before we reset the channel if it is not
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * already reset (flags == VGEN_FLAG_NEED_LDCRESET).
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vio_net_report_err_t rep_err = portp->vcb.vio_net_report_err;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rep_err(portp->vhp, VIO_NET_RES_DOWN);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Clear hstate and hphase */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (flags == VGEN_FLAG_NEED_LDCRESET || flags == VGEN_FLAG_UNINIT) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "Reset Done, ldc_status(%d)\n", istatus);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* disable further callbacks */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_set_cb_mode failed\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* flags == VGEN_FLAG_EVT_RESET */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc status(%d)\n", ldcp->ldc_status);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * As the connection is now reset, mark the channel
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * link_state as 'down' and notify the stack if needed.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->link_state != LINK_STATE_DOWN) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (is_vsw_port == B_TRUE) { /* vswitch port ? */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * As the channel link is down, mark physical link also
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * as down. After the channel comes back up and
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * handshake completes, we will get an update on the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physlink state from vswitch (if this device has been
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * configured to get phys link updates).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->phys_link_state = LINK_STATE_DOWN;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Update link state to the stack */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_link_update(vgenp, ldcp->link_state);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * As the channel is being reset, redirect traffic to the peer through
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vswitch, until the channel becomes ready to be used again.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (is_vsw_port == B_FALSE && vgenp->vsw_portp != NULL) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) atomic_swap_32(&portp->use_vsw_port, B_TRUE);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Cancel handshake watchdog timeout */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Cancel transmit watchdog timeout */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Stop the msg worker thread */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_TX_DRING && curthread != ldcp->msg_thread) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Grab all locks while we tear down tx/rx resources */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Destroy the local dring which is exported to the peer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Unmap the remote dring which is imported from the peer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Bring up the channel and restart handshake
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * only if the channel is not being torn down.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Setup handshake parameters to restart a new handshake */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Bring the channel up */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_status err\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* If the channel is UP, start handshake */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Channel is up; use this port from now on.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) atomic_swap_32(&portp->use_vsw_port,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Initialize local session id */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* clear peer session id */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Initiate Handshake process with peer ldc endpoint by
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * sending version info vio message. If that fails we
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * go back to the top of this function to process the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * error again. Note that we can be in this loop for
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * 'vgen_ldc_max_resets' times, after which the channel
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * is not brought up.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We still hold 'reset_in_progress'; so we can
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * just loop back to the top to restart error
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna } else { /* flags == VGEN_FLAG_UNINIT */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Close the channel - retry on EAGAIN */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna while ((rv = ldc_close(ldcp->ldc_handle)) == EAGAIN) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna "!vnet%d: Error(%d) closing the channel(0x%lx)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Done processing channel reset; clear the atomic flag */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Initiate handshake with the peer by sending various messages
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * based on the handshake-phase that the channel is currently in.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * start timer, for entire handshake process, turn this timer
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * off if all phases of handshake complete successfully and
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * hphase goes to VH_DONE(below) or channel is reset due to
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * errors or vgen_ldc_uninit() is invoked(vgen_stop).
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna drv_usectohz(vgen_hwd_interval * MICROSEC));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Phase 1 involves negotiating the version */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_send_version_negotiate(ldcp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DBG1(vgenp, ldcp, "Handshake Done\n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * The channel is up and handshake is done successfully. Now we
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * can mark the channel link_state as 'up'. We also notify the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * stack if the channel is connected to vswitch.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ldcp->portp == vgenp->vsw_portp) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If this channel(port) is connected to vsw,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * need to sync multicast table with vsw.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgenp->pls_negotiated == B_FALSE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * We haven't negotiated with vswitch to get
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physical link state updates. We can update
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * update the stack at this point as the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * channel to vswitch is up and the handshake
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * is done successfully.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * If we have negotiated to get physical link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state updates, then we won't notify the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the stack here; we do that as soon as
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * vswitch sends us the initial phys link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * (see vgen_handle_physlink_info()).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_link_update(vgenp, ldcp->link_state);
3af08d828975d7e2581b6829e0eecff14d87a483lm * Check if mac layer should be notified to restart
3af08d828975d7e2581b6829e0eecff14d87a483lm * transmissions. This can happen if the channel got
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * reset and while tx_blocked is set.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* start transmit watchdog timer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->wd_tid = timeout(vgen_tx_watchdog, (caddr_t)ldcp,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna drv_usectohz(vgen_txwd_interval * 1000));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if the current handshake phase has completed successfully and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * return the status.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Phase1 is done, if version negotiation
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * completed successfully.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Phase 2 is done, if attr info
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * has been exchanged successfully.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna status = ((ldcp->hstate & ATTR_INFO_EXCHANGED) ==
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Phase 3 is done, if dring registration
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * has been exchanged successfully.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna status = ((ldcp->hstate & DRING_INFO_EXCHANGED) ==
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Phase 4 is done, if rdx msg has been exchanged */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status == 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Link State Update Notes:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * The link state of the channel connected to vswitch is reported as the link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state of the vnet device, by default. If the channel is down or reset, then
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the link state is marked 'down'. If the channel is 'up' *and* handshake
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * between the vnet and vswitch is successful, then the link state is marked
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 'up'. If physical network link state is desired, then the vnet device must
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * be configured to get physical link updates and the 'linkprop' property
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * in the virtual-device MD node indicates this. As part of attribute exchange
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the vnet device negotiates with the vswitch to obtain physical link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * updates. If it successfully negotiates, vswitch sends an initial physlink
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * msg once the handshake is done and further whenever the physical link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * changes. Currently we don't have mac layer interfaces to report two distinct
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * link states - virtual and physical. Thus, if the vnet has been configured to
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * get physical link updates, then the link status will be reported as 'up'
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * only when both the virtual and physical links are up.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_link_update(vgen_t *vgenp, link_state_t link_state)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnet_link_update(vgenp->vnetp, link_state);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a version info msg from the peer or an ACK/NACK from the peer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to a version info msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_version_negotiate(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Cache sid of peer if this is the first time */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If we are not already in VH_PHASE1, reset to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * pre-handshake state, and initiate handshake
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to the peer too.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save peer's requested values */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unsupported dev_class, send NACK */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* nack with next lower version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* major version match - ACK version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * lower minor version to the one this endpt
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * supports, if necessary
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* no version match - send NACK */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* VER_ACK_SENT and VER_ACK_RCVD */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* local and peer versions match? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* move to the next phase */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This should not happen. */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid Phase(%u)\n", ldcp->hphase);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* SUCCESS - we have agreed on a version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* VER_ACK_SENT and VER_ACK_RCVD */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* local and peer versions match? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* move to the next phase */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This should not happen. */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_NACK_RCVD next ver(%d,%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check if version in NACK is zero */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major == 0 && vermsg->ver_minor == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Version Negotiation has failed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* select next lower version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* major version match */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * no version match.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Version Negotiation has failed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Version Negotiation Failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *rp = &ldcp->peer_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* save peer's values */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process address type, ack frequency and transfer mode attributes.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if ((msg->addr_type != ADDR_TYPE_MAC) ||
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process dring mode attribute.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Versions >= 1.6:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Though we are operating in v1.6 mode, it is possible that
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * RxDringData mode has been disabled either on this guest or
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * on the peer guest. If so, we revert to pre v1.6 behavior of
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * TxDring mode. But this must be agreed upon in both
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * directions of attr exchange. We first determine the mode
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * that can be negotiated.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((msg->options & VIO_RX_DRING_DATA) != 0 &&
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We are capable of handling RxDringData AND the peer
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * is also capable of it; we enable RxDringData mode on
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * this channel.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna } else if ((msg->options & VIO_TX_DRING) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If the peer is capable of TxDring mode, we
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * negotiate TxDring mode on this channel.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We support only VIO_TX_DRING and VIO_RX_DRING_DATA
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * modes. We don't support VIO_RX_DRING mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If we have received an ack for the attr info that we sent,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * then check if the dring mode matches what the peer had ack'd
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * (saved in local hparams). If they don't match, we fail the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* send NACK */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Save the negotiated dring mode in our attr
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * parameters, so it gets sent in the attr info from us
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* save the negotiated dring mode in the msg to be replied */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process MTU attribute.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Versions >= 1.4:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Validate mtu of the peer is at least ETHERMAX. Then, the mtu
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * is negotiated down to the minimum of our mtu and peer's mtu.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna mtu = MIN(msg->mtu, vgenp->max_frame_size);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If we have received an ack for the attr info
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * that we sent, then check if the mtu computed
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * above matches the mtu that the peer had ack'd
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * (saved in local hparams). If they don't
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * match, we fail the handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* send NACK */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Save the mtu computed above in our
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * attr parameters, so it gets sent in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * the attr info from us to the peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* save the MIN mtu in the msg to be replied */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* versions < 1.4, mtu must match */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_attr_ack(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process dring mode attribute.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Versions >= 1.6:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * The ack msg sent by the peer contains the negotiated dring
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * mode between our capability (that we had sent in our attr
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * info) and the peer's capability.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If we have sent an ack for the attr info msg from
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * the peer, check if the dring mode that was
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * negotiated then (saved in local hparams) matches the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * mode that the peer has ack'd. If they don't match,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * we fail the handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((msg->options & lp->dring_mode) == 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Peer ack'd with a mode that we don't
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * support; we fail the handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((msg->options & (VIO_TX_DRING|VIO_RX_DRING_DATA))
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna == (VIO_TX_DRING|VIO_RX_DRING_DATA)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Peer must ack with only one negotiated mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Otherwise fail handshake.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Save the negotiated mode, so we can validate it when
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * we receive attr info from the peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process Physical Link Update attribute.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Versions >= 1.5:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If the vnet device has been configured to get
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * physical link state updates, check the corresponding
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * bits in the ack msg, if the peer is vswitch.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (((lp->physlink_update & PHYSLINK_UPDATE_STATE_MASK) ==
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ((msg->physlink_update & PHYSLINK_UPDATE_STATE_MASK) ==
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Process MTU attribute.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Versions >= 1.4:
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * The ack msg sent by the peer contains the minimum of
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * our mtu (that we had sent in our attr info) and the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If we have sent an ack for the attr info msg from
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * the peer, check if the mtu that was computed then
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * (saved in local hparams) matches the mtu that the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * peer has ack'd. If they don't match, we fail the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If the mtu ack'd by the peer is > our mtu
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * fail handshake. Otherwise, save the mtu, so
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * we can validate it when we receive attr info
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * from our peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Handle an attribute info msg from the peer or an ACK/NACK from the peer
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * to an attr info msg that we sent.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_attr_msg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vnet_attr_msg_t *msg = (vnet_attr_msg_t *)tagp;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "Rcvd ATTR_INFO subtype(%d),"
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna " Invalid Phase(%u)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handle_attr_info(ldcp, msg);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* send reply msg back to peer */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg),
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (tagp->vio_subtype == VIO_SUBTYPE_NACK) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DBG2(vgenp, ldcp, "ATTR_ACK_SENT \n");
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_dring_reg_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (lp->dring_mode != ((vio_dring_reg_msg_t *)tagp)->options)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * The earlier version of Solaris vnet driver doesn't set the
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * option (VIO_TX_DRING in its case) correctly in its dring reg
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * message. We workaround that here by doing the check only
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * for versions >= v1.6.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna "Rcvd dring reg option (%d), negotiated mode (%d)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ((vio_dring_reg_msg_t *)tagp)->options, lp->dring_mode);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Map dring exported by the peer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_map_dring(ldcp, (void *)tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Map data buffers exported by the peer if we are in RxDringData mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_map_data(ldcp, (void *)tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ldcp->peer_hparams.dring_ready == B_FALSE) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->peer_hparams.dring_ready = B_TRUE;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_dring_reg_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* save dring_ident acked by peer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna lp->dring_ident = ((vio_dring_reg_msg_t *)tagp)->dring_ident;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* local dring is now ready */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a descriptor ring register msg from the peer or an ACK/NACK from
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the peer to a dring register msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* dring_info can be rcvd in any of the phases after Phase1 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Rcvd DRING_INFO Subtype (%d), Invalid Phase(%u)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handle_dring_reg_info(ldcp, tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna VNET_DRING_REG_EXT_MSG_SIZE(ldcp->tx_data_ncookies);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msgsize = sizeof (vio_dring_reg_msg_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp, msgsize,
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (tagp->vio_subtype == VIO_SUBTYPE_NACK) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handle_dring_reg_ack(ldcp, tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "DRING_NACK_RCVD");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a rdx info msg from the peer or an ACK/NACK
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * from the peer to a rdx info msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Rcvd RDX_INFO Subtype (%d), Invalid Phase(%u)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vio_rdx_msg_t),
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Handle ACK/NACK from vsw to a set multicast msg that we sent */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vnet_mcast_msg_t *msgp = (vnet_mcast_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* vnet shouldn't recv set mcast msg, only vsw handles it */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success adding/removing multicast addr */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* multicast remove request failed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* multicast add request failed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* delete address from the table */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Physical link information message from the peer. Only vswitch should send
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * us this message; if the vnet device has been configured to get physical link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state updates. Note that we must have already negotiated this with the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * vswitch during attribute exchange phase of handshake.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_handle_physlink_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnet_physlink_msg_t *msgp = (vnet_physlink_msg_t *)tagp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->portp != vgenp->vsw_portp) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * drop the message and don't process; as we should
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * receive physlink_info message from only vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (vgenp->pls_negotiated == B_FALSE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * drop the message and don't process; as we should receive
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physlink_info message only if physlink update is enabled for
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the device and negotiated with vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if ((msgp->physlink_info & VNET_PHYSLINK_STATE_MASK) ==
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (vgenp->phys_link_state != link_state) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* Now update the stack */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* send reply msg back to peer */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna sizeof (vnet_physlink_msg_t), B_FALSE);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* vnet shouldn't recv physlink acks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "rcvd PHYSLINK_ACK \n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* vnet shouldn't recv physlink nacks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "rcvd PHYSLINK_NACK \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handler for control messages received from the peer ldc end-point */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_handle_attr_msg(ldcp, tagp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * If we are in the process of resetting the vswitch channel,
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * drop the dds message. A new handshake will be initiated
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * when the channel comes back up after the reset and dds
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * negotiation can then continue.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_handle_physlink_info(ldcp, tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* handler for error messages received from the peer ldc end-point */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function handles raw pkt data messages received over the channel.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Currently, only priority-eth-type frames are received through this mechanism.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * In this case, the frame(data) is present within the message itself which
f0ca1d9a12d54d304791bc74525e2010ca924726sb * is copied into an mblk before sending it up the stack.
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vmp = vio_multipool_allocb(&ldcp->vmp, size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb "unable to process priority frame\n");
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* copy the frame from the payload of raw data msg into the mblk */
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* update stats */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If polling is currently enabled, add the packet to the priority
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * packets list and return. It will be picked up by the polling thread.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->rx_pri_head = ldcp->rx_pri_tail = mp;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * dummy pkt data handler function for vnet protocol version 1.0
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* handler for data messages received from the peer ldc end-point */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t msglen)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We check the data msg seqnum. This is needed only in TxDring mode.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna tagp->vio_subtype == VIO_SUBTYPE_INFO) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_check_datamsg_seq(ldcp, tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = ldcp->rx_dringdata((void *)ldcp, (void *)tagp);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->rx_pktdata((void *)ldcp, (void *)tagp, msglen);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_ldc_reset(vgen_ldc_t *ldcp, vgen_caller_t caller)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Set the flag to indicate reset is in progress */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (atomic_cas_uint(&ldcp->reset_in_progress, 0, 1) != 0) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* another thread is already in the process of resetting */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_process_reset(ldcp, VGEN_FLAG_NEED_LDCRESET);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (caller == VGEN_LDC_CB || caller == VGEN_MSG_THR) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * If the channel has been reset max # of times, without successfully
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * completing handshake, stop and do not bring the channel up.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ldcp->ldc_reset_count == vgen_ldc_max_resets) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna cmn_err(CE_WARN, "!vnet%d: exceeded number of permitted"
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna " handshake attempts (%d) on channel %ld",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgenp->instance, vgen_ldc_max_resets, ldcp->ldc_id);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((rv != 0) && (rv == EWOULDBLOCK)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We send a stopped message to peer (sender) as we are turning
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * off polled mode. This effectively restarts data interrupts
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * by allowing the peer to send further dring data msgs to us.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msg.dring_ident = ldcp->peer_hparams.dring_ident;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_send_dringack_shm(ldcp, (vio_msg_tag_t *)&msg,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna VNET_START_IDX_UNSPEC, end_ix, VIO_DP_STOPPED);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_rx_poll(void *arg, int bytes_to_pickup)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (lp->dring_mode == VIO_RX_DRING_DATA) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna mp = vgen_poll_rcv_shm(ldcp, bytes_to_pickup);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna mp = vgen_poll_rcv(ldcp, bytes_to_pickup);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* transmit watchdog timeout handler */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna tx_blocked_lbolt = ldcp->tx_blocked_lbolt;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ((ddi_get_lbolt() - tx_blocked_lbolt) >
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna drv_usectohz(vgen_txwd_timeout * 1000))) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Something is wrong; the peer is not picking up the packets
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * in the transmit dring. We now go ahead and reset the channel
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * to break out of this condition.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "transmit timeout lbolt(%lx), "
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna "tx_blocked_lbolt(%lx)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (vgen_inject_error(ldcp, VGEN_ERR_TXTIMEOUT)) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* tx timeout triggered for debugging */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna vgen_inject_err_flag &= ~(VGEN_ERR_TXTIMEOUT);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Clear tid before invoking vgen_ldc_reset(). Otherwise,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * it will result in a deadlock when vgen_process_reset() tries
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * to untimeout() on seeing a non-zero tid, but it is being
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * invoked by the timer itself in this case.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Cancelled by vgen_process_reset() */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Now reset the channel.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna rv = vgen_ldc_reset(ldcp, VGEN_OTHER);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * We have successfully reset the channel. If we are
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * in tx flow controlled state, clear it now and enable
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * transmit in the upper layer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Channel has been reset by us or some other thread is already
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * in the process of resetting. In either case, we return
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * without restarting the timer. When handshake completes and
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * the channel is ready for data transmit/receive we start a
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * new watchdog timer.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Restart the timer */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Cancelled by vgen_process_reset() */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ldcp->wd_tid = timeout(vgen_tx_watchdog, (caddr_t)ldcp,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna drv_usectohz(vgen_txwd_interval * 1000));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Handshake watchdog timeout handler */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "handshake timeout phase(%x) state(%x)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* Cancelled by vgen_process_reset() */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Something is wrong; handshake with the peer seems to be hung. We now
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * go ahead and reset the channel to break out of this condition.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna (void) vgen_ldc_reset(ldcp, VGEN_OTHER);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna/* Check if the session id in the received message is valid */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (tagp->vio_sid != ldcp->peer_sid) {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna DWARN(vgenp, ldcp, "sid mismatch: expected(%x), rcvd(%x)\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * Initialize the common part of dring registration
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * message; used in both TxDring and RxDringData modes.
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_init_dring_reg_msg(vgen_ldc_t *ldcp, vio_dring_reg_msg_t *msg,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna tagp->vio_subtype_env = VIO_DRING_REG;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* get dring info msg payload from ldcp->local */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna bcopy(&(ldcp->local_hparams.dring_cookie), &(msg->cookie[0]),
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msg->ncookies = ldcp->local_hparams.dring_ncookies;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msg->num_descriptors = ldcp->local_hparams.num_desc;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna msg->descriptor_size = ldcp->local_hparams.desc_size;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * dring_ident is set to 0. After mapping the dring, peer sets this
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * value and sends it in the ack, which is saved in
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna * vgen_handle_dring_reg().
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG dblk_sz = RXDRING_DBLK_SZ(vgenp->max_frame_size);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Print debug messages - set to 0xf to enable all msgs
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatnavgen_debug_printf(const char *fname, vgen_t *vgenp,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_ioctl(void *arg, queue_t *q, mblk_t *mp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna IOC_INVAL = -1, /* bad, NAK with EINVAL */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_force_link_state(portp, iocp->ioc_cmd);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna (rv == 0) ? (status = IOC_ACK) : (status = IOC_INVAL);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* Error, reply with a NAK and EINVAL error */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* OK, reply with an ACK */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_force_link_state(vgen_port_t *portp, int cmd)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_status err\n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* if channel is already UP - restart handshake */