vsw_phys.c revision da14cebe459d3275048785f25bd869cb09b5307f
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * CDDL HEADER START
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * The contents of this file are subject to the terms of the
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Common Development and Distribution License (the "License").
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * You may not use this file except in compliance with the License.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * See the License for the specific language governing permissions
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * and limitations under the License.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * When distributing Covered Code, include this CDDL HEADER in each
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If applicable, add the following below this CDDL HEADER, with the
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * fields enclosed by brackets "[]" replaced with your own identifying
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * information: Portions Copyright [yyyy] [name of copyright owner]
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * CDDL HEADER END
ee03c681cedb48165922333190cdd8b230ffa073wentaoy * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Use is subject to license terms.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* MAC Ring table functions. */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_port_rx_cb(void *, mac_resource_handle_t, mblk_t *,
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_if_rx_cb(void *, mac_resource_handle_t, mblk_t *, boolean_t);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* MAC layer routines */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int vsw_set_port_hw_addr(vsw_port_t *port);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_unset_hw_addr(vsw_t *, vsw_port_t *, int);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int vsw_maccl_open(vsw_t *vswp, vsw_port_t *port, int type);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_maccl_close(vsw_t *vswp, vsw_port_t *port, int type);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_mac_multicast_add_all(vsw_t *vswp, vsw_port_t *portp, int type);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_mac_multicast_remove_all(vsw_t *vswp,
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_mac_add_vlans(vsw_t *vswp, mac_client_handle_t mch,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint8_t *macaddr, uint16_t flags, vsw_vlanid_t *vids, int nvids);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void vsw_mac_remove_vlans(mac_client_handle_t mch, vsw_vlanid_t *vids,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic void vsw_mac_set_mtu(vsw_t *vswp, uint32_t mtu);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* Support functions */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint vsw_mac_multicast_add(vsw_t *vswp, vsw_port_t *port, mcst_addr_t *mcst_p,
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_mac_multicast_remove(vsw_t *vswp, vsw_port_t *port,
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint vsw_mac_client_init(vsw_t *vswp, vsw_port_t *port, int type);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_mac_client_cleanup(vsw_t *vswp, vsw_port_t *port, int type);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmblk_t *vsw_tx_msg(vsw_t *, mblk_t *, int, vsw_port_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_publish_macaddr(vsw_t *vswp, vsw_port_t *portp);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_port_mac_reconfig(vsw_port_t *portp, boolean_t update_vlans,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint16_t new_pvid, vsw_vlanid_t *new_vids, int new_nvids);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_mac_port_reconfig_vlans(vsw_port_t *portp, uint16_t new_pvid,
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid vsw_if_mac_reconfig(vsw_t *vswp, boolean_t update_vlans,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint16_t new_pvid, vsw_vlanid_t *new_vids, int new_nvids);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Functions imported from other files.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengextern int vsw_portsend(vsw_port_t *port, mblk_t *mp);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengextern void vsw_hio_port_reset(vsw_port_t *portp, boolean_t immediate);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengextern uint32_t vsw_vlan_frame_untag(void *arg, int type, mblk_t **np,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic char mac_mtu_propname[] = "mtu";
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Tunables used in this file.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (type == VSW_LOCALDEV) ? rw_enter(&vswp->maccl_rwlock, RW_WRITER) :\
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (type == VSW_LOCALDEV) ? rw_enter(&vswp->maccl_rwlock, RW_READER) :\
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (type == VSW_LOCALDEV) ? rw_exit(&vswp->maccl_rwlock) : \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Locking strategy in this file is explained as follows:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * - A global lock(vswp->mac_lock) is used to protect the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC calls that deal with entire device. That is, the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * operations that deal with mac_handle which include
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_open()/close() and mac_client_open().
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * - A per port/interface RW lock(maccl_rwlock) is used protect
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the operations that deal with the MAC client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * When both mac_lock and maccl_rwlock need to be held, the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_lock need be acquired first and then maccl_rwlock. That is,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_lock---->maccl_rwlock
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The 'mca_lock' that protects the mcast list is also acquired
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * within the context of maccl_rwlock. The hierarchy for this
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * one is as below:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * maccl_rwlock---->mca_lock
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Program unicast and multicast addresses of vsw interface and the ports
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * into the network device.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Open a mac client and program addresses */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = vsw_mac_client_init(vswp, NULL, VSW_LOCALDEV);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "!vsw%d: failed to program interface "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Notify the MAC layer of the changed address.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* program unicast address of ports in the network device */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (port = plist->head; port != NULL; port = port->p_next) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Open a mac client and program addresses */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = vsw_mac_client_init(vswp, port, VSW_VNETPORT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "!vsw%d: failed to program port(%d) "
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* announce macaddr of vnets to the physical switch */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb for (port = plist->head; port != NULL; port = port->p_next) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove unicast, multicast addresses and close mac clients
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * for the vsw interface and all ports.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Cleanup and close the mac client for the interface */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_client_cleanup(vswp, NULL, VSW_LOCALDEV);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Cleanup and close the mac clients for all ports */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Open the underlying network device for access in layer2 mode.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 on success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EAGAIN if mac_open() fails due to the device being not available yet.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * EIO on any other failures.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* already open */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mac_open_retries++ >= vsw_mac_open_retries) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* exceeded max retries */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((rv = mac_open_by_linkname(vswp->physname, &vswp->mh)) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If mac_open() failed and the error indicates that either
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the dlmgmtd door or the device is not available yet, we
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * return EAGAIN to indicate that mac_open() needs to be
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * retried. For example, this may happen during boot up, if
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the required link aggregation groups(devices) have not
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * been created yet.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cmn_err(CE_WARN, "vsw%d: mac_open %s failed rv:%x",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Close the underlying physical device.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Add multicast addr.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_multicast_add(vsw_t *vswp, vsw_port_t *port, mcst_addr_t *mcst_p,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mch = (type == VSW_LOCALDEV) ? vswp->mch : port->p_mch;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ret = mac_multicast_add(mch, mcst_p->mca.ether_addr_octet);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "program multicast address(%s) err=%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove multicast addr.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_multicast_remove(vsw_t *vswp, vsw_port_t *port, mcst_addr_t *mcst_p,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mch = (type == VSW_LOCALDEV) ? vswp->mch : port->p_mch;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_multicast_remove(mch, mcst_p->mca.ether_addr_octet);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Add all multicast addresses of the port.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_multicast_add_all(vsw_t *vswp, vsw_port_t *portp, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (mcap = mcap; mcap != NULL; mcap = mcap->nextp) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = mac_multicast_add(mch, (uchar_t *)&mcap->mca);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove all multicast addresses of the port.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_multicast_remove_all(vsw_t *vswp, vsw_port_t *portp, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) mac_multicast_remove(mch, (uchar_t *)&mcap->mca);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Open a mac client and program uncast and multicast addresses
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * for a port or the interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 0 on success
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * non-zero for failure.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_client_init(vsw_t *vswp, vsw_port_t *port, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Release mac_lock now */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Open a MAC client for a port or an interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The flags and their purpose as below:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC_OPEN_FLAGS_NO_HWRINGS -- This flag is used by default
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * for all ports/interface so that they are associated with
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * default group & resources. It will not be used for the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ports that have HybridIO is enabled so that the h/w resources
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * assigned to it.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC_OPEN_FLAGS_SHARES_DESIRED -- This flag is used to indicate
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * that a port desires a Share. This will be the case with the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the ports that have hybrid mode enabled. This will only cause
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC layer to allocate a share and corresponding resources
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ahead of time.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC_OPEN_FLAGS_TAG_DISABLE -- This flag is used for VLAN
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * support. It will cause MAC to not add any tags, but expect
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * vsw to tag the packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC_OPEN_FLAGS_STRIP_DISABLE -- This flag is used for VLAN
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * support. It will case the MAC layer to not strip the tags.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Vsw may have to strip the tag for pvid case.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_maccl_open(vsw_t *vswp, vsw_port_t *port, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * In case net-dev is changed (either set to nothing or
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * using aggregation device), return success here as the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * timeout mechanism will handle it.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mchp = (type == VSW_LOCALDEV) ? &vswp->mch : &port->p_mch;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* already open */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(mac_cl_name, MAXNAMELEN, "%s%d%s%d", dev_name,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(mac_cl_name, MAXNAMELEN, "%s%s%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = mac_client_open(vswp->mh, mchp, mac_cl_name, flags);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cmn_err(CE_NOTE, "!vsw%d:%s mac_client_open() failed\n",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Clean up by removing uncast, multicast addresses and
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * closing the MAC client for a port or the interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_client_cleanup(vsw_t *vswp, vsw_port_t *port, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Close a MAC client for a port or an interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_maccl_close(vsw_t *vswp, vsw_port_t *port, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mchp = (type == VSW_LOCALDEV) ? &vswp->mch : &port->p_mch;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Cleanup MAC client related stuff for all ports.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (port = plist->head; port != NULL; port = port->p_next) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_client_cleanup(vswp, port, VSW_VNETPORT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Depending on the mode specified, the capabilites and capacity
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * of the underlying device setup the physical device.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If in layer 3 mode, then do nothing.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If in layer 2 mode, open a mac client and program the mac-address
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and vlan-ids. The MAC layer will take care of programming
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the address into h/w or set the h/w into promiscuous mode.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns 0 success, 1 on failure.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_set_hw(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If in layer 3 mode do nothing.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If in layer 2 switched mode remove the address from the physical
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If in layer 2 promiscuous mode disable promisc mode.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns 0 on success.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_unset_hw(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Program the macaddress and vlans of a port.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns 0 on sucess, 1 on failure.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If the port has a specific 'pvid', then
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * register with that vlan-id, otherwise register
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * with VLAN_ID_NONE.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng macaddr = (uint8_t *)port->p_macaddr.ether_addr_octet;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = mac_unicast_add(port->p_mch, macaddr, mac_flags,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "macaddr,vid(%s, %d) err=%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng D2(vswp, "%s:programmed macaddr(%s) vid(%d) into device %s",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Add vlans to the MAC layer */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_rx_set(port->p_mch, vsw_port_rx_cb, (void *)port);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Program the macaddress and vlans of a port.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns 0 on sucess, 1 on failure.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng macaddr = (uint8_t *)vswp->if_addr.ether_addr_octet;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* check if it is the primary macaddr of the card. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ether_cmp((void *)primary_addr, (void*)macaddr) == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If the interface has a specific 'pvid', then
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * register with that vlan-id, otherwise register
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * with VLAN_ID_NONE.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rv = mac_unicast_add(vswp->mch, macaddr, mac_flags,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "macaddr,vid(%s, %d) err=%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng D2(vswp, "%s:programmed macaddr(%s) vid(%d) into device %s",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_add_vlans(vswp, vswp->mch, macaddr, mac_flags,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_rx_set(vswp->mch, vsw_if_rx_cb, (void *)vswp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove a unicast mac address which has previously been programmed
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns 0 on sucess, 1 on failure.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_unset_hw_addr(vsw_t *vswp, vsw_port_t *port, int type)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* First clear the callback */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Remove vlans */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((type == VSW_LOCALDEV) && (vswp->addr_set == B_TRUE)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else if ((type == VSW_VNETPORT) && (port->addr_set == B_TRUE)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) mac_unicast_remove(port->p_mch, port->p_muh);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * receive callback routine for vsw interface. Invoked by MAC layer when there
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * are pkts being passed up from physical device for this vsw interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* ARGSUSED */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_if_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng count = vsw_vlan_frame_untag(vswp, VSW_LOCALDEV, &mp, &mpt);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * receive callback routine for port. Invoked by MAC layer when there
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * are pkts being passed up from physical device for this port.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* ARGSUSED */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_port_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Send the packets to the peer directly.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Send a message out over the physical device
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * via the MAC layer.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Returns any mblks that it was unable to transmit.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_tx_msg(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *port)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mch = (caller == VSW_LOCALDEV) ? vswp->mch : port->p_mch;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng muh = (caller == VSW_LOCALDEV) ? vswp->muh : port->p_muh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* packets are sent or dropped */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) mac_tx(mch, mp, 0, MAC_DROP_ON_NO_DESC, NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * vsw_port_mac_reconfig -- Cleanup and close the MAC client
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and reopen and re-configure the MAC client with new flags etc.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * This function is useful for two different purposes:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 1) To update the MAC client with new vlan-ids. This is done
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * by freeing the existing vlan-ids and reopen with the new
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 2) If the Hybrid mode status of a port changes, then the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC client need to be closed and re-opened, otherwise,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Share related resources may not be freed(hybird mode disabled)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * or assigned(hybrid mode enabled). To accomplish this,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * this function simply closes and reopens the MAC client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The reopen will result in using the flags based on the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * new hybrid mode of the port.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_port_mac_reconfig(vsw_port_t *portp, boolean_t update_vlans,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint16_t new_pvid, vsw_vlanid_t *new_vids, int new_nvids)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove the multi-cast addresses, unicast address
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and close the mac-client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_multicast_remove_all(vswp, portp, VSW_VNETPORT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Now re-open the mac-client and
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * configure unicast addr and multicast addrs.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "set unicast address\n", vswp->instance, portp->p_instance);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_multicast_add_all(vswp, portp, VSW_VNETPORT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * vsw_if_mac_reconfig -- Reconfigure the vsw interfaace's mac-client
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * by closing and re-opening it. This function is used handle the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * following two cases:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 1) Handle the MAC address change for the interface.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * 2) Handle vlan update.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_if_mac_reconfig(vsw_t *vswp, boolean_t update_vlans,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint16_t new_pvid, vsw_vlanid_t *new_vids, int new_nvids)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Remove the multi-cast addresses, unicast address
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and close the mac-client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_multicast_remove_all(vswp, NULL, VSW_LOCALDEV);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Now re-open the mac-client and
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * configure unicast addr and multicast addrs.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cmn_err(CE_NOTE, "!vsw%d:failed to set unicast address\n",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_mac_multicast_add_all(vswp, NULL, VSW_LOCALDEV);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * vsw_mac_port_reconfig_vlans -- Reconfigure a port to handle
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * vlan configuration update. As the removal of the last unicast-address,vid
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * from the MAC client results in releasing all resources, it expects
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * no Shares to be associated with such MAC client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * To handle vlan configuration update for a port that already has
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * a Share bound, then we need to free that share prior to reconfiguration.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Initiate the hybrdIO setup again after the completion of reconfiguration.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_port_reconfig_vlans(vsw_port_t *portp, uint16_t new_pvid,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * As the reconfiguration involves the close of
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac client, cleanup HybridIO and later restart
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * HybridIO setup again.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng vsw_port_mac_reconfig(portp, B_TRUE, new_pvid, new_vids, new_nvids);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* reset to setup the HybridIO again. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* Add vlans to MAC client */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_add_vlans(vsw_t *vswp, mac_client_handle_t mch, uint8_t *macaddr,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Add vlans to the MAC layer */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < nvids; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rv != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "macaddr,vid(%s, %d) err=%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* Remove vlans from the MAC client */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_mac_remove_vlans(mac_client_handle_t mch, vsw_vlanid_t *vids, int nvids)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < nvids; i++) {
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb#define ARH_FIXED_LEN 8 /* Length of fixed part of ARP header(see arp.h) */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * Send a gratuitous RARP packet to notify the physical switch to update its
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * Layer2 forwarding table for the given mac address. This is done to allow the
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * switch to quickly learn the macaddr-port association when a guest is live
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * migrated or when vsw's physical device is changed dynamically. Any protocol
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * packet would serve this purpose, but we choose RARP, as it allows us to
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * accomplish this within L2 (ie, no need to specify IP addr etc in the packet)
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * The macaddr of vnet is retained across migration. Hence, we don't need to
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * update the arp cache of other hosts within the broadcast domain. Note that
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * it is harmless to send these RARP packets during normal port attach of a
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * client vnet. This can can be turned off if needed, by setting
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb * vsw_publish_macaddr_count to zero in /etc/system.
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvsw_publish_macaddr(vsw_t *vswp, vsw_port_t *portp)
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* Initialize eth header */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb bcopy(ðerbroadcastaddr, &ehp->ether_dhost, ETHERADDRL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bcopy(&portp->p_macaddr, &ehp->ether_shost, ETHERADDRL);
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* Initialize arp packet */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb arh = (struct arphdr *)(mp->b_rptr + sizeof (struct ether_header));
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb arh->ar_hrd = htons(ARPHRD_ETHER); /* Hardware type: ethernet */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb arh->ar_pro = htons(ETHERTYPE_IP); /* Protocol type: IP */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb arh->ar_hln = ETHERADDRL; /* Length of hardware address: 6 */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb arh->ar_op = htons(REVARP_REQUEST); /* Opcode: REVARP Request */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* Sender's hardware address and protocol address */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* Target hardware address and protocol address */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb mp->b_wptr += ETHERMIN; /* total size is 42; round up to ETHERMIN */
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb for (count = 0; count < vsw_publish_macaddr_count; count++) {
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb /* transmit the packet */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnavsw_mac_set_mtu(vsw_t *vswp, uint32_t mtu)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna "!vsw%d: Unable to set the mtu:%d, in the "
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna "physical device:%s\n",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* save the original mtu of physdev to reset it back later if needed */