xref: /illumos-gate/usr/src/uts/sun4v/io/vnet_common.c (revision bbfa0259e68b6b625e9e085053d41d620f185eee)
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