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 * 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 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 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 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 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 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 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 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