minios: add lwIP 1.3.0 support This is to be applied on top of the POSIX-time patch only in patch2: unchanged: --- a/extras/mini-os/Makefile Fri Jan 18 16:43:44 2008 +0000 +++ b/extras/mini-os/Makefile Fri Jan 18 18:18:12 2008 +0000 @@ -47,6 +47,13 @@ EXTRA_INC # This must be before include minios.mk! include $(TARGET_ARCH_DIR)/arch.mk +ifneq ($(LWIPDIR),) +lwip=y +DEF_CFLAGS += -DHAVE_LWIP +DEF_CFLAGS += -I$(LWIPDIR)/src/include +DEF_CFLAGS += -I$(LWIPDIR)/src/include/ipv4 +endif + # Include common mini-os makerules. include minios.mk @@ -90,6 +97,24 @@ arch_lib: arch_lib: $(MAKE) --directory=$(TARGET_ARCH_DIR) || exit 1; +ifeq ($(lwip),y) +# lwIP library +LWC := $(shell find $(LWIPDIR)/ -type f -name ''*.c'') +LWC := $(filter-out %6.c %ip6_addr.c %ethernetif.c, $(LWC)) +LWC += lwip-arch.c lwip-net.c +LWO := $(patsubst %.c,%.o,$(LWC)) + +lwip.a: $(LWO) + $(RM) $@ + $(AR) cqs $@ $^ + +OBJS += lwip.a + +OBJS := $(filter-out $(LWO), $(OBJS)) +else +OBJS := $(filter-out daytime.o lwip%.o, $(OBJS)) +endif + $(TARGET): links $(OBJS) arch_lib $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o @@ -107,6 +132,7 @@ clean: arch_clean done rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz find . -type l | xargs rm -f + $(RM) lwip.a $(LWO) rm -f tags TAGS only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/daytime.c Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,64 @@ +/* + * daytime.c: a simple network service based on lwIP and mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#include <os.h> +#include <xmalloc.h> +#include <console.h> +#include <netfront.h> +#include <lwip/api.h> + +static char message[29]; + +void run_server(void *p) +{ + struct ip_addr listenaddr = { 0 }; + struct ip_addr ipaddr = { htonl(0x0a000001) }; + struct ip_addr netmask = { htonl(0xff000000) }; + struct ip_addr gw = { 0 }; + struct netconn *listener; + struct netconn *session; + struct timeval tv; + err_t rc; + + start_networking(); + networking_set_addr(&ipaddr, &netmask, &gw); + + tprintk("Opening connection\n"); + + listener = netconn_new(NETCONN_TCP); + tprintk("Connection at %p\n", listener); + + rc = netconn_bind(listener, &listenaddr, 13); + if (rc != ERR_OK) { + tprintk("Failed to bind connection: %i\n", rc); + return; + } + + rc = netconn_listen(listener); + if (rc != ERR_OK) { + tprintk("Failed to listen on connection: %i\n", rc); + return; + } + + while (1) { + session = netconn_accept(listener); + if (session == NULL) + continue; + + gettimeofday(&tv, NULL); + sprintf(message, "%20lu.%6.6lu\n", tv.tv_sec, tv.tv_usec); + (void) netconn_write(session, message, strlen(message), NETCONN_COPY); + (void) netconn_disconnect(session); + (void) netconn_delete(session); + } +} + + +int app_main(start_info_t *si) +{ + create_thread("server", run_server, NULL); + return 0; +} only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/arch/cc.h Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,83 @@ +/* + * lwip/arch/cc.h + * + * Compiler-specific types and macros for lwIP running on mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#ifndef __LWIP_ARCH_CC_H__ +#define __LWIP_ARCH_CC_H__ + +/* Typedefs for the types used by lwip - */ +#include <os.h> +#include <types.h> +#include <time.h> +typedef u8 u8_t; +typedef s8 s8_t; +typedef u16 u16_t; +typedef s16 s16_t; +typedef u32 u32_t; +typedef s32 s32_t; +typedef u64 u64_t; +typedef s64 s64_t; +typedef uintptr_t mem_ptr_t; + +typedef u16 u_short; + +/* Compiler hints for packing lwip''s structures - */ +#define PACK_STRUCT_FIELD(_x) _x +#define PACK_STRUCT_STRUCT __attribute__ ((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +/* Platform specific diagnostic output - */ + +extern void lwip_printk(char *fmt, ...); +#define LWIP_PLATFORM_DIAG(_x) do { lwip_printk _x ; } while (0) + +extern void lwip_die(char *fmt, ...); +#define LWIP_PLATFORM_ASSERT(_x) do { lwip_die(_x); } while(0) + +/* "lightweight" synchronization mechanisms - */ +/* SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. */ +/* SYS_ARCH_PROTECT(x) - enter protection mode. */ +/* SYS_ARCH_UNPROTECT(x) - leave protection mode. */ + +/* If the compiler does not provide memset() this file must include a */ +/* definition of it, or include a file which defines it. */ +#include <lib.h> + +/* This file must either include a system-local <errno.h> which defines */ +/* the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO */ +/* to make lwip/arch.h define the codes which are used throughout. */ +#include <errno.h> + +/* Not required by the docs, but needed for network-order calculations */ +#include <endian.h> + +#include <inttypes.h> +#define S16_F PRIi16 +#define U16_F PRIu16 +#define X16_F PRIx16 +#define S32_F PRIi32 +#define U32_F PRIu32 +#define X32_F PRIx32 + +#if 0 +#ifndef DBG_ON +#define DBG_ON LWIP_DBG_ON +#endif +#define LWIP_DEBUG DBG_ON +//#define IP_DEBUG DBG_ON +#define TCP_DEBUG DBG_ON +#define TCP_INPUT_DEBUG DBG_ON +#define TCP_QLEN_DEBUG DBG_ON +#define TCPIP_DEBUG DBG_ON +#define DBG_TYPES_ON DBG_ON +#endif + +/* TODO: checksum doesn''t work fine?! */ +#define CHECKSUM_CHECK_TCP 0 + +#endif /* __LWIP_ARCH_CC_H__ */ only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/arch/perf.h Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,15 @@ +/* + * lwip/arch/perf.h + * + * Arch-specific performance measurement for lwIP running on mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#ifndef __LWIP_ARCH_PERF_H__ +#define __LWIP_ARCH_PERF_H__ + +#define PERF_START do { } while(0) +#define PERF_STOP(_x) do { (void)(_x); } while (0) + +#endif /* __LWIP_ARCH_PERF_H__ */ only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/arch/sys_arch.h Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,35 @@ +/* + * lwip/arch/sys_arch.h + * + * Arch-specific semaphores and mailboxes for lwIP running on mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#ifndef __LWIP_ARCH_SYS_ARCH_H__ +#define __LWIP_ARCH_SYS_ARCH_H__ + +#include <os.h> +#include <xmalloc.h> +#include <semaphore.h> + +typedef struct semaphore *sys_sem_t; +#define SYS_SEM_NULL ((sys_sem_t) NULL) + +struct mbox { + int count; + void **messages; + struct semaphore read_sem; + struct semaphore write_sem; + int writer; + int reader; +}; + +typedef struct mbox *sys_mbox_t; +#define SYS_MBOX_NULL ((sys_mbox_t) 0) + +typedef struct thread *sys_thread_t; + +typedef unsigned long sys_prot_t; + +#endif /*__LWIP_ARCH_SYS_ARCH_H__ */ only in patch2: unchanged: --- a/extras/mini-os/include/console.h Fri Jan 18 16:43:44 2008 +0000 +++ b/extras/mini-os/include/console.h Fri Jan 18 18:18:12 2008 +0000 @@ -38,8 +38,11 @@ #include<traps.h> +void print(int direct, const char *fmt, va_list args); void printk(const char *fmt, ...); void xprintk(const char *fmt, ...); + +#define tprintk(_fmt, _args...) printk("[%s] " _fmt, current->name, ##_args) void xencons_rx(char *buf, unsigned len, struct pt_regs *regs); void xencons_tx(void); only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/lwipopts.h Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,22 @@ +/* + * lwipopts.h + * + * Configuration for lwIP running on mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#ifndef __LWIP_LWIPOPTS_H__ +#define __LWIP_LWIPOPTS_H__ + +#define SYS_LIGHTWEIGHT_PROT 1 +#define MEM_LIBC_MALLOC 1 +#define LWIP_TIMEVAL_PRIVATE 0 +#define LWIP_DHCP 1 +#define LWIP_COMPAT_SOCKETS 0 +#define LWIP_IGMP 1 +#define MEMP_NUM_SYS_TIMEOUT 10 +#define TCP_SND_BUF 3000 +#define TCP_MSS 1500 + +#endif /* __LWIP_LWIPOPTS_H__ */ only in patch2: unchanged: --- a/extras/mini-os/include/netfront.h Fri Jan 18 16:43:44 2008 +0000 +++ b/extras/mini-os/include/netfront.h Fri Jan 18 18:18:12 2008 +0000 @@ -1,7 +1,19 @@ #include <wait.h> +#ifdef HAVE_LWIP +#include <lwip/netif.h> +#endif struct netfront_dev; struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6]); void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len); void shutdown_netfront(struct netfront_dev *dev); extern struct wait_queue_head netfront_queue; + +#ifdef HAVE_LWIP +/* Call this to bring up the netfront interface and the lwIP stack. + * N.B. _must_ be called from a thread; it''s not safe to call this from + * app_main(). */ +void start_networking(void); + +void networking_set_addr(struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw); +#endif only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/lwip-arch.c Fri Jan 18 18:18:12 2008 +0000 @@ -0,0 +1,293 @@ +/* + * lwip-arch.c + * + * Arch-specific semaphores and mailboxes for lwIP running on mini-os + * + * Tim Deegan <Tim.Deegan@eu.citrix.net>, July 2007 + */ + +#include <os.h> +#include <time.h> +#include <console.h> +#include <xmalloc.h> +#include <lwip/sys.h> +#include <stdarg.h> + +/* Is called to initialize the sys_arch layer */ +void sys_init(void) +{ +} + +/* Creates and returns a new semaphore. The "count" argument specifies + * the initial state of the semaphore. */ +sys_sem_t sys_sem_new(u8_t count) +{ + struct semaphore *sem = xmalloc(struct semaphore); + sem->count = count; + init_waitqueue_head(&sem->wait); + return sem; +} + +/* Deallocates a semaphore. */ +void sys_sem_free(sys_sem_t sem) +{ + xfree(sem); +} + +/* Signals a semaphore. */ +void sys_sem_signal(sys_sem_t sem) +{ + up(sem); +} + +/* Blocks the thread while waiting for the semaphore to be + * signaled. If the "timeout" argument is non-zero, the thread should + * only be blocked for the specified time (measured in + * milliseconds). + * + * If the timeout argument is non-zero, the return value is the number of + * milliseconds spent waiting for the semaphore to be signaled. If the + * semaphore wasn''t signaled within the specified time, the return value is + * SYS_ARCH_TIMEOUT. If the thread didn''t have to wait for the semaphore + * (i.e., it was already signaled), the function may return zero. */ +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) +{ + /* Slightly more complicated than the normal minios semaphore: + * need to wake on timeout *or* signal */ + sys_prot_t prot; + s64_t then = NOW(); + s64_t deadline; + + if (timeout == 0) + deadline = 0; + else + deadline = then + MILLISECS(timeout); + + while(1) { + wait_event_deadline(sem->wait, (sem->count > 0), deadline); + + prot = sys_arch_protect(); + /* Atomically check that we can proceed */ + if (sem->count > 0 || (deadline && NOW() >= deadline)) + break; + sys_arch_unprotect(prot); + } + + if (sem->count > 0) { + sem->count--; + sys_arch_unprotect(prot); + return NSEC_TO_MSEC(NOW() - then); + } + + sys_arch_unprotect(prot); + return SYS_ARCH_TIMEOUT; +} + +/* Creates an empty mailbox. */ +sys_mbox_t sys_mbox_new(int size) +{ + struct mbox *mbox = xmalloc(struct mbox); + if (!size) + size = 32; + else if (size == 1) + size = 2; + mbox->count = size; + mbox->messages = xmalloc_array(void*, size); + init_SEMAPHORE(&mbox->read_sem, 0); + mbox->reader = 0; + init_SEMAPHORE(&mbox->write_sem, size); + mbox->writer = 0; + return mbox; +} + +/* Deallocates a mailbox. If there are messages still present in the + * mailbox when the mailbox is deallocated, it is an indication of a + * programming error in lwIP and the developer should be notified. */ +void sys_mbox_free(sys_mbox_t mbox) +{ + ASSERT(mbox->reader == mbox->writer); + xfree(mbox->messages); + xfree(mbox); +} + +/* Posts the "msg" to the mailbox, internal version that actually does the + * post. */ +static void do_mbox_post(sys_mbox_t mbox, void *msg) +{ + /* The caller got a semaphore token, so we are now allowed to increment + * writer, but we still need to prevent concurrency between writers + * (interrupt handler vs main) */ + sys_prot_t prot = sys_arch_protect(); + mbox->messages[mbox->writer] = msg; + mbox->writer = (mbox->writer + 1) % mbox->count; + ASSERT(mbox->reader != mbox->writer); + sys_arch_unprotect(prot); + up(&mbox->read_sem); +} + +/* Posts the "msg" to the mailbox. */ +void sys_mbox_post(sys_mbox_t mbox, void *msg) +{ + if (mbox == SYS_MBOX_NULL) + return; + down(&mbox->write_sem); + do_mbox_post(mbox, msg); +} + +/* Try to post the "msg" to the mailbox. */ +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg) +{ + if (mbox == SYS_MBOX_NULL) + return ERR_BUF; + if (!trydown(&mbox->write_sem)) + return ERR_MEM; + do_mbox_post(mbox, msg); + return ERR_OK; +} + +/* + * Fetch a message from a mailbox. Internal version that actually does the + * fetch. + */ +static void do_mbox_fetch(sys_mbox_t mbox, void **msg) +{ + sys_prot_t prot; + /* The caller got a semaphore token, so we are now allowed to increment + * reader, but we may still need to prevent concurrency between readers. + * FIXME: can there be concurrent readers? */ + prot = sys_arch_protect(); + ASSERT(mbox->reader != mbox->writer); + if (msg != NULL) + *msg = mbox->messages[mbox->reader]; + mbox->reader = (mbox->reader + 1) % mbox->count; + sys_arch_unprotect(prot); + up(&mbox->write_sem); +} + +/* Blocks the thread until a message arrives in the mailbox, but does + * not block the thread longer than "timeout" milliseconds (similar to + * the sys_arch_sem_wait() function). The "msg" argument is a result + * parameter that is set by the function (i.e., by doing "*msg + * ptr"). The "msg" parameter maybe NULL to indicate that the message + * should be dropped. + * + * The return values are the same as for the sys_arch_sem_wait() function: + * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a + * timeout. */ +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) +{ + u32 rv; + if (mbox == SYS_MBOX_NULL) + return SYS_ARCH_TIMEOUT; + + rv = sys_arch_sem_wait(&mbox->read_sem, timeout); + if ( rv == SYS_ARCH_TIMEOUT ) + return rv; + + do_mbox_fetch(mbox, msg); + return 0; +} + +/* This is similar to sys_arch_mbox_fetch, however if a message is not + * present in the mailbox, it immediately returns with the code + * SYS_MBOX_EMPTY. On success 0 is returned. + * + * To allow for efficient implementations, this can be defined as a + * function-like macro in sys_arch.h instead of a normal function. For + * example, a naive implementation could be: + * #define sys_arch_mbox_tryfetch(mbox,msg) \ + * sys_arch_mbox_fetch(mbox,msg,1) + * although this would introduce unnecessary delays. */ + +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg) { + if (mbox == SYS_MBOX_NULL) + return SYS_ARCH_TIMEOUT; + + if (!trydown(&mbox->read_sem)) + return SYS_MBOX_EMPTY; + + do_mbox_fetch(mbox, msg); + return 0; +} + + +/* Returns a pointer to the per-thread sys_timeouts structure. In lwIP, + * each thread has a list of timeouts which is repressented as a linked + * list of sys_timeout structures. The sys_timeouts structure holds a + * pointer to a linked list of timeouts. This function is called by + * the lwIP timeout scheduler and must not return a NULL value. + * + * In a single threadd sys_arch implementation, this function will + * simply return a pointer to a global sys_timeouts variable stored in + * the sys_arch module. */ +struct sys_timeouts *sys_arch_timeouts(void) +{ + static struct sys_timeouts timeout; + return &timeout; +} + + +/* Starts a new thread with priority "prio" that will begin its execution in the + * function "thread()". The "arg" argument will be passed as an argument to the + * thread() function. The id of the new thread is returned. Both the id and + * the priority are system dependent. */ +static struct thread *lwip_thread; +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) +{ + struct thread *t; + if (stacksize > STACK_SIZE) { + printk("Can''t start lwIP thread: stack size %d is too large for our %d\n", stacksize, STACK_SIZE); + do_exit(); + } + lwip_thread = t = create_thread(name, thread, arg); + return t; +} + +/* This optional function does a "fast" critical region protection and returns + * the previous protection level. This function is only called during very short + * critical regions. An embedded system which supports ISR-based drivers might + * want to implement this function by disabling interrupts. Task-based systems + * might want to implement this by using a mutex or disabling tasking. This + * function should support recursive calls from the same task or interrupt. In + * other words, sys_arch_protect() could be called while already protected. In + * that case the return value indicates that it is already protected. + * + * sys_arch_protect() is only required if your port is supporting an operating + * system. */ +sys_prot_t sys_arch_protect(void) +{ + unsigned long flags; + local_irq_save(flags); + return flags; +} + +/* This optional function does a "fast" set of critical region protection to the + * value specified by pval. See the documentation for sys_arch_protect() for + * more information. This function is only required if your port is supporting + * an operating system. */ +void sys_arch_unprotect(sys_prot_t pval) +{ + local_irq_restore(pval); +} + +/* non-fatal, print a message. */ +void lwip_printk(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + printk("lwIP: "); + print(0, fmt, args); + va_end(args); +} + +/* fatal, print message and abandon execution. */ +void lwip_die(char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + printk("lwIP assertion failed: "); + print(0, fmt, args); + va_end(args); + printk("\n"); + BUG(); +} only in patch2: unchanged: --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/lwip-net.c Fri Jan 18 18:18:12 2008 +0000 @@ -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"); +} only in patch2: unchanged: --- a/extras/mini-os/minios.mk Fri Jan 18 16:43:44 2008 +0000 +++ b/extras/mini-os/minios.mk Fri Jan 18 18:18:12 2008 +0000 @@ -6,7 +6,7 @@ debug = y # Define some default flags. # NB. ''-Wcast-qual'' is nasty, so I omitted it. -DEF_CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format +DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel