Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/ethernet.h>
     31 #include <sys/vnet_common.h>
     32 #include <sys/vlan.h>
     33 #include <sys/stream.h>
     34 #include <sys/strsun.h>
     35 #include <sys/byteorder.h>
     36 
     37 /* convert mac address from string to uint64_t */
     38 uint64_t
     39 vnet_macaddr_strtoul(const uint8_t *macaddr)
     40 {
     41 	uint64_t val = 0;
     42 	int i;
     43 
     44 	for (i = 0; i < ETHERADDRL; i++) {
     45 		val <<= 8;
     46 		val |= macaddr[i];
     47 	}
     48 
     49 	return (val);
     50 }
     51 
     52 /* convert mac address from uint64_t to string */
     53 void
     54 vnet_macaddr_ultostr(uint64_t val, uint8_t *macaddr)
     55 {
     56 	int i;
     57 	uint64_t value;
     58 
     59 	value = val;
     60 	for (i = ETHERADDRL - 1; i >= 0; i--) {
     61 		macaddr[i] = value & 0xFF;
     62 		value >>= 8;
     63 	}
     64 }
     65 
     66 mblk_t *
     67 vnet_vlan_insert_tag(mblk_t *mp, uint16_t vid)
     68 {
     69 	struct ether_vlan_header	*evhp;
     70 	mblk_t				*nmp;
     71 	size_t				n;
     72 	uint_t				pri = 0;
     73 
     74 	if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VLAN_TAGSZ) {
     75 
     76 		/* mblk has space to insert tag */
     77 
     78 		/*
     79 		 * move src and dst mac addrs in the header back by VLAN_TAGSZ.
     80 		 */
     81 		ovbcopy(mp->b_rptr, mp->b_rptr - VLAN_TAGSZ, 2 * ETHERADDRL);
     82 		mp->b_rptr -= VLAN_TAGSZ;
     83 
     84 		/* now insert tpid and tci */
     85 		evhp = (struct ether_vlan_header *)mp->b_rptr;
     86 		evhp->ether_tpid = htons(ETHERTYPE_VLAN);
     87 		evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
     88 
     89 	} else { /* no space in the mblk for tag */
     90 
     91 		/*
     92 		 * allocate a mblk to create a new frame hdr with the tag
     93 		 */
     94 		nmp = allocb(sizeof (struct  ether_vlan_header),
     95 		    BPRI_MED);
     96 		if (nmp == NULL) {
     97 			freemsg(mp);
     98 			return (NULL);
     99 		}
    100 
    101 		/*
    102 		 * copy the src and dst mac addrs in the header to the new mblk
    103 		 */
    104 		n = 2 * ETHERADDRL;
    105 		bcopy(mp->b_rptr, nmp->b_rptr, n);
    106 
    107 		/* initialize the vlan tag in the new mblk */
    108 		evhp = (struct ether_vlan_header *)nmp->b_rptr;
    109 		evhp->ether_tpid = htons(ETHERTYPE_VLAN);
    110 		evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
    111 
    112 		/* copy ethertype to new mblk */
    113 		bcopy(mp->b_rptr + n, nmp->b_rptr + n + VLAN_TAGSZ,
    114 		    sizeof (evhp->ether_type));
    115 
    116 		/* skip over the header in the original mblk */
    117 		mp->b_rptr += sizeof (struct ether_header);
    118 
    119 		/* fix the end of frame header in the new mblk */
    120 		nmp->b_wptr += sizeof (struct ether_vlan_header);
    121 
    122 		/*
    123 		 * now link the new mblk which contains just the frame
    124 		 * header with the original mblk which contains rest of
    125 		 * the frame.
    126 		 */
    127 		nmp->b_cont = mp;
    128 		mp = nmp;
    129 
    130 	}
    131 
    132 	return (mp);
    133 }
    134 
    135 mblk_t *
    136 vnet_vlan_remove_tag(mblk_t *mp)
    137 {
    138 	size_t				n;
    139 	mblk_t				*nmp;
    140 
    141 	if (DB_REF(mp) == 1) { /* mblk can be modified to untag(not shared) */
    142 
    143 		/* move src & dst addrs in the header forward by VLAN_TAGSZ */
    144 		ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, 2 * ETHERADDRL);
    145 		mp->b_rptr += VLAN_TAGSZ;
    146 
    147 	} else {
    148 
    149 		/* allocate a new header */
    150 		nmp = allocb(sizeof (struct  ether_header), BPRI_MED);
    151 		if (nmp == NULL) {
    152 			freemsg(mp);
    153 			return (NULL);
    154 		}
    155 
    156 		/*
    157 		 * copy the src and dst mac addrs in the header to the new mblk
    158 		 */
    159 		n = 2 * ETHERADDRL;
    160 		bcopy(mp->b_rptr, nmp->b_rptr, n);
    161 
    162 		/* skip over vlan tag and copy ethertype to new mblk */
    163 		bcopy(mp->b_rptr + n + VLAN_TAGSZ, nmp->b_rptr + n,
    164 		    sizeof (uint16_t));
    165 
    166 		/* skip over the header in the original mblk */
    167 		mp->b_rptr += sizeof (struct ether_vlan_header);
    168 
    169 		/* fix the end of frame header in the new mblk */
    170 		nmp->b_wptr += sizeof (struct ether_header);
    171 
    172 		/*
    173 		 * now link the new mblk which contains the frame header
    174 		 * without vlan tag and the original mblk which contains rest
    175 		 * of the frame.
    176 		 */
    177 		nmp->b_cont = mp;
    178 		mp = nmp;
    179 
    180 	}
    181 
    182 	return (mp);
    183 }
    184 
    185 int
    186 vnet_dring_entry_copy(vnet_public_desc_t *from, vnet_public_desc_t *to,
    187     uint8_t mtype, ldc_dring_handle_t handle, uint64_t start, uint64_t stop)
    188 {
    189 	int rv;
    190 	on_trap_data_t otd;
    191 
    192 	if ((rv = VIO_DRING_ACQUIRE(&otd, mtype, handle, start, stop)) != 0)
    193 		return (rv);
    194 
    195 	*to = *from;
    196 
    197 	rv = VIO_DRING_RELEASE_NOCOPYOUT(mtype);
    198 
    199 	return (rv);
    200 }
    201 
    202 int
    203 vnet_dring_entry_set_dstate(vnet_public_desc_t *descp, uint8_t mtype,
    204     ldc_dring_handle_t handle, uint64_t start, uint64_t stop, uint8_t dstate)
    205 {
    206 	int rv;
    207 	on_trap_data_t otd;
    208 
    209 	rv = VIO_DRING_ACQUIRE_NOCOPYIN(&otd, mtype);
    210 	if (rv)
    211 		return (rv);
    212 
    213 	descp->hdr.dstate = dstate;
    214 
    215 	rv = VIO_DRING_RELEASE(mtype, handle, start, stop);
    216 
    217 	return (rv);
    218 }
    219