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