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
vnet_macaddr_strtoul(const uint8_t * macaddr)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
vnet_macaddr_ultostr(uint64_t val,uint8_t * macaddr)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 *
vnet_vlan_insert_tag(mblk_t * mp,uint16_t vid)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 *
vnet_vlan_remove_tag(mblk_t * mp)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
vnet_dring_entry_copy(vnet_public_desc_t * from,vnet_public_desc_t * to,uint8_t mtype,ldc_dring_handle_t handle,uint64_t start,uint64_t stop)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
vnet_dring_entry_set_dstate(vnet_public_desc_t * descp,uint8_t mtype,ldc_dring_handle_t handle,uint64_t start,uint64_t stop,uint8_t dstate)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