* same with xv6
[mascara-docs.git] / i386 / MIT / course / src / git.lab / net / lwip / jos / jif / jif.c
blob54f89ab548ee83f9b9f5b55dcc63c536a08e5af5
1 /*
2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25 * OF SUCH DAMAGE.
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
33 #include <inc/lib.h>
34 #include <inc/ns.h>
36 #include <jif/jif.h>
38 #include "lwip/opt.h"
39 #include "lwip/def.h"
40 #include "lwip/mem.h"
41 #include "lwip/pbuf.h"
42 #include "lwip/sys.h"
43 #include <lwip/stats.h>
45 #include <netif/etharp.h>
47 #define PKTMAP 0x10000000
49 struct jif {
50 struct eth_addr *ethaddr;
51 envid_t envid;
54 static void
55 low_level_init(struct netif *netif)
57 int r;
59 netif->hwaddr_len = 6;
60 netif->mtu = 1500;
61 netif->flags = NETIF_FLAG_BROADCAST;
63 // MAC address is hardcoded to eliminate a system call
64 netif->hwaddr[0] = 0x52;
65 netif->hwaddr[1] = 0x54;
66 netif->hwaddr[2] = 0x00;
67 netif->hwaddr[3] = 0x12;
68 netif->hwaddr[4] = 0x34;
69 netif->hwaddr[5] = 0x56;
73 * low_level_output():
75 * Should do the actual transmission of the packet. The packet is
76 * contained in the pbuf that is passed to the function. This pbuf
77 * might be chained.
80 static err_t
81 low_level_output(struct netif *netif, struct pbuf *p)
83 int r = sys_page_alloc(0, (void *)PKTMAP, PTE_U|PTE_W|PTE_P);
84 if (r < 0)
85 panic("jif: could not allocate page of memory");
86 struct jif_pkt *pkt = (struct jif_pkt *)PKTMAP;
88 struct jif *jif;
89 jif = netif->state;
91 char *txbuf = pkt->jp_data;
92 int txsize = 0;
93 struct pbuf *q;
94 for (q = p; q != NULL; q = q->next) {
95 /* Send the data from the pbuf to the interface, one pbuf at a
96 time. The size of the data in each pbuf is kept in the ->len
97 variable. */
99 if (txsize + q->len > 2000)
100 panic("oversized packet, fragment %d txsize %d\n", q->len, txsize);
101 memcpy(&txbuf[txsize], q->payload, q->len);
102 txsize += q->len;
105 pkt->jp_len = txsize;
107 ipc_send(jif->envid, NSREQ_OUTPUT, (void *)pkt, PTE_P|PTE_W|PTE_U);
108 sys_page_unmap(0, (void *)pkt);
110 return ERR_OK;
114 * low_level_input():
116 * Should allocate a pbuf and transfer the bytes of the incoming
117 * packet from the interface into the pbuf.
120 static struct pbuf *
121 low_level_input(void *va)
123 struct jif_pkt *pkt = (struct jif_pkt *)va;
124 s16_t len = pkt->jp_len;
126 struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
127 if (p == 0)
128 return 0;
130 /* We iterate over the pbuf chain until we have read the entire
131 * packet into the pbuf. */
132 void *rxbuf = (void *) pkt->jp_data;
133 int copied = 0;
134 struct pbuf *q;
135 for (q = p; q != NULL; q = q->next) {
136 /* Read enough bytes to fill this pbuf in the chain. The
137 * available data in the pbuf is given by the q->len
138 * variable. */
139 int bytes = q->len;
140 if (bytes > (len - copied))
141 bytes = len - copied;
142 memcpy(q->payload, rxbuf + copied, bytes);
143 copied += bytes;
146 return p;
149 * jif_output():
151 * This function is called by the TCP/IP stack when an IP packet
152 * should be sent. It calls the function called low_level_output() to
153 * do the actual transmission of the packet.
157 static err_t
158 jif_output(struct netif *netif, struct pbuf *p,
159 struct ip_addr *ipaddr)
161 /* resolve hardware address, then send (or queue) packet */
162 return etharp_output(netif, p, ipaddr);
166 * jif_input():
168 * This function should be called when a packet is ready to be read
169 * from the interface. It uses the function low_level_input() that
170 * should handle the actual reception of bytes from the network
171 * interface.
175 void
176 jif_input(struct netif *netif, void *va)
178 struct jif *jif;
179 struct eth_hdr *ethhdr;
180 struct pbuf *p;
182 jif = netif->state;
184 /* move received packet into a new pbuf */
185 p = low_level_input(va);
187 /* no packet could be read, silently ignore this */
188 if (p == NULL) return;
189 /* points to packet payload, which starts with an Ethernet header */
190 ethhdr = p->payload;
192 switch (htons(ethhdr->type)) {
193 case ETHTYPE_IP:
194 /* update ARP table */
195 etharp_ip_input(netif, p);
196 /* skip Ethernet header */
197 pbuf_header(p, -(int)sizeof(struct eth_hdr));
198 /* pass to network layer */
199 netif->input(p, netif);
200 break;
202 case ETHTYPE_ARP:
203 /* pass p to ARP module */
204 etharp_arp_input(netif, jif->ethaddr, p);
205 break;
207 default:
208 pbuf_free(p);
213 * jif_init():
215 * Should be called at the beginning of the program to set up the
216 * network interface. It calls the function low_level_init() to do the
217 * actual setup of the hardware.
221 err_t
222 jif_init(struct netif *netif)
224 struct jif *jif;
225 envid_t *output_envid;
227 jif = mem_malloc(sizeof(struct jif));
229 if (jif == NULL) {
230 LWIP_DEBUGF(NETIF_DEBUG, ("jif_init: out of memory\n"));
231 return ERR_MEM;
234 output_envid = (envid_t *)netif->state;
236 netif->state = jif;
237 netif->output = jif_output;
238 netif->linkoutput = low_level_output;
239 memcpy(&netif->name[0], "en", 2);
241 jif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
242 jif->envid = *output_envid;
244 low_level_init(netif);
246 etharp_init();
248 // qemu user-net is dumb; if the host OS does not send and ARP request
249 // first, the qemu will send packets destined for the host using the mac
250 // addr 00:00:00:00:00; do a arp request for the user-net NAT at 10.0.2.2
251 uint32_t ipaddr = inet_addr("10.0.2.2");
252 etharp_query(netif, (struct ip_addr *) &ipaddr, 0);
254 return ERR_OK;