ia64/xen-unstable

view extras/mini-os/lwip-net.c @ 19557:226ef307cd2e

AMD IOMMU: Fix ioapic interrupt remapping

A few ioapic redirection entries are initialized by hypervisor before
enabling iommu hardware. This patch copies those entries from ioapic
redirection table into interrupt remapping table after interrupt
remapping table has been allocated.

Signed-off-by: Wei Wang <wei.wang2@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Apr 17 13:16:39 2009 +0100 (2009-04-17)
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 }