#
TCPSTACK=UIP
+#
+#TCPSTACK, uIP is used currently
+#
+UIP=OFF
+#
+#LWIP, ON -- used, OFF -- not used
+#
+LWIP=ON
#
-TCPSTACK_C_SRCS := psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c resolv.c
-TCPSTACK_C_OBJS := $(TCPSTACK_C_SRCS:%.c=net/%.o)
-TCPSTACK_OBJS := $(TCPSTACK_C_OBJS)
+ifeq ($(UIP),ON)
+ UIP_C_SRCS := psock.c timer.c uip_arp.c uip.c uip-fw.c uiplib.c uip-neighbor.c uip-split.c resolv.c
+ UIP_C_OBJS := $(UIP_C_SRCS:%.c=net/%.o)
+else
+ UIP_C_SRCS :=
+ UIP_C_OBJS :=
+endif
+
+ifeq ($(LWIP),ON)
+ LWIP_OBJS := lwip/*.o
+ CC_LWIP_OPTS := -I$(PROJECT_ROOT)/include/lwip -I$(PROJECT_ROOT)/include/lwip/ipv4 -I$(PROJECT_ROOT)/include/libc -DLWIP_DEBUG
+else
+ LWIP_OBJS :=
+ CC_LWIP_OPTS :=
+endif
+TCPSTACK_OBJS := $(UIP_C_OBJS) $(LWIP_OBJS)
# ----------------------------------------------------------------------
# Compilation of kernel C source files
geekos/%.o : geekos/%.c
- $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $< -o geekos/$*.o
+ $(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_KERNEL_OPTS) $(CC_LWIP_OPTS) $< -o geekos/$*.o
# Compilation of kernel assembly source files
#include <geekos/ktypes.h>
#include <geekos/defs.h>
+
+// to stop the compilation warnings
+extern void Print(const char* fmt, ...);
+extern void Set_Current_Attr(uchar_t attrib);
+
/*
* This struct reflects the contents of the stack when
* a C interrupt handler function is called.
#define NE2K_IRQ 11 /* Interrupt channel */
+
+/* Physical Address of Network Card */
+#define PHY_ADDR1 0x52
+#define PHY_ADDR2 0x54
+#define PHY_ADDR3 0x00
+#define PHY_ADDR4 0x12
+#define PHY_ADDR5 0x34
+#define PHY_ADDR6 0x58
+
+
struct NE2K_REGS {
uchar_t cr;
uchar_t isr;
#define TIMER_IRQ 0
-extern volatile ulong_t g_numTicks;
+extern volatile unsigned long g_numTicks;
typedef void (*timerCallback)(int, void*);
void Micro_Delay(int us);
+unsigned long clock_time(void); //return elipsed millisecs
+
#endif /* GEEKOS_TIMER_H */
char *strpbrk(const char *s, const char *accept);
char *strncat(char *s1, const char *s2, size_t limit);
int fprintf(FILE *file, char *fmt, ...);
-//int fflush(FILE *file);
+int fflush(FILE *file);
+int printf(char *fmt, ...);
--- /dev/null
+#ifndef __PING_H__
+#define __PING_H__
+
+void ping_init(void);
+
+#endif /* __PING_H__ */
/* Include some files for defining library routines */
#include <string.h>
-
-extern int fflush(FILE *file);
-extern int printf(char *fmt, ...);
-extern void abort (void);
-
+#include <geekos/debug.h>
/* Define platform endianness */
#ifndef BYTE_ORDER
//#include <stdio.h>
//#include <stdlib.h>
/* Plaform specific diagnostic output */
-#define LWIP_PLATFORM_DIAG(x) //do {printf x;} while(0)
+#define LWIP_PLATFORM_DIAG(x) do {PrintBoth x;} while(0)//do {printf x;} while(0)
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
#define PERF_STOP(x) /* null definition */
#endif /* PERF */
+#if 0
+
void perf_print(unsigned long c1l, unsigned long c1h,
unsigned long c2l, unsigned long c2h,
char *key);
void perf_init(char *fname);
+#endif
+
#endif /* __ARCH_PERF_H__ */
#ifndef __LWIP_IP_ADDR_H__
#define __LWIP_IP_ADDR_H__
-#include "lwip/opt.h"
+#include <lwip/lwip/opt.h>
#ifdef __cplusplus
extern "C" {
* Include user defined options first. Anything not defined in these files
* will be set to standard values. Override anything you dont like!
*/
-#include "lwipopts.h"
+#include <lwip/lwipopts.h>
#include "lwip/debug.h"
/*
* TCP_WND: The size of a TCP window.
*/
#ifndef TCP_WND
-#define TCP_WND 2048
+#define TCP_WND 1024 //2048
#endif
/**
* LWIP_NETIF_API==1: Support netif api (in netifapi.c)
*/
#ifndef LWIP_NETIF_API
-#define LWIP_NETIF_API 0
+#define LWIP_NETIF_API 1
#endif
/**
--- /dev/null
+/* ne2k network interface for lwip\r
+ *\r
+ * Lei Xia (lxia@northwestern.edu)\r
+ */
+
+#ifndef __NETIF_NE2KIF_H__
+#define __NETIF_NE2KIF_H__
+
+#include <lwip/lwip/netif.h>
+#include <lwip/lwip/err.h>
+#include <geekos/ktypes.h>
+#include <geekos/ne2k.h>
+
+extern struct netif ne2kif;
+
+err_t ne2kif_init(struct netif *netif);
+
+void ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt);
+
+err_t ne2kif_output(struct netif * netif, struct pbuf * p);
+
+#endif /*__NETIF_NE2KIF_H__*/
*
* \hideinitializer
*/
-typedef unsigned char u8_t;
+//conflict with lwip
+//typedef unsigned char u8_t;
/**
* 16 bit datatype
*
* \hideinitializer
*/
-typedef unsigned short int u16_t;
+//confict with lwip
+//typedef unsigned short int u16_t;
/**
* Statistics datatype
#include <geekos/irq.h>
#include <geekos/malloc.h>
#include <geekos/string.h>
+
+#ifdef UIP
#include <uip/uip.h>
#include <uip/uip_arp.h>
+#endif
#define DEBUG 1
#define TX_START_BUFF 0x40
cr->ps = 0x01; /* Switch to reg page 1 */
Out_Byte(NE2K_CR, regs->cr);
- /* Set the physical address of the card to 52:54:00:12:34:58 */
- Out_Byte(NE2K_CR+0x01, 0x52);
- Out_Byte(NE2K_CR+0x02, 0x54);
- Out_Byte(NE2K_CR+0x03, 0x00);
- Out_Byte(NE2K_CR+0x04, 0x12);
- Out_Byte(NE2K_CR+0x05, 0x34);
- Out_Byte(NE2K_CR+0x06, 0x58);
+ /* Set the physical address of the card */
+ Out_Byte(NE2K_CR+0x01, PHY_ADDR1);
+ Out_Byte(NE2K_CR+0x02, PHY_ADDR2);
+ Out_Byte(NE2K_CR+0x03, PHY_ADDR3);
+ Out_Byte(NE2K_CR+0x04, PHY_ADDR4);
+ Out_Byte(NE2K_CR+0x05, PHY_ADDR5);
+ Out_Byte(NE2K_CR+0x06, PHY_ADDR6);
/* Set the multicast address register to all 1s; accepts all multicast packets */
uint_t i;
* an ARP packet, which is sent out instead. The original packet will need to be
* retransmitted at some point in the future.
*/
+#ifdef UIP
+
int NE2K_Transmit(uint_t size)
{
uip_arp_out();
return 0;
}
+#endif
+
int NE2K_Send_Packet(uchar_t *packet, uint_t size)
{
struct _CR * cr = (struct _CR*)&(regs->cr);
-/*
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National
- * Science Foundation and the Department of Energy.
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico. You can find out more at
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software. You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
+/* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
+/* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
+
#include <geekos/net.h>
#include <geekos/socket.h>
#include <geekos/ne2k.h>
+#include <lwip/apps/ping.h>
+#include <lwip/lwip/sockets.h>
+#include <lwip/ipv4/lwip/ip_addr.h>
+#include <lwip/netif/ne2kif.h>
+#include <lwip/sys.h>
+#include <lwip/netifapi.h>
+#include <lwip/tcpip.h>
+#include <netif/etharp.h>
+#include <geekos/debug.h>
-void Init_Network() {
- init_socket_layer();
+
+static void
+tcpip_init_done(void *arg)
+{
+ sys_sem_t *sem;
+ sem = arg;
+ sys_sem_signal(*sem);
}
+void Init_Network() {
+
+ //temporay now we are using lwip sockets
+ // init_socket_layer();
+
+ struct ip_addr ipaddr, netmask, gateway;
+ sys_sem_t sem;
+ err_t err;
+
+ sem = sys_sem_new(0);
+
+#ifdef LWIP_DEBUG
+ PrintBoth("lwIP: before tcpip_init\n");
+#endif
+ tcpip_init(tcpip_init_done, &sem); //initial the whole lwip module
+#ifdef LWIP_DEBUG
+ PrintBoth("lwIP: After tcpip_init\n");
+#endif
+ sys_sem_wait(sem);
+ sys_sem_free(sem);
+
+ IP4_ADDR(&gateway, 192,168,1,1);
+ IP4_ADDR(&ipaddr, 192,168,1,2);
+ IP4_ADDR(&netmask, 255,255,255,0);
+
+
+ err = netifapi_netif_add(&ne2kif, &ipaddr, &netmask, &gateway,
+ NULL, ne2kif_init, ethernet_input);
+
+ if (err != ERR_OK){
+ PrintBoth("lwip: initial network failed! add netif error %d/n", err);
+ return;
+ }
+
+ netifapi_netif_set_default(&ne2kif);
+
+ //initial a network application
+ ping_init();
+}
+
+
+#if 0
void test_network() {
uchar_t local_addr[4];
local_addr[2] = 2;
local_addr[3] = 21;
- set_ip_addr(local_addr);
+// set_ip_addr(local_addr);
remote_addr[0] = 10;
remote_addr[1] = 0;
remote_addr[3] = 20;
- connect(remote_addr, 4301);
+ // connect(remote_addr, 4301);
}
+
+#endif
#include <geekos/socket.h>
#include <geekos/malloc.h>
#include <geekos/ne2k.h>
+
+#ifdef UIP
+
#include <uip/uip.h>
#include <uip/uip_arp.h>
+
#include <geekos/vmm_stubs.h>
#include <geekos/debug.h>
#include <geekos/timer.h>
-
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
#define MAX_SOCKS 1024
#endif /* UIP_APPCALL */
-
-
static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
static void periodic_caller(int timer_id, void * arg);
void init_socket_layer() {
+
int i = 0;
bool iflag;
sockets[i].state = CLOSED;
}
-
-
//initiate uIP
uip_init();
uip_arp_init();
- //setup device driver
- Init_Ne2k(&Packet_Received);
+ //setup device driver
+ Init_Ne2k(&Packet_Received);
iflag = Begin_Int_Atomic();
Start_Timer(2, periodic_caller, NULL);
End_Int_Atomic(iflag);
-
}
-
-
-
void set_ip_addr(uchar_t addr[4]) {
uip_ipaddr_t ipaddr;
uip_ipaddr(ipaddr, addr[0], addr[1], addr[2], addr[3]); /* Local IP address */
uip_sethostaddr(ipaddr);
}
-
static int allocate_socket_fd() {
int i = 0;
}
-
static void periodic_caller(int timer_id, void * arg) {
int i;
//handle the periodic calls of uIP
return 0;
}
+
+
+#endif /* UIP */
#include <geekos/synch.h>
#include <geekos/timer.h>
+#include <geekos/debug.h>
+
/*
* NOTES:
* - The GeekOS mutex and condition variable APIs are based on those
}
/*
+ * Destroy Mutex
+ */
+void Mutex_Destroy(struct Mutex* mutex)
+{
+
+
+}
+
+/*
+ * Condition Destroy
+ */
+void Cond_Destroy(struct Condition* cond)
+{
+
+
+}
+
+/*
* Initialize given condition.
*/
void Cond_Init(struct Condition* cond)
*/
volatile ulong_t g_numTicks;
-ulong_t clock_time(void){
- return g_numTicks;
-}
-
-
/*
* Number of times the spin loop can execute during one timer tick
*/
# define Debug(args...)
#endif
+ulong_t clock_time(void){//in millisec
+ return g_numTicks * (1000/HZ);
+}
+
/* ----------------------------------------------------------------------
* Private functions
* ---------------------------------------------------------------------- */
KASSERT(!Interrupts_Enabled());
+ PrintBoth ("there\n");
+
if (timeEventCount == MAX_TIMER_EVENTS) {
return -1;
} else {
LOCK_TCPIP_CORE();
while (1) { /* MAIN Loop */
+
+ PrintBoth("In tcp_thread: main loop\n");
+
sys_mbox_fetch(mbox, (void *)&msg);
+
switch (msg->type) {
#if LWIP_NETCONN
case TCPIP_MSG_API:
--- /dev/null
+/**
+ * @file
+ * Ping sender module
+ *
+ */
+
+/*
+ * 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.
+ *
+ */
+
+/**
+ * This is an example of a "ping" sender (with raw API and socket API).
+ * It can be used as a start point to maintain opened a network connection, or
+ * like a network "watchdog" for your device.
+ *
+ */
+
+#include "lwip/opt.h"
+
+#if LWIP_RAW && LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/mem.h"
+#include "lwip/raw.h"
+#include "lwip/icmp.h"
+#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+#include "lwip/inet_chksum.h"
+
+#include "apps/ping.h"
+
+#include <geekos/timer.h>
+#include <geekos/ktypes.h>
+
+/**
+ * PING_DEBUG: Enable debugging for PING.
+ */
+#ifndef PING_DEBUG
+#define PING_DEBUG LWIP_DBG_ON
+#endif
+
+/** ping target - should be a "struct ip_addr" */
+#ifndef PING_TARGET
+#define PING_TARGET (netif_default?netif_default->gw:ip_addr_any)
+#endif
+
+/** ping receive timeout - in milliseconds */
+#ifndef PING_RCV_TIMEO
+#define PING_RCV_TIMEO 1000
+#endif
+
+/** ping delay - in milliseconds */
+#ifndef PING_DELAY
+#define PING_DELAY 1000
+#endif
+
+/** ping identifier - must fit on a u16_t */
+#ifndef PING_ID
+#define PING_ID 0xAFAF
+#endif
+
+/** ping additional data size to include in the packet */
+#ifndef PING_DATA_SIZE
+#define PING_DATA_SIZE 32
+#endif
+
+/** ping result action - no default action */
+#ifndef PING_RESULT
+#define PING_RESULT(ping_ok)
+#endif
+
+/* ping variables */
+static u16_t ping_seq_num;
+static u32_t ping_time;
+
+#if NO_SYS
+/* port-defined functions used for timer execution */
+void sys_msleep(u32_t ms);
+u32_t sys_now();
+#endif /* NO_SYS */
+
+/** Prepare a echo ICMP request */
+static void
+ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
+{
+ int i;
+
+ ICMPH_TYPE_SET(iecho,ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = htons(++ping_seq_num);
+ iecho->chksum = inet_chksum(iecho, len);
+
+ /* fill the additional data buffer with some data */
+ for(i = 0; i < PING_DATA_SIZE; i++) {
+ ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = i;
+ }
+}
+
+#if LWIP_SOCKET
+
+/* Ping using the socket ip */
+static err_t
+ping_send(int s, struct ip_addr *addr)
+{
+ int err;
+ struct icmp_echo_hdr *iecho;
+ struct sockaddr_in to;
+ size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
+
+ if (!(iecho = mem_malloc(ping_size))) {
+ return ERR_MEM;
+ }
+
+ ping_prepare_echo(iecho, ping_size);
+
+ to.sin_len = sizeof(to);
+ to.sin_family = AF_INET;
+ to.sin_addr.s_addr = addr->addr;
+
+ err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
+
+ mem_free(iecho);
+
+ return (err ? ERR_OK : ERR_VAL);
+}
+
+static void
+ping_recv(int s)
+{
+ char buf[64];
+ int fromlen, len;
+ struct sockaddr_in from;
+ struct ip_hdr *iphdr;
+ struct icmp_echo_hdr *iecho;
+
+ while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0) {
+ if (len >= (sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
+ ip_addr_debug_print(PING_DEBUG, (struct ip_addr *)&(from.sin_addr));
+ LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
+
+ iphdr = (struct ip_hdr *)buf;
+ iecho = (struct icmp_echo_hdr *)(buf+(IPH_HL(iphdr) * 4));
+ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
+ /* do some ping result processing */
+ PING_RESULT((ICMPH_TYPE(iecho) == ICMP_ER));
+ return;
+ } else {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: drop\n"));
+ }
+ }
+ }
+
+ if (len == 0) {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: recv - %lu ms - timeout\n", (sys_now()-ping_time)));
+ }
+
+ /* do some ping result processing */
+ PING_RESULT(0);
+}
+
+static void
+ping_thread(void *arg)
+{
+ int s;
+ int timeout = PING_RCV_TIMEO;
+ struct ip_addr ping_target;
+
+ LWIP_UNUSED_ARG(arg);
+
+ if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
+ return;
+ }
+
+ lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+
+ while (1) {
+ ping_target = PING_TARGET;
+
+ if (ping_send(s, &ping_target) == ERR_OK) {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
+ ip_addr_debug_print(PING_DEBUG, &ping_target);
+ LWIP_DEBUGF( PING_DEBUG, ("\n"));
+
+ ping_time = sys_now();
+ ping_recv(s);
+ } else {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
+ ip_addr_debug_print(PING_DEBUG, &ping_target);
+ LWIP_DEBUGF( PING_DEBUG, (" - error\n"));
+ }
+ sys_msleep(PING_DELAY);
+ }
+}
+
+#else /* LWIP_SOCKET */
+
+/* Ping using the raw ip */
+static u8_t
+ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr)
+{
+ struct icmp_echo_hdr *iecho;
+
+ if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
+ iecho = p->payload;
+
+ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
+ LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
+ ip_addr_debug_print(PING_DEBUG, addr);
+ LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
+
+ /* do some ping result processing */
+ PING_RESULT(1);
+ }
+ }
+
+ return 1; /* eat the event */
+}
+
+static void
+ping_send(struct raw_pcb *raw, struct ip_addr *addr)
+{
+ struct pbuf *p;
+ struct icmp_echo_hdr *iecho;
+ size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
+
+ if (!(p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM))) {
+ return;
+ }
+ if ((p->len == p->tot_len) && (p->next == NULL)) {
+ iecho = p->payload;
+
+ ping_prepare_echo(iecho, ping_size);
+
+ raw_sendto(raw, p, addr);
+ ping_time = sys_now();
+ }
+ pbuf_free(p);
+}
+
+static void
+ping_timeout(void *arg)
+{
+ struct raw_pcb *pcb = (struct raw_pcb*)arg;
+ struct ip_addr ping_target = PING_TARGET;
+
+ LWIP_ASSERT("ping_timeout: no pcb given!", pcb != NULL);
+
+ LWIP_DEBUGF( PING_DEBUG, ("ping: send "));
+ ip_addr_debug_print(PING_DEBUG, &ping_target);
+ LWIP_DEBUGF( PING_DEBUG, ("\n"));
+
+ ping_send(pcb, &ping_target);
+
+ sys_timeout(PING_DELAY, ping_timeout, pcb);
+}
+
+static void
+ping_raw_init(void)
+{
+ struct raw_pcb *pcb;
+
+ if (!(pcb = raw_new(IP_PROTO_ICMP))) {
+ return;
+ }
+
+ raw_recv(pcb, ping_recv, NULL);
+ raw_bind(pcb, IP_ADDR_ANY);
+ sys_timeout(PING_DELAY, ping_timeout, pcb);
+}
+
+#endif /* LWIP_SOCKET */
+
+void
+ping_init(void)
+{
+#if LWIP_SOCKET
+ sys_thread_new("ping_thread", ping_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
+#else /* LWIP_SOCKET */
+ ping_raw_init();
+#endif /* LWIP_SOCKET */
+}
+
+
+u32_t
+sys_now()
+{
+ ulong_t msec;
+
+ msec = clock_time();
+
+ return msec;
+}
+
+#endif /* LWIP_RAW && LWIP_ICMP */
* will block until there is more room instead of just
* leaking messages.
*/
+/*
+ * Modified by Lei Xia (lxia@northwestern.edu) to fit to Palacios, 9/29/2008
+ */
#include "lwip/debug.h"
#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
+#include <palacios/vmm.h>
#include <geekos/synch.h>
#include <geekos/kthread.h>
#include <geekos/debug.h>
+#include <geekos/timer.h>
#include <geekos/malloc.h>
#include "lwip/sys.h"
};
-static struct timeval starttime;
+//static struct timeval starttime;
//static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
static struct Mutex lwprot_mutex; // !!!! need to be initiated, void Mutex_Init(struct Mutex* mutex);
//static pthread_t lwprot_thread = (pthread_t) 0xDEAD;
-static struct Kernel_Thread lwprot_thread = (struct Kernel_Thread) 0xDEAD; //!!!!! how to set it to a NULL thread?
+//static struct Kernel_Thread lwprot_thread = (struct Kernel_Thread) 0xDEAD; //!!!!! how to set it to a NULL thread?
-static int lwprot_count = 0;
+//static int lwprot_count = 0;
static struct sys_sem *sys_sem_new_(u8_t count);
static void sys_sem_free_(struct sys_sem *sem);
}
-//!!!!!!!!!!!!backto this function later
/*-----------------------------------------------------------------------------------*/
sys_thread_t
sys_thread_new(char *name, void (* function)(void *arg), void *arg, int stacksize, int prio)
{
- int code;
+ //int code;
//pthread_t tmp;
struct Kernel_Thread *tmp;
struct sys_thread *st = NULL;
thread = current_thread();
return &thread->timeouts;
}
+
+
/*-----------------------------------------------------------------------------------*/
/** sys_prot_t sys_arch_protect(void)
sys_arch_protect() is only required if your port is supporting an operating
system.
*/
+
+#if 0
sys_prot_t
sys_arch_protect(void)
{
{
if (--lwprot_count == 0)
{
- lwprot_thread = (Kernel_Thread) 0xDEAD;
+ lwprot_thread = (struc Kernel_Thread) 0xDEAD;
Mutex_Unlock(&lwprot_mutex);
}
}
}
+#endif
/*-----------------------------------------------------------------------------------*/
#define HZ 100
#endif
+#if 0
unsigned long
sys_jiffies(void)
{
usec /= 1000000L / HZ;
return HZ * sec + usec;
}
+#endif
#if PPP_DEBUG
va_start(args, format);
//vprintf(format, args);
- SerialPrintList(format, args);
+ PrintDebug(format, args);
va_end(args);
}
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/stats.c $(LWIPDIR)/core/sys.c \
- $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c \
+ $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c $(LWIPDIR)/core/raw.c\
$(LWIPDIR)/core/tcp_out.c $(LWIPDIR)/core/udp.c $(LWIPDIR)/core/init.c
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c $(LWIPDIR)/core/ipv4/ip.c \
$(LWIPDIR)/core/ipv4/inet.c $(LWIPDIR)/core/ipv4/ip_addr.c \
- $(LWIPDIR)/core/ipv4/inet_chksum.c
+ $(LWIPDIR)/core/ipv4/inet_chksum.c $(LWIPDIR)/core/ipv4/ip_frag.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \
- $(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c $(LWIPDIR)/api/netdb.c
+ $(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c $(LWIPDIR)/api/netdb.c $(LWIPDIR)/api/netifapi.c
# NETIFFILES: Files implementing various generic network interface functions.'
-NETIFFILES=$(LWIPDIR)/netif/loopif.c \
- $(LWIPDIR)/netif/etharp.c
+NETIFFILES=$(LWIPDIR)/netif/loopif.c $(LWIPDIR)/netif/ne2kif.c $(LWIPDIR)/netif/etharp.c
# ARCHFILES: Architecture specific files.
ARCHFILES=$(LWIPDIR)/arch/sys_arch.c
+# APPFILES: Application files
+APPFILES=$(LWIPDIR)/apps/ping.c
+
# LWIPFILES: All the above.
-LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
+LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES) $(APPFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
-#LWIPLIB=lwip.o
+# LWIPLIB=lwip.o
%.o:
$(CC) $(CFLAGS) -c $(LWIPFILES)
-all: $(LWIPOBJS)
+all: $(LWIPOBJS)
cp *.o $(PROJECT_ROOT)build/lwip/
.PHONY: all
clean:
- rm -f *.o $(LWIPLIB) *.s .depend* *.core
+ rm -f *.o .depend*
depend dep: .depend
include .depend
-##$(LWIPLIB): $(LWIPOBJS)
-## $(CC) -g -nostartfiles -shared -static $^ -o $@
+# $(LWIPLIB): $(LWIPOBJS)
+# $(CC) -g -nostartfiles -shared -static $^ -o $@
.depend: $(LWIPFILES)
$(CC) $(CFLAGS) -MM $^ > .depend || rm -f .depend
if (TCP_SNDLOWAT > TCP_SND_BUF)
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n"));
if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE))
- LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n"));
+ LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE: %d\n", (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE)));
if (TCP_WND < TCP_MSS)
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
#endif /* LWIP_TCP */
--- /dev/null
+/**\r
+ * @file\r
+ * Ethernet Interface for ne2k device\r
+ *\r
+ * Lei Xia (lxia@northwestern.edu\r
+ */\r
+\r
+#include "lwip/opt.h"\r
+ \r
+\r
+#include "lwip/def.h"\r
+#include "lwip/mem.h"\r
+#include "lwip/pbuf.h"\r
+#include "lwip/sys.h"\r
+#include <lwip/stats.h>\r
+#include <lwip/snmp.h>\r
+#include "netif/etharp.h"\r
+#include "netif/ppp_oe.h"\r
+#include "lwip/netifapi.h"\r
+#include "netif/ne2kif.h"\r
+\r
+\r
+#include <geekos/ne2k.h>\r
+#include <geekos/ktypes.h>\r
+#include <geekos/debug.h>\r
+\r
+\r
+struct netif ne2kif; \r
+\r
+/**\r
+ * This function should do the actual transmission of the packet. The packet is\r
+ * contained in the pbuf that is passed to the function. This pbuf\r
+ * might be chained.\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)\r
+ * @return ERR_OK if the packet could be sent\r
+ * an err_t value if the packet couldn't be sent\r
+ *\r
+ * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to\r
+ * strange results. You might consider waiting for space in the DMA queue\r
+ * to become availale since the stack doesn't retry to send a packet\r
+ * dropped because of memory failure (except for the TCP timers).\r
+ */\r
+\r
+err_t\r
+ne2kif_output(struct netif *netif, struct pbuf *p)\r
+{\r
+ struct pbuf *q;\r
+ int size, offset, remlen;\r
+ uchar_t *packet;\r
+ \r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */\r
+#endif\r
+\r
+ size = p->tot_len;\r
+ offset = 0;\r
+ remlen = size;\r
+\r
+ packet = (uchar_t *)Malloc (remlen);\r
+\r
+ for(q = p; q != NULL && remlen >0; q = q->next) {\r
+ /* Send the data from the pbuf to the interface, one pbuf at a\r
+ time. The size of the data in each pbuf is kept in the ->len\r
+ variable. */\r
+\r
+ memcpy(packet+offset, q->payload, q->len < remlen? q->len:remlen);\r
+ remlen -= q->len;\r
+ offset += q->len;\r
+ \r
+ }\r
+ NE2K_Send_Packet(packet, size);\r
+\r
+ //signal that packet should be sent();\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
+#endif\r
+ \r
+ LINK_STATS_INC(link.xmit);\r
+\r
+ return ERR_OK;\r
+}\r
+\r
+\r
+/**\r
+ * This function should be called when a packet is ready to be read\r
+ * from the interface. It uses the function low_level_input() that\r
+ * should handle the actual reception of bytes from the network\r
+ * interface. Then the type of the received packet is determined and\r
+ * the appropriate input function is called.\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ */\r
+void\r
+ne2kif_input(struct NE2K_Packet_Info * info, uchar_t * pkt)\r
+{\r
+ struct pbuf *p, *q;\r
+ uint_t offset;\r
+ uint_t len, rlen;\r
+ \r
+ len = info->size; \r
+\r
+ PrintBoth("Ne2k: Packet REceived\n");\r
+\r
+#if ETH_PAD_SIZE\r
+ len += ETH_PAD_SIZE; // allow room for Ethernet padding \r
+#endif\r
+\r
+ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
+ \r
+ if (p != NULL) {\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, -ETH_PAD_SIZE); // drop the padding word \r
+#endif\r
+\r
+ // iterate over the pbuf chain until it has read the entire packet into the pbuf.\r
+ for(offset = 0, q = p; q != NULL && rlen > 0; q = q->next) {\r
+ memcpy(q->payload, pkt+offset, rlen > q->len? q->len: rlen);\r
+ rlen -= q->len;\r
+ offset += q->len;\r
+ }\r
+\r
+#if ETH_PAD_SIZE\r
+ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */\r
+#endif\r
+\r
+ LINK_STATS_INC(link.recv);\r
+ } else {\r
+ LINK_STATS_INC(link.memerr);\r
+ LINK_STATS_INC(link.drop);\r
+ }\r
+\r
+ Free(pkt);\r
+ \r
+ if (p == NULL) return;\r
+ /* points to packet payload, which starts with an Ethernet header */\r
+ //ethhdr = p->payload;\r
+\r
+ /* full packet send to tcpip_thread to process */\r
+ if (ne2kif.input(p, &ne2kif)!=ERR_OK)\r
+ { LWIP_DEBUGF(NETIF_DEBUG, ("ne2kif_input: IP input error\n"));\r
+ pbuf_free(p);\r
+ p = NULL;\r
+ }\r
+\r
+#if 0\r
+ switch (htons(ethhdr->type)) {\r
+ /* IP or ARP packet? */\r
+ case ETHTYPE_IP:\r
+ case ETHTYPE_ARP:\r
+#if PPPOE_SUPPORT\r
+ /* PPPoE packet? */\r
+ case ETHTYPE_PPPOEDISC:\r
+ case ETHTYPE_PPPOE:\r
+#endif /* PPPOE_SUPPORT */\r
+ \r
+ break;\r
+\r
+ default:\r
+ pbuf_free(p);\r
+ p = NULL;\r
+ break;\r
+ }\r
+#endif\r
+\r
+}\r
+\r
+/**\r
+ * Should be called at the beginning of the program to set up the\r
+ * network interface. It calls the function low_level_init() to do the\r
+ * actual setup of the hardware.\r
+ *\r
+ * This function should be passed as a parameter to netif_add().\r
+ *\r
+ * @param netif the lwip network interface structure for this ethernetif\r
+ * @return ERR_OK if the loopif is initialized\r
+ * ERR_MEM if private data couldn't be allocated\r
+ * any other err_t on error\r
+ */\r
+err_t\r
+ne2kif_init(struct netif *netif)\r
+{\r
+\r
+#if LWIP_NETIF_HOSTNAME\r
+ /* Initialize interface hostname */\r
+ netif->hostname = "lwip";\r
+#endif /* LWIP_NETIF_HOSTNAME */\r
+\r
+ /*\r
+ * Initialize the snmp variables and counters inside the struct netif.\r
+ * The last argument should be replaced with your link speed, in units\r
+ * of bits per second.\r
+ */\r
+ NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);\r
+\r
+ netif->state = NULL;\r
+ netif->name[0] = 'n';\r
+ netif->name[1] = 'e';\r
+ /* We directly use etharp_output() here to save a function call.\r
+ * You can instead declare your own function an call etharp_output()\r
+ * from it if you have to do some checks before sending (e.g. if link\r
+ * is available...) */\r
+ netif->output = etharp_output;\r
+ netif->linkoutput = ne2kif_output;\r
+ \r
+\r
+ /* set MAC hardware address length */\r
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;\r
+\r
+ /* set MAC hardware address */\r
+ netif->hwaddr[0] = PHY_ADDR1;\r
+ netif->hwaddr[1] = PHY_ADDR2;\r
+ netif->hwaddr[2] = PHY_ADDR3;\r
+ netif->hwaddr[3] = PHY_ADDR4;\r
+ netif->hwaddr[4] = PHY_ADDR5;\r
+ netif->hwaddr[5] = PHY_ADDR6;\r
+\r
+ /* maximum transfer unit */\r
+ netif->mtu = 1500;\r
+ \r
+ /* device capabilities */\r
+ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */\r
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;\r
+\r
+ //initate ne2k hardware\r
+ Init_Ne2k(&ne2kif_input);\r
+\r
+ return ERR_OK;\r
+}\r
uip_flags = 0;
return;
}
+
/*---------------------------------------------------------------------------*/
+/* replicate defined in lwip.c,
u16_t
htons(u16_t val)
{
return HTONS(val);
}
+*/
+
/*---------------------------------------------------------------------------*/
void
uip_send(const void *data, int len)
XED_OBJS := $(XED_C_OBJS) $(XED_GAS_OBJS)
+
DEVICE_C_SRCS := generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c serial.c ramdisk.c cdrom.c
DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
+
# ----------------------------------------------------------------------
# Tools -
# This section defines programs that are used to build GeekOS.
-
palacios/%.o : palacios/%.c
$(TARGET_CC) -c $(CC_GENERAL_OPTS) $(CC_VMM_OPTS) $< -o palacios/$*.o
vgabios_link:
ln -s -f ../src/vmboot/vgabios/VGABIOS-lgpl-latest.bin vgabios
+force_lwip:
+ (cd ../src/lwip/build; make clean; make)
+
force_rombios: rombios_link
(cd ../src/vmboot/rombios; make clean; make)
force_payload: force_rombios force_vgabios
../scripts/make_payload.pl payload_layout.txt vm_kernel
-inter1: force_payload
+inter1: force_payload force_lwip
-make clean
world: inter1 vmm
--- /dev/null
+/* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
+/* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
+
+#ifndef GEEKOS_SOCKET_H
+#define GEEKOS_SOCKET_H
+
+#include <geekos/ring_buffer.h>
+#include <geekos/kthread.h>
+
+#ifdef UIP
+#include <uip/uip.h>
+
+
+typedef enum {WAITING, CLOSED, LISTEN, ESTABLISHED} sock_state_t;
+
+struct socket {
+ int in_use;
+ struct Thread_Queue recv_wait_queue;
+ struct ring_buffer *send_buf;
+ struct ring_buffer *recv_buf;
+ struct uip_conn *con;
+
+ sock_state_t state;
+
+};
+
+
+void init_socket_layer();
+
+int connect(const uchar_t ip_addr[4], ushort_t port);
+int close(const int sockfd);
+int recv(int sockfd, void * buf, uint_t len);
+int send(int sockfd, void * buf, uint_t len);
+
+void set_ip_addr(uchar_t addr[4]);
+
+#endif /* UIP */
+
+
+#endif