aboutsummaryrefslogtreecommitdiffstats
path: root/extras/mini-os/lwip-net.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-01-21 11:20:52 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-01-21 11:20:52 +0000
commit0464a12749f9b868bd681cbd93c3b3227e23ea8a (patch)
tree21a66419dd63914f00f0ea5eaab8c4a168657be1 /extras/mini-os/lwip-net.c
parentafb13d4890c7b505865b8264247c2049fd0c2227 (diff)
downloadxen-0464a12749f9b868bd681cbd93c3b3227e23ea8a.tar.gz
xen-0464a12749f9b868bd681cbd93c3b3227e23ea8a.tar.bz2
xen-0464a12749f9b868bd681cbd93c3b3227e23ea8a.zip
minios: add lwIP 1.3.0 support
Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Diffstat (limited to 'extras/mini-os/lwip-net.c')
-rw-r--r--extras/mini-os/lwip-net.c360
1 files changed, 360 insertions, 0 deletions
diff --git a/extras/mini-os/lwip-net.c b/extras/mini-os/lwip-net.c
new file mode 100644
index 0000000000..1983d23431
--- /dev/null
+++ b/extras/mini-os/lwip-net.c
@@ -0,0 +1,360 @@
+/*
+ * lwip-net.c
+ *
+ * interface between lwIP's ethernet and Mini-os's netfront.
+ * For now, support only one network interface, as mini-os does.
+ *
+ * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007
+ * based on lwIP's ethernetif.c skeleton file, copyrights as below.
+ */
+
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#include <os.h>
+
+#include "lwip/opt.h"
+#include "lwip/def.h"
+#include "lwip/mem.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+
+#include <lwip/stats.h>
+#include <lwip/sys.h>
+#include <lwip/mem.h>
+#include <lwip/memp.h>
+#include <lwip/pbuf.h>
+#include <netif/etharp.h>
+#include <lwip/tcpip.h>
+#include <lwip/tcp.h>
+#include <lwip/netif.h>
+#include <lwip/dhcp.h>
+
+#include "netif/etharp.h"
+
+#include <netfront.h>
+
+/* Define those to better describe your network interface. */
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+#define IF_IPADDR 0x00000000
+#define IF_NETMASK 0x00000000
+
+/* Only have one network interface at a time. */
+static struct netif *the_interface = NULL;
+
+static unsigned char rawmac[6];
+static struct netfront_dev *dev;
+
+/* Forward declarations. */
+static err_t netfront_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr);
+
+/*
+ * low_level_output():
+ *
+ * Should do the actual transmission of the packet. The packet is
+ * contained in the pbuf that is passed to the function. This pbuf
+ * might be chained.
+ *
+ */
+
+static err_t
+low_level_output(struct netif *netif, struct pbuf *p)
+{
+#ifdef ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* Send the data from the pbuf to the interface, one pbuf at a
+ time. The size of the data in each pbuf is kept in the ->len
+ variable. */
+ if (!p->next) {
+ /* Only one fragment, can send it directly */
+ netfront_xmit(dev, p->payload, p->len);
+ } else {
+ unsigned char data[p->tot_len], *cur;
+ struct pbuf *q;
+
+ for(q = p, cur = data; q != NULL; cur += q->len, q = q->next)
+ memcpy(cur, q->payload, q->len);
+ netfront_xmit(dev, data, p->tot_len);
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.xmit);
+
+ return ERR_OK;
+}
+
+
+
+/*
+ * netfront_output():
+ *
+ * This function is called by the TCP/IP stack when an IP packet
+ * should be sent. It calls the function called low_level_output() to
+ * do the actual transmission of the packet.
+ *
+ */
+
+static err_t
+netfront_output(struct netif *netif, struct pbuf *p,
+ struct ip_addr *ipaddr)
+{
+
+ /* resolve hardware address, then send (or queue) packet */
+ return etharp_output(netif, p, ipaddr);
+
+}
+
+/*
+ * netfront_input():
+ *
+ * This function should be called when a packet is ready to be read
+ * from the interface.
+ *
+ */
+
+static void
+netfront_input(struct netif *netif, unsigned char* data, int len)
+{
+ struct eth_hdr *ethhdr;
+ struct pbuf *p, *q;
+
+#if ETH_PAD_SIZE
+ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
+#endif
+
+ /* move received packet into a new pbuf */
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p == NULL) {
+ LINK_STATS_INC(link.memerr);
+ LINK_STATS_INC(link.drop);
+ return;
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
+#endif
+
+ /* We iterate over the pbuf chain until we have read the entire
+ * packet into the pbuf. */
+ for(q = p; q != NULL && len > 0; q = q->next) {
+ /* Read enough bytes to fill this pbuf in the chain. The
+ * available data in the pbuf is given by the q->len
+ * variable. */
+ memcpy(q->payload, data, len < q->len ? len : q->len);
+ data += q->len;
+ len -= q->len;
+ }
+
+#if ETH_PAD_SIZE
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
+#endif
+
+ LINK_STATS_INC(link.recv);
+
+ /* points to packet payload, which starts with an Ethernet header */
+ ethhdr = p->payload;
+
+ ethhdr = p->payload;
+
+ switch (htons(ethhdr->type)) {
+ /* IP packet? */
+ case ETHTYPE_IP:
+#if 0
+/* CSi disabled ARP table update on ingress IP packets.
+ This seems to work but needs thorough testing. */
+ /* update ARP table */
+ etharp_ip_input(netif, p);
+#endif
+ /* skip Ethernet header */
+ pbuf_header(p, -(s16)sizeof(struct eth_hdr));
+ /* pass to network layer */
+ tcpip_input(p, netif);
+ break;
+
+ case ETHTYPE_ARP:
+ /* pass p to ARP module */
+ etharp_arp_input(netif, (struct eth_addr *) netif->hwaddr, p);
+ break;
+ default:
+ pbuf_free(p);
+ p = NULL;
+ break;
+ }
+}
+
+
+/*
+ * netif_rx(): overrides the default netif_rx behaviour in the netfront driver.
+ *
+ * Pull received packets into a pbuf queue for the low_level_input()
+ * function to pass up to lwIP.
+ */
+
+void netif_rx(unsigned char* data, int len)
+{
+ if (the_interface != NULL) {
+ netfront_input(the_interface, data, len);
+ wake_up(&netfront_queue);
+ }
+ /* By returning, we ack the packet and relinquish the RX ring slot */
+}
+
+/*
+ * Set the IP, mask and gateway of the IF
+ */
+void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw)
+{
+ netif_set_ipaddr(the_interface, ipaddr);
+ netif_set_netmask(the_interface, netmask);
+ netif_set_gw(the_interface, gw);
+}
+
+
+static void
+arp_timer(void *arg)
+{
+ etharp_tmr();
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+}
+
+/*
+ * netif_netfront_init():
+ *
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ */
+
+err_t
+netif_netfront_init(struct netif *netif)
+{
+ unsigned char *mac = netif->state;
+
+#if LWIP_SNMP
+ /* ifType ethernetCsmacd(6) @see RFC1213 */
+ netif->link_type = 6;
+ /* your link speed here */
+ netif->link_speed = ;
+ netif->ts = 0;
+ netif->ifinoctets = 0;
+ netif->ifinucastpkts = 0;
+ netif->ifinnucastpkts = 0;
+ netif->ifindiscards = 0;
+ netif->ifoutoctets = 0;
+ netif->ifoutucastpkts = 0;
+ netif->ifoutnucastpkts = 0;
+ netif->ifoutdiscards = 0;
+#endif
+
+ netif->name[0] = IFNAME0;
+ netif->name[1] = IFNAME1;
+ netif->output = netfront_output;
+ netif->linkoutput = low_level_output;
+
+ the_interface = netif;
+
+ /* set MAC hardware address */
+ netif->hwaddr_len = 6;
+ netif->hwaddr[0] = mac[0];
+ netif->hwaddr[1] = mac[1];
+ netif->hwaddr[2] = mac[2];
+ netif->hwaddr[3] = mac[3];
+ netif->hwaddr[4] = mac[4];
+ netif->hwaddr[5] = mac[5];
+
+ /* No interesting per-interface state */
+ netif->state = NULL;
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* broadcast capability */
+ netif->flags = NETIF_FLAG_BROADCAST;
+
+ etharp_init();
+
+ sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
+
+ return ERR_OK;
+}
+
+/*
+ * Thread run by netfront: bring up the IP address and fire lwIP timers.
+ */
+static __DECLARE_SEMAPHORE_GENERIC(tcpip_is_up, 0);
+static void tcpip_bringup_finished(void *p)
+{
+ tprintk("TCP/IP bringup ends.\n");
+ up(&tcpip_is_up);
+}
+
+/*
+ * Utility function to bring the whole lot up. Call this from app_main()
+ * or similar -- it starts netfront and have lwIP start its thread,
+ * which calls back to tcpip_bringup_finished(), which
+ * lets us know it's OK to continue.
+ */
+void start_networking(void)
+{
+ struct netif *netif;
+ struct ip_addr ipaddr = { htonl(IF_IPADDR) };
+ struct ip_addr netmask = { htonl(IF_NETMASK) };
+ struct ip_addr gw = { 0 };
+
+ tprintk("Waiting for network.\n");
+
+ dev = init_netfront(NULL, NULL, rawmac);
+
+ tprintk("TCP/IP bringup begins.\n");
+
+ netif = xmalloc(struct netif);
+ tcpip_init(tcpip_bringup_finished, netif);
+
+ netif_add(netif, &ipaddr, &netmask, &gw, rawmac,
+ netif_netfront_init, ip_input);
+ netif_set_default(netif);
+ netif_set_up(netif);
+
+ down(&tcpip_is_up);
+
+ tprintk("Network is ready.\n");
+}