xref: /illumos-gate/usr/src/stand/lib/inet/ibd.c (revision fa9e4066)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*fa9e4066Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <dhcp_impl.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <socket_impl.h>
327c478bd9Sstevel@tonic-gate #include <socket_inet.h>
337c478bd9Sstevel@tonic-gate #include <sys/time.h>
347c478bd9Sstevel@tonic-gate #include <sys/socket.h>
357c478bd9Sstevel@tonic-gate #include <net/if.h>
367c478bd9Sstevel@tonic-gate #include <net/if_arp.h>
377c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
407c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h>
417c478bd9Sstevel@tonic-gate #include <sys/promif.h>
427c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h>
437c478bd9Sstevel@tonic-gate #include <sys/salib.h>
447c478bd9Sstevel@tonic-gate #include <sys/bootdebug.h>
457c478bd9Sstevel@tonic-gate #include <sys/ib/clients/ibd/ibd.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include "ipv4.h"
487c478bd9Sstevel@tonic-gate #include "dhcpv4.h"
497c478bd9Sstevel@tonic-gate #include "ipv4_impl.h"
507c478bd9Sstevel@tonic-gate #include "mac.h"
517c478bd9Sstevel@tonic-gate #include "mac_impl.h"
527c478bd9Sstevel@tonic-gate #include "ibd_inet.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate struct ibd_arp {
557c478bd9Sstevel@tonic-gate 	struct arphdr	ea_hdr;		/* fixed-size header */
567c478bd9Sstevel@tonic-gate 	ipoib_mac_t	arp_sha;	/* sender hardware address */
577c478bd9Sstevel@tonic-gate 	uchar_t		arp_spa[4];	/* sender protocol address */
587c478bd9Sstevel@tonic-gate 	ipoib_mac_t	arp_tha;	/* target hardware address */
597c478bd9Sstevel@tonic-gate 	uchar_t		arp_tpa[4];	/* target protocol address */
607c478bd9Sstevel@tonic-gate };
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate extern int errno;
637c478bd9Sstevel@tonic-gate ipoib_mac_t ibdbroadcastaddr;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * Assumptions about OBP behavior (refer FWARC 2002/702, 2003/251):
677c478bd9Sstevel@tonic-gate  * 1. prom_write() accepts the 20 byte destination address as the
687c478bd9Sstevel@tonic-gate  * first component in the send buffer. The buffer pointer points
697c478bd9Sstevel@tonic-gate  * to the start of this 20 byte address. The length parameter is
707c478bd9Sstevel@tonic-gate  * the IPoIB datagram size with the 20 byte of destination
717c478bd9Sstevel@tonic-gate  * address.
727c478bd9Sstevel@tonic-gate  * 2. OBP will not provide max-frame-size, since obp can only
737c478bd9Sstevel@tonic-gate  * determine that by querying the IBA mcg, and thus the property
747c478bd9Sstevel@tonic-gate  * has to be /chosen:ipib-frame-size. This will refer to the IPoIB
757c478bd9Sstevel@tonic-gate  * link MTU as per section 4.0 of ietf i/d, ie, the 4 byte IPoIB
767c478bd9Sstevel@tonic-gate  * header plus the IP payload mtu. Plus the 20 bytes of addressing
777c478bd9Sstevel@tonic-gate  * information.
787c478bd9Sstevel@tonic-gate  * 3. OBP will not provide mac-address property for IPoIB since there
797c478bd9Sstevel@tonic-gate  * are built in assumptions about 6 byte address with that. Instead,
807c478bd9Sstevel@tonic-gate  * /chosen:ipib-address will provide the local address.
817c478bd9Sstevel@tonic-gate  * 4. prom_read() returns 20 byte 0'ed filler followed by 4 byte
827c478bd9Sstevel@tonic-gate  * IPoIB header followed by IP payload. The return value is -2,
837c478bd9Sstevel@tonic-gate  * -1, 0, or the length of the received IPoIB datagram alongwith
847c478bd9Sstevel@tonic-gate  * the 20 bytes MBZ. The buffer pointer points to the start of
857c478bd9Sstevel@tonic-gate  * the 20 MBZ bytes. The length parameter reflects the max data
867c478bd9Sstevel@tonic-gate  * size that should be copied into the buffer including the 20
877c478bd9Sstevel@tonic-gate  * MBZ bytes.
887c478bd9Sstevel@tonic-gate  * 5. OBP will not provide chosen-network-type, only
897c478bd9Sstevel@tonic-gate  * network-interface-type = ipib. On an Infiniband device, this
907c478bd9Sstevel@tonic-gate  * however does not guarantee that it is a network device.
917c478bd9Sstevel@tonic-gate  * 6. OBP will provide the DHCP client id in /chosen:client-id.
927c478bd9Sstevel@tonic-gate  * 7. /chosen:ipib-broadcast will provide the broadcast address.
937c478bd9Sstevel@tonic-gate  * 8. OBP will validate that RARP is not being used before
947c478bd9Sstevel@tonic-gate  * allowing boot to proceed to inetboot.
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate struct arp_packet {
987c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		arp_eh;
997c478bd9Sstevel@tonic-gate 	struct ibd_arp		arp_ea;
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate #define	dprintf	if (boothowto & RB_DEBUG) printf
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate static char *
ibd_print(ipoib_mac_t * ea)1057c478bd9Sstevel@tonic-gate ibd_print(ipoib_mac_t *ea)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	unsigned char *macaddr = (unsigned char *)ea;
1087c478bd9Sstevel@tonic-gate 	static char pbuf[(3 * IPOIB_ADDRL) + 1];
1097c478bd9Sstevel@tonic-gate 	int i;
1107c478bd9Sstevel@tonic-gate 	char *ptr = pbuf;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	ptr = pbuf + sprintf(pbuf, "%x", *macaddr++);
1137c478bd9Sstevel@tonic-gate 	for (i = 0; i < (IPOIB_ADDRL - 1); i++)
1147c478bd9Sstevel@tonic-gate 		ptr += sprintf(ptr, ":%x", *macaddr++);
1157c478bd9Sstevel@tonic-gate 	return (pbuf);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * Common ARP code. Broadcast the packet and wait for the right response.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  * If arp is called for, caller expects a hardware address in the
1237c478bd9Sstevel@tonic-gate  * source hardware address (sha) field of the "out" argument.
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  * IPoIB does not support RARP (see ibd_revarp()).
1267c478bd9Sstevel@tonic-gate  *
1277c478bd9Sstevel@tonic-gate  * Returns TRUE if transaction succeeded, FALSE otherwise.
1287c478bd9Sstevel@tonic-gate  *
1297c478bd9Sstevel@tonic-gate  * The timeout argument is the number of milliseconds to wait for a
1307c478bd9Sstevel@tonic-gate  * response. An infinite timeout can be specified as 0xffffffff.
1317c478bd9Sstevel@tonic-gate  */
1327c478bd9Sstevel@tonic-gate static int
ibd_comarp(struct arp_packet * out,uint32_t timeout)1337c478bd9Sstevel@tonic-gate ibd_comarp(struct arp_packet *out, uint32_t timeout)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate 	struct arp_packet *in = (struct arp_packet *)mac_state.mac_buf;
1367c478bd9Sstevel@tonic-gate 	int count, time, feedback, len, delay = 2;
1377c478bd9Sstevel@tonic-gate 	char    *ind = "-\\|/";
1387c478bd9Sstevel@tonic-gate 	struct in_addr tmp_ia;
1397c478bd9Sstevel@tonic-gate 	uint32_t wait_time;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&out->arp_eh.ipoib_dest,
1427c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_hrd =  htons(ARPHRD_IB);
1457c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_pro = htons(ETHERTYPE_IP);
1467c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_hln = IPOIB_ADDRL;
1477c478bd9Sstevel@tonic-gate 	out->arp_ea.arp_pln = sizeof (struct in_addr);
1487c478bd9Sstevel@tonic-gate 	bcopy(mac_state.mac_addr_buf, (caddr_t)&out->arp_ea.arp_sha,
1497c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
1507c478bd9Sstevel@tonic-gate 	ipv4_getipaddr(&tmp_ia);
1517c478bd9Sstevel@tonic-gate 	tmp_ia.s_addr = htonl(tmp_ia.s_addr);
1527c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&tmp_ia, (caddr_t)out->arp_ea.arp_spa,
1537c478bd9Sstevel@tonic-gate 	    sizeof (struct in_addr));
1547c478bd9Sstevel@tonic-gate 	feedback = 0;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	wait_time = prom_gettime() + timeout;
1577c478bd9Sstevel@tonic-gate 	for (count = 0; timeout == ~0U || prom_gettime() < wait_time; count++) {
1587c478bd9Sstevel@tonic-gate 		if (count == IBD_WAITCNT) {
1597c478bd9Sstevel@tonic-gate 			/*
1607c478bd9Sstevel@tonic-gate 			 * Since IPoIB does not support RARP (see ibd_revarp),
1617c478bd9Sstevel@tonic-gate 			 * we know that out->arp_ea.arp_op == ARPOP_REQUEST.
1627c478bd9Sstevel@tonic-gate 			 */
1637c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)out->arp_ea.arp_tpa,
1647c478bd9Sstevel@tonic-gate 			    (caddr_t)&tmp_ia, sizeof (struct in_addr));
1657c478bd9Sstevel@tonic-gate 			printf("\nRequesting MAC address for: %s\n",
1667c478bd9Sstevel@tonic-gate 			    inet_ntoa(tmp_ia));
1677c478bd9Sstevel@tonic-gate 		}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 		(void) prom_write(mac_state.mac_dev, (caddr_t)out,
1707c478bd9Sstevel@tonic-gate 		    sizeof (*out), 0, NETWORK);
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 		if (count >= IBD_WAITCNT)
1737c478bd9Sstevel@tonic-gate 			printf("%c\b", ind[feedback++ % 4]); /* activity */
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 		time = prom_gettime() + (delay * 1000);	/* broadcast delay */
1767c478bd9Sstevel@tonic-gate 		while (prom_gettime() <= time) {
1777c478bd9Sstevel@tonic-gate 			len = prom_read(mac_state.mac_dev, mac_state.mac_buf,
1787c478bd9Sstevel@tonic-gate 			    mac_state.mac_mtu, 0, NETWORK);
1797c478bd9Sstevel@tonic-gate 			if (len < sizeof (struct arp_packet))
1807c478bd9Sstevel@tonic-gate 				continue;
1817c478bd9Sstevel@tonic-gate 			if (in->arp_ea.arp_pro != ntohs(ETHERTYPE_IP))
1827c478bd9Sstevel@tonic-gate 				continue;
1837c478bd9Sstevel@tonic-gate 			/*
1847c478bd9Sstevel@tonic-gate 			 * Since IPoIB does not support RARP (see ibd_revarp),
1857c478bd9Sstevel@tonic-gate 			 * we know that out->arp_ea.arp_op == ARPOP_REQUEST.
1867c478bd9Sstevel@tonic-gate 			 */
1877c478bd9Sstevel@tonic-gate 			if (in->arp_eh.ipoib_rhdr.ipoib_type !=
1887c478bd9Sstevel@tonic-gate 			    ntohs(ETHERTYPE_ARP))
1897c478bd9Sstevel@tonic-gate 				continue;
1907c478bd9Sstevel@tonic-gate 			if (in->arp_ea.arp_op != ntohs(ARPOP_REPLY))
1917c478bd9Sstevel@tonic-gate 				continue;
1927c478bd9Sstevel@tonic-gate 			if (bcmp((caddr_t)in->arp_ea.arp_spa,
1937c478bd9Sstevel@tonic-gate 			    (caddr_t)out->arp_ea.arp_tpa,
1947c478bd9Sstevel@tonic-gate 			    sizeof (struct in_addr)) != 0)
1957c478bd9Sstevel@tonic-gate 				continue;
1967c478bd9Sstevel@tonic-gate 			if (boothowto & RB_VERBOSE) {
1977c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)in->arp_ea.arp_spa,
1987c478bd9Sstevel@tonic-gate 				    (caddr_t)&tmp_ia,
1997c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
2007c478bd9Sstevel@tonic-gate 				printf("Found %s @ %s\n",
2017c478bd9Sstevel@tonic-gate 				    inet_ntoa(tmp_ia),
2027c478bd9Sstevel@tonic-gate 				    ibd_print(&in->arp_ea.arp_sha));
2037c478bd9Sstevel@tonic-gate 			}
2047c478bd9Sstevel@tonic-gate 			/* copy hardware addr into "out" for caller */
2057c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)&in->arp_ea.arp_sha,
2067c478bd9Sstevel@tonic-gate 			    (caddr_t)&out->arp_ea.arp_sha, IPOIB_ADDRL);
2077c478bd9Sstevel@tonic-gate 			return (TRUE);
2087c478bd9Sstevel@tonic-gate 		}
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 		delay = delay * 2;	/* Double the request delay */
2117c478bd9Sstevel@tonic-gate 		if (delay > 64)		/* maximum delay is 64 seconds */
2127c478bd9Sstevel@tonic-gate 			delay = 64;
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 	return (FALSE);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate  * ARP client side
2197c478bd9Sstevel@tonic-gate  * Broadcasts to determine MAC address given network order IP address.
2207c478bd9Sstevel@tonic-gate  * See RFC 826
2217c478bd9Sstevel@tonic-gate  *
2227c478bd9Sstevel@tonic-gate  * Returns TRUE if successful, FALSE otherwise.
2237c478bd9Sstevel@tonic-gate  */
2247c478bd9Sstevel@tonic-gate static int
ibd_arp(struct in_addr * ip,void * hap,uint32_t timeout)2257c478bd9Sstevel@tonic-gate ibd_arp(struct in_addr *ip, void *hap, uint32_t timeout)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	ipoib_mac_t *ep = (ipoib_mac_t *)hap;
2287c478bd9Sstevel@tonic-gate 	struct arp_packet out;
2297c478bd9Sstevel@tonic-gate 	int result;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (!initialized)
2327c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	bzero((char *)&out, sizeof (struct arp_packet));
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	out.arp_eh.ipoib_rhdr.ipoib_type = htons(ETHERTYPE_ARP);
2377c478bd9Sstevel@tonic-gate 	out.arp_ea.arp_op = htons(ARPOP_REQUEST);
2387c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&out.arp_ea.arp_tha,
2397c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL);
2407c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)ip, (caddr_t)out.arp_ea.arp_tpa,
2417c478bd9Sstevel@tonic-gate 	    sizeof (struct in_addr));
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	result = ibd_comarp(&out, timeout);
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (result && (ep != NULL)) {
2467c478bd9Sstevel@tonic-gate 		bcopy((caddr_t)&out.arp_ea.arp_sha, (caddr_t)ep, IPOIB_ADDRL);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	return (result);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * Reverse ARP client side
2537c478bd9Sstevel@tonic-gate  * Determine our Internet address given our MAC address
2547c478bd9Sstevel@tonic-gate  * See RFC 903
2557c478bd9Sstevel@tonic-gate  */
2567c478bd9Sstevel@tonic-gate static void
ibd_revarp(void)2577c478bd9Sstevel@tonic-gate ibd_revarp(void)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	prom_panic("IPoIB can not boot with RARP.");
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /* ARGSUSED */
2637c478bd9Sstevel@tonic-gate static int
ibd_header_len(struct inetgram * igm)2647c478bd9Sstevel@tonic-gate ibd_header_len(struct inetgram *igm)
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate 	/*
2677c478bd9Sstevel@tonic-gate 	 * We indicate to upper layers to leave enough space
2687c478bd9Sstevel@tonic-gate 	 * in output buffers for filling in the IPoIB header
2697c478bd9Sstevel@tonic-gate 	 * and the 20 byte destination address in ibd_output().
2707c478bd9Sstevel@tonic-gate 	 */
2717c478bd9Sstevel@tonic-gate 	return (IPOIB_HDRSIZE + IPOIB_ADDRL);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate  * Handle a IP datagram addressed to our MAC address or to the link
2767c478bd9Sstevel@tonic-gate  * layer broadcast address. Also respond to ARP requests. Generates
2777c478bd9Sstevel@tonic-gate  * inetgrams as long as there's data and the mac level IP timeout timer
2787c478bd9Sstevel@tonic-gate  * hasn't expired. As soon as there is no data, we try for
2797c478bd9Sstevel@tonic-gate  * IBD_INPUT_ATTEMPTS for more, then exit the loop, even if there is time
2807c478bd9Sstevel@tonic-gate  * left, since we expect to have data waiting for us when we're called, we just
2817c478bd9Sstevel@tonic-gate  * don't know how much.
2827c478bd9Sstevel@tonic-gate  *
2837c478bd9Sstevel@tonic-gate  * We workaround slow proms (some proms have hard sleeps for as much as 3msec)
2847c478bd9Sstevel@tonic-gate  * even though there are is data waiting.
2857c478bd9Sstevel@tonic-gate  *
2867c478bd9Sstevel@tonic-gate  * Returns the total number of MEDIA_LVL frames placed on the socket.
2877c478bd9Sstevel@tonic-gate  * Caller is expected to free up the inetgram resources.
2887c478bd9Sstevel@tonic-gate  */
2897c478bd9Sstevel@tonic-gate static int
ibd_input(int index)2907c478bd9Sstevel@tonic-gate ibd_input(int index)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	struct inetgram		*inp;
2937c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		*eh;
2947c478bd9Sstevel@tonic-gate 	int		frames = 0;	/* successful frames */
2957c478bd9Sstevel@tonic-gate 	int		attempts = 0;	/* failed attempts after success */
2967c478bd9Sstevel@tonic-gate 	int16_t		len = 0, data_len;
2977c478bd9Sstevel@tonic-gate 	uint32_t	timeout, reltime;
2987c478bd9Sstevel@tonic-gate 	uint32_t	pre_pr, post_pr; /* prom_read interval */
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3017c478bd9Sstevel@tonic-gate 	int		failures = 0;		/* total failures */
3027c478bd9Sstevel@tonic-gate 	int		total_attempts = 0;	/* total prom_read */
3037c478bd9Sstevel@tonic-gate 	int		no_data = 0;		/* no data in prom */
3047c478bd9Sstevel@tonic-gate 	int		arps = 0;		/* arp requests processed */
3057c478bd9Sstevel@tonic-gate 	uint32_t	tot_pr = 0;		/* prom_read time */
3067c478bd9Sstevel@tonic-gate 	uint32_t	tot_pc = 0;		/* inetgram creation time */
3077c478bd9Sstevel@tonic-gate 	uint32_t	pre_pc;
3087c478bd9Sstevel@tonic-gate 	uint32_t	now;
3097c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if (!initialized)
3127c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if ((reltime = sockets[index].in_timeout) == 0)
3157c478bd9Sstevel@tonic-gate 		reltime = mac_state.mac_in_timeout;
3167c478bd9Sstevel@tonic-gate 	timeout = prom_gettime() + reltime;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	do {
3197c478bd9Sstevel@tonic-gate 		if (frames > IBD_MAX_FRAMES) {
3207c478bd9Sstevel@tonic-gate 			/* someone is trying a denial of service attack */
3217c478bd9Sstevel@tonic-gate 			break;
3227c478bd9Sstevel@tonic-gate 		}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		/*
3257c478bd9Sstevel@tonic-gate 		 * The following is being paranoid about possible bugs
3267c478bd9Sstevel@tonic-gate 		 * where prom_read() returns a nonzero length, even when
3277c478bd9Sstevel@tonic-gate 		 * it's not read a packet; it zeroes out the header to
3287c478bd9Sstevel@tonic-gate 		 * compensate. Paranoia from calvin prom (V2) days.
3297c478bd9Sstevel@tonic-gate 		 */
3307c478bd9Sstevel@tonic-gate 		bzero(mac_state.mac_buf, sizeof (ipoib_ptxhdr_t));
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 		/*
3337c478bd9Sstevel@tonic-gate 		 * Prom_read() will return 0 or -2 if no data is present. A
3347c478bd9Sstevel@tonic-gate 		 * return value of -1 means an error has occurred. We adjust
3357c478bd9Sstevel@tonic-gate 		 * the timeout by calling the time spent in prom_read() "free".
3367c478bd9Sstevel@tonic-gate 		 * prom_read() returns the number of bytes actually read, but
3377c478bd9Sstevel@tonic-gate 		 * will only copy "len" bytes into our buffer. Adjust in
3387c478bd9Sstevel@tonic-gate 		 * case the MTU is wrong.
3397c478bd9Sstevel@tonic-gate 		 */
3407c478bd9Sstevel@tonic-gate 		pre_pr = prom_gettime();
3417c478bd9Sstevel@tonic-gate 		len = prom_read(mac_state.mac_dev, mac_state.mac_buf,
3427c478bd9Sstevel@tonic-gate 		    mac_state.mac_mtu, 0, NETWORK);
3437c478bd9Sstevel@tonic-gate 		post_pr = prom_gettime();
3447c478bd9Sstevel@tonic-gate 		timeout += (post_pr - pre_pr);
3457c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3467c478bd9Sstevel@tonic-gate 		tot_pr += (post_pr - pre_pr);
3477c478bd9Sstevel@tonic-gate 		total_attempts++;
3487c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 		if (len > mac_state.mac_mtu) {
3517c478bd9Sstevel@tonic-gate 			dprintf("ibd_input: adjusting MTU %d -> %d\n",
3527c478bd9Sstevel@tonic-gate 			    mac_state.mac_mtu, len);
3537c478bd9Sstevel@tonic-gate 			bkmem_free(mac_state.mac_buf, mac_state.mac_mtu);
3547c478bd9Sstevel@tonic-gate 			mac_state.mac_mtu = len;
3557c478bd9Sstevel@tonic-gate 			mac_state.mac_buf = bkmem_alloc(mac_state.mac_mtu);
3567c478bd9Sstevel@tonic-gate 			if (mac_state.mac_buf == NULL) {
3577c478bd9Sstevel@tonic-gate 				prom_panic("ibd_input: Cannot reallocate "
3587c478bd9Sstevel@tonic-gate 				    "netbuf memory.");
3597c478bd9Sstevel@tonic-gate 			}
3607c478bd9Sstevel@tonic-gate 			len = 0; /* pretend there was no data */
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 		if (len == -1) {
3647c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3657c478bd9Sstevel@tonic-gate 			failures++;
3667c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3677c478bd9Sstevel@tonic-gate 			break;
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 		if (len == 0 || len == -2) {
3707c478bd9Sstevel@tonic-gate 			if (frames != 0)
3717c478bd9Sstevel@tonic-gate 				attempts++;
3727c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3737c478bd9Sstevel@tonic-gate 			no_data++;
3747c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3757c478bd9Sstevel@tonic-gate 			continue;
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 		eh = (ipoib_ptxhdr_t *)mac_state.mac_buf;
3797c478bd9Sstevel@tonic-gate 		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_IP) &&
3807c478bd9Sstevel@tonic-gate 		    len >= (sizeof (ipoib_ptxhdr_t) + sizeof (struct ip))) {
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 			int offset;
3837c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3847c478bd9Sstevel@tonic-gate 			pre_pc = prom_gettime();
3857c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 			inp = (struct inetgram *)bkmem_zalloc(
3887c478bd9Sstevel@tonic-gate 			    sizeof (struct inetgram));
3897c478bd9Sstevel@tonic-gate 			if (inp == NULL) {
3907c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
3917c478bd9Sstevel@tonic-gate 				return (frames == 0 ? -1 : frames);
3927c478bd9Sstevel@tonic-gate 			}
3937c478bd9Sstevel@tonic-gate 			offset = sizeof (ipoib_ptxhdr_t);
3947c478bd9Sstevel@tonic-gate 			data_len = len - offset;
3957c478bd9Sstevel@tonic-gate 			inp->igm_mp = allocb(data_len, 0);
3967c478bd9Sstevel@tonic-gate 			if (inp->igm_mp == NULL) {
3977c478bd9Sstevel@tonic-gate 				errno = ENOMEM;
3987c478bd9Sstevel@tonic-gate 				bkmem_free((caddr_t)inp,
3997c478bd9Sstevel@tonic-gate 				    sizeof (struct inetgram));
4007c478bd9Sstevel@tonic-gate 				return (frames == 0 ? -1 : frames);
4017c478bd9Sstevel@tonic-gate 			}
4027c478bd9Sstevel@tonic-gate 			bcopy((caddr_t)(mac_state.mac_buf + offset),
4037c478bd9Sstevel@tonic-gate 			    inp->igm_mp->b_rptr, data_len);
4047c478bd9Sstevel@tonic-gate 			inp->igm_mp->b_wptr += data_len;
4057c478bd9Sstevel@tonic-gate 			inp->igm_level = NETWORK_LVL;
4067c478bd9Sstevel@tonic-gate 			add_grams(&sockets[index].inq, inp);
4077c478bd9Sstevel@tonic-gate 			frames++;
4087c478bd9Sstevel@tonic-gate 			attempts = 0;
4097c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4107c478bd9Sstevel@tonic-gate 			tot_pc += prom_gettime() - pre_pc;
4117c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4127c478bd9Sstevel@tonic-gate 			continue;
4137c478bd9Sstevel@tonic-gate 		}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		if (eh->ipoib_rhdr.ipoib_type == ntohs(ETHERTYPE_ARP) &&
4167c478bd9Sstevel@tonic-gate 		    len >= sizeof (struct arp_packet)) {
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 			struct in_addr		ip;
4197c478bd9Sstevel@tonic-gate 			struct ibd_arp		*ea;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4227c478bd9Sstevel@tonic-gate 			printf("ibd_input: ARP message received\n");
4237c478bd9Sstevel@tonic-gate 			arps++;
4247c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 			ea = (struct ibd_arp *)(mac_state.mac_buf +
4277c478bd9Sstevel@tonic-gate 			    sizeof (ipoib_ptxhdr_t));
4287c478bd9Sstevel@tonic-gate 			if (ea->arp_pro != ntohs(ETHERTYPE_IP))
4297c478bd9Sstevel@tonic-gate 				continue;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 			ipv4_getipaddr(&ip);
4327c478bd9Sstevel@tonic-gate 			ip.s_addr = ntohl(ip.s_addr);
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 			if (ea->arp_op == ntohs(ARPOP_REQUEST) &&
4357c478bd9Sstevel@tonic-gate 			    ip.s_addr != INADDR_ANY &&
4367c478bd9Sstevel@tonic-gate 			    (bcmp((caddr_t)ea->arp_tpa, (caddr_t)&ip,
4377c478bd9Sstevel@tonic-gate 			    sizeof (struct in_addr)) == 0)) {
4387c478bd9Sstevel@tonic-gate 				ea->arp_op = htons(ARPOP_REPLY);
4397c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ea->arp_sha,
4407c478bd9Sstevel@tonic-gate 				    (caddr_t)&eh->ipoib_dest, IPOIB_ADDRL);
4417c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ea->arp_sha,
4427c478bd9Sstevel@tonic-gate 				    (caddr_t)&ea->arp_tha, IPOIB_ADDRL);
4437c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)ea->arp_spa,
4447c478bd9Sstevel@tonic-gate 				    (caddr_t)ea->arp_tpa,
4457c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
4467c478bd9Sstevel@tonic-gate 				bcopy(mac_state.mac_addr_buf,
4477c478bd9Sstevel@tonic-gate 				    (caddr_t)&ea->arp_sha,
4487c478bd9Sstevel@tonic-gate 				    mac_state.mac_addr_len);
4497c478bd9Sstevel@tonic-gate 				bcopy((caddr_t)&ip, (caddr_t)ea->arp_spa,
4507c478bd9Sstevel@tonic-gate 				    sizeof (struct in_addr));
4517c478bd9Sstevel@tonic-gate 				(void) prom_write(mac_state.mac_dev,
4527c478bd9Sstevel@tonic-gate 				    mac_state.mac_buf,
4537c478bd9Sstevel@tonic-gate 				    sizeof (struct arp_packet), 0, NETWORK);
4547c478bd9Sstevel@tonic-gate 				/* don't charge for ARP replies */
4557c478bd9Sstevel@tonic-gate 				timeout += reltime;
4567c478bd9Sstevel@tonic-gate 			}
4577c478bd9Sstevel@tonic-gate 		}
4587c478bd9Sstevel@tonic-gate 	} while (attempts < IBD_INPUT_ATTEMPTS &&
4597c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4607c478bd9Sstevel@tonic-gate 	    (now = prom_gettime()) < timeout);
4617c478bd9Sstevel@tonic-gate #else
4627c478bd9Sstevel@tonic-gate 	    prom_gettime() < timeout);
4637c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4667c478bd9Sstevel@tonic-gate 	printf("ibd_input(%d): T/S/N/A/F/P/M: %d/%d/%d/%d/%d/%d/%d "
4677c478bd9Sstevel@tonic-gate 	    "T/O: %d < %d = %s\n", index, total_attempts, frames, no_data,
4687c478bd9Sstevel@tonic-gate 	    arps, failures, tot_pr, tot_pc, now, timeout,
4697c478bd9Sstevel@tonic-gate 	    (now < timeout) ? "TRUE" : "FALSE");
4707c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4717c478bd9Sstevel@tonic-gate 	return (frames);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /*
4757c478bd9Sstevel@tonic-gate  * Send out an IPoIB datagram. We expect a IP frame appropriately fragmented
4767c478bd9Sstevel@tonic-gate  * at this level.
4777c478bd9Sstevel@tonic-gate  *
4787c478bd9Sstevel@tonic-gate  * Errno is set and -1 is returned if an error occurs. Number of bytes sent
4797c478bd9Sstevel@tonic-gate  * is returned on success.
4807c478bd9Sstevel@tonic-gate  */
4817c478bd9Sstevel@tonic-gate /* ARGSUSED */
4827c478bd9Sstevel@tonic-gate static int
ibd_output(int index,struct inetgram * ogp)4837c478bd9Sstevel@tonic-gate ibd_output(int index, struct inetgram *ogp)
4847c478bd9Sstevel@tonic-gate {
4857c478bd9Sstevel@tonic-gate 	int			header_len, result;
4867c478bd9Sstevel@tonic-gate 	ipoib_ptxhdr_t		eh;
4877c478bd9Sstevel@tonic-gate 	struct ip		*ip;
4887c478bd9Sstevel@tonic-gate 	struct in_addr		tmpip, ipdst;
4897c478bd9Sstevel@tonic-gate 	int			broadcast = FALSE;
4907c478bd9Sstevel@tonic-gate 	int			size;
4917c478bd9Sstevel@tonic-gate 	mblk_t			*mp;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	if (!initialized)
4947c478bd9Sstevel@tonic-gate 		prom_panic("IPoIB device is not initialized.");
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (ogp->igm_level != MEDIA_LVL) {
4977c478bd9Sstevel@tonic-gate 		dprintf("ibd_output: frame type wrong: socket: %d\n",
4987c478bd9Sstevel@tonic-gate 		    index * SOCKETTYPE);
4997c478bd9Sstevel@tonic-gate 		errno = EINVAL;
5007c478bd9Sstevel@tonic-gate 		return (-1);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	header_len = IPOIB_HDRSIZE + IPOIB_ADDRL;
5047c478bd9Sstevel@tonic-gate 	mp = ogp->igm_mp;
5057c478bd9Sstevel@tonic-gate 	size = mp->b_wptr - mp->b_rptr;
5067c478bd9Sstevel@tonic-gate 	if (size > (mac_state.mac_mtu - IPOIB_ADDRL)) {
5077c478bd9Sstevel@tonic-gate 		dprintf("ibd_output: frame size too big: %d\n", size);
5087c478bd9Sstevel@tonic-gate 		errno = E2BIG;
5097c478bd9Sstevel@tonic-gate 		return (-1);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	size += header_len;
5137c478bd9Sstevel@tonic-gate 	ip = (struct ip *)(mp->b_rptr);
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	eh.ipoib_rhdr.ipoib_type = htons(ETHERTYPE_IP);
5167c478bd9Sstevel@tonic-gate 	eh.ipoib_rhdr.ipoib_mbz = 0;
5177c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&ip->ip_dst, (caddr_t)&ipdst, sizeof (ipdst));
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (ipdst.s_addr == htonl(INADDR_BROADCAST))
5207c478bd9Sstevel@tonic-gate 		broadcast = TRUE; /* limited broadcast */
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (!broadcast) {
5237c478bd9Sstevel@tonic-gate 		struct in_addr mask;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 		ipv4_getnetmask(&mask);
5267c478bd9Sstevel@tonic-gate 		mask.s_addr = htonl(mask.s_addr);
5277c478bd9Sstevel@tonic-gate 		if (mask.s_addr != htonl(INADDR_BROADCAST) &&
5287c478bd9Sstevel@tonic-gate 		    (ipdst.s_addr & ~mask.s_addr) == 0) {
5297c478bd9Sstevel@tonic-gate 			broadcast = TRUE; /* directed broadcast */
5307c478bd9Sstevel@tonic-gate 		} else {
5317c478bd9Sstevel@tonic-gate 			if (ogp->igm_router.s_addr != htonl(INADDR_ANY))
5327c478bd9Sstevel@tonic-gate 				tmpip.s_addr = ogp->igm_router.s_addr;
5337c478bd9Sstevel@tonic-gate 			else
5347c478bd9Sstevel@tonic-gate 				tmpip.s_addr = ipdst.s_addr;
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 			result = mac_get_arp(&tmpip, (void *)&eh.ipoib_dest,
5377c478bd9Sstevel@tonic-gate 			    IPOIB_ADDRL, mac_state.mac_arp_timeout);
5387c478bd9Sstevel@tonic-gate 			if (!result) {
5397c478bd9Sstevel@tonic-gate 				errno = ETIMEDOUT;
5407c478bd9Sstevel@tonic-gate 				dprintf("ibd_output: ARP request for %s "
5417c478bd9Sstevel@tonic-gate 				    "timed out.\n", inet_ntoa(tmpip));
5427c478bd9Sstevel@tonic-gate 				return (-1);
5437c478bd9Sstevel@tonic-gate 			}
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	if (broadcast)
5487c478bd9Sstevel@tonic-gate 		bcopy((caddr_t)&ibdbroadcastaddr, (caddr_t)&eh.ipoib_dest,
5497c478bd9Sstevel@tonic-gate 		    IPOIB_ADDRL);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	/* add the ibd header */
5527c478bd9Sstevel@tonic-gate 	mp->b_rptr -= sizeof (eh);
5537c478bd9Sstevel@tonic-gate 	bcopy((caddr_t)&eh, mp->b_rptr, sizeof (eh));
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5567c478bd9Sstevel@tonic-gate 	printf("ibd_output(%d): level(%d) frame(0x%x) len(%d)\n",
5577c478bd9Sstevel@tonic-gate 	    index, ogp->igm_level, mp->b_rptr, size);
5587c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	return (prom_write(mac_state.mac_dev, (char *)mp->b_rptr, size,
5617c478bd9Sstevel@tonic-gate 	    0, NETWORK));
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate void
ibd_init(void)5657c478bd9Sstevel@tonic-gate ibd_init(void)
5667c478bd9Sstevel@tonic-gate {
567*fa9e4066Sahrens 	pnode_t	chosen;
5687c478bd9Sstevel@tonic-gate 	char	*mtuprop = "ipib-frame-size";
5697c478bd9Sstevel@tonic-gate 	char	*bcastprop = "ipib-broadcast";
5707c478bd9Sstevel@tonic-gate 	char	*addrprop = "ipib-address";
5717c478bd9Sstevel@tonic-gate 	char	*cidprop = "client-id";
5727c478bd9Sstevel@tonic-gate 	int	cidlen;
5737c478bd9Sstevel@tonic-gate 	uint8_t	dhcpcid[DHCP_MAX_CID_LEN];
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	mac_state.mac_addr_len = IPOIB_ADDRL;
5767c478bd9Sstevel@tonic-gate 	mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len);
5777c478bd9Sstevel@tonic-gate 	if (mac_state.mac_addr_buf == NULL)
5787c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot allocate memory.");
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	chosen = prom_finddevice("/chosen");
5817c478bd9Sstevel@tonic-gate 	if (chosen == OBP_NONODE || chosen == OBP_BADNODE)
5827c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen.");
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, addrprop, (caddr_t)mac_state.mac_addr_buf) !=
5857c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL)
5867c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen:ipib-address\n.");
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, bcastprop, (caddr_t)&ibdbroadcastaddr) !=
5897c478bd9Sstevel@tonic-gate 	    IPOIB_ADDRL)
5907c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Cannot find /chosen:ipib-broadcast\n.");
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if (((cidlen = prom_getproplen(chosen, cidprop)) <= 0) ||
5937c478bd9Sstevel@tonic-gate 	    (cidlen > DHCP_MAX_CID_LEN) || (prom_getprop(chosen, cidprop,
5947c478bd9Sstevel@tonic-gate 	    (caddr_t)&dhcpcid) != cidlen))
5957c478bd9Sstevel@tonic-gate 		prom_panic("ibd_init: Invalid /chosen:client-id\n.");
5967c478bd9Sstevel@tonic-gate 	dhcp_set_client_id(dhcpcid, cidlen);
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/*
5997c478bd9Sstevel@tonic-gate 	 * Note that prom reports mtu including 20 bytes of
6007c478bd9Sstevel@tonic-gate 	 * addressing information.
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 	if (prom_getprop(chosen, mtuprop,
6037c478bd9Sstevel@tonic-gate 	    (caddr_t)&mac_state.mac_mtu) <= 0)
6047c478bd9Sstevel@tonic-gate 		mac_state.mac_mtu = IBDSIZE + IPOIB_ADDRL;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/*
6077c478bd9Sstevel@tonic-gate 	 * Tell upper layers that we can support a little
6087c478bd9Sstevel@tonic-gate 	 * more. We will be taking off these 20 bytes at
6097c478bd9Sstevel@tonic-gate 	 * the start before we invoke prom_write() to send
6107c478bd9Sstevel@tonic-gate 	 * over the wire.
6117c478bd9Sstevel@tonic-gate 	 */
6127c478bd9Sstevel@tonic-gate 	mac_state.mac_arp_timeout = IBD_ARP_TIMEOUT;
6137c478bd9Sstevel@tonic-gate 	mac_state.mac_in_timeout = IBD_IN_TIMEOUT;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	mac_state.mac_arp = ibd_arp;
6167c478bd9Sstevel@tonic-gate 	mac_state.mac_rarp = ibd_revarp;
6177c478bd9Sstevel@tonic-gate 	mac_state.mac_header_len = ibd_header_len;
6187c478bd9Sstevel@tonic-gate 	mac_state.mac_input = ibd_input;
6197c478bd9Sstevel@tonic-gate 	mac_state.mac_output = ibd_output;
6207c478bd9Sstevel@tonic-gate }
621