15462Swentaoy /* 25462Swentaoy * CDDL HEADER START 35462Swentaoy * 45462Swentaoy * The contents of this file are subject to the terms of the 55462Swentaoy * Common Development and Distribution License (the "License"). 65462Swentaoy * You may not use this file except in compliance with the License. 75462Swentaoy * 85462Swentaoy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95462Swentaoy * or http://www.opensolaris.org/os/licensing. 105462Swentaoy * See the License for the specific language governing permissions 115462Swentaoy * and limitations under the License. 125462Swentaoy * 135462Swentaoy * When distributing Covered Code, include this CDDL HEADER in each 145462Swentaoy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155462Swentaoy * If applicable, add the following below this CDDL HEADER, with the 165462Swentaoy * fields enclosed by brackets "[]" replaced with your own identifying 175462Swentaoy * information: Portions Copyright [yyyy] [name of copyright owner] 185462Swentaoy * 195462Swentaoy * CDDL HEADER END 205462Swentaoy */ 215462Swentaoy 225462Swentaoy /* 23*6419Ssb155480 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245462Swentaoy * Use is subject to license terms. 255462Swentaoy */ 265462Swentaoy 275462Swentaoy #pragma ident "%Z%%M% %I% %E% SMI" 285462Swentaoy 295462Swentaoy #include <sys/types.h> 305462Swentaoy #include <sys/ethernet.h> 315462Swentaoy #include <sys/vnet_common.h> 32*6419Ssb155480 #include <sys/vlan.h> 33*6419Ssb155480 #include <sys/stream.h> 34*6419Ssb155480 #include <sys/strsun.h> 35*6419Ssb155480 #include <sys/byteorder.h> 365462Swentaoy 375462Swentaoy /* convert mac address from string to uint64_t */ 385462Swentaoy uint64_t 395462Swentaoy vnet_macaddr_strtoul(const uint8_t *macaddr) 405462Swentaoy { 415462Swentaoy uint64_t val = 0; 425462Swentaoy int i; 435462Swentaoy 445462Swentaoy for (i = 0; i < ETHERADDRL; i++) { 455462Swentaoy val <<= 8; 465462Swentaoy val |= macaddr[i]; 475462Swentaoy } 485462Swentaoy 495462Swentaoy return (val); 505462Swentaoy } 515462Swentaoy 525462Swentaoy /* convert mac address from uint64_t to string */ 535462Swentaoy void 545462Swentaoy vnet_macaddr_ultostr(uint64_t val, uint8_t *macaddr) 555462Swentaoy { 565462Swentaoy int i; 575462Swentaoy uint64_t value; 585462Swentaoy 595462Swentaoy value = val; 605462Swentaoy for (i = ETHERADDRL - 1; i >= 0; i--) { 615462Swentaoy macaddr[i] = value & 0xFF; 625462Swentaoy value >>= 8; 635462Swentaoy } 645462Swentaoy } 65*6419Ssb155480 66*6419Ssb155480 mblk_t * 67*6419Ssb155480 vnet_vlan_insert_tag(mblk_t *mp, uint16_t vid) 68*6419Ssb155480 { 69*6419Ssb155480 struct ether_vlan_header *evhp; 70*6419Ssb155480 mblk_t *nmp; 71*6419Ssb155480 size_t n; 72*6419Ssb155480 uint_t pri = 0; 73*6419Ssb155480 74*6419Ssb155480 if (DB_REF(mp) == 1 && MBLKHEAD(mp) >= VLAN_TAGSZ) { 75*6419Ssb155480 76*6419Ssb155480 /* mblk has space to insert tag */ 77*6419Ssb155480 78*6419Ssb155480 /* 79*6419Ssb155480 * move src and dst mac addrs in the header back by VLAN_TAGSZ. 80*6419Ssb155480 */ 81*6419Ssb155480 ovbcopy(mp->b_rptr, mp->b_rptr - VLAN_TAGSZ, 2 * ETHERADDRL); 82*6419Ssb155480 mp->b_rptr -= VLAN_TAGSZ; 83*6419Ssb155480 84*6419Ssb155480 /* now insert tpid and tci */ 85*6419Ssb155480 evhp = (struct ether_vlan_header *)mp->b_rptr; 86*6419Ssb155480 evhp->ether_tpid = htons(ETHERTYPE_VLAN); 87*6419Ssb155480 evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid)); 88*6419Ssb155480 89*6419Ssb155480 } else { /* no space in the mblk for tag */ 90*6419Ssb155480 91*6419Ssb155480 /* 92*6419Ssb155480 * allocate a mblk to create a new frame hdr with the tag 93*6419Ssb155480 */ 94*6419Ssb155480 nmp = allocb(sizeof (struct ether_vlan_header), 95*6419Ssb155480 BPRI_MED); 96*6419Ssb155480 if (nmp == NULL) { 97*6419Ssb155480 freemsg(mp); 98*6419Ssb155480 return (NULL); 99*6419Ssb155480 } 100*6419Ssb155480 101*6419Ssb155480 /* 102*6419Ssb155480 * copy the src and dst mac addrs in the header to the new mblk 103*6419Ssb155480 */ 104*6419Ssb155480 n = 2 * ETHERADDRL; 105*6419Ssb155480 bcopy(mp->b_rptr, nmp->b_rptr, n); 106*6419Ssb155480 107*6419Ssb155480 /* initialize the vlan tag in the new mblk */ 108*6419Ssb155480 evhp = (struct ether_vlan_header *)nmp->b_rptr; 109*6419Ssb155480 evhp->ether_tpid = htons(ETHERTYPE_VLAN); 110*6419Ssb155480 evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid)); 111*6419Ssb155480 112*6419Ssb155480 /* copy ethertype to new mblk */ 113*6419Ssb155480 bcopy(mp->b_rptr + n, nmp->b_rptr + n + VLAN_TAGSZ, 114*6419Ssb155480 sizeof (evhp->ether_type)); 115*6419Ssb155480 116*6419Ssb155480 /* skip over the header in the original mblk */ 117*6419Ssb155480 mp->b_rptr += sizeof (struct ether_header); 118*6419Ssb155480 119*6419Ssb155480 /* fix the end of frame header in the new mblk */ 120*6419Ssb155480 nmp->b_wptr += sizeof (struct ether_vlan_header); 121*6419Ssb155480 122*6419Ssb155480 /* 123*6419Ssb155480 * now link the new mblk which contains just the frame 124*6419Ssb155480 * header with the original mblk which contains rest of 125*6419Ssb155480 * the frame. 126*6419Ssb155480 */ 127*6419Ssb155480 nmp->b_cont = mp; 128*6419Ssb155480 mp = nmp; 129*6419Ssb155480 130*6419Ssb155480 } 131*6419Ssb155480 132*6419Ssb155480 return (mp); 133*6419Ssb155480 } 134*6419Ssb155480 135*6419Ssb155480 mblk_t * 136*6419Ssb155480 vnet_vlan_remove_tag(mblk_t *mp) 137*6419Ssb155480 { 138*6419Ssb155480 size_t n; 139*6419Ssb155480 mblk_t *nmp; 140*6419Ssb155480 141*6419Ssb155480 if (DB_REF(mp) == 1) { /* mblk can be modified to untag(not shared) */ 142*6419Ssb155480 143*6419Ssb155480 /* move src & dst addrs in the header forward by VLAN_TAGSZ */ 144*6419Ssb155480 ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, 2 * ETHERADDRL); 145*6419Ssb155480 mp->b_rptr += VLAN_TAGSZ; 146*6419Ssb155480 147*6419Ssb155480 } else { 148*6419Ssb155480 149*6419Ssb155480 /* allocate a new header */ 150*6419Ssb155480 nmp = allocb(sizeof (struct ether_header), BPRI_MED); 151*6419Ssb155480 if (nmp == NULL) { 152*6419Ssb155480 freemsg(mp); 153*6419Ssb155480 return (NULL); 154*6419Ssb155480 } 155*6419Ssb155480 156*6419Ssb155480 /* 157*6419Ssb155480 * copy the src and dst mac addrs in the header to the new mblk 158*6419Ssb155480 */ 159*6419Ssb155480 n = 2 * ETHERADDRL; 160*6419Ssb155480 bcopy(mp->b_rptr, nmp->b_rptr, n); 161*6419Ssb155480 162*6419Ssb155480 /* skip over vlan tag and copy ethertype to new mblk */ 163*6419Ssb155480 bcopy(mp->b_rptr + n + VLAN_TAGSZ, nmp->b_rptr + n, 164*6419Ssb155480 sizeof (uint16_t)); 165*6419Ssb155480 166*6419Ssb155480 /* skip over the header in the original mblk */ 167*6419Ssb155480 mp->b_rptr += sizeof (struct ether_vlan_header); 168*6419Ssb155480 169*6419Ssb155480 /* fix the end of frame header in the new mblk */ 170*6419Ssb155480 nmp->b_wptr += sizeof (struct ether_header); 171*6419Ssb155480 172*6419Ssb155480 /* 173*6419Ssb155480 * now link the new mblk which contains the frame header 174*6419Ssb155480 * without vlan tag and the original mblk which contains rest 175*6419Ssb155480 * of the frame. 176*6419Ssb155480 */ 177*6419Ssb155480 nmp->b_cont = mp; 178*6419Ssb155480 mp = nmp; 179*6419Ssb155480 180*6419Ssb155480 } 181*6419Ssb155480 182*6419Ssb155480 return (mp); 183*6419Ssb155480 } 184