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