ia64/xen-unstable

view extras/mini-os/lwip-net.c @ 18811:390ef36eb596

Remove Xen-private definitions from kexec public header.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 19 13:13:39 2008 +0000 (2008-11-19)
parents 433d1b26fd51
children
line source
1 /*
2 * lwip-net.c
3 *
4 * interface between lwIP's ethernet and Mini-os's netfront.
5 * For now, support only one network interface, as mini-os does.
6 *
7 * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
8 * based on lwIP's ethernetif.c skeleton file, copyrights as below.
9 */
12 /*
13 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without modification,
17 * are permitted provided that the following conditions are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright notice,
20 * this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 * 3. The name of the author may not be used to endorse or promote products
25 * derived from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
30 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
32 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36 * OF SUCH DAMAGE.
37 *
38 * This file is part of the lwIP TCP/IP stack.
39 *
40 * Author: Adam Dunkels <adam@sics.se>
41 *
42 */
44 #include <os.h>
46 #include "lwip/opt.h"
47 #include "lwip/def.h"
48 #include "lwip/mem.h"
49 #include "lwip/pbuf.h"
50 #include "lwip/sys.h"
52 #include <lwip/stats.h>
53 #include <lwip/sys.h>
54 #include <lwip/mem.h>
55 #include <lwip/memp.h>
56 #include <lwip/pbuf.h>
57 #include <netif/etharp.h>
58 #include <lwip/tcpip.h>
59 #include <lwip/tcp.h>
60 #include <lwip/netif.h>
61 #include <lwip/dhcp.h>
63 #include "netif/etharp.h"
65 #include <netfront.h>
67 /* Define those to better describe your network interface. */
68 #define IFNAME0 'e'
69 #define IFNAME1 'n'
71 #define IF_IPADDR 0x00000000
72 #define IF_NETMASK 0x00000000
74 /* Only have one network interface at a time. */
75 static struct netif *the_interface = NULL;
77 static unsigned char rawmac[6];
78 static struct netfront_dev *dev;
80 /* Forward declarations. */
81 static err_t netfront_output(struct netif *netif, struct pbuf *p,
82 struct ip_addr *ipaddr);
84 /*
85 * low_level_output():
86 *
87 * Should do the actual transmission of the packet. The packet is
88 * contained in the pbuf that is passed to the function. This pbuf
89 * might be chained.
90 *
91 */
93 static err_t
94 low_level_output(struct netif *netif, struct pbuf *p)
95 {
96 if (!dev)
97 return ERR_OK;
99 #ifdef ETH_PAD_SIZE
100 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
101 #endif
103 /* Send the data from the pbuf to the interface, one pbuf at a
104 time. The size of the data in each pbuf is kept in the ->len
105 variable. */
106 if (!p->next) {
107 /* Only one fragment, can send it directly */
108 netfront_xmit(dev, p->payload, p->len);
109 } else {
110 unsigned char data[p->tot_len], *cur;
111 struct pbuf *q;
113 for(q = p, cur = data; q != NULL; cur += q->len, q = q->next)
114 memcpy(cur, q->payload, q->len);
115 netfront_xmit(dev, data, p->tot_len);
116 }
118 #if ETH_PAD_SIZE
119 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
120 #endif
122 LINK_STATS_INC(link.xmit);
124 return ERR_OK;
125 }
129 /*
130 * netfront_output():
131 *
132 * This function is called by the TCP/IP stack when an IP packet
133 * should be sent. It calls the function called low_level_output() to
134 * do the actual transmission of the packet.
135 *
136 */
138 static err_t
139 netfront_output(struct netif *netif, struct pbuf *p,
140 struct ip_addr *ipaddr)
141 {
143 /* resolve hardware address, then send (or queue) packet */
144 return etharp_output(netif, p, ipaddr);
146 }
148 /*
149 * netfront_input():
150 *
151 * This function should be called when a packet is ready to be read
152 * from the interface.
153 *
154 */
156 static void
157 netfront_input(struct netif *netif, unsigned char* data, int len)
158 {
159 struct eth_hdr *ethhdr;
160 struct pbuf *p, *q;
162 #if ETH_PAD_SIZE
163 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
164 #endif
166 /* move received packet into a new pbuf */
167 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
168 if (p == NULL) {
169 LINK_STATS_INC(link.memerr);
170 LINK_STATS_INC(link.drop);
171 return;
172 }
174 #if ETH_PAD_SIZE
175 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
176 #endif
178 /* We iterate over the pbuf chain until we have read the entire
179 * packet into the pbuf. */
180 for(q = p; q != NULL && len > 0; q = q->next) {
181 /* Read enough bytes to fill this pbuf in the chain. The
182 * available data in the pbuf is given by the q->len
183 * variable. */
184 memcpy(q->payload, data, len < q->len ? len : q->len);
185 data += q->len;
186 len -= q->len;
187 }
189 #if ETH_PAD_SIZE
190 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
191 #endif
193 LINK_STATS_INC(link.recv);
195 /* points to packet payload, which starts with an Ethernet header */
196 ethhdr = p->payload;
198 ethhdr = p->payload;
200 switch (htons(ethhdr->type)) {
201 /* IP packet? */
202 case ETHTYPE_IP:
203 #if 0
204 /* CSi disabled ARP table update on ingress IP packets.
205 This seems to work but needs thorough testing. */
206 /* update ARP table */
207 etharp_ip_input(netif, p);
208 #endif
209 /* skip Ethernet header */
210 pbuf_header(p, -(s16)sizeof(struct eth_hdr));
211 /* pass to network layer */
212 if (tcpip_input(p, netif) == ERR_MEM)
213 /* Could not store it, drop */
214 pbuf_free(p);
215 break;
217 case ETHTYPE_ARP:
218 /* pass p to ARP module */
219 etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
220 break;
222 default:
223 pbuf_free(p);
224 p = NULL;
225 break;
226 }
227 }
230 /*
231 * netif_rx(): overrides the default netif_rx behaviour in the netfront driver.
232 *
233 * Pull received packets into a pbuf queue for the low_level_input()
234 * function to pass up to lwIP.
235 */
237 void netif_rx(unsigned char* data, int len)
238 {
239 if (the_interface != NULL) {
240 netfront_input(the_interface, data, len);
241 wake_up(&netfront_queue);
242 }
243 /* By returning, we ack the packet and relinquish the RX ring slot */
244 }
246 /*
247 * Set the IP, mask and gateway of the IF
248 */
249 void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw)
250 {
251 netif_set_ipaddr(the_interface, ipaddr);
252 netif_set_netmask(the_interface, netmask);
253 netif_set_gw(the_interface, gw);
254 }
257 static void
258 arp_timer(void *arg)
259 {
260 etharp_tmr();
261 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
262 }
264 /*
265 * netif_netfront_init():
266 *
267 * Should be called at the beginning of the program to set up the
268 * network interface. It calls the function low_level_init() to do the
269 * actual setup of the hardware.
270 *
271 */
273 err_t
274 netif_netfront_init(struct netif *netif)
275 {
276 unsigned char *mac = netif->state;
278 #if LWIP_SNMP
279 /* ifType ethernetCsmacd(6) @see RFC1213 */
280 netif->link_type = 6;
281 /* your link speed here */
282 netif->link_speed = ;
283 netif->ts = 0;
284 netif->ifinoctets = 0;
285 netif->ifinucastpkts = 0;
286 netif->ifinnucastpkts = 0;
287 netif->ifindiscards = 0;
288 netif->ifoutoctets = 0;
289 netif->ifoutucastpkts = 0;
290 netif->ifoutnucastpkts = 0;
291 netif->ifoutdiscards = 0;
292 #endif
294 netif->name[0] = IFNAME0;
295 netif->name[1] = IFNAME1;
296 netif->output = netfront_output;
297 netif->linkoutput = low_level_output;
299 the_interface = netif;
301 /* set MAC hardware address */
302 netif->hwaddr_len = 6;
303 netif->hwaddr[0] = mac[0];
304 netif->hwaddr[1] = mac[1];
305 netif->hwaddr[2] = mac[2];
306 netif->hwaddr[3] = mac[3];
307 netif->hwaddr[4] = mac[4];
308 netif->hwaddr[5] = mac[5];
310 /* No interesting per-interface state */
311 netif->state = NULL;
313 /* maximum transfer unit */
314 netif->mtu = 1500;
316 /* broadcast capability */
317 netif->flags = NETIF_FLAG_BROADCAST;
319 etharp_init();
321 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
323 return ERR_OK;
324 }
326 /*
327 * Thread run by netfront: bring up the IP address and fire lwIP timers.
328 */
329 static __DECLARE_SEMAPHORE_GENERIC(tcpip_is_up, 0);
330 static void tcpip_bringup_finished(void *p)
331 {
332 tprintk("TCP/IP bringup ends.\n");
333 up(&tcpip_is_up);
334 }
336 /*
337 * Utility function to bring the whole lot up. Call this from app_main()
338 * or similar -- it starts netfront and have lwIP start its thread,
339 * which calls back to tcpip_bringup_finished(), which
340 * lets us know it's OK to continue.
341 */
342 void start_networking(void)
343 {
344 struct netif *netif;
345 struct ip_addr ipaddr = { htonl(IF_IPADDR) };
346 struct ip_addr netmask = { htonl(IF_NETMASK) };
347 struct ip_addr gw = { 0 };
348 char *ip = NULL;
350 tprintk("Waiting for network.\n");
352 dev = init_netfront(NULL, NULL, rawmac, &ip);
354 if (ip) {
355 ipaddr.addr = inet_addr(ip);
356 if (IN_CLASSA(ntohl(ipaddr.addr)))
357 netmask.addr = htonl(IN_CLASSA_NET);
358 else if (IN_CLASSB(ntohl(ipaddr.addr)))
359 netmask.addr = htonl(IN_CLASSB_NET);
360 else if (IN_CLASSC(ntohl(ipaddr.addr)))
361 netmask.addr = htonl(IN_CLASSC_NET);
362 else
363 tprintk("Strange IP %s, leaving netmask to 0.\n", ip);
364 }
365 tprintk("IP %x netmask %x gateway %x.\n",
366 ntohl(ipaddr.addr), ntohl(netmask.addr), ntohl(gw.addr));
368 tprintk("TCP/IP bringup begins.\n");
370 netif = xmalloc(struct netif);
371 tcpip_init(tcpip_bringup_finished, netif);
373 netif_add(netif, &ipaddr, &netmask, &gw, rawmac,
374 netif_netfront_init, ip_input);
375 netif_set_default(netif);
376 netif_set_up(netif);
378 down(&tcpip_is_up);
380 tprintk("Network is ready.\n");
381 }
383 /* Shut down the network */
384 void stop_networking(void)
385 {
386 if (dev)
387 shutdown_netfront(dev);
388 }