xref: /titanic_54/usr/src/stand/lib/inet/ibd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <dhcp_impl.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <socket_impl.h>
32*7c478bd9Sstevel@tonic-gate #include <socket_inet.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
35*7c478bd9Sstevel@tonic-gate #include <net/if.h>
36*7c478bd9Sstevel@tonic-gate #include <net/if_arp.h>
37*7c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
38*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
39*7c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
40*7c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/promif.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/salib.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/ib/clients/ibd/ibd.h>
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include "ipv4.h"
48*7c478bd9Sstevel@tonic-gate #include "dhcpv4.h"
49*7c478bd9Sstevel@tonic-gate #include "ipv4_impl.h"
50*7c478bd9Sstevel@tonic-gate #include "mac.h"
51*7c478bd9Sstevel@tonic-gate #include "mac_impl.h"
52*7c478bd9Sstevel@tonic-gate #include "ibd_inet.h"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate struct ibd_arp {
55*7c478bd9Sstevel@tonic-gate 	struct arphdr	ea_hdr;		/* fixed-size header */
56*7c478bd9Sstevel@tonic-gate 	ipoib_mac_t	arp_sha;	/* sender hardware address */
57*7c478bd9Sstevel@tonic-gate 	uchar_t		arp_spa[4];	/* sender protocol address */
58*7c478bd9Sstevel@tonic-gate 	ipoib_mac_t	arp_tha;	/* target hardware address */
59*7c478bd9Sstevel@tonic-gate 	uchar_t		arp_tpa[4];	/* target protocol address */
60*7c478bd9Sstevel@tonic-gate };
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate extern int errno;
63*7c478bd9Sstevel@tonic-gate ipoib_mac_t ibdbroadcastaddr;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate /*
66*7c478bd9Sstevel@tonic-gate  * Assumptions about OBP behavior (refer FWARC 2002/702, 2003/251):
67*7c478bd9Sstevel@tonic-gate  * 1. prom_write() accepts the 20 byte destination address as the
68*7c478bd9Sstevel@tonic-gate  * first component in the send buffer. The buffer pointer points
69*7c478bd9Sstevel@tonic-gate  * to the start of this 20 byte address. The length parameter is
70*7c478bd9Sstevel@tonic-gate  * the IPoIB datagram size with the 20 byte of destination
71*7c478bd9Sstevel@tonic-gate  * address.
72*7c478bd9Sstevel@tonic-gate  * 2. OBP will not provide max-frame-size, since obp can only
73*7c478bd9Sstevel@tonic-gate  * determine that by querying the IBA mcg, and thus the property
74*7c478bd9Sstevel@tonic-gate  * has to be /chosen:ipib-frame-size. This will refer to the IPoIB
75*7c478bd9Sstevel@tonic-gate  * link MTU as per section 4.0 of ietf i/d, ie, the 4 byte IPoIB
76*7c478bd9Sstevel@tonic-gate  * header plus the IP payload mtu. Plus the 20 bytes of addressing
77*7c478bd9Sstevel@tonic-gate  * information.
78*7c478bd9Sstevel@tonic-gate  * 3. OBP will not provide mac-address property for IPoIB since there
79*7c478bd9Sstevel@tonic-gate  * are built in assumptions about 6 byte address with that. Instead,
80*7c478bd9Sstevel@tonic-gate  * /chosen:ipib-address will provide the local address.
81*7c478bd9Sstevel@tonic-gate  * 4. prom_read() returns 20 byte 0'ed filler followed by 4 byte
82*7c478bd9Sstevel@tonic-gate  * IPoIB header followed by IP payload. The return value is -2,
83*7c478bd9Sstevel@tonic-gate  * -1, 0, or the length of the received IPoIB datagram alongwith
84*7c478bd9Sstevel@tonic-gate  * the 20 bytes MBZ. The buffer pointer points to the start of
85*7c478bd9Sstevel@tonic-gate  * the 20 MBZ bytes. The length parameter reflects the max data
86*7c478bd9Sstevel@tonic-gate  * size that should be copied into the buffer including the 20
87*7c478bd9Sstevel@tonic-gate  * MBZ bytes.
88*7c478bd9Sstevel@tonic-gate  * 5. OBP will not provide chosen-network-type, only
89*7c478bd9Sstevel@tonic-gate  * network-interface-type = ipib. On an Infiniband device, this
90*7c478bd9Sstevel@tonic-gate  * however does not guarantee that it is a network device.
91*7c478bd9Sstevel@tonic-gate  * 6. OBP will provide the DHCP client id in /chosen:client-id.
92*7c478bd9Sstevel@tonic-gate  * 7. /chosen:ipib-broadcast will provide the broadcast address.
93*7c478bd9Sstevel@tonic-gate  * 8. OBP will validate that RARP is not being used before
94*7c478bd9Sstevel@tonic-gate  * allowing boot to proceed to inetboot.
95*7c478bd9Sstevel@tonic-gate  */
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate struct arp_packet {
98*7c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		arp_eh;
99*7c478bd9Sstevel@tonic-gate 	struct ibd_arp		arp_ea;
100*7c478bd9Sstevel@tonic-gate };
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate #define	dprintf	if (boothowto & RB_DEBUG) printf
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate static char *
105*7c478bd9Sstevel@tonic-gate ibd_print(ipoib_mac_t *ea)
106*7c478bd9Sstevel@tonic-gate {
107*7c478bd9Sstevel@tonic-gate 	unsigned char *macaddr = (unsigned char *)ea;
108*7c478bd9Sstevel@tonic-gate 	static char pbuf[(3 * IPOIB_ADDRL) + 1];
109*7c478bd9Sstevel@tonic-gate 	int i;
110*7c478bd9Sstevel@tonic-gate 	char *ptr = pbuf;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	ptr = pbuf + sprintf(pbuf, "%x", *macaddr++);
113*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < (IPOIB_ADDRL - 1); i++)
114*7c478bd9Sstevel@tonic-gate 		ptr += sprintf(ptr, ":%x", *macaddr++);
115*7c478bd9Sstevel@tonic-gate 	return (pbuf);
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate /*
120*7c478bd9Sstevel@tonic-gate  * Common ARP code. Broadcast the packet and wait for the right response.
121*7c478bd9Sstevel@tonic-gate  *
122*7c478bd9Sstevel@tonic-gate  * If arp is called for, caller expects a hardware address in the
123*7c478bd9Sstevel@tonic-gate  * source hardware address (sha) field of the "out" argument.
124*7c478bd9Sstevel@tonic-gate  *
125*7c478bd9Sstevel@tonic-gate  * IPoIB does not support RARP (see ibd_revarp()).
126*7c478bd9Sstevel@tonic-gate  *
127*7c478bd9Sstevel@tonic-gate  * Returns TRUE if transaction succeeded, FALSE otherwise.
128*7c478bd9Sstevel@tonic-gate  *
129*7c478bd9Sstevel@tonic-gate  * The timeout argument is the number of milliseconds to wait for a
130*7c478bd9Sstevel@tonic-gate  * response. An infinite timeout can be specified as 0xffffffff.
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate static int
133*7c478bd9Sstevel@tonic-gate ibd_comarp(struct arp_packet *out, uint32_t timeout)
134*7c478bd9Sstevel@tonic-gate {
135*7c478bd9Sstevel@tonic-gate 	struct arp_packet *in = (struct arp_packet *)mac_state.mac_buf;
136*7c478bd9Sstevel@tonic-gate 	int count, time, feedback, len, delay = 2;
137*7c478bd9Sstevel@tonic-gate 	char    *ind = "-\\|/";
138*7c478bd9Sstevel@tonic-gate 	struct in_addr tmp_ia;
139*7c478bd9Sstevel@tonic-gate 	uint32_t wait_time;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&out->arp_eh.ipoib_dest,
142*7c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_hrd =  htons(ARPHRD_IB);
145*7c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_pro = htons(ETHERTYPE_IP);
146*7c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_hln = IPOIB_ADDRL;
147*7c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_pln = sizeof (struct in_addr);
148*7c478bd9Sstevel@tonic-gate 	bcopy(mac_state.mac_addr_buf, (caddr_t)&out->arp_ea.arp_sha,
149*7c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
150*7c478bd9Sstevel@tonic-gate 	ipv4_getipaddr(&tmp_ia);
151*7c478bd9Sstevel@tonic-gate 	tmp_ia.s_addr = htonl(tmp_ia.s_addr);
152*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&tmp_ia, (caddr_t)out->arp_ea.arp_spa,
153*7c478bd9Sstevel@tonic-gate 	    sizeof (struct in_addr));
154*7c478bd9Sstevel@tonic-gate 	feedback = 0;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	wait_time = prom_gettime() + timeout;
157*7c478bd9Sstevel@tonic-gate 	for (count = 0; timeout == ~0U || prom_gettime() < wait_time; count++) {
158*7c478bd9Sstevel@tonic-gate 		if (count == IBD_WAITCNT) {
159*7c478bd9Sstevel@tonic-gate 			/*
160*7c478bd9Sstevel@tonic-gate 			 * Since IPoIB does not support RARP (see ibd_revarp),
161*7c478bd9Sstevel@tonic-gate 			 * we know that out->arp_ea.arp_op == ARPOP_REQUEST.
162*7c478bd9Sstevel@tonic-gate 			 */
163*7c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)out->arp_ea.arp_tpa,
164*7c478bd9Sstevel@tonic-gate 			    (caddr_t)&tmp_ia, sizeof (struct in_addr));
165*7c478bd9Sstevel@tonic-gate 			printf("\nRequesting MAC address for: %s\n",
166*7c478bd9Sstevel@tonic-gate 			    inet_ntoa(tmp_ia));
167*7c478bd9Sstevel@tonic-gate 		}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 		(void) prom_write(mac_state.mac_dev, (caddr_t)out,
170*7c478bd9Sstevel@tonic-gate 		    sizeof (*out), 0, NETWORK);
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 		if (count >= IBD_WAITCNT)
173*7c478bd9Sstevel@tonic-gate 			printf("%c\b", ind[feedback++ % 4]); /* activity */
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 		time = prom_gettime() + (delay * 1000);	/* broadcast delay */
176*7c478bd9Sstevel@tonic-gate 		while (prom_gettime() <= time) {
177*7c478bd9Sstevel@tonic-gate 			len = prom_read(mac_state.mac_dev, mac_state.mac_buf,
178*7c478bd9Sstevel@tonic-gate 			    mac_state.mac_mtu, 0, NETWORK);
179*7c478bd9Sstevel@tonic-gate 			if (len < sizeof (struct arp_packet))
180*7c478bd9Sstevel@tonic-gate 				continue;
181*7c478bd9Sstevel@tonic-gate 			if (in->arp_ea.arp_pro != ntohs(ETHERTYPE_IP))
182*7c478bd9Sstevel@tonic-gate 				continue;
183*7c478bd9Sstevel@tonic-gate 			/*
184*7c478bd9Sstevel@tonic-gate 			 * Since IPoIB does not support RARP (see ibd_revarp),
185*7c478bd9Sstevel@tonic-gate 			 * we know that out->arp_ea.arp_op == ARPOP_REQUEST.
186*7c478bd9Sstevel@tonic-gate 			 */
187*7c478bd9Sstevel@tonic-gate 			if (in->arp_eh.ipoib_rhdr.ipoib_type !=
188*7c478bd9Sstevel@tonic-gate 			    ntohs(ETHERTYPE_ARP))
189*7c478bd9Sstevel@tonic-gate 				continue;
190*7c478bd9Sstevel@tonic-gate 			if (in->arp_ea.arp_op != ntohs(ARPOP_REPLY))
191*7c478bd9Sstevel@tonic-gate 				continue;
192*7c478bd9Sstevel@tonic-gate 			if (bcmp((caddr_t)in->arp_ea.arp_spa,
193*7c478bd9Sstevel@tonic-gate 			    (caddr_t)out->arp_ea.arp_tpa,
194*7c478bd9Sstevel@tonic-gate 			    sizeof (struct in_addr)) != 0)
195*7c478bd9Sstevel@tonic-gate 				continue;
196*7c478bd9Sstevel@tonic-gate 			if (boothowto & RB_VERBOSE) {
197*7c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)in->arp_ea.arp_spa,
198*7c478bd9Sstevel@tonic-gate 				    (caddr_t)&tmp_ia,
199*7c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
200*7c478bd9Sstevel@tonic-gate 				printf("Found %s @ %s\n",
201*7c478bd9Sstevel@tonic-gate 				    inet_ntoa(tmp_ia),
202*7c478bd9Sstevel@tonic-gate 				    ibd_print(&in->arp_ea.arp_sha));
203*7c478bd9Sstevel@tonic-gate 			}
204*7c478bd9Sstevel@tonic-gate 			/* copy hardware addr into "out" for caller */
205*7c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)&in->arp_ea.arp_sha,
206*7c478bd9Sstevel@tonic-gate 			    (caddr_t)&out->arp_ea.arp_sha, IPOIB_ADDRL);
207*7c478bd9Sstevel@tonic-gate 			return (TRUE);
208*7c478bd9Sstevel@tonic-gate 		}
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 		delay = delay * 2;	/* Double the request delay */
211*7c478bd9Sstevel@tonic-gate 		if (delay > 64)		/* maximum delay is 64 seconds */
212*7c478bd9Sstevel@tonic-gate 			delay = 64;
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 	return (FALSE);
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * ARP client side
219*7c478bd9Sstevel@tonic-gate  * Broadcasts to determine MAC address given network order IP address.
220*7c478bd9Sstevel@tonic-gate  * See RFC 826
221*7c478bd9Sstevel@tonic-gate  *
222*7c478bd9Sstevel@tonic-gate  * Returns TRUE if successful, FALSE otherwise.
223*7c478bd9Sstevel@tonic-gate  */
224*7c478bd9Sstevel@tonic-gate static int
225*7c478bd9Sstevel@tonic-gate ibd_arp(struct in_addr *ip, void *hap, uint32_t timeout)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	ipoib_mac_t *ep = (ipoib_mac_t *)hap;
228*7c478bd9Sstevel@tonic-gate 	struct arp_packet out;
229*7c478bd9Sstevel@tonic-gate 	int result;
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	if (!initialized)
232*7c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	bzero((char *)&out, sizeof (struct arp_packet));
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	out.arp_eh.ipoib_rhdr.ipoib_type = htons(ETHERTYPE_ARP);
237*7c478bd9Sstevel@tonic-gate 	out.arp_ea.arp_op = htons(ARPOP_REQUEST);
238*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&out.arp_ea.arp_tha,
239*7c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
240*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)ip, (caddr_t)out.arp_ea.arp_tpa,
241*7c478bd9Sstevel@tonic-gate 	    sizeof (struct in_addr));
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	result = ibd_comarp(&out, timeout);
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (result && (ep != NULL)) {
246*7c478bd9Sstevel@tonic-gate 		bcopy((caddr_t)&out.arp_ea.arp_sha, (caddr_t)ep, IPOIB_ADDRL);
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate 	return (result);
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate /*
252*7c478bd9Sstevel@tonic-gate  * Reverse ARP client side
253*7c478bd9Sstevel@tonic-gate  * Determine our Internet address given our MAC address
254*7c478bd9Sstevel@tonic-gate  * See RFC 903
255*7c478bd9Sstevel@tonic-gate  */
256*7c478bd9Sstevel@tonic-gate static void
257*7c478bd9Sstevel@tonic-gate ibd_revarp(void)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	prom_panic("IPoIB can not boot with RARP.");
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
263*7c478bd9Sstevel@tonic-gate static int
264*7c478bd9Sstevel@tonic-gate ibd_header_len(struct inetgram *igm)
265*7c478bd9Sstevel@tonic-gate {
266*7c478bd9Sstevel@tonic-gate 	/*
267*7c478bd9Sstevel@tonic-gate 	 * We indicate to upper layers to leave enough space
268*7c478bd9Sstevel@tonic-gate 	 * in output buffers for filling in the IPoIB header
269*7c478bd9Sstevel@tonic-gate 	 * and the 20 byte destination address in ibd_output().
270*7c478bd9Sstevel@tonic-gate 	 */
271*7c478bd9Sstevel@tonic-gate 	return (IPOIB_HDRSIZE + IPOIB_ADDRL);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  * Handle a IP datagram addressed to our MAC address or to the link
276*7c478bd9Sstevel@tonic-gate  * layer broadcast address. Also respond to ARP requests. Generates
277*7c478bd9Sstevel@tonic-gate  * inetgrams as long as there's data and the mac level IP timeout timer
278*7c478bd9Sstevel@tonic-gate  * hasn't expired. As soon as there is no data, we try for
279*7c478bd9Sstevel@tonic-gate  * IBD_INPUT_ATTEMPTS for more, then exit the loop, even if there is time
280*7c478bd9Sstevel@tonic-gate  * left, since we expect to have data waiting for us when we're called, we just
281*7c478bd9Sstevel@tonic-gate  * don't know how much.
282*7c478bd9Sstevel@tonic-gate  *
283*7c478bd9Sstevel@tonic-gate  * We workaround slow proms (some proms have hard sleeps for as much as 3msec)
284*7c478bd9Sstevel@tonic-gate  * even though there are is data waiting.
285*7c478bd9Sstevel@tonic-gate  *
286*7c478bd9Sstevel@tonic-gate  * Returns the total number of MEDIA_LVL frames placed on the socket.
287*7c478bd9Sstevel@tonic-gate  * Caller is expected to free up the inetgram resources.
288*7c478bd9Sstevel@tonic-gate  */
289*7c478bd9Sstevel@tonic-gate static int
290*7c478bd9Sstevel@tonic-gate ibd_input(int index)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate 	struct inetgram		*inp;
293*7c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		*eh;
294*7c478bd9Sstevel@tonic-gate 	int		frames = 0;	/* successful frames */
295*7c478bd9Sstevel@tonic-gate 	int		attempts = 0;	/* failed attempts after success */
296*7c478bd9Sstevel@tonic-gate 	int16_t		len = 0, data_len;
297*7c478bd9Sstevel@tonic-gate 	uint32_t	timeout, reltime;
298*7c478bd9Sstevel@tonic-gate 	uint32_t	pre_pr, post_pr; /* prom_read interval */
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
301*7c478bd9Sstevel@tonic-gate 	int		failures = 0;		/* total failures */
302*7c478bd9Sstevel@tonic-gate 	int		total_attempts = 0;	/* total prom_read */
303*7c478bd9Sstevel@tonic-gate 	int		no_data = 0;		/* no data in prom */
304*7c478bd9Sstevel@tonic-gate 	int		arps = 0;		/* arp requests processed */
305*7c478bd9Sstevel@tonic-gate 	uint32_t	tot_pr = 0;		/* prom_read time */
306*7c478bd9Sstevel@tonic-gate 	uint32_t	tot_pc = 0;		/* inetgram creation time */
307*7c478bd9Sstevel@tonic-gate 	uint32_t	pre_pc;
308*7c478bd9Sstevel@tonic-gate 	uint32_t	now;
309*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	if (!initialized)
312*7c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 	if ((reltime = sockets[index].in_timeout) == 0)
315*7c478bd9Sstevel@tonic-gate 		reltime = mac_state.mac_in_timeout;
316*7c478bd9Sstevel@tonic-gate 	timeout = prom_gettime() + reltime;
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	do {
319*7c478bd9Sstevel@tonic-gate 		if (frames > IBD_MAX_FRAMES) {
320*7c478bd9Sstevel@tonic-gate 			/* someone is trying a denial of service attack */
321*7c478bd9Sstevel@tonic-gate 			break;
322*7c478bd9Sstevel@tonic-gate 		}
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 		/*
325*7c478bd9Sstevel@tonic-gate 		 * The following is being paranoid about possible bugs
326*7c478bd9Sstevel@tonic-gate 		 * where prom_read() returns a nonzero length, even when
327*7c478bd9Sstevel@tonic-gate 		 * it's not read a packet; it zeroes out the header to
328*7c478bd9Sstevel@tonic-gate 		 * compensate. Paranoia from calvin prom (V2) days.
329*7c478bd9Sstevel@tonic-gate 		 */
330*7c478bd9Sstevel@tonic-gate 		bzero(mac_state.mac_buf, sizeof (ipoib_ptxhdr_t));
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 		/*
333*7c478bd9Sstevel@tonic-gate 		 * Prom_read() will return 0 or -2 if no data is present. A
334*7c478bd9Sstevel@tonic-gate 		 * return value of -1 means an error has occurred. We adjust
335*7c478bd9Sstevel@tonic-gate 		 * the timeout by calling the time spent in prom_read() "free".
336*7c478bd9Sstevel@tonic-gate 		 * prom_read() returns the number of bytes actually read, but
337*7c478bd9Sstevel@tonic-gate 		 * will only copy "len" bytes into our buffer. Adjust in
338*7c478bd9Sstevel@tonic-gate 		 * case the MTU is wrong.
339*7c478bd9Sstevel@tonic-gate 		 */
340*7c478bd9Sstevel@tonic-gate 		pre_pr = prom_gettime();
341*7c478bd9Sstevel@tonic-gate 		len = prom_read(mac_state.mac_dev, mac_state.mac_buf,
342*7c478bd9Sstevel@tonic-gate 		    mac_state.mac_mtu, 0, NETWORK);
343*7c478bd9Sstevel@tonic-gate 		post_pr = prom_gettime();
344*7c478bd9Sstevel@tonic-gate 		timeout += (post_pr - pre_pr);
345*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
346*7c478bd9Sstevel@tonic-gate 		tot_pr += (post_pr - pre_pr);
347*7c478bd9Sstevel@tonic-gate 		total_attempts++;
348*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 		if (len > mac_state.mac_mtu) {
351*7c478bd9Sstevel@tonic-gate 			dprintf("ibd_input: adjusting MTU %d -> %d\n",
352*7c478bd9Sstevel@tonic-gate 			    mac_state.mac_mtu, len);
353*7c478bd9Sstevel@tonic-gate 			bkmem_free(mac_state.mac_buf, mac_state.mac_mtu);
354*7c478bd9Sstevel@tonic-gate 			mac_state.mac_mtu = len;
355*7c478bd9Sstevel@tonic-gate 			mac_state.mac_buf = bkmem_alloc(mac_state.mac_mtu);
356*7c478bd9Sstevel@tonic-gate 			if (mac_state.mac_buf == NULL) {
357*7c478bd9Sstevel@tonic-gate 				prom_panic("ibd_input: Cannot reallocate "
358*7c478bd9Sstevel@tonic-gate 				    "netbuf memory.");
359*7c478bd9Sstevel@tonic-gate 			}
360*7c478bd9Sstevel@tonic-gate 			len = 0; /* pretend there was no data */
361*7c478bd9Sstevel@tonic-gate 		}
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 		if (len == -1) {
364*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
365*7c478bd9Sstevel@tonic-gate 			failures++;
366*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
367*7c478bd9Sstevel@tonic-gate 			break;
368*7c478bd9Sstevel@tonic-gate 		}
369*7c478bd9Sstevel@tonic-gate 		if (len == 0 || len == -2) {
370*7c478bd9Sstevel@tonic-gate 			if (frames != 0)
371*7c478bd9Sstevel@tonic-gate 				attempts++;
372*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
373*7c478bd9Sstevel@tonic-gate 			no_data++;
374*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
375*7c478bd9Sstevel@tonic-gate 			continue;
376*7c478bd9Sstevel@tonic-gate 		}
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 		eh = (ipoib_ptxhdr_t *)mac_state.mac_buf;
379*7c478bd9Sstevel@tonic-gate 		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_IP) &&
380*7c478bd9Sstevel@tonic-gate 		    len >= (sizeof (ipoib_ptxhdr_t) + sizeof (struct ip))) {
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 			int offset;
383*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
384*7c478bd9Sstevel@tonic-gate 			pre_pc = prom_gettime();
385*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 			inp = (struct inetgram *)bkmem_zalloc(
388*7c478bd9Sstevel@tonic-gate 			    sizeof (struct inetgram));
389*7c478bd9Sstevel@tonic-gate 			if (inp == NULL) {
390*7c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
391*7c478bd9Sstevel@tonic-gate 				return (frames == 0 ? -1 : frames);
392*7c478bd9Sstevel@tonic-gate 			}
393*7c478bd9Sstevel@tonic-gate 			offset = sizeof (ipoib_ptxhdr_t);
394*7c478bd9Sstevel@tonic-gate 			data_len = len - offset;
395*7c478bd9Sstevel@tonic-gate 			inp->igm_mp = allocb(data_len, 0);
396*7c478bd9Sstevel@tonic-gate 			if (inp->igm_mp == NULL) {
397*7c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
398*7c478bd9Sstevel@tonic-gate 				bkmem_free((caddr_t)inp,
399*7c478bd9Sstevel@tonic-gate 				    sizeof (struct inetgram));
400*7c478bd9Sstevel@tonic-gate 				return (frames == 0 ? -1 : frames);
401*7c478bd9Sstevel@tonic-gate 			}
402*7c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)(mac_state.mac_buf + offset),
403*7c478bd9Sstevel@tonic-gate 			    inp->igm_mp->b_rptr, data_len);
404*7c478bd9Sstevel@tonic-gate 			inp->igm_mp->b_wptr += data_len;
405*7c478bd9Sstevel@tonic-gate 			inp->igm_level = NETWORK_LVL;
406*7c478bd9Sstevel@tonic-gate 			add_grams(&sockets[index].inq, inp);
407*7c478bd9Sstevel@tonic-gate 			frames++;
408*7c478bd9Sstevel@tonic-gate 			attempts = 0;
409*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
410*7c478bd9Sstevel@tonic-gate 			tot_pc += prom_gettime() - pre_pc;
411*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
412*7c478bd9Sstevel@tonic-gate 			continue;
413*7c478bd9Sstevel@tonic-gate 		}
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_ARP) &&
416*7c478bd9Sstevel@tonic-gate 		    len >= sizeof (struct arp_packet)) {
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 			struct in_addr		ip;
419*7c478bd9Sstevel@tonic-gate 			struct ibd_arp		*ea;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
422*7c478bd9Sstevel@tonic-gate 			printf("ibd_input: ARP message received\n");
423*7c478bd9Sstevel@tonic-gate 			arps++;
424*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 			ea = (struct ibd_arp *)(mac_state.mac_buf +
427*7c478bd9Sstevel@tonic-gate 			    sizeof (ipoib_ptxhdr_t));
428*7c478bd9Sstevel@tonic-gate 			if (ea->arp_pro != ntohs(ETHERTYPE_IP))
429*7c478bd9Sstevel@tonic-gate 				continue;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 			ipv4_getipaddr(&ip);
432*7c478bd9Sstevel@tonic-gate 			ip.s_addr = ntohl(ip.s_addr);
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 			if (ea->arp_op == ntohs(ARPOP_REQUEST) &&
435*7c478bd9Sstevel@tonic-gate 			    ip.s_addr != INADDR_ANY &&
436*7c478bd9Sstevel@tonic-gate 			    (bcmp((caddr_t)ea->arp_tpa, (caddr_t)&ip,
437*7c478bd9Sstevel@tonic-gate 			    sizeof (struct in_addr)) == 0)) {
438*7c478bd9Sstevel@tonic-gate 				ea->arp_op = htons(ARPOP_REPLY);
439*7c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ea->arp_sha,
440*7c478bd9Sstevel@tonic-gate 				    (caddr_t)&eh->ipoib_dest, IPOIB_ADDRL);
441*7c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ea->arp_sha,
442*7c478bd9Sstevel@tonic-gate 				    (caddr_t)&ea->arp_tha, IPOIB_ADDRL);
443*7c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)ea->arp_spa,
444*7c478bd9Sstevel@tonic-gate 				    (caddr_t)ea->arp_tpa,
445*7c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
446*7c478bd9Sstevel@tonic-gate 				bcopy(mac_state.mac_addr_buf,
447*7c478bd9Sstevel@tonic-gate 				    (caddr_t)&ea->arp_sha,
448*7c478bd9Sstevel@tonic-gate 				    mac_state.mac_addr_len);
449*7c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ip, (caddr_t)ea->arp_spa,
450*7c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
451*7c478bd9Sstevel@tonic-gate 				(void) prom_write(mac_state.mac_dev,
452*7c478bd9Sstevel@tonic-gate 				    mac_state.mac_buf,
453*7c478bd9Sstevel@tonic-gate 				    sizeof (struct arp_packet), 0, NETWORK);
454*7c478bd9Sstevel@tonic-gate 				/* don't charge for ARP replies */
455*7c478bd9Sstevel@tonic-gate 				timeout += reltime;
456*7c478bd9Sstevel@tonic-gate 			}
457*7c478bd9Sstevel@tonic-gate 		}
458*7c478bd9Sstevel@tonic-gate 	} while (attempts < IBD_INPUT_ATTEMPTS &&
459*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
460*7c478bd9Sstevel@tonic-gate 	    (now = prom_gettime()) < timeout);
461*7c478bd9Sstevel@tonic-gate #else
462*7c478bd9Sstevel@tonic-gate 	    prom_gettime() < timeout);
463*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
466*7c478bd9Sstevel@tonic-gate 	printf("ibd_input(%d): T/S/N/A/F/P/M: %d/%d/%d/%d/%d/%d/%d "
467*7c478bd9Sstevel@tonic-gate 	    "T/O: %d < %d = %s\n", index, total_attempts, frames, no_data,
468*7c478bd9Sstevel@tonic-gate 	    arps, failures, tot_pr, tot_pc, now, timeout,
469*7c478bd9Sstevel@tonic-gate 	    (now < timeout) ? "TRUE" : "FALSE");
470*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
471*7c478bd9Sstevel@tonic-gate 	return (frames);
472*7c478bd9Sstevel@tonic-gate }
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate /*
475*7c478bd9Sstevel@tonic-gate  * Send out an IPoIB datagram. We expect a IP frame appropriately fragmented
476*7c478bd9Sstevel@tonic-gate  * at this level.
477*7c478bd9Sstevel@tonic-gate  *
478*7c478bd9Sstevel@tonic-gate  * Errno is set and -1 is returned if an error occurs. Number of bytes sent
479*7c478bd9Sstevel@tonic-gate  * is returned on success.
480*7c478bd9Sstevel@tonic-gate  */
481*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
482*7c478bd9Sstevel@tonic-gate static int
483*7c478bd9Sstevel@tonic-gate ibd_output(int index, struct inetgram *ogp)
484*7c478bd9Sstevel@tonic-gate {
485*7c478bd9Sstevel@tonic-gate 	int			header_len, result;
486*7c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		eh;
487*7c478bd9Sstevel@tonic-gate 	struct ip		*ip;
488*7c478bd9Sstevel@tonic-gate 	struct in_addr		tmpip, ipdst;
489*7c478bd9Sstevel@tonic-gate 	int			broadcast = FALSE;
490*7c478bd9Sstevel@tonic-gate 	int			size;
491*7c478bd9Sstevel@tonic-gate 	mblk_t			*mp;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	if (!initialized)
494*7c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 	if (ogp->igm_level != MEDIA_LVL) {
497*7c478bd9Sstevel@tonic-gate 		dprintf("ibd_output: frame type wrong: socket: %d\n",
498*7c478bd9Sstevel@tonic-gate 		    index * SOCKETTYPE);
499*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
500*7c478bd9Sstevel@tonic-gate 		return (-1);
501*7c478bd9Sstevel@tonic-gate 	}
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	header_len = IPOIB_HDRSIZE + IPOIB_ADDRL;
504*7c478bd9Sstevel@tonic-gate 	mp = ogp->igm_mp;
505*7c478bd9Sstevel@tonic-gate 	size = mp->b_wptr - mp->b_rptr;
506*7c478bd9Sstevel@tonic-gate 	if (size > (mac_state.mac_mtu - IPOIB_ADDRL)) {
507*7c478bd9Sstevel@tonic-gate 		dprintf("ibd_output: frame size too big: %d\n", size);
508*7c478bd9Sstevel@tonic-gate 		errno = E2BIG;
509*7c478bd9Sstevel@tonic-gate 		return (-1);
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	size += header_len;
513*7c478bd9Sstevel@tonic-gate 	ip = (struct ip *)(mp->b_rptr);
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 	eh.ipoib_rhdr.ipoib_type = htons(ETHERTYPE_IP);
516*7c478bd9Sstevel@tonic-gate 	eh.ipoib_rhdr.ipoib_mbz = 0;
517*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ip->ip_dst, (caddr_t)&ipdst, sizeof (ipdst));
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	if (ipdst.s_addr == htonl(INADDR_BROADCAST))
520*7c478bd9Sstevel@tonic-gate 		broadcast = TRUE; /* limited broadcast */
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	if (!broadcast) {
523*7c478bd9Sstevel@tonic-gate 		struct in_addr mask;
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 		ipv4_getnetmask(&mask);
526*7c478bd9Sstevel@tonic-gate 		mask.s_addr = htonl(mask.s_addr);
527*7c478bd9Sstevel@tonic-gate 		if (mask.s_addr != htonl(INADDR_BROADCAST) &&
528*7c478bd9Sstevel@tonic-gate 		    (ipdst.s_addr & ~mask.s_addr) == 0) {
529*7c478bd9Sstevel@tonic-gate 			broadcast = TRUE; /* directed broadcast */
530*7c478bd9Sstevel@tonic-gate 		} else {
531*7c478bd9Sstevel@tonic-gate 			if (ogp->igm_router.s_addr != htonl(INADDR_ANY))
532*7c478bd9Sstevel@tonic-gate 				tmpip.s_addr = ogp->igm_router.s_addr;
533*7c478bd9Sstevel@tonic-gate 			else
534*7c478bd9Sstevel@tonic-gate 				tmpip.s_addr = ipdst.s_addr;
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 			result = mac_get_arp(&tmpip, (void *)&eh.ipoib_dest,
537*7c478bd9Sstevel@tonic-gate 			    IPOIB_ADDRL, mac_state.mac_arp_timeout);
538*7c478bd9Sstevel@tonic-gate 			if (!result) {
539*7c478bd9Sstevel@tonic-gate 				errno = ETIMEDOUT;
540*7c478bd9Sstevel@tonic-gate 				dprintf("ibd_output: ARP request for %s "
541*7c478bd9Sstevel@tonic-gate 				    "timed out.\n", inet_ntoa(tmpip));
542*7c478bd9Sstevel@tonic-gate 				return (-1);
543*7c478bd9Sstevel@tonic-gate 			}
544*7c478bd9Sstevel@tonic-gate 		}
545*7c478bd9Sstevel@tonic-gate 	}
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	if (broadcast)
548*7c478bd9Sstevel@tonic-gate 		bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&eh.ipoib_dest,
549*7c478bd9Sstevel@tonic-gate 		    IPOIB_ADDRL);
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 	/* add the ibd header */
552*7c478bd9Sstevel@tonic-gate 	mp->b_rptr -= sizeof (eh);
553*7c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&eh, mp->b_rptr, sizeof (eh));
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
556*7c478bd9Sstevel@tonic-gate 	printf("ibd_output(%d): level(%d) frame(0x%x) len(%d)\n",
557*7c478bd9Sstevel@tonic-gate 	    index, ogp->igm_level, mp->b_rptr, size);
558*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	return (prom_write(mac_state.mac_dev, (char *)mp->b_rptr, size,
561*7c478bd9Sstevel@tonic-gate 	    0, NETWORK));
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate void
565*7c478bd9Sstevel@tonic-gate ibd_init(void)
566*7c478bd9Sstevel@tonic-gate {
567*7c478bd9Sstevel@tonic-gate 	dnode_t	chosen;
568*7c478bd9Sstevel@tonic-gate 	char	*mtuprop = "ipib-frame-size";
569*7c478bd9Sstevel@tonic-gate 	char	*bcastprop = "ipib-broadcast";
570*7c478bd9Sstevel@tonic-gate 	char	*addrprop = "ipib-address";
571*7c478bd9Sstevel@tonic-gate 	char	*cidprop = "client-id";
572*7c478bd9Sstevel@tonic-gate 	int	cidlen;
573*7c478bd9Sstevel@tonic-gate 	uint8_t	dhcpcid[DHCP_MAX_CID_LEN];
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 	mac_state.mac_addr_len = IPOIB_ADDRL;
576*7c478bd9Sstevel@tonic-gate 	mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len);
577*7c478bd9Sstevel@tonic-gate 	if (mac_state.mac_addr_buf == NULL)
578*7c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot allocate memory.");
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	chosen = prom_finddevice("/chosen");
581*7c478bd9Sstevel@tonic-gate 	if (chosen == OBP_NONODE || chosen == OBP_BADNODE)
582*7c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen.");
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, addrprop, (caddr_t)mac_state.mac_addr_buf) !=
585*7c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL)
586*7c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen:ipib-address\n.");
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, bcastprop, (caddr_t)&ibdbroadcastaddr) !=
589*7c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL)
590*7c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen:ipib-broadcast\n.");
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 	if (((cidlen = prom_getproplen(chosen, cidprop)) <= 0) ||
593*7c478bd9Sstevel@tonic-gate 	    (cidlen > DHCP_MAX_CID_LEN) || (prom_getprop(chosen, cidprop,
594*7c478bd9Sstevel@tonic-gate 	    (caddr_t)&dhcpcid) != cidlen))
595*7c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Invalid /chosen:client-id\n.");
596*7c478bd9Sstevel@tonic-gate 	dhcp_set_client_id(dhcpcid, cidlen);
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	/*
599*7c478bd9Sstevel@tonic-gate 	 * Note that prom reports mtu including 20 bytes of
600*7c478bd9Sstevel@tonic-gate 	 * addressing information.
601*7c478bd9Sstevel@tonic-gate 	 */
602*7c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, mtuprop,
603*7c478bd9Sstevel@tonic-gate 	    (caddr_t)&mac_state.mac_mtu) <= 0)
604*7c478bd9Sstevel@tonic-gate 		mac_state.mac_mtu = IBDSIZE + IPOIB_ADDRL;
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	/*
607*7c478bd9Sstevel@tonic-gate 	 * Tell upper layers that we can support a little
608*7c478bd9Sstevel@tonic-gate 	 * more. We will be taking off these 20 bytes at
609*7c478bd9Sstevel@tonic-gate 	 * the start before we invoke prom_write() to send
610*7c478bd9Sstevel@tonic-gate 	 * over the wire.
611*7c478bd9Sstevel@tonic-gate 	 */
612*7c478bd9Sstevel@tonic-gate 	mac_state.mac_arp_timeout = IBD_ARP_TIMEOUT;
613*7c478bd9Sstevel@tonic-gate 	mac_state.mac_in_timeout = IBD_IN_TIMEOUT;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	mac_state.mac_arp = ibd_arp;
616*7c478bd9Sstevel@tonic-gate 	mac_state.mac_rarp = ibd_revarp;
617*7c478bd9Sstevel@tonic-gate 	mac_state.mac_header_len = ibd_header_len;
618*7c478bd9Sstevel@tonic-gate 	mac_state.mac_input = ibd_input;
619*7c478bd9Sstevel@tonic-gate 	mac_state.mac_output = ibd_output;
620*7c478bd9Sstevel@tonic-gate }
621