f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy/*
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * CDDL HEADER START
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy *
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * The contents of this file are subject to the terms of the
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * Common Development and Distribution License (the "License").
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * You may not use this file except in compliance with the License.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy *
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * or http://www.opensolaris.org/os/licensing.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * See the License for the specific language governing permissions
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * and limitations under the License.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy *
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * When distributing Covered Code, include this CDDL HEADER in each
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * If applicable, add the following below this CDDL HEADER, with the
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * fields enclosed by brackets "[]" replaced with your own identifying
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * information: Portions Copyright [yyyy] [name of copyright owner]
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy *
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * CDDL HEADER END
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy */
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy * Use is subject to license terms.
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy */
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy#pragma ident "%Z%%M% %I% %E% SMI"
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy#include <sys/types.h>
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy#include <sys/ethernet.h>
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy#include <sys/vnet_common.h>
c1c61f44e88f4c8c155272ee56d868043146096asb#include <sys/vlan.h>
c1c61f44e88f4c8c155272ee56d868043146096asb#include <sys/stream.h>
c1c61f44e88f4c8c155272ee56d868043146096asb#include <sys/strsun.h>
c1c61f44e88f4c8c155272ee56d868043146096asb#include <sys/byteorder.h>
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy/* convert mac address from string to uint64_t */
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoyuint64_t
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoyvnet_macaddr_strtoul(const uint8_t *macaddr)
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy{
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy uint64_t val = 0;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy int i;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy for (i = 0; i < ETHERADDRL; i++) {
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy val <<= 8;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy val |= macaddr[i];
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy }
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy return (val);
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy}
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy/* convert mac address from uint64_t to string */
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoyvoid
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoyvnet_macaddr_ultostr(uint64_t val, uint8_t *macaddr)
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy{
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy int i;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy uint64_t value;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy value = val;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy for (i = ETHERADDRL - 1; i >= 0; i--) {
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy macaddr[i] = value & 0xFF;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy value >>= 8;
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy }
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asbmblk_t *
c1c61f44e88f4c8c155272ee56d868043146096asbvnet_vlan_insert_tag(mblk_t *mp, uint16_t vid)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb struct ether_vlan_header *evhp;
c1c61f44e88f4c8c155272ee56d868043146096asb mblk_t *nmp;
c1c61f44e88f4c8c155272ee56d868043146096asb size_t n;
c1c61f44e88f4c8c155272ee56d868043146096asb uint_t pri = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VLAN_TAGSZ) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* mblk has space to insert tag */
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * move src and dst mac addrs in the header back by VLAN_TAGSZ.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb ovbcopy(mp->b_rptr, mp->b_rptr - VLAN_TAGSZ, 2 * ETHERADDRL);
c1c61f44e88f4c8c155272ee56d868043146096asb mp->b_rptr -= VLAN_TAGSZ;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* now insert tpid and tci */
c1c61f44e88f4c8c155272ee56d868043146096asb evhp = (struct ether_vlan_header *)mp->b_rptr;
c1c61f44e88f4c8c155272ee56d868043146096asb evhp->ether_tpid = htons(ETHERTYPE_VLAN);
c1c61f44e88f4c8c155272ee56d868043146096asb evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else { /* no space in the mblk for tag */
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * allocate a mblk to create a new frame hdr with the tag
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp = allocb(sizeof (struct ether_vlan_header),
c1c61f44e88f4c8c155272ee56d868043146096asb BPRI_MED);
c1c61f44e88f4c8c155272ee56d868043146096asb if (nmp == NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb freemsg(mp);
c1c61f44e88f4c8c155272ee56d868043146096asb return (NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * copy the src and dst mac addrs in the header to the new mblk
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb n = 2 * ETHERADDRL;
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(mp->b_rptr, nmp->b_rptr, n);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* initialize the vlan tag in the new mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb evhp = (struct ether_vlan_header *)nmp->b_rptr;
c1c61f44e88f4c8c155272ee56d868043146096asb evhp->ether_tpid = htons(ETHERTYPE_VLAN);
c1c61f44e88f4c8c155272ee56d868043146096asb evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* copy ethertype to new mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(mp->b_rptr + n, nmp->b_rptr + n + VLAN_TAGSZ,
c1c61f44e88f4c8c155272ee56d868043146096asb sizeof (evhp->ether_type));
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* skip over the header in the original mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb mp->b_rptr += sizeof (struct ether_header);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* fix the end of frame header in the new mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp->b_wptr += sizeof (struct ether_vlan_header);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * now link the new mblk which contains just the frame
c1c61f44e88f4c8c155272ee56d868043146096asb * header with the original mblk which contains rest of
c1c61f44e88f4c8c155272ee56d868043146096asb * the frame.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp->b_cont = mp;
c1c61f44e88f4c8c155272ee56d868043146096asb mp = nmp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asbmblk_t *
c1c61f44e88f4c8c155272ee56d868043146096asbvnet_vlan_remove_tag(mblk_t *mp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb size_t n;
c1c61f44e88f4c8c155272ee56d868043146096asb mblk_t *nmp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (DB_REF(mp) == 1) { /* mblk can be modified to untag(not shared) */
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* move src & dst addrs in the header forward by VLAN_TAGSZ */
c1c61f44e88f4c8c155272ee56d868043146096asb ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, 2 * ETHERADDRL);
c1c61f44e88f4c8c155272ee56d868043146096asb mp->b_rptr += VLAN_TAGSZ;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* allocate a new header */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp = allocb(sizeof (struct ether_header), BPRI_MED);
c1c61f44e88f4c8c155272ee56d868043146096asb if (nmp == NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb freemsg(mp);
c1c61f44e88f4c8c155272ee56d868043146096asb return (NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * copy the src and dst mac addrs in the header to the new mblk
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb n = 2 * ETHERADDRL;
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(mp->b_rptr, nmp->b_rptr, n);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* skip over vlan tag and copy ethertype to new mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(mp->b_rptr + n + VLAN_TAGSZ, nmp->b_rptr + n,
c1c61f44e88f4c8c155272ee56d868043146096asb sizeof (uint16_t));
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* skip over the header in the original mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb mp->b_rptr += sizeof (struct ether_vlan_header);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* fix the end of frame header in the new mblk */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp->b_wptr += sizeof (struct ether_header);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * now link the new mblk which contains the frame header
c1c61f44e88f4c8c155272ee56d868043146096asb * without vlan tag and the original mblk which contains rest
c1c61f44e88f4c8c155272ee56d868043146096asb * of the frame.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb nmp->b_cont = mp;
c1c61f44e88f4c8c155272ee56d868043146096asb mp = nmp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb}
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeehaint
bbfa0259e68b6b625e9e085053d41d620f185eeehavnet_dring_entry_copy(vnet_public_desc_t *from, vnet_public_desc_t *to,
bbfa0259e68b6b625e9e085053d41d620f185eeeha uint8_t mtype, ldc_dring_handle_t handle, uint64_t start, uint64_t stop)
bbfa0259e68b6b625e9e085053d41d620f185eeeha{
bbfa0259e68b6b625e9e085053d41d620f185eeeha int rv;
bbfa0259e68b6b625e9e085053d41d620f185eeeha on_trap_data_t otd;
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha if ((rv = VIO_DRING_ACQUIRE(&otd, mtype, handle, start, stop)) != 0)
bbfa0259e68b6b625e9e085053d41d620f185eeeha return (rv);
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha *to = *from;
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = VIO_DRING_RELEASE_NOCOPYOUT(mtype);
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha return (rv);
bbfa0259e68b6b625e9e085053d41d620f185eeeha}
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeehaint
bbfa0259e68b6b625e9e085053d41d620f185eeehavnet_dring_entry_set_dstate(vnet_public_desc_t *descp, uint8_t mtype,
bbfa0259e68b6b625e9e085053d41d620f185eeeha ldc_dring_handle_t handle, uint64_t start, uint64_t stop, uint8_t dstate)
bbfa0259e68b6b625e9e085053d41d620f185eeeha{
bbfa0259e68b6b625e9e085053d41d620f185eeeha int rv;
bbfa0259e68b6b625e9e085053d41d620f185eeeha on_trap_data_t otd;
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = VIO_DRING_ACQUIRE_NOCOPYIN(&otd, mtype);
bbfa0259e68b6b625e9e085053d41d620f185eeeha if (rv)
bbfa0259e68b6b625e9e085053d41d620f185eeeha return (rv);
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha descp->hdr.dstate = dstate;
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = VIO_DRING_RELEASE(mtype, handle, start, stop);
bbfa0259e68b6b625e9e085053d41d620f185eeeha
bbfa0259e68b6b625e9e085053d41d620f185eeeha return (rv);
bbfa0259e68b6b625e9e085053d41d620f185eeeha}