Add eCos glue.

This commit is contained in:
jani 2003-02-28 14:29:13 +00:00
parent 782a790c07
commit d9d0f12c61
20 changed files with 2863 additions and 0 deletions

41
ports/ecos/README Normal file
View File

@ -0,0 +1,41 @@
This part of the lwip-contrib section is the ecos glue
You must have the current lwip sources checked out and the scripts here will hopefully generate
a correct EPK suitable for use with ecos.
To make an ecos package:
Run the mkepk script something like this
# EPK=/dir/of/epk LWIP_CVS=/dir/of/checked/out/lwip ./mkepk
This will put the generated EPK in the dir you specify
then add that EPK to your package repository and use it
Build example:
#ecosconfig new edb7xxx kernel
#ecosconfig add lwip
this will default to SLIP connection.If you also
#ecosconfig add net_drivers
you'll be able to configure for ethernet
In both cases set LWIP_MY_ADDR and LWIP_SERV_ADDR (means host/gateway for eth or host/peer for slip)
#ecosconfig tree
#make tests
and you can try any of the five tests included
Tests:
udpecho - echo service port 7 on UDP
tcpecho - ditto on TCP
sockets - as tcpecho but written with the socket API not the lwip specific API
https - http server on port 80 written with the raw API
nc_test_slave - a port of the test with the same name in net/common to lwip. Used to compare
lwIP throughput to that of the FreeBSD stack.In this matchup lwIP gets a well deserved
silver medal.Not bad for a newcomer ;)
Bugreports (or even better patches) at jani@iv.ro not the lwip or ecos mailing lists!!
Only if you peek into the lwip sources and think you found a bug post to lwip-users.

7
ports/ecos/copy Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
#make an ecos epk from CVS lwIP
CURRENT=$EPK/net/lwip_tcpip/current
mkdir -p `dirname $CURRENT/$2`
cp -f $LWIP_CVS/$1 $CURRENT/$2

View File

@ -0,0 +1,81 @@
2003-02-28 Jani Monoses <jani@iv.ro>
* all: Synch with latest lwip CVS and a bunch of other updates
2002-06-21 Jani Monoses <jani@iv.ro>
* all:sync with/tweak lwIP from lwIP-CVS snapshot 29-05-2002 (no more memory reclaims,
reorganized ARP/ethernet layer,TCP modifications...)
* put the package under net/ where the other two *BSD stacks are and
* ecosif.c:modified to use new etharp code.
2002-05-17 Jani Monoses <jani@iv.ro>
* tcpip.c:bugfix from lwIP CVS in addition to the ones locally corrected
during the past few weeks
* lwip.cdl:saner(greater) default for TCP related values
2002-04-24 Jani Monoses <jani@iv.ro>
* sys_arch.c: replace fix_mempool with allocation 'by hand'
for thread stacks to not worry about allocator overhead and
it's simpler too.
2002-04-23 Jani Monoses <jani@iv.ro>
* lwip.cdl,sys_arch.c : memory usage for thread stacks and others
configurable
* sys_arch.c: "stupid bug of the month" - use parantheses in macro
tick_to_ms().Without this semaphore wait could falsely return 0
every 10 minutes or so meaning 'not taken' which would lead to
deadlock.
2002-04-17 Jani Monoses <jani@iv.ro>
* bugfixes in sys_arch.c: if no memory is available return NULL
semaphore and mbox (use cyg_mempool_var_try_alloc() instead of blocking
version as this prevents DoS attacks when memory is full).Free the
allocated memory too after semaphore and mbox destruction.
2002-04-15 Cristian Vlasin <cris@iv.ro>
* more CDL work:IP addresses now settable,statistics gathering
selection
2002-04-12 Jani Monoses <jani@iv.ro>,Cristian Vlasin <cris@iv.ro>
* tests/ : add test cases
* cdl/lwip.cdl : verbosity options and some other configuration
* bugfix in sys_arch.c : sys_arch_mbox_fetch should check for NULL data
* changed package name to CYGPKG_NET_LWIP
2002-04-05 Jani Monoses <jani@iv.ro>
* First version.Contains a somewhat reorganized lwIP-0.5.3 tree,
a bugfix in sockets.c and eCos glue.
//===========================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000, 2001,2002 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//===========================================================================

View File

@ -0,0 +1,539 @@
#====================================================================
#
# lwip_net.cdl
#
# lwIP network stack configuration data
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): cris@iv.ro, jani@iv.ro
# Original data: jani@iv.ro
# Contributors:
# Date: 2002-06-21
#
#####DESCRIPTIONEND####
#
# ====================================================================
# !!!!conditional compile for UDP, sockets ...
cdl_package CYGPKG_NET_LWIP {
display "lwIP"
description "Lightweight TCP/IP stack"
requires {CYGPKG_IO_ETH_DRIVERS || (CYGPKG_LWIP_SLIP == 1)}
compile core/mem.c \
core/memp.c \
core/netif.c \
core/pbuf.c \
core/stats.c \
core/sys.c \
core/tcp.c \
core/tcp_in.c \
core/tcp_out.c \
core/udp.c \
core/inet.c \
core/ipv4/icmp.c \
core/ipv4/ip.c \
core/ipv4/ip_addr.c \
core/ipv4/ip_frag.c \
api/api_lib.c \
api/api_msg.c \
api/tcpip.c \
api/err.c \
api/sockets.c \
netif/etharp.c \
ecos/sys_arch.c \
ecos/init.c
cdl_option CYGPKG_LWIP_STATS {
display "Turn ON/OFF statistics"
flavor bool
default_value 0
description "
Check this box to turn ON statistics options for lwIP."
}
cdl_component CYGPKG_LWIP_IPV4_CONF {
display "IPV4 netconf"
flavor none
no_define
description "
See suboptions to define gateway IP, local IP and netmask."
cdl_option CYGPKG_LWIP_SERV_ADDR {
display "Gateway IP"
flavor data
default_value {"192,168,1,1"}
description "
Gateway's IP address."
}
cdl_option CYGPKG_LWIP_MY_ADDR {
display "My IP"
flavor data
default_value {"192,168,1,222"}
description "
The IP address for this device."
}
cdl_option CYGPKG_LWIP_NETMASK {
display "Netmask"
flavor data
default_value {"255,255,255,0"}
description "
Netmask of the local network."
}
}
cdl_component CYGPKG_LWIP_MEM_OPTIONS {
display "Memory options"
flavor none
no_define
description "
Memory options for lwIP."
cdl_option CYGPKG_LWIP_MEM_ALIGNMENT {
display "Memory alignment"
flavor data
default_value 4
description "
MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4,
2 byte alignment -> define MEM_ALIGNMENT to 2."
}
cdl_option CYGPKG_LWIP_MEM_SIZE {
display "Memory size"
flavor data
default_value 2000
description "
MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_PBUF {
display "Number of memp struct pbufs"
flavor data
default_value 8
description "
MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_UDP_PCB {
display "Simultaneous UDP control blocks "
flavor data
default_value 4
description "
MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP 'connection'."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_TCP_PCB {
display "Simultaneous active TCP connections "
flavor data
default_value 5
description "
MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_TCP_PCB_LISTEN {
display "Listening TCP connections"
flavor data
default_value 8
description "
MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_TCP_SEG {
display "Simultaneous TCP segments queued"
flavor data
default_value 8
description "
MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_SYS_TIMEOUT {
display "Simultaneous active timeouts"
flavor data
default_value 3
description "
MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts."
}
cdl_component CYGPKG_LWIP_CYGPKG_LWIP_MEM_SEQ_API {
display "Sequential API settings"
flavor none
no_define
description "
The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API."
cdl_option CYGPKG_LWIP_MEMP_NUM_NETBUF {
display "Struct netbufs"
flavor data
default_value 2
description "
MEMP_NUM_NETBUF: the number of struct netbufs."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_NETCONN {
display "Struct netconns"
flavor data
default_value 4
description "
MEMP_NUM_NETCONN: the number of struct netconns."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_APIMSG {
display "Struct api_msgs"
flavor data
default_value 8
description "
MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs."
}
cdl_option CYGPKG_LWIP_MEMP_NUM_TCPIP_MSG {
display "Struct tcpip_msgs"
flavor data
default_value 8
description "
MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c."
}
}
}
cdl_component CYGPKG_LWIP_PBUF_OPTIONS {
display "PBUF"
flavor none
no_define
cdl_option CYGPKG_LWIP_PBUF_POOL_SIZE {
display "PBUF pool size"
flavor data
default_value 6
description "
PBUF_POOL_SIZE: the number of buffers in the pbuf pool."
}
cdl_option CYGPKG_LWIP_PBUF_POOL_BUFSIZE {
display "PBUF buffer size"
flavor data
default_value 1024
description "
PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool."
}
cdl_option CYGPKG_LWIP_PBUF_LINK_HLEN {
display "Allocation for a link level header"
flavor data
calculated {CYGPKG_LWIP_SLIP ? 0 : 16}
description "
PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header."
}
}
cdl_component CYGPKG_LWIP_TCP_OPTIONS {
display "TCP"
flavor none
no_define
cdl_option CYGPKG_LWIP_TCP {
display "Activate TCP"
flavor bool
default_value 1
description ""
}
cdl_option CYGPKG_LWIP_TCP_TTL {
display "Time To Live"
flavor data
default_value 255
description ""
}
cdl_option CYGPKG_LWIP_TCP_QUEUE_OOSEQ {
display "Queue segments"
flavor bool
default_value 1
description "
Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory."
}
cdl_option CYGPKG_LWIP_TCP_MSS {
display "Maximum segment size"
flavor data
default_value 1460
description "
TCP Maximum segment size."
}
cdl_option CYGPKG_LWIP_TCP_SND_BUF {
display "Sender buffer space"
flavor data
default_value 1460
description "
TCP sender buffer space (bytes)."
}
cdl_option CYGPKG_LWIP_TCP_SND_QUEUELEN {
display "Sender pbufs"
flavor data
calculated "4 * CYGPKG_LWIP_TCP_SND_BUF/CYGPKG_LWIP_TCP_MSS"
description "
TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work."
}
cdl_option CYGPKG_LWIP_TCP_WND {
display "Receive window"
flavor data
default_value 4096
description "
TCP receive window."
}
cdl_option CYGPKG_LWIP_TCP_MAXRTX {
display "Segment retransmissions"
flavor data
default_value 12
description "
Maximum number of retransmissions of data segments."
}
cdl_option CYGPKG_LWIP_TCP_SYNMAXRTX {
display "Syn retransmissions"
flavor data
default_value 4
description "
Maximum number of retransmissions of SYN segments."
}
}
cdl_component CYGPKG_LWIP_ARP_OPTIONS {
display "ARP"
flavor none
no_define
cdl_option CYGPKG_LWIP_ARP_TABLE_SIZE {
display "ARP table size"
flavor data
default_value 10
description ""
}
}
cdl_component CYGPKG_LWIP_IP {
display "IP"
flavor none
no_define
cdl_option CYGPKG_LWIP_IP_FORWARD {
display "IP forwarding"
flavor bool
default_value 1
description "
Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0."
}
cdl_option CYGPKG_LWIP_IP_OPTIONS {
display "Allow IP options"
flavor bool
default_value 1
description "
If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped."
}
}
cdl_component CYGPKG_LWIP_ICMP_OPTIONS {
display "ICMP"
flavor none
no_define
cdl_option CYGPKG_LWIP_ICMP_TTL {
display "ICMP Time To Live"
flavor data
default_value 255
description ""
}
}
cdl_component CYGPKG_LWIP_DHCP_OPTIONS {
display "DHCP"
flavor none
no_define
cdl_option CYGPKG_LWIP_DHCP {
display "Activate DHCP"
flavor bool
default_value 0
description "
Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces."
compile core/dhcp.c
}
cdl_option CYGPKG_LWIP_DHCP_DOES_ARP_CHECK {
display "Check offered address"
flavor bool
default_value 0
description "
1 if you want to do an ARP check on the offered address
(recommended)."
}
}
cdl_component CYGPKG_LWIP_SLIP {
display "SLIP"
flavor bool
requires CYGPKG_IO_SERIAL_DEVICES
default_value 0
description "IP over serial line"
compile netif/slipif.c ecos/sio.c
cdl_option CYGPKG_LWIP_SLIP_DEV {
display "Serial device"
flavor data
default_value {"\"/dev/ser2\""}
description "
Which serial port to use SLIP on."
}
}
cdl_component CYGPKG_LWIP_UDP_OPTIONS {
display "UDP"
flavor none
no_define
cdl_option CYGPKG_LWIP_UDP {
display "Activate UDP"
flavor bool
default_value 1
description ""
}
cdl_option CYGPKG_LWIP_UDP_TTL {
display "Time To Live"
flavor data
default_value 255
description ""
}
}
cdl_component CYGPKG_LWIP_APP_MEM_OPTIONS {
display "Memory options for apps"
flavor none
no_define
description "Memory options for applications."
cdl_option CYGNUM_LWIP_VARMEMPOOL_SIZE {
display "Size of variable memory pool"
flavor data
default_value 2048
description "
Memory required to hold semaphore, mbox and thread structures
are allocated from this memory pool.
"
}
cdl_option CYGNUM_LWIP_APP_THREADS {
display "Number of network threads in application"
flavor data
default_value 1
description "
At startup at least two lwIP threads are created:the polling(input) thread
and the TCP/IP (output) thread.Additionally your application creates one
or more threads.
Set this option to the maximum number of threads you will create through
sys_thread_new().Threads which you create through cyg_thread_create()
are not lwIP threads and don't count.This number is needed so that enough
static memory is reserved for stack space.
"
}
cdl_option CYGNUM_LWIP_THREAD_STACK_SIZE {
display "Size of per thread stack in lwIP"
flavor data
default_value 4096
description "
Since stack space for threads needs to be statically allocated you can
specify the amount of memory to use for each network thread.
"
}
}
cdl_option CYGPKG_NET_LWIP_TESTS {
display "Some lwIP tests"
flavor data
no_define
calculated {
"tests/tcpecho tests/udpecho tests/httpd.c tests/socket.c tests/nc_test_slave"
}
description "
This option specifies the set of tests for lwIP.They show the usage of
the raw, the sequential and the BSD socket compatible APIs"
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: cc.h,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__
#include <cyg/error/codes.h>
#include <cyg/infra/cyg_type.h>
#if (CYG_BYTEORDER == CYG_LSBFIRST)
#define BYTE_ORDER LITTLE_ENDIAN
#else
#define BYTE_ORDER BIG_ENDIAN
#endif
typedef unsigned char u8_t;
typedef signed char s8_t;
typedef unsigned short u16_t;
typedef signed short s16_t;
typedef unsigned long u32_t;
typedef signed long s32_t;
typedef unsigned long mem_ptr_t;
#define PACK_STRUCT_FIELD(x) x __attribute__((packed))
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#include <cyg/infra/cyg_ass.h>
#define LWIP_PLATFORM_DIAG(x) {diag_printf x;}
#define LWIP_PLATFORM_ASSERT(x) {CYG_FAIL(x);}
#define SYS_ARCH_DECL_PROTECT(x)
#define SYS_ARCH_PROTECT(x)
#define SYS_ARCH_UNPROTECT(x)
#endif /* __ARCH_CC_H__ */

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: perf.h,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#ifndef __PERF_H__
#define __PERF_H__
#define PERF_START /* null definition */
#define PERF_STOP(x) /* null definition */
#endif /* __PERF_H__ */

View File

@ -0,0 +1,13 @@
#ifndef __SYS_ECOS_H__
#define __SYS_ECOS_H__
#include <cyg/kernel/kapi.h>
#define SYS_MBOX_NULL (sys_mbox_t)NULL
#define SYS_SEM_NULL (sys_sem_t)NULL
typedef cyg_sem_t * sys_sem_t;
typedef cyg_handle_t sys_mbox_t;
typedef cyg_thread * sys_thread_t;
#endif /* __SYS_ECOS_H__ */

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: lwipopts.h,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
/*include the configuration made with configtool*/
#include <pkgconf/net_lwip.h>
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT CYGPKG_LWIP_MEM_ALIGNMENT
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE CYGPKG_LWIP_MEM_SIZE
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF CYGPKG_LWIP_MEMP_NUM_PBUF
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB CYGPKG_LWIP_MEMP_NUM_UDP_PCB
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB CYGPKG_LWIP_MEMP_NUM_TCP_PCB
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN CYGPKG_LWIP_MEMP_NUM_TCP_PCB_LISTEN
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG CYGPKG_LWIP_MEMP_NUM_TCP_SEG
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT CYGPKG_LWIP_MEMP_NUM_SYS_TIMEOUT
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF CYGPKG_LWIP_MEMP_NUM_NETBUF
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN CYGPKG_LWIP_MEMP_NUM_NETCONN
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
communication between the TCP/IP stack and the sequential
programs. */
#define MEMP_NUM_API_MSG CYGPKG_LWIP_MEMP_NUM_APIMSG
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG CYGPKG_LWIP_MEMP_NUM_TCPIP_MSG
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE CYGPKG_LWIP_PBUF_POOL_SIZE
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE CYGPKG_LWIP_PBUF_POOL_BUFSIZE
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
#define PBUF_LINK_HLEN CYGPKG_LWIP_PBUF_LINK_HLEN
/* ---------- TCP options ---------- */
#define LWIP_TCP CYGPKG_LWIP_TCP
#define TCP_TTL CYGPKG_LWIP_TCP_TTL
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ CYGPKG_LWIP_TCP_QUEUE_OOSEQ
/* TCP Maximum segment size. */
#define TCP_MSS CYGPKG_LWIP_TCP_MSS
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF CYGPKG_LWIP_TCP_SND_BUF
#define TCP_SNDLOWAT TCP_SND_BUF/2
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN CYGPKG_LWIP_TCP_SND_QUEUELEN
/* TCP receive window. */
#define TCP_WND CYGPKG_LWIP_TCP_WND
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX CYGPKG_LWIP_TCP_MAXRTX
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX CYGPKG_LWIP_TCP_SYNMAXRTX
/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE CYGPKG_LWIP_ARP_TABLE_SIZE
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD CYGPKG_LWIP_IP_FORWARD
/* If defined to 1, IP options are allowed (but not parsed). If
defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS CYGPKG_LWIP_IP_OPTIONS
/* ---------- ICMP options ---------- */
#define ICMP_TTL CYGPKG_LWIP_ICMP_TTL
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces.*/
#ifdef CYGPKG_LWIP_DHCP
#define LWIP_DHCP CYGPKG_LWIP_DHCP
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK CYGPKG_LWIP_DHCP_DOES_ARP_CHECK
#endif
/* ---------- UDP options ---------- */
#define LWIP_UDP CYGPKG_LWIP_UDP
#define UDP_TTL CYGPKG_LWIP_UDP_TTL
#define LWIP_SLIP CYGPKG_LWIP_SLIP
#define SLIP_DEV CYGPKG_LWIP_SLIP_DEV
/* ---------- Statistics options ---------- */
#define STATS
#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */
#endif /* __LWIPOPTS_H__ */

View File

@ -0,0 +1,72 @@
/*
* init.c - helper code for initing applications that use lwIP
*/
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "lwip/ip_addr.h"
#include "lwipopts.h"
#if LWIP_DHCP
#include "lwip/dhcp.h"
#endif
void inline IP_ADDR(struct ip_addr *ipaddr, char a, char b, char c, char d)
{
IP4_ADDR(ipaddr,a,b,c,d);
}
void tcpip_init_done(void * arg)
{
sys_sem_t *sem = arg;
sys_sem_signal(*sem);
}
struct netif mynetif;
extern err_t ecosif_init(struct netif *);
/*
* Called by the eCos application at startup
* wraps various init calls
*/
void lwip_init(void)
{
sys_sem_t sem;
sys_init(); /* eCos specific initialization */
mem_init(); /* heap based memory allocator */
memp_init(); /* pool based memory allocator */
pbuf_init(); /* packet buffer allocator */
netif_init(); /* netif layer */
/* Start the stack.It will spawn a new dedicated thread */
sem = sys_sem_new(0);
tcpip_init(tcpip_init_done,&sem);
sys_sem_wait(sem);
sys_sem_free(sem);
#if LWIP_SLIP
lwip_set_addr(&mynetif);
slipif_init(&mynetif);
#else
ecosglue_init();
#endif
// ecosif_init(&mynetif);
}
void lwip_set_addr(struct netif *netif)
{
struct ip_addr ipaddr, netmask, gw;
IP_ADDR(&gw, CYGPKG_LWIP_SERV_ADDR);
IP_ADDR(&ipaddr, CYGPKG_LWIP_MY_ADDR);
IP_ADDR(&netmask, CYGPKG_LWIP_NETMASK);
netif_set_addr(netif, &ipaddr, &netmask, &gw);
netif->next = NULL;
netif_list = netif;
netif->input = tcpip_input;
}

View File

@ -0,0 +1,47 @@
/* Serial operations for SLIP */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/netif.h"
#include "lwipopts.h"
#include <cyg/io/io.h>
static cyg_io_handle_t ser;
static int len;
void sio_send(char c,void * dev)
{
len = 1;
cyg_io_write(*(cyg_io_handle_t*)dev, &c, &len);
// if (len!=1)
// diag_printf("err send\n");
}
char sio_recv(void * dev)
{
char c;
len = 1;
cyg_io_read(*(cyg_io_handle_t *)dev, &c, &len);
// if (len!=1)
// diag_printf("err recv\n");
return c;
}
void * sio_open(int devnum)
{
int res;
// diag_printf("fun\n");
res = cyg_io_lookup(SLIP_DEV, &ser);
// if (res != ENOERR)
// diag_printf("shit\n");
return &ser;
}

View File

@ -0,0 +1,235 @@
/*
* This file implements the eCos specific sys_arch functions used by lwIP
*/
#include "lwipopts.h"
#include "arch/sys_arch.h"
#include "lwip/sys.h"
#include "lwip/def.h"
#include "lwip/debug.h"
//FIXME use CYG_HWR_whatever for RTC
/* lwIp timeouts are milliseconds, eCos time unit is clock tick */
//1s = 1000ms = 100ticks (eCos default is 100 tick per second for most(all?) platforms)
#define tick_to_msec(tick) ((u16_t)((tick)*10+1))
#define msec_to_tick(msec) ((cyg_tick_count_t)(msec+9)/10)
/* We use a common var mempool for allocating semaphores, mboxes and threads... */
static char memvar[CYGNUM_LWIP_VARMEMPOOL_SIZE];
static cyg_mempool_var var_mempool;
static cyg_handle_t var_mempool_h;
#define SYS_THREADS 2 /* polling thread and tcpip_thread */
#define THREAD_COUNT (CYGNUM_LWIP_APP_THREADS + SYS_THREADS)
static char memfix[CYGNUM_LWIP_THREAD_STACK_SIZE * THREAD_COUNT];
/* List of threads: associate eCos thread info with lwIP timeout info */
struct lwip_thread {
struct lwip_thread * next;
struct sys_timeouts to;
cyg_handle_t th;
cyg_thread t;
} *threads;
/*
* Timeout for threads which were not created by sys_thread_new
* usually "main"
*/
struct sys_timeouts to;
/*
* Set up memory pools and threads
*/
void sys_init(void)
{
cyg_mempool_var_create(memvar, sizeof(memvar), &var_mempool_h, &var_mempool);
threads = NULL;
to.next = NULL;
}
/*------------------------------------ Message boxes ----------------------------------------*/
/*
* Create a new mbox.If no memory is available return NULL
*/
sys_mbox_t sys_mbox_new(void)
{
cyg_mbox * mbox;
cyg_handle_t m;
mbox = (cyg_mbox *)cyg_mempool_var_try_alloc(var_mempool_h, sizeof(cyg_mbox));
/* out of memory? */
if(!mbox)
return SYS_MBOX_NULL;
cyg_mbox_create(&m, mbox);
return m;
}
/*
* Destroy the mbox and release the space it took up in the pool
*/
void sys_mbox_free(sys_mbox_t mbox)
{
cyg_mbox_delete(mbox);
cyg_mempool_var_free(var_mempool_h,(void*)mbox);
}
/*
* Post data to a mbox.
*/
void sys_mbox_post(sys_mbox_t mbox, void *data)
{
while (cyg_mbox_put(mbox,data) == false);
}
#if 0
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg){
void *d;
d = cyg_mbox_get(mbox);
if (msg)
*msg = d;
}
#endif
/*
* Fetch data from a mbox.Wait for at most timeout millisecs
* Return 0 if timed out otherwise time spent waiting or 1
* if there was no wait.
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u32_t timeout)
{
void *d;
cyg_tick_count_t end_time = 0, start_time = 0;
if (timeout) {
start_time = cyg_current_time();
d = cyg_mbox_timed_get(mbox, start_time + msec_to_tick(timeout));
end_time = cyg_current_time();
if (d == NULL)
return 0;
} else {
d = cyg_mbox_get(mbox);
}
if (data)
*data = d;
return tick_to_msec(end_time - start_time);
}
/*----------------------------------------- Semaphores ------------------------------------ */
/*
* Create a new semaphore and initialize it.
* If no memory is available return NULL
*/
sys_sem_t sys_sem_new(u8_t count)
{
sys_sem_t sem;
sem = (cyg_sem_t *)cyg_mempool_var_try_alloc(var_mempool_h, sizeof(cyg_sem_t));
/* out of memory? */
if(!sem)
return SYS_SEM_NULL;
cyg_semaphore_init(sem, count);
return sem;
}
#if 0
void
sys_sem_wait(sys_sem_t sem)
{
cyg_semaphore_wait(sem);
}
void
sys_timeout(u16_t msecs, sys_timeout_handler h, void *arg)
{}
#endif
/*
* Wait on a semaphore for at most timeout millisecs
* Return 0 if timed out otherwise time spent waiting or 1
* if there was no wait.
*/
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
{
cyg_bool_t r;
cyg_tick_count_t end_time = 0, start_time = 0;
if (timeout) {
start_time = cyg_current_time();
r = cyg_semaphore_timed_wait(sem, start_time + msec_to_tick(timeout));
end_time = cyg_current_time();
if (r == false) {
return 0;
}
} else {
cyg_semaphore_wait(sem);
}
return tick_to_msec(end_time - start_time);
}
/*
* Signal a semaphore
*/
void sys_sem_signal(sys_sem_t sem)
{
cyg_semaphore_post(sem);
}
/*
* Destroy the semaphore and release the space it took up in the pool
*/
void sys_sem_free(sys_sem_t sem)
{
cyg_semaphore_destroy(sem);
cyg_mempool_var_free(var_mempool_h,(void*)sem);
}
/*
* Create new thread
*/
sys_thread_t sys_thread_new(void (*function) (void *arg), void *arg)
{
struct lwip_thread * nt;
void * stack;
static int thread_count = 0;
nt = (struct lwip_thread *)cyg_mempool_var_alloc(var_mempool_h, sizeof(struct lwip_thread));
nt->next = threads;
nt->to.next = NULL;
threads = nt;
stack = (void *)(memfix+CYGNUM_LWIP_THREAD_STACK_SIZE*thread_count++);
cyg_thread_create(5, (cyg_thread_entry_t *)function, (cyg_addrword_t)arg,
(char *)arg , stack, CYGNUM_LWIP_THREAD_STACK_SIZE, &(nt->th), &(nt->t) );
cyg_thread_resume(nt->th);
return NULL;
}
/*
* Return current thread's timeout info
*/
struct sys_timeouts *sys_arch_timeouts(void)
{
cyg_handle_t ct;
struct lwip_thread *t;
ct = cyg_thread_self();
for(t = threads; t; t = t->next)
if (t->th == ct)
return &(t->to);
return &to;
}

View File

@ -0,0 +1,274 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: httpd.c,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
struct http_state {
char *file;
u32_t left;
u8_t retries;
};
/* Stack smashing arch-independent shellcode: will brick your target :-) */
static const char sdata[] __attribute__ ((aligned)) = {
0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32,
0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x43, 0x6f, 0x6e,
0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a,
0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c,
0xd, 0xa, 0xd, 0xa, 0x49, 0x74, 0x20, 0x77, 0x6f, 0x72,
0x6b, 0x65, 0x64, 0x2e, 0xa, };
/*-----------------------------------------------------------------------------------*/
static void
conn_err(void *arg, err_t err)
{
struct http_state *hs;
hs = arg;
mem_free(hs);
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
mem_free(hs);
tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
err_t err;
u16_t len;
/* We cannot send more data than space avaliable in the send
buffer. */
if(tcp_sndbuf(pcb) < hs->left) {
len = tcp_sndbuf(pcb);
} else {
len = hs->left;
}
do {
err = tcp_write(pcb, hs->file, len, 0);
if(err == ERR_MEM) {
len /= 2;
}
} while(err == ERR_MEM && len > 1);
if(err == ERR_OK) {
hs->file += len;
hs->left -= len;
}
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
struct http_state *hs;
hs = arg;
/* printf("Polll\n");*/
if(hs == NULL) {
/* printf("Null, close\n");*/
tcp_abort(pcb);
return ERR_ABRT;
} else {
++hs->retries;
if(hs->retries == 4) {
tcp_abort(pcb);
return ERR_ABRT;
}
send_data(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
struct http_state *hs;
hs = arg;
hs->retries = 0;
if(hs->left > 0) {
send_data(pcb, hs);
} else {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
int i;
char *data;
struct http_state *hs;
hs = arg;
if(err == ERR_OK && p != NULL) {
/* Inform TCP that we have taken the data. */
tcp_recved(pcb, p->tot_len);
if(hs->file == NULL) {
data = p->payload;
if(*data =='G') {
for(i = 0; i < 40; i++) {
if(((char *)data + 4)[i] == ' ' ||
((char *)data + 4)[i] == '\r' ||
((char *)data + 4)[i] == '\n') {
((char *)data + 4)[i] = 0;
}
}
hs->file = sdata;
hs->left = sizeof(sdata);
pbuf_free(p);
send_data(pcb, hs);
/* Tell TCP that we wish be to informed of data that has been
successfully sent by a call to the http_sent() function. */
tcp_sent(pcb, http_sent);
} else {
pbuf_free(p);
close_conn(pcb, hs);
}
} else {
pbuf_free(p);
}
}
if(err == ERR_OK && p == NULL) {
close_conn(pcb, hs);
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct http_state *hs;
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
hs = mem_malloc(sizeof(struct http_state));
if(hs == NULL) {
return ERR_MEM;
}
/* Initialize the structure. */
hs->file = NULL;
hs->left = 0;
hs->retries = 0;
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, hs);
/* Tell TCP that we wish to be informed of incoming data by a call
to the http_recv() function. */
tcp_recv(pcb, http_recv);
tcp_err(pcb, conn_err);
tcp_poll(pcb, http_poll, 4);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void *arg)
{
struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 80);
pcb = tcp_listen(pcb);
tcp_accept(pcb, http_accept);
while(1)
cyg_thread_delay(1000);
}
void
tmain(void * p)
{
lwip_init();
sys_thread_new(httpd_init, (void*)"httpd");
}
#define STACK_SIZE 0x1000
static char stack[STACK_SIZE];
static cyg_thread thread_data;
static cyg_handle_t thread_handle;
void
cyg_user_start(void)
{
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
tmain, // entry
0, // entry parameter
"thread", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle, // Handle
&thread_data // Thread data structure
);
cyg_thread_resume(thread_handle); // Start it
}

View File

@ -0,0 +1,144 @@
//==========================================================================
//
// tests/nc_test_framework.h
//
// Network characterization tests framework
//
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// Date: 2000-01-10
// Purpose:
// Description:
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
#ifndef _TESTS_NC_TEST_FRAMEWORK_H_
#define _TESTS_NC_TEST_FRAMEWORK_H_
#define test_printf diag_printf
typedef cyg_addrword_t test_param_t;
#ifndef true
#define false 0
#define true 1
#endif
#define NC_SLAVE_PORT 7777
#define NC_MASTER_PORT 7776
#define NC_TESTING_SLAVE_PORT 8770
#define NC_TESTING_MASTER_PORT 8771
#define __string(s) #s
#define _string(s) __string(s)
//
// The basic idea behind this test structure is that one end will run
// in "slave" mode and the other in "master" mode. Typically, the slave
// will run on a target platform with the master running on a host.
//
// The slave starts up by listening for a connection on the "SLAVE_PORT".
// In order for the testing to require the minimum stack support, this
// connection (and the protocol) will use UDP.
//
// The master will connect to the slave and send it a request over this
// connection. Once the slave accepts the request, then master and slave
// will execute the operation, typically a test. The control connection
// will remain active until the master sends a 'disconnect' request. The
// control connection will be broken after the reply to this request has
// been sent.
//
#define MAX_ERRORS 5 // Give up after this many errors
#define NC_REPLY_TIMEOUT 10 // The slave may be slow
#define NC_TEST_TIMEOUT 3 // More generous for tests
#define NC_RESULTS_TIMEOUT (MAX_ERRORS+2)*NC_TEST_TIMEOUT
struct nc_request {
int type; // Description of request
int seq; // Sequence number, used to build response
int nbufs; // Number of "buffers" to send
int buflen; // Length of each buffer
int slave_port; // Network ports to use
int master_port;
int timeout; // Max time to wait for any packet
};
#define NC_REQUEST_DISCONNECT 0x0001
#define NC_REQUEST_UDP_SEND 0x0010 // Slave to send UDP data
#define NC_REQUEST_UDP_RECV 0x0011 // Slave to receive UDP data
#define NC_REQUEST_UDP_ECHO 0x0012 // Master->slave->master
#define NC_REQUEST_TCP_SEND 0x0020 // Slave to send TCP data
#define NC_REQUEST_TCP_RECV 0x0021 // Slave to receive TCP data
#define NC_REQUEST_TCP_ECHO 0x0022 // Master->slave->master
#define NC_REQUEST_START_IDLE 0x0100 // Start some idle processing
#define NC_REQUEST_STOP_IDLE 0x0101 // Stop idle processing
#define NC_REQUEST_SET_LOAD 0x0200 // Set the background load level
struct nc_reply {
int response; // ACK or NAK
int seq; // Must match request
int reason; // If NAK, why request turned down
union { // Miscellaneous data, depending on request
struct {
long elapsed_time; // In 10ms "ticks"
long count[2]; // Result
} idle_results;
} misc;
};
#define NC_REPLY_ACK 0x0001 // Request accepted
#define NC_REPLY_NAK 0x0000 // Request denied
#define NC_REPLY_NAK_UNKNOWN_REQUEST 0x0001
#define NC_REPLY_NAK_BAD_REQUEST 0x0002 // Slave can't handle
#define NC_REPLY_NAK_NO_BACKGROUND 0x0003 // Slave can't do background/idle
//
// Test data 'packets' look like this
struct nc_test_data {
long key1;
int seq;
int len;
long key2;
char data[0]; // Actual data
};
#define NC_TEST_DATA_KEY1 0xC0DEADC0
#define NC_TEST_DATA_KEY2 0xC0DEADC1
struct nc_test_results {
long key1; // Identify uniquely as a response record
int seq; // Matches request
int nsent;
int nrecvd;
long key2; // Additional verification
};
#define NC_TEST_RESULT_KEY1 0xDEADC0DE
#define NC_TEST_RESULT_KEY2 0xDEADC1DE
#endif // _TESTS_NC_TEST_FRAMEWORK_H_

View File

@ -0,0 +1,789 @@
//==========================================================================
//
// tests/nc_test_slave.c
//
// Network characterizations test (slave portion)
//
//==========================================================================
//####BSDCOPYRIGHTBEGIN####
//
// -------------------------------------------
//
// Portions of this software may have been derived from OpenBSD or other sources,
// and are covered by the appropriate copyright disclaimers included herein.
//
// -------------------------------------------
//
//####BSDCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// Date: 2000-01-10
// Purpose:
// Description:
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
// Network characterization test code - slave portion
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_arch.h>
#include "nc_test_framework.h"
#include <cyg/error/errno.h>
#include <cyg/error/codes.h>
#include <cyg/error/strerror.h>
#include <cyg/infra/diag.h>
#include <lwip/inet.h>
#include <lwip/arch.h>
#include <lwip/sockets.h>
#ifndef CYGPKG_LIBC_STDIO
#define perror(s) diag_printf(#s ": %s\n", strerror(errno))
#endif
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)
#define MAX_LOAD_THREAD_LEVEL 20
#define MIN_LOAD_THREAD_LEVEL 0
#define NUM_LOAD_THREADS 10
#define CYGPKG_NET_THREAD_PRIORITY 7
#define IDLE_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY+3
#define LOAD_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-1
#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-2
#define DESIRED_BACKGROUND_LOAD 20
#define CYGHWR_NET_DRIVERS 1
static char main_thread_stack[CYGHWR_NET_DRIVERS][STACK_SIZE];
static cyg_thread main_thread_data[CYGHWR_NET_DRIVERS];
static cyg_handle_t main_thread_handle[CYGHWR_NET_DRIVERS];
static char idle_thread_stack[STACK_SIZE];
static cyg_thread idle_thread_data;
static cyg_handle_t idle_thread_handle;
static cyg_sem_t idle_thread_sem;
volatile static long long idle_thread_count;
static cyg_tick_count_t idle_thread_start_time;
static cyg_tick_count_t idle_thread_stop_time;
static char load_thread_stack[NUM_LOAD_THREADS][STACK_SIZE];
static cyg_thread load_thread_data[NUM_LOAD_THREADS];
static cyg_handle_t load_thread_handle[NUM_LOAD_THREADS];
static cyg_sem_t load_thread_sem[NUM_LOAD_THREADS];
static long load_thread_level;
static void calibrate_load(int load);
static void start_load(int load);
static void do_some_random_computation(int p);
#define abs(n) ((n) < 0 ? -(n) : (n))
#define test_param_t cyg_addrword_t
#ifdef CYGDBG_NET_TIMING_STATS
extern void show_net_times(void);
#endif
#define MAX_BUF 8192
static unsigned char in_buf[MAX_BUF], out_buf[MAX_BUF];
extern void
cyg_test_exit(void);
static void
test_delay(int ticks)
{
cyg_thread_delay(ticks);
}
void
pexit(char *s)
{
perror(s);
#ifdef CYGDBG_NET_TIMING_STATS
show_net_times();
#endif
cyg_test_exit();
}
//
// Generic UDP test
//
static void
do_udp_test(int s1, struct nc_request *req, struct sockaddr_in *master)
{
int i, s, td_len, seq, seq_errors, lost;
struct sockaddr_in test_chan_slave, test_chan_master;
fd_set fds;
struct timeval timeout;
struct nc_test_results results;
struct nc_test_data *tdp;
int nsent, nrecvd;
int need_recv, need_send;
need_recv = true; need_send = true;
switch (ntohl(req->type)) {
case NC_REQUEST_UDP_SEND:
need_recv = false;
need_send = true;
break;
case NC_REQUEST_UDP_RECV:
need_recv = true;
need_send = false;
break;
case NC_REQUEST_UDP_ECHO:
break;
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
pexit("datagram socket");
}
memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave));
test_chan_slave.sin_family = AF_INET;
test_chan_slave.sin_len = sizeof(test_chan_slave);
test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY);
test_chan_slave.sin_port = htons(ntohl(req->slave_port));
if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) {
perror("bind");
close(s);
}
memcpy(&test_chan_master, master, sizeof(*master));
test_chan_master.sin_port = htons(ntohl(req->master_port));
nsent = 0; nrecvd = 0; seq = 0; seq_errors = 0; lost = 0;
for (i = 0; i < ntohl(req->nbufs); i++) {
if (need_recv) {
FD_ZERO(&fds);
FD_SET(s, &fds);
timeout.tv_sec = NC_TEST_TIMEOUT;
timeout.tv_usec = 0;
if (select(s+1, &fds, 0, 0, &timeout) <= 0) {
test_printf("recvfrom timeout, expecting seq #%d\n", seq);
if (++lost > MAX_ERRORS) {
test_printf("... giving up\n");
break;
}
} else {
nrecvd++;
tdp = (struct nc_test_data *)in_buf;
td_len = ntohl(req->buflen) + sizeof(struct nc_test_data);
if (recvfrom(s, tdp, td_len, 0, 0, 0) < 0) {
perror("recvfrom");
close(s);
return;
}
if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) &&
(ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) {
if (ntohl(tdp->seq) != seq) {
test_printf("Packets out of sequence - recvd: %d, expected: %d\n",
ntohl(tdp->seq), seq);
seq = ntohl(tdp->seq);
seq_errors++;
}
} else {
test_printf("Bad data packet - key: %x/%x, seq: %d\n",
ntohl(tdp->key1), ntohl(tdp->key2),
ntohl(tdp->seq));
}
}
}
if (need_send) {
int retries = 10;
int sent = false;
int res;
tdp = (struct nc_test_data *)out_buf;
tdp->key1 = htonl(NC_TEST_DATA_KEY1);
tdp->key2 = htonl(NC_TEST_DATA_KEY2);
tdp->seq = htonl(seq);
td_len = ntohl(req->buflen) + sizeof(struct nc_test_data);
tdp->len = htonl(td_len);
while (!sent && (--retries >= 0)) {
res = sendto(s, tdp, td_len, 0,
(struct sockaddr *)&test_chan_master, sizeof(test_chan_master));
if (res > 0) {
sent = true;
break;
}
if (errno == ENOBUFS) {
// Saturated the system
test_delay(1); // Time for 200 500 byte 10-baseT packets
} else {
// What else to do?
close(s);
return;
}
}
if (sent) {
nsent++;
} else {
perror("sendto");
}
}
seq++;
}
results.key1 = htonl(NC_TEST_RESULT_KEY1);
results.key2 = htonl(NC_TEST_RESULT_KEY2);
results.seq = req->seq;
results.nsent = htonl(nsent);
results.nrecvd = htonl(nrecvd);
if (sendto(s, &results, sizeof(results), 0,
(struct sockaddr *)&test_chan_master, sizeof(test_chan_master)) < 0) {
perror("sendto results");
}
close(s);
}
//
// Read data from a stream, accounting for the fact that packet 'boundaries'
// are not preserved. This can also timeout (which would probably wreck the
// data boundaries).
//
int
do_read(int fd, void *buf, int buflen)
{
char *p = (char *)buf;
int len = buflen;
int res;
while (len) {
res = read(fd, p, len);
if (res < 0) {
perror("read");
} else {
len -= res;
p += res;
if (res == 0) {
break;
}
}
}
return (buflen - len);
}
//
// Generic TCP test
//
static void
do_tcp_test(int s1, struct nc_request *req, struct sockaddr_in *master)
{
int i, s, len, td_len, seq, seq_errors, lost, test_chan, res;
struct sockaddr_in test_chan_slave, test_chan_master;
struct nc_test_results results;
struct nc_test_data *tdp;
int nsent, nrecvd;
int need_recv, need_send;
int one = 1;
static int slave_tcp_port = -1;
need_recv = true; need_send = true;
switch (ntohl(req->type)) {
case NC_REQUEST_TCP_SEND:
need_recv = false;
need_send = true;
break;
case NC_REQUEST_TCP_RECV:
need_recv = true;
need_send = false;
break;
case NC_REQUEST_TCP_ECHO:
break;
}
if (slave_tcp_port < 0) {
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) {
pexit("datagram socket");
}
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
perror("setsockopt SO_REUSEADDR");
return;
}
#ifdef SO_REUSEPORT
if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
perror("setsockopt SO_REUSEPORT");
return;
}
#endif
memset((char *) &test_chan_slave, 0, sizeof(test_chan_slave));
test_chan_slave.sin_family = AF_INET;
test_chan_slave.sin_len = sizeof(test_chan_slave);
test_chan_slave.sin_addr.s_addr = htonl(INADDR_ANY);
test_chan_slave.sin_port = htons(ntohl(req->slave_port));
if (bind(s, (struct sockaddr *) &test_chan_slave, sizeof(test_chan_slave)) < 0) {
perror("bind");
close(s);
}
listen(s, 128);
slave_tcp_port = s;
}
s = slave_tcp_port;
len = sizeof(test_chan_master);
if ((test_chan = accept(s, (struct sockaddr *)&test_chan_master, &len)) < 0) {
pexit("accept");
}
len = sizeof(test_chan_master);
getpeername(test_chan, (struct sockaddr *)&test_chan_master, &len);
// test_printf("connection from %s.%d\n", inet_ntoa(test_chan_master.sin_addr),
// ntohs(test_chan_master.sin_port));
nsent = 0; nrecvd = 0; seq = 0; seq_errors = 0; lost = 0;
for (i = 0; i < ntohl(req->nbufs); i++) {
if (need_recv) {
tdp = (struct nc_test_data *)in_buf;
td_len = ntohl(req->buflen) + sizeof(struct nc_test_data);
res = do_read(test_chan, tdp, td_len);
if (res != td_len) {
test_printf("recvfrom timeout, expecting seq #%d\n", seq);
if (++lost > MAX_ERRORS) {
test_printf("... giving up\n");
break;
}
} else {
nrecvd++;
if ((ntohl(tdp->key1) == NC_TEST_DATA_KEY1) &&
(ntohl(tdp->key2) == NC_TEST_DATA_KEY2)) {
if (ntohl(tdp->seq) != seq) {
test_printf("Packets out of sequence - recvd: %d, expected: %d\n",
ntohl(tdp->seq), seq);
seq = ntohl(tdp->seq);
seq_errors++;
}
} else {
test_printf("Bad data packet - key: %x/%x, seq: %d\n",
ntohl(tdp->key1), ntohl(tdp->key2),
ntohl(tdp->seq));
}
}
}
if (need_send) {
tdp = (struct nc_test_data *)out_buf;
tdp->key1 = htonl(NC_TEST_DATA_KEY1);
tdp->key2 = htonl(NC_TEST_DATA_KEY2);
tdp->seq = htonl(seq);
td_len = ntohl(req->buflen) + sizeof(struct nc_test_data);
tdp->len = htonl(td_len);
if (write(test_chan, tdp, td_len) != td_len) {
perror("write");
if (errno == ENOBUFS) {
// Saturated the system
test_delay(25);
} else {
// What else to do?
close(test_chan);
return;
}
} else {
nsent++;
}
}
seq++;
}
results.key1 = htonl(NC_TEST_RESULT_KEY1);
results.key2 = htonl(NC_TEST_RESULT_KEY2);
results.seq = req->seq;
results.nsent = htonl(nsent);
results.nrecvd = htonl(nrecvd);
if (write(test_chan, &results, sizeof(results)) != sizeof(results)) {
perror("write");
}
close(test_chan);
}
//
// Protocol driver for testing slave.
//
// This function is the main routine running here, handling requests sent from
// the master and providing various responses.
//
static void
nc_slave(test_param_t param)
{
int s, masterlen;
struct sockaddr_in my_addr, master;
struct nc_request req;
struct nc_reply reply;
int done = false;
test_printf("Start test for eth%d\n", param);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
pexit("datagram socket");
}
memset((char *) &my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_len = sizeof(my_addr);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
my_addr.sin_port = htons(NC_SLAVE_PORT);
if (bind(s, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
pexit("bind");
}
while (!done) {
masterlen = sizeof(master);
if (recvfrom(s, &req, sizeof(req), 0, (struct sockaddr *)&master, &masterlen) < 0) {
pexit("recvfrom");
}
#if 0
test_printf("Request %d from %s:%d\n", ntohl(req.type),
inet_ntoa(master.sin_addr), ntohs(master.sin_port));
#endif
reply.response = htonl(NC_REPLY_ACK);
reply.seq = req.seq;
switch (ntohl(req.type)) {
case NC_REQUEST_DISCONNECT:
done = true;
break;
case NC_REQUEST_UDP_SEND:
test_printf("UDP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_UDP_RECV:
test_printf("UDP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_UDP_ECHO:
test_printf("UDP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_TCP_SEND:
test_printf("TCP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_TCP_RECV:
test_printf("TCP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_TCP_ECHO:
test_printf("TCP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen));
break;
case NC_REQUEST_SET_LOAD:
start_load(ntohl(req.nbufs));
break;
case NC_REQUEST_START_IDLE:
test_printf("Start IDLE thread\n");
idle_thread_count = 0;
idle_thread_start_time = cyg_current_time();
cyg_semaphore_post(&idle_thread_sem);
break;
case NC_REQUEST_STOP_IDLE:
cyg_semaphore_wait(&idle_thread_sem);
idle_thread_stop_time = cyg_current_time();
test_printf("Stop IDLE thread\n");
reply.misc.idle_results.elapsed_time = htonl(idle_thread_stop_time - idle_thread_start_time);
reply.misc.idle_results.count[0] = htonl(idle_thread_count >> 32);
reply.misc.idle_results.count[1] = htonl((long)idle_thread_count);
break;
default:
test_printf("Unrecognized request: %d\n", ntohl(req.type));
reply.response = htonl(NC_REPLY_NAK);
reply.reason = htonl(NC_REPLY_NAK_UNKNOWN_REQUEST);
break;
}
if (sendto(s, &reply, sizeof(reply), 0, (struct sockaddr *)&master, masterlen) < 0) {
pexit("sendto");
}
if (reply.response == ntohl(NC_REPLY_NAK)) {
continue;
}
switch (ntohl(req.type)) {
case NC_REQUEST_UDP_SEND:
case NC_REQUEST_UDP_RECV:
case NC_REQUEST_UDP_ECHO:
do_udp_test(s, &req, &master);
break;
case NC_REQUEST_TCP_SEND:
case NC_REQUEST_TCP_RECV:
case NC_REQUEST_TCP_ECHO:
do_tcp_test(s, &req, &master);
break;
case NC_REQUEST_START_IDLE:
case NC_REQUEST_STOP_IDLE:
case NC_REQUEST_SET_LOAD:
default:
break;
}
}
close(s);
}
void
net_test(test_param_t param)
{
// int i;
if (param == 0) {
test_printf("Start Network Characterization - SLAVE\n");
calibrate_load(DESIRED_BACKGROUND_LOAD);
}
nc_slave(param);
#ifdef CYGDBG_NET_TIMING_STATS
show_net_times();
#endif
cyg_test_exit();
}
//
// This function is called to calibrate the "background load" which can be
// applied during testing. It will be called before any commands from the
// host are managed.
//
static void
calibrate_load(int desired_load)
{
long long no_load_idle, load_idle;
int percent_load;
int high, low;
// Set limits
high = MAX_LOAD_THREAD_LEVEL;
low = MIN_LOAD_THREAD_LEVEL;
test_printf("Start Network Characterization - SLAVE\n");
// Compute the "no load" idle value
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
test_printf("Start Network Characterization - SLAVE\n");
cyg_thread_delay(1*100); // Pause for one second
test_printf("Start Network Characterization - SLAVE\n");
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
test_printf("Start Network Characterization - SLAVE\n");
no_load_idle = idle_thread_count;
diag_printf("No load = %d\n", (int)idle_thread_count);
// First ensure that the HIGH level is indeed higher
while (true) {
load_thread_level = high;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("High Load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
if ( percent_load > desired_load )
break; // HIGH level is indeed higher
low = load_thread_level; // known to be lower
high *= 2; // else double it and try again
}
// Now chop down to the level required
while (true) {
load_thread_level = (high + low) / 2;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("Load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
if (((high-low) <= 1) || (abs(desired_load-percent_load) <= 2)) break;
if (percent_load < desired_load) {
low = load_thread_level;
} else {
high = load_thread_level;
}
}
// Now we are within a few percent of the target; scale the load
// factor to get a better fit, and test it, print the answer.
load_thread_level *= desired_load;
load_thread_level /= percent_load;
start_load(desired_load); // Start up a given load
idle_thread_count = 0;
cyg_semaphore_post(&idle_thread_sem); // Start idle thread
cyg_thread_delay(1*100); // Pause for one second
cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread
load_idle = idle_thread_count;
start_load(0); // Shut down background load
percent_load = 100 - ((load_idle * 100) / no_load_idle);
diag_printf("Final load[%d] = %d => %d%%\n", load_thread_level,
(int)idle_thread_count, percent_load);
// no_load_idle_count_1_second = no_load_idle;
}
//
// This function is called to set up a load level of 'load' percent (given
// as a whole number, e.g. start_load(20) would mean initiate a background
// load of 20%, leaving the cpu 80% idle).
//
static void
start_load(int load)
{
static int prev_load = 0;
int i;
test_printf("Set background load = %d%%\n", load);
if (load == 0) {
if (prev_load == 0) return; // Nothing out there to stop
for (i = 0; i < prev_load/10; i++) {
cyg_semaphore_wait(&load_thread_sem[i]);
}
prev_load = 0;
} else {
for (i = 0; i < load/10; i++) {
cyg_semaphore_post(&load_thread_sem[i]);
}
prev_load = load;
}
}
//
// These thread(s) do some amount of "background" computing. This is used
// to simulate a given load level. They need to be run at a higher priority
// than the network code itself.
//
// Like the "idle" thread, they run as long as their "switch" (aka semaphore)
// is enabled.
//
void
net_load(cyg_addrword_t who)
{
int i;
while (true) {
cyg_semaphore_wait(&load_thread_sem[who]);
for (i = 0; i < load_thread_level; i++) {
do_some_random_computation(i);
}
cyg_thread_delay(1); // Wait until the next 'tick'
cyg_semaphore_post(&load_thread_sem[who]);
}
}
//
// Some arbitrary computation, designed to use up the CPU and cause associated
// cache "thrash" behaviour - part of background load modelling.
//
static void
do_some_random_computation(int p)
{
// Just something that might be "hard"
volatile double x;
x = ((p * 10) * 3.14159) / 180.0; // radians
}
//
// This thread does nothing but count. It will be allowed to count
// as long as the semaphore is "free".
//
void
net_idle(cyg_addrword_t param)
{
while (true) {
cyg_semaphore_wait(&idle_thread_sem);
idle_thread_count++;
cyg_semaphore_post(&idle_thread_sem);
}
}
#if 0
void
cyg_start(void *n)
{
int i;
// Create processing threads
for (i = 0; i < CYGHWR_NET_DRIVERS; i++) {
cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority
net_test, // entry
i, // entry parameter
"Network test", // Name
&main_thread_stack[i][0], // Stack
STACK_SIZE, // Size
&main_thread_handle[i], // Handle
&main_thread_data[i] // Thread data structure
);
}
cyg_thread_resume(main_thread_handle[0]); // Start first one
// Create the idle thread environment
cyg_semaphore_init(&idle_thread_sem, 0);
cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority
net_idle, // entry
0, // entry parameter
"Network idle", // Name
&idle_thread_stack[0], // Stack
STACK_SIZE, // Size
&idle_thread_handle, // Handle
&idle_thread_data // Thread data structure
);
cyg_thread_resume(idle_thread_handle); // Start it
// Create the load threads and their environment(s)
for (i = 0; i < NUM_LOAD_THREADS; i++) {
cyg_semaphore_init(&load_thread_sem[i], 0);
cyg_thread_create(LOAD_THREAD_PRIORITY, // Priority
net_load, // entry
i, // entry parameter
"Background load", // Name
&load_thread_stack[i][0], // Stack
STACK_SIZE, // Size
&load_thread_handle[i], // Handle
&load_thread_data[i] // Thread data structure
);
cyg_thread_resume(load_thread_handle[i]); // Start it
}
cyg_scheduler_start();
}
#endif
void
tmain(void * p)
{
lwip_init();
sys_thread_new(net_test, 0);
}
static char stack[STACK_SIZE];
static cyg_thread thread_data;
static cyg_handle_t thread_handle;
void
cyg_user_start(void)
{
int i;
// Create the idle thread environment
cyg_semaphore_init(&idle_thread_sem, 0);
cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority
net_idle, // entry
0, // entry parameter
"Network idle", // Name
&idle_thread_stack[0], // Stack
STACK_SIZE, // Size
&idle_thread_handle, // Handle
&idle_thread_data // Thread data structure
);
cyg_thread_resume(idle_thread_handle); // Start it
// Create the load threads and their environment(s)
for (i = 0; i < NUM_LOAD_THREADS; i++) {
cyg_semaphore_init(&load_thread_sem[i], 0);
cyg_thread_create(LOAD_THREAD_PRIORITY, // Priority
net_load, // entry
i, // entry parameter
"Background load", // Name
&load_thread_stack[i][0], // Stack
STACK_SIZE, // Size
&load_thread_handle[i], // Handle
&load_thread_data[i] // Thread data structure
);
cyg_thread_resume(load_thread_handle[i]); // Start it
}
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
tmain, // entry
0, // entry parameter
"socket echo test", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle, // Handle
&thread_data // Thread data structure
);
cyg_thread_resume(thread_handle); // Start it
}

View File

@ -0,0 +1,58 @@
/* Simple test-case for the BSD socket API : echo on TCP port 7 */
#include "lwip/sys.h"
#define LWIP_COMPAT_SOCKETS 1
#include "lwip/sockets.h"
char buf[400];
static void
socket_thread(void *arg)
{
int sock,s;
int len;
struct sockaddr_in addr,rem;
sock = socket(AF_INET,SOCK_STREAM,0);
addr.sin_family = AF_INET;
addr.sin_port = htons(7);
addr.sin_addr.s_addr = INADDR_ANY;
bind(sock,(struct sockaddr *)&addr,sizeof(addr));
listen(sock,5);
while(1) {
len = sizeof(rem);
s = accept(sock,(struct sockaddr*)&rem,&len);
while((len = read(s,buf,400)) > 0)
write(s,buf,len);
close(s);
}
}
void
tmain(void * p)
{
lwip_init();
sys_thread_new(socket_thread, (void*)"socket");
}
#define STACK_SIZE 0x1000
static char stack[STACK_SIZE];
static cyg_thread thread_data;
static cyg_handle_t thread_handle;
void
cyg_user_start(void)
{
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
tmain, // entry
0, // entry parameter
"socket echo test", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle, // Handle
&thread_data // Thread data structure
);
cyg_thread_resume(thread_handle); // Start it
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: tcpecho.c,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#include "lwip/sys.h"
#include "lwip/api.h"
static void
tcpecho_thread(void *arg)
{
struct netconn *conn, *newconn;
err_t err;
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
/* Bind connection to well known port number 7. */
netconn_bind(conn, NULL, 7);
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while(1) {
/* Grab new connection. */
newconn = netconn_accept(conn);
/* Process the new connection. */
if(newconn != NULL) {
struct netbuf *buf;
void *data;
u16_t len;
while((buf = netconn_recv(newconn)) != NULL) {
do {
netbuf_data(buf, &data, &len);
err = netconn_write(newconn, data, len, NETCONN_COPY);
if(err != ERR_OK) {
}
} while(netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/* Close connection and discard connection identifier. */
netconn_delete(newconn);
}
}
}
void
tmain(void * p)
{
lwip_init();
sys_thread_new(tcpecho_thread, (void*)"tcpecho");
}
#define STACK_SIZE 0x4000
static char stack[STACK_SIZE];
static cyg_thread thread_data;
static cyg_handle_t thread_handle;
void
cyg_user_start(void)
{
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
tmain, // entry
0, // entry parameter
"TCP echo test", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle, // Handle
&thread_data // Thread data structure
);
cyg_thread_resume(thread_handle); // Start it
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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>
*
* $Id: udpecho.c,v 1.1 2003/02/28 14:29:13 jani Exp $
*/
#include "lwip/api.h"
#include "lwip/sys.h"
/*-----------------------------------------------------------------------------------*/
char buffer[100];
void
udpecho_thread(void *arg)
{
struct netconn *conn;
struct netbuf *buf;
struct ip_addr *addr;
unsigned short port;
conn = netconn_new(NETCONN_UDP);
netconn_bind(conn, NULL, 7);
while(1) {
buf = netconn_recv(conn);
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
netconn_connect(conn, addr, port);
netconn_send(conn, buf);
netbuf_copy(buf, buffer, sizeof(buffer));
netbuf_delete(buf);
}
}
/*-----------------------------------------------------------------------------------*/
void tmain(void * i)
{
lwip_init();
sys_thread_new(udpecho_thread, (void*)"udpecho");
}
#define STACK_SIZE 0x1000
static char stack[STACK_SIZE];
static cyg_thread thread_data;
static cyg_handle_t thread_handle;
void
cyg_user_start(void)
{
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
tmain, // entry
0, // entry parameter
"UDP echo test", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle, // Handle
&thread_data // Thread data structure
);
cyg_thread_resume(thread_handle); // Start it
}

View File

@ -0,0 +1,7 @@
package CYGPKG_NET_LWIP {
alias {"lwIP" lwip}
directory net/lwip_tcpip
script cdl/lwip_net.cdl
description "lightweight TCP/IP stack: lwIP"
}

49
ports/ecos/files Normal file
View File

@ -0,0 +1,49 @@
src/api/api_lib.c src/api/api_lib.c
src/api/api_msg.c src/api/api_msg.c
src/api/err.c src/api/err.c
src/api/sockets.c src/api/sockets.c
src/api/tcpip.c src/api/tcpip.c
src/core/tcp_out.c src/core/tcp_out.c
src/core/inet.c src/core/inet.c
src/core/mem.c src/core/mem.c
src/core/memp.c src/core/memp.c
src/core/netif.c src/core/netif.c
src/core/pbuf.c src/core/pbuf.c
src/core/stats.c src/core/stats.c
src/core/sys.c src/core/sys.c
src/core/tcp.c src/core/tcp.c
src/core/ipv4/ip_addr.c src/core/ipv4/ip_addr.c
src/core/ipv4/icmp.c src/core/ipv4/icmp.c
src/core/ipv4/ip.c src/core/ipv4/ip.c
src/core/ipv4/ip_frag.c src/core/ipv4/ip_frag.c
src/core/udp.c src/core/udp.c
src/core/dhcp.c src/core/dhcp.c
src/core/tcp_in.c src/core/tcp_in.c
src/include/ipv4/lwip/ip_addr.h include/lwip/ip_addr.h
src/include/ipv4/lwip/icmp.h include/lwip/icmp.h
src/include/ipv4/lwip/inet.h include/lwip/inet.h
src/include/ipv4/lwip/ip.h include/lwip/ip.h
src/include/ipv4/lwip/ip_frag.h include/lwip/ip_frag.h
src/include/lwip/api_msg.h include/lwip/api_msg.h
src/include/lwip/api.h include/lwip/api.h
src/include/lwip/arch.h include/lwip/arch.h
src/include/lwip/sockets.h include/lwip/sockets.h
src/include/lwip/debug.h include/lwip/debug.h
src/include/lwip/def.h include/lwip/def.h
src/include/lwip/err.h include/lwip/err.h
src/include/lwip/snmp.h include/lwip/snmp.h
src/include/lwip/mem.h include/lwip/mem.h
src/include/lwip/memp.h include/lwip/memp.h
src/include/lwip/netif.h include/lwip/netif.h
src/include/lwip/opt.h include/lwip/opt.h
src/include/lwip/pbuf.h include/lwip/pbuf.h
src/include/lwip/stats.h include/lwip/stats.h
src/include/lwip/sys.h include/lwip/sys.h
src/include/lwip/tcp.h include/lwip/tcp.h
src/include/lwip/tcpip.h include/lwip/tcpip.h
src/include/lwip/udp.h include/lwip/udp.h
src/include/lwip/dhcp.h include/lwip/dhcp.h
src/include/netif/etharp.h include/netif/etharp.h
src/include/netif/slipif.h include/netif/slipif.h
src/netif/etharp.c src/netif/etharp.c
src/netif/slipif.c src/netif/slipif.c

27
ports/ecos/mkepk Executable file
View File

@ -0,0 +1,27 @@
#!/bin/sh
#make an ecos epk from CVS lwIP
if [ $EPK"" == "" ]; then
echo you must set the EPK environment var to the dir you want the EPK in
exit;
fi
if [ $LWIP_CVS"" == "" ]; then
echo you must set the LWIP_CVS environment var to the dir you checked out the lwip module
LWIP_CVS=../../../lwip;
exit;
fi
#cleanup
rm -Rf $EPK/*
#copy files from CVS
xargs -n 2 ./copy < files
#copy ecos specific files
cp -R ecos/* $EPK
#make epk
cd $EPK && tar czf lwip.epk *