Porting PicoTCP WIP

This commit is contained in:
2025-10-29 14:29:06 +01:00
parent 6722f42e68
commit 815c2239fe
464 changed files with 235009 additions and 24 deletions

View File

@@ -0,0 +1,10 @@
CC=gcc
CFLAGS=-ggdb -I../build/include/ -L../build/lib/ -lpicotcp -lvdeplug
APPNAME=test_tftp_app_client
.PHONY: clean
all: test_tftp_app_client
test_tftp_app_client: test_tftp_app_client.o
$(CC) -o test_tftp_app_client ../build/modules/pico_dev_vde.o $^ $(CFLAGS)
clean:
rm -f ${APPNAME}.o

View File

@@ -0,0 +1,6 @@
To run these tests on your linux system, you will have to install these dependencies:
* vde2
* libvdeplug2-dev
* libpcap0.8-dev
This will allow you to compile the 'make test' and run the tests

360
kernel/picotcp/test/autotest.sh Executable file
View File

@@ -0,0 +1,360 @@
#!/bin/bash
TFTP_EXEC_DIR="$(pwd)/build/test"
TFTP_WORK_DIR="${TFTP_EXEC_DIR}/tmp"
TFTP_WORK_SUBDIR="${TFTP_WORK_DIR}/subdir"
TFTP_WORK_FILE="test.img"
function tftp_setup() {
dd if=/dev/urandom bs=1000 count=10 of=${1}/$TFTP_WORK_FILE
}
function tftp_cleanup() {
echo CLEANUP
pwd;ls
killall -wq picoapp.elf
rm -rf $TFTP_WORK_DIR
if [ $1 ]; then
exit $1
fi
}
if ! [ -x "$(command -v vde_switch)" ]; then
echo 'VDE Switch is not installed.' >&2
fi
if [ ! -e test/vde_sock_start_user.sh ]; then
echo "VDE SOCK START FILE NOT FOUND. NO VDE SETUP. EXITING"
exit 1
else
echo "VDE SOCK START SCRIPT STARTED."
./test/vde_sock_start_user.sh
fi
rm -f /tmp/pico-mem-report-*
sleep 2
ulimit -c unlimited
killall -wq picoapp.elf
killall -wq picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ 6LoWPAN PING 1HOP (1500B) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(build/test/picoapp6.elf -6 0,0,0) &
pids="$! "
sleep 1
(build/test/picoapp6.elf -6 1,2,1 -a noop) &
pids+="$! "
sleep 1
build/test/picoapp6.elf -6 2,1,0 -a ping,2aaa:abcd:0000:0000:0200:00aa:ab00:0001,1500,0,1 || exit 1
#TODO roll out this check for all "daemon" processes
for pid in $pids; do ps -o pid= -p $pid || exit 1; done # check whether daemon processes didn't die from e.g. ASAN
killall -w picoapp6.elf -s SIGQUIT
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ 6LoWPAN UDP 1HOP (1400B) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#TODO are these "daemon" processes that need to be killed, or are they intended to halt on their own, giving a status code?
(build/test/picoapp6.elf -6 0,0,0) &
sleep 1
(build/test/picoapp6.elf -6 1,2,1 -a udpecho,::0,6667,) &
sleep 1
build/test/picoapp6.elf -6 2,1,0 -a udpclient,2aaa:abcd:0000:0000:0200:00aa:ab00:0001,6667,6667,1400,10,1, || exit 1
killall -w picoapp6.elf -s SIGQUIT
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ MULTICAST6 TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic1,/tmp/pic0.ctl,aaaa::2,ffff::, -a mcastreceive_ipv6,aaaa::2,ff00::e007:707,6667,6667,) &
(./build/test/picoapp6.elf --vde pic2,/tmp/pic0.ctl,aaaa::3,ffff::, -a mcastreceive_ipv6,aaaa::3,ff00::e007:707,6667,6667,) &
(./build/test/picoapp6.elf --vde pic3,/tmp/pic0.ctl,aaaa::4,ffff::, -a mcastreceive_ipv6,aaaa::4,ff00::e007:707,6667,6667,) &
sleep 2
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::, -a mcastsend_ipv6,aaaa::1,ff00::e007:707,6667,6667,|| exit 1
killall -w picoapp6.elf -s SIGQUIT
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING6 LOCALHOST TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
./build/test/picoapp6.elf --loop -a ping,::1,,,, || exit 1
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING6 TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,,,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a ping,aaaa::1,,,, || exit 1
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING6 TEST (aborted in 4 seconds...) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,,,) &
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a ping,aaaa::1,64,4,,) &
sleep 7
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP6 TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,, -a tcpbench,r,6667,,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a tcpbench,t,aaaa::1,6667,, || exit 1
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP6 TEST (with 2% packet loss on both directions) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,2,2, -a tcpbench,r,6667,,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a tcpbench,t,aaaa::1,6667,, || exit 1
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP6 TEST (nagle) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,, -a tcpbench,r,6667,n,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a tcpbench,t,aaaa::1,6667,n, || exit 1
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ UDP6 TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::1,ffff::,,, -a udpecho,::0,6667,) &
pids="$! "
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,aaaa::2,ffff::,,, -a udpclient,aaaa::1,6667,6667,1400,100,10, || exit 1
wait $pids || exit 1
killall -w picoapp6.elf
echo
echo
echo
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ IPV6 FWD TCP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp6.elf --vde pic0,/tmp/pic1.ctl,2001:aabb::2,ffff:ffff::,2001:aabb::ff,, -a tcpbench,r,6667,,) &
(./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,2001:aaaa::ff,ffff:ffff::,,, --vde pic1,/tmp/pic1.ctl,2001:aabb::ff,ffff:ffff::,,, -a noop,) &
./build/test/picoapp6.elf --vde pic0,/tmp/pic0.ctl,2001:aaaa::1,ffff:ffff::,2001:aaaa::ff,, -a tcpbench,t,2001:aabb::2,6667,, || exit 1
sleep 2
killall -w picoapp6.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ MULTICAST TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667:) &
(./build/test/picoapp.elf --vde pic2:/tmp/pic0.ctl:10.40.0.4:255.255.0.0: -a mcastreceive:10.40.0.4:224.7.7.7:6667:6667:) &
(./build/test/picoapp.elf --vde pic3:/tmp/pic0.ctl:10.40.0.5:255.255.0.0: -a mcastreceive:10.40.0.5:224.7.7.7:6667:6667:) &
sleep 2
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667: || exit 1
killall -w picoapp.elf
echo
echo
echo
echo
echo
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ IPV4 tests! ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING LOCALHOST TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
./build/test/picoapp.elf --loop -a ping:127.0.0.1:::: || exit 1
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:::: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ PING TEST -- Aborted in 4 seconds ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a ping:10.40.0.8:64:4::) &
sleep 7
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::: -a tcpbench:r:6667::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a tcpbench:t:10.40.0.8:6667:: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP TEST (with global route) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0:::: --vde pic1:/tmp/pic1.ctl:10.50.0.10:255.255.0.0:10.50.0.1: -a tcpbench:r:6667::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a tcpbench:t:10.40.0.8:6667:: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP TEST (with 2% packet loss on both directions) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0::2:2: -a tcpbench:r:6667::) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a tcpbench:t:10.40.0.8:6667:: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TCP TEST (nagle) ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0::: -a tcpbench:r:6667:n:) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a tcpbench:t:10.40.0.8:6667:n: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ UDP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0::: -a udpecho:10.40.0.8:6667:) &
pids="$! "
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a udpclient:10.40.0.8:6667:6667:1400:100:10: || exit 1
wait $pids || exit 1
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ UDP TEST with fragmentation ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0::: -a udpecho:10.40.0.8:6667:) &
pids="$! "
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0::: -a udpclient:10.40.0.8:6667:6667:4500:100:10: || exit 1
wait $pids || exit 1
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ NAT TCP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.10:255.255.0.0::: --vde pic1:/tmp/pic1.ctl:10.50.0.10:255.255.0.0: -a natbox:10.50.0.10) &
sleep 2
(./build/test/picoapp.elf --vde pic0:/tmp/pic1.ctl:10.50.0.8:255.255.0.0::: -a tcpbench:r:6667:) &
sleep 2
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0:10.40.0.10::: -a tcpbench:t:10.50.0.8:6667: || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ NAT UDP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.10:255.255.0.0::: --vde pic1:/tmp/pic1.ctl:10.50.0.10:255.255.0.0::: -a natbox:10.50.0.10) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic1.ctl:10.50.0.8:255.255.0.0::: -a udpecho:10.50.0.8:6667:) &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0:10.40.0.10::: -a udpclient:10.50.0.8:6667:6667:1400:100:10: || exit 1
#sometimes udpecho finishes before reaching wait %2
#wait %2
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ MULTICAST TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0::: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667:) &
(./build/test/picoapp.elf --vde pic2:/tmp/pic0.ctl:10.40.0.4:255.255.0.0::: -a mcastreceive:10.40.0.4:224.7.7.7:6667:6667:) &
(./build/test/picoapp.elf --vde pic3:/tmp/pic0.ctl:10.40.0.5:255.255.0.0::: -a mcastreceive:10.40.0.5:224.7.7.7:6667:6667:) &
sleep 2
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0::: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667: || exit 1
killall -w picoapp.elf
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ DHCP TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.1:255.255.0.0::: -a dhcpserver:pic0:10.40.0.1:255.255.255.0:64:128:) &
./build/test/picoapp.elf --barevde pic0:/tmp/pic0.ctl: -a dhcpclient:pic0 || exit 1
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ DHCP DUAL TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0::: -a dhcpserver:pic0:10.40.0.2:255.255.255.0:64:128:) &
(./build/test/picoapp.elf --vde pic1:/tmp/pic1.ctl:10.50.0.2:255.255.0.0::: -a dhcpserver:pic1:10.50.0.2:255.255.255.0:64:128:) &
./build/test/picoapp.elf --barevde pic0:/tmp/pic0.ctl: --barevde pic1:/tmp/pic1.ctl: -a dhcpclient:pic0:pic1: || exit 1
killall -w picoapp.elf
#TO DO: the ping address 169.254.22.5 is hardcoded in the slaacv4 test. Nice to pass that by parameter
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ SLAACV4 TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:169.254.22.5:255.255.0.0:::) &
./build/test/picoapp.elf --barevde pic0:/tmp/pic0.ctl: -a slaacv4:pic0 || exit 1
killall -w picoapp.elf
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0:10.40.0.1::: -a udpdnsclient:www.google.be:173.194.67.94:: &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0:10.40.0.1::: -a udpdnsclient:ipv6.google.be:doesntmatter:ipv6: &
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.0.0:10.50.0.1::: -a sntp:0.europe.pool.ntp.org &
sleep 20
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ MDNS TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#retrieve a local mdns host name from the host
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app mdns:hostfoo.local:hostbar.local:) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.3:255.255.255.0:10.50.0.1: --app mdns:hostbar.local:hostfoo.local:) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app mdns:hostfoobar.local:nonexisting.local:) &
sleep 10
killall -w picoapp.elf
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ DNS_SD TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#register a service
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app dns_sd:host.local:WebServer) &
(./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.3:255.255.255.0:10.50.0.1: --app dns_sd:host.local:WebServer) &
sleep 30
killall -w picoapp.elf
sleep 1
sync
# TFTP TEST BEGINS...
if [ ! -d $TFTP_WORK_DIR ]; then
mkdir $TFTP_WORK_DIR || exit 1
fi
if [ ! -d ${TFTP_WORK_SUBDIR}/server ]; then
mkdir $TFTP_WORK_SUBDIR || exit 1
fi
pushd $TFTP_WORK_DIR
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TFTP GET TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
tftp_setup $TFTP_WORK_DIR
(${TFTP_EXEC_DIR}/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app tftp:S:) &
cd $TFTP_WORK_SUBDIR
sleep 2
${TFTP_EXEC_DIR}/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.3:255.255.255.0:10.50.0.1: --app tftp:R:${TFTP_WORK_FILE}:10.50.0.2: || tftp_cleanup 1
sleep 3
killall -w picoapp.elf
sleep 1
rm $TFTP_WORK_FILE
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "~~~ TFTP PUT TEST ~~~"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
(${TFTP_EXEC_DIR}/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app tftp:S:) &
cd $TFTP_WORK_DIR
tftp_setup $TFTP_WORK_DIR
sleep 2
${TFTP_EXEC_DIR}/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.3:255.255.255.0:10.50.0.1: --app tftp:T:${TFTP_WORK_FILE}:10.50.0.2: || tftp_cleanup 1
sleep 3
tftp_cleanup
popd
# TFTP TEST ENDS.
MAXMEM=`cat /tmp/pico-mem-report-* | sort -r -n |head -1`
echo
echo
echo
echo "MAX memory used: $MAXMEM"
rm -f /tmp/pico-mem-report-*
./test/vde_sock_start_user.sh stop
echo "SUCCESS!"

View File

@@ -0,0 +1,4 @@
#!/bin/bash
./test/units.sh || exit 1
./test/autotest.sh || exit 2
exit 0

View File

@@ -0,0 +1,12 @@
#include "pico_stack.h"
#if defined(PICO_SUPPORT_RTOS) || defined (PICO_SUPPORT_PTHREAD)
volatile uint32_t pico_ms_tick;
#endif
int main(void)
{
pico_stack_init();
pico_stack_tick();
return 0;
}

View File

@@ -0,0 +1,36 @@
PREFIX?=../../build
CFLAGS+=-I../../include/ -I../../modules -I../../build/include -I . -ggdb
$(PREFIX)/examples/%.o: %.c
@mkdir -p $(PREFIX)/examples
@echo -e "\t[CC] $@"
@$(CC) -c $(CFLAGS) -o $@ $<
OBJS:= \
$(PREFIX)/examples/dhcp_client.o \
$(PREFIX)/examples/dhcp_server.o \
$(PREFIX)/examples/dns_sd.o \
$(PREFIX)/examples/dnsclient.o \
$(PREFIX)/examples/mdns.o \
$(PREFIX)/examples/multicast_recv.o \
$(PREFIX)/examples/multicast_ip6_recv.o \
$(PREFIX)/examples/multicast_send.o \
$(PREFIX)/examples/multicast_ip6_send.o \
$(PREFIX)/examples/natbox.o \
$(PREFIX)/examples/noop.o \
$(PREFIX)/examples/ping.o \
$(PREFIX)/examples/slaacv4.o \
$(PREFIX)/examples/sntp.o \
$(PREFIX)/examples/tcpbench.o \
$(PREFIX)/examples/tcpclient.o \
$(PREFIX)/examples/tcpecho.o \
$(PREFIX)/examples/tftp.o \
$(PREFIX)/examples/udp_client.o \
$(PREFIX)/examples/udp_echo.o \
$(PREFIX)/examples/udpnat.o \
$(PREFIX)/examples/udp_sendto_test.o \
$(PREFIX)/examples/iperfc.o \
all: $(OBJS)

View File

@@ -0,0 +1,114 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_dhcp_client.h>
#include <pico_socket.h>
#include <pico_icmp4.h>
#include <pico_device.h>
/*** START DHCP Client ***/
#ifdef PICO_SUPPORT_DHCPC
/* This must stay global, its lifetime is the same as the dhcp negotiation */
uint32_t dhcpclient_xid;
static uint8_t dhcpclient_devices = 0;
void ping_callback_dhcpclient(struct pico_icmp4_stats *s)
{
char host[30] = { };
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("DHCP client: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n",
s->size, host, s->seq, (long unsigned int)s->time);
if (s->seq >= 3) {
dbg("DHCP client: TEST SUCCESS!\n");
if (--dhcpclient_devices <= 0)
exit(0);
}
} else {
dbg("DHCP client: ping %lu to %s error %d\n", s->seq, host, s->err);
dbg("DHCP client: TEST FAILED!\n");
exit(1);
}
}
void callback_dhcpclient(void *arg, int code)
{
struct pico_ip4 address = ZERO_IP4, gateway = ZERO_IP4;
char s_address[16] = { }, s_gateway[16] = { };
printf("DHCP client: callback happened with code %d!\n", code);
if (code == PICO_DHCP_SUCCESS) {
address = pico_dhcp_get_address(arg);
gateway = pico_dhcp_get_gateway(arg);
pico_ipv4_to_string(s_address, address.addr);
pico_ipv4_to_string(s_gateway, gateway.addr);
printf("DHCP client: got IP %s assigned with cli %p\n", s_address, arg);
#ifdef PICO_SUPPORT_PING
pico_icmp4_ping(s_gateway, 3, 1000, 5000, 32, ping_callback_dhcpclient);
/* optional test to check routing when links get added and deleted */
/* do {
char *new_arg = NULL, *p = NULL;
new_arg = calloc(1, strlen(s_address) + strlen(":224.7.7.7:6667:6667") + 1);
p = strcat(new_arg, s_address);
p = strcat(p + strlen(s_address), ":224.7.7.7:6667:6667");
app_mcastsend(new_arg);
} while (0);
*/
#endif
}
}
void app_dhcp_client(char *arg)
{
char *sdev = NULL;
char *nxt = arg;
struct pico_device *dev = NULL;
if (!nxt)
goto out;
while (nxt) {
if (nxt) {
nxt = cpy_arg(&sdev, nxt);
if(!sdev) {
goto out;
}
}
dev = pico_get_device(sdev);
if(dev == NULL) {
if (sdev)
free(sdev);
printf("%s: error getting device %s: %s\n", __FUNCTION__, dev->name, strerror(pico_err));
exit(255);
}
printf("Starting negotiation\n");
if (pico_dhcp_initiate_negotiation(dev, &callback_dhcpclient, &dhcpclient_xid) < 0) {
printf("%s: error initiating negotiation: %s\n", __FUNCTION__, strerror(pico_err));
if (sdev)
free(sdev);
exit(255);
}
if (sdev)
free(sdev);
dhcpclient_devices++;
}
return;
out:
fprintf(stderr, "dhcpclient expects the following format: dhcpclient:dev_name:[dev_name]\n");
if (sdev)
free(sdev);
exit(255);
}
#endif
/*** END DHCP Client ***/

View File

@@ -0,0 +1,99 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_device.h>
#include <pico_dhcp_server.h>
/*** START DHCP Server ***/
#ifdef PICO_SUPPORT_DHCPD
/* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.1:255.255.0.0: -a dhcpserver:pic0:10.40.0.1:255.255.255.0:64:128
* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.10:255.255.255.0: --vde pic1:/tmp/pic1.ctl:10.50.0.10:255.255.255.0: \
* -a dhcpserver:pic0:10.40.0.10:255.255.255.0:64:128:pic1:10.50.0.10:255.255.255.0:64:128
*/
void app_dhcp_server(char *arg)
{
struct pico_device *dev = NULL;
struct pico_dhcp_server_setting s = {
0
};
int pool_start = 0, pool_end = 0;
char *s_name = NULL, *s_addr = NULL, *s_netm = NULL, *s_pool_start = NULL, *s_pool_end = NULL;
char *nxt = arg;
if (!nxt)
goto out;
while (nxt) {
if (nxt) {
nxt = cpy_arg(&s_name, nxt);
if (!s_name) {
goto out;
}
} else {
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_addr, nxt);
if (s_addr) {
pico_string_to_ipv4(s_addr, &s.server_ip.addr);
} else {
goto out;
}
} else {
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_netm, nxt);
if (s_netm) {
pico_string_to_ipv4(s_netm, &s.netmask.addr);
} else {
goto out;
}
} else {
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_pool_start, nxt);
if (s_pool_start && atoi(s_pool_start)) {
pool_start = atoi(s_pool_start);
} else {
goto out;
}
} else {
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_pool_end, nxt);
if (s_pool_end && atoi(s_pool_end)) {
pool_end = atoi(s_pool_end);
} else {
goto out;
}
} else {
goto out;
}
dev = (struct pico_device *)pico_get_device(s_name);
if (dev == NULL) {
fprintf(stderr, "No device with name %s found\n", s_name);
exit(255);
}
s.dev = dev;
s.pool_start = (s.server_ip.addr & s.netmask.addr) | long_be(pool_start);
s.pool_end = (s.server_ip.addr & s.netmask.addr) | long_be(pool_end);
pico_dhcp_server_initiate(&s);
}
return;
out:
fprintf(stderr, "dhcpserver expects the following format: dhcpserver:dev_name:dev_addr:dev_netm:pool_start:pool_end\n");
exit(255);
}
#endif
/*** END DHCP Server ***/

View File

@@ -0,0 +1,112 @@
#include "utils.h"
#include <pico_dns_sd.h>
#include <pico_ipv4.h>
#include <pico_addressing.h>
#include <pico_device.h>
#include <pico_ipv4.h>
/*** START DNS_SD ***/
#ifdef PICO_SUPPORT_DNS_SD
#define TTL 30
#define SECONDS 10
static int fully_initialized = 0;
static char *service_name = NULL;
void dns_sd_claimed_callback( pico_mdns_rtree *tree,
char *str,
void *arg )
{
printf("DONE - Registering DNS-SD Service\n");
IGNORE_PARAMETER(tree);
IGNORE_PARAMETER(str);
IGNORE_PARAMETER(arg);
}
void dns_sd_init_callback( pico_mdns_rtree *tree,
char *str,
void *arg )
{
PICO_DNS_SD_KV_VECTOR_DECLARE(key_value_pair_vector);
IGNORE_PARAMETER(str);
IGNORE_PARAMETER(arg);
IGNORE_PARAMETER(tree);
pico_dns_sd_kv_vector_add(&key_value_pair_vector, "key", "value");
printf("DONE - Initialising DNS Service Discovery module.\n");
if (pico_dns_sd_register_service(service_name,
"_http._tcp", 80,
&key_value_pair_vector,
TTL, dns_sd_claimed_callback, NULL) < 0) {
printf("Registering service failed!\n");
}
fully_initialized = 1;
}
void app_dns_sd(char *arg, struct pico_ip4 address)
{
char *hostname;
char *nxt = arg;
uint64_t starttime = 0;
int once = 0;
if (!nxt) {
exit(255);
}
nxt = cpy_arg(&hostname, nxt);
if(!hostname) {
exit(255);
}
if(!nxt) {
printf("Not enough args supplied!\n");
exit(255);
}
nxt = cpy_arg(&service_name, nxt);
if(!service_name) {
exit(255);
}
printf("\nStarting DNS Service Discovery module...\n");
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL) != 0) {
printf("Initialisation returned with Error!\n");
exit(255);
}
printf("\nTry reinitialising DNS-SD\n");
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL)) {
printf("Initialisation returned with Error!\n");
exit(255);
}
printf("DONE - Re-initialising DNS-SD module.\n");
starttime = PICO_TIME_MS();
printf("Starting time: %d\n", starttime);
while(1) {
pico_stack_tick();
usleep(2000);
if (((PICO_TIME_MS() - starttime) > SECONDS * 1000) && fully_initialized && !once) {
printf("\nTry reinitialising DNS-SD (a second time)\n");
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL)) {
printf("Initialisation returned with Error!\n");
exit(255);
}
once = 1;
printf("DONE - Re-initialising mDNS module. (a second time)\n");
}
}
}
#endif
/*** END DNS_SD ***/

View File

@@ -0,0 +1,120 @@
#include <stdint.h>
#include <pico_stack.h>
#include <pico_ipv4.h>
#include <pico_dns_client.h>
#include "utils.h"
extern int IPV6_MODE;
/*** START UDP DNS CLIENT ***/
/*
./test/vde_sock_start.sh
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
iptables -A FORWARD -i pic0 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o pic0 -j ACCEPT
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0:10.40.0.1: -a udpdnsclient:www.google.be:173.194.67.94
*/
void cb_udpdnsclient_getaddr(char *ip, void *arg)
{
uint8_t *id = (uint8_t *) arg;
if (!ip) {
picoapp_dbg("%s: ERROR occured! (id: %u)\n", __FUNCTION__, *id);
return;
}
picoapp_dbg("%s: ip %s (id: %u)\n", __FUNCTION__, ip, *id);
if (arg)
PICO_FREE(arg);
}
void cb_udpdnsclient_getname(char *name, void *arg)
{
uint8_t *id = (uint8_t *) arg;
if (!name) {
picoapp_dbg("%s: ERROR occured! (id: %u)\n", __FUNCTION__, *id);
return;
}
picoapp_dbg("%s: name %s (id: %u)\n", __FUNCTION__, name, *id);
if (arg)
PICO_FREE(arg);
}
void app_udpdnsclient(char *arg)
{
struct pico_ip4 nameserver;
char *dname, *daddr;
char *nxt;
char *ipver;
int v = 4;
uint8_t *getaddr_id, *getname_id, *getaddr6_id, *getname6_id;
nxt = cpy_arg(&dname, arg);
if (!dname || !nxt) {
picoapp_dbg(" udpdnsclient expects the following format: udpdnsclient:dest_name:dest_ip:[ipv6]\n");
exit(255);
}
nxt = cpy_arg(&daddr, nxt);
if (!daddr || !nxt) {
picoapp_dbg(" udpdnsclient expects the following format: udpdnsclient:dest_name:dest_ip:[ipv6]\n");
exit(255);
}
nxt = cpy_arg(&ipver, nxt);
if (!ipver || strcmp("ipv6", ipver) != 0)
v = 4;
else
v = 6;
picoapp_dbg("UDP DNS client started.\n");
picoapp_dbg("----- Deleting non existant nameserver -----\n");
pico_string_to_ipv4("127.0.0.1", &nameserver.addr);
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_DEL);
picoapp_dbg("----- Adding 8.8.8.8 nameserver -----\n");
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
picoapp_dbg("----- Deleting 8.8.8.8 nameserver -----\n");
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_DEL);
picoapp_dbg("----- Adding 8.8.8.8 nameserver -----\n");
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
picoapp_dbg("----- Adding 8.8.4.4 nameserver -----\n");
pico_string_to_ipv4("8.8.4.4", &nameserver.addr);
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
if (!IPV6_MODE) {
if (v == 4) {
picoapp_dbg("Mode: IPv4\n");
getaddr_id = calloc(1, sizeof(uint8_t));
*getaddr_id = 1;
picoapp_dbg(">>>>> DNS GET ADDR OF %s\n", dname);
pico_dns_client_getaddr(dname, &cb_udpdnsclient_getaddr, getaddr_id);
getname_id = calloc(1, sizeof(uint8_t));
*getname_id = 2;
picoapp_dbg(">>>>> DNS GET NAME OF %s\n", daddr);
pico_dns_client_getname(daddr, &cb_udpdnsclient_getname, getname_id);
return;
}
picoapp_dbg("Mode: IPv6\n");
#ifdef PICO_SUPPORT_IPV6
getaddr6_id = calloc(1, sizeof(uint8_t));
*getaddr6_id = 3;
picoapp_dbg(">>>>> DNS GET ADDR6 OF %s\n", dname);
pico_dns_client_getaddr6(dname, &cb_udpdnsclient_getaddr, getaddr6_id);
getname6_id = calloc(1, sizeof(uint8_t));
*getname6_id = 4;
picoapp_dbg(">>>>> DNS GET NAME OF ipv6 addr 2a00:1450:400c:c06::64\n");
pico_dns_client_getname6("2a00:1450:400c:c06::64", &cb_udpdnsclient_getname, getname6_id);
#endif
}
return;
}
/*** END UDP DNS CLIENT ***/

View File

@@ -0,0 +1,142 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "pico_ipv6.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "utils.h"
#define DURATION 30
struct iperf_hdr {
int32_t flags; /* 0 */
int32_t numThreads; /* 1 */
int32_t mPort; /* 5001 */
int32_t bufferlen; /* 0 */
int32_t mWinBand; /* 0 */
int32_t mAmount; /* 0xfffffc18 */
};
#define IPERF_PORT 5001
#define MTU 1444
#define SEND_BUF_SIZ (1024 * 2048)
char *cpy_arg(char **dst, char *str);
extern int IPV6_MODE;
static pico_time deadline;
static void panic(void)
{
for(;; ) ;
}
static char buf[MTU] = {};
static void buf_paint(void)
{
char paint[11] = "0123456789";
int i;
for (i = 0; i < MTU; i++) {
buf[i] = paint[i % 10];
}
}
static void send_hdr(struct pico_socket *s)
{
struct iperf_hdr hdr = {};
hdr.numThreads = long_be(1);
hdr.mPort = long_be(5001);
hdr.mAmount = long_be(0xfffffc18);
pico_socket_write(s, &hdr, sizeof(hdr));
deadline = PICO_TIME_MS() + DURATION * 1000;
}
static void iperf_cb(uint16_t ev, struct pico_socket *s)
{
int r;
static int end = 0;
if (ev & PICO_SOCK_EV_CONN) {
send_hdr(s);
return;
}
if ((!end) && (ev & PICO_SOCK_EV_WR)) {
if (PICO_TIME_MS() > deadline) {
pico_socket_close(s);
if (!pico_timer_add(2000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
end++;
}
pico_socket_write(s, buf, MTU);
}
if (!(end) && (ev & (PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE))) {
if (!pico_timer_add(2000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
end++;
}
}
static void iperfc_socket_setup(union pico_address *addr, uint16_t family)
{
int yes = 1;
uint16_t send_port = 0;
struct pico_socket *s = NULL;
uint32_t bufsize = SEND_BUF_SIZ;
send_port = short_be(5001);
s = pico_socket_open(family, PICO_PROTO_TCP, &iperf_cb);
pico_socket_setoption(s, PICO_SOCKET_OPT_SNDBUF, &bufsize);
pico_socket_connect(s, addr, send_port);
}
void app_iperfc(char *arg)
{
struct pico_ip4 my_eth_addr, netmask;
struct pico_device *pico_dev_eth;
char *daddr = NULL, *dport = NULL;
char *nxt = arg;
uint16_t send_port = 0, listen_port = short_be(5001);
int i = 0, ret = 0, yes = 1;
struct pico_socket *s = NULL;
uint16_t family = PICO_PROTO_IPV4;
union pico_address dst = {
.ip4 = {0}, .ip6 = {{0}}
};
union pico_address inaddr_any = {
.ip4 = {0}, .ip6 = {{0}}
};
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&daddr, arg);
if (daddr) {
if (!IPV6_MODE)
pico_string_to_ipv4(daddr, &dst.ip4.addr);
#ifdef PICO_SUPPORT_IPV6
else {
pico_string_to_ipv6(daddr, dst.ip6.addr);
family = PICO_PROTO_IPV6;
}
#endif
} else {
goto out;
}
} else {
/* missing dest_addr */
goto out;
}
iperfc_socket_setup(&dst, family);
return;
out:
dbg("Error parsing options!\n");
exit(1);
}

View File

@@ -0,0 +1,83 @@
#include "utils.h"
#include "pico_dns_common.h"
#include "pico_mdns.h"
#include "pico_ipv4.h"
#include "pico_addressing.h"
/*** START MDNS ***/
#ifdef PICO_SUPPORT_MDNS
#define SECONDS 10
static int fully_initialized = 0;
void mdns_init_callback( pico_mdns_rtree *rtree,
char *str,
void *arg )
{
printf("\nInitialised with hostname: %s\n\n", str);
fully_initialized = 1;
}
void app_mdns(char *arg, struct pico_ip4 address)
{
char *hostname, *peername;
char *nxt = arg;
uint64_t starttime = 0;
int once = 0;
if (!nxt)
exit(255);
nxt = cpy_arg(&hostname, nxt);
if(!hostname) {
exit(255);
}
if(!nxt) {
printf("Not enough args supplied!\n");
exit(255);
}
nxt = cpy_arg(&peername, nxt);
if(!peername) {
exit(255);
}
printf("\nStarting mDNS module...\n");
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
printf("Initialisation returned with Error!\n");
exit(255);
}
printf("\nTry reinitialising mDNS\n");
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
printf("Initialisation returned with Error!\n");
exit(255);
}
printf("DONE - Re-initialising mDNS module.\n");
starttime = PICO_TIME_MS();
printf("Starting time: %d\n", starttime);
while(1) {
pico_stack_tick();
usleep(2000);
if (((PICO_TIME_MS() - starttime) > SECONDS * 1000) && fully_initialized && !once) {
printf("\nTry reinitialising mDNS (a second time)\n");
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
printf("Initialisation returned with Error!\n");
exit(255);
}
once = 1;
printf("DONE - Re-initialising mDNS module. (a second time)\n");
}
}
}
#endif
/*** END MDNS ***/

View File

@@ -0,0 +1,182 @@
#include "utils.h"
#include <pico_ipv6.h>
#include <pico_socket.h>
extern void app_udpecho(char *arg);
/*** START Multicast RECEIVE + ECHO ***/
/*
* multicast receive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port:sendto_port
* link_addr: mcastreceive picoapp IP address
* mcast_addr: multicast IP address to receive
* listen_port: port number on which the mcastreceive listens
* sendto_port: port number to echo multicast traffic to (echo to originating IP address)
*
* f.e.: ./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
extern struct udpecho_pas *udpecho_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastreceive_ipv6(char *arg)
{
char *new_arg = NULL, *p = NULL, *nxt = arg;
char *laddr = NULL, *maddr = NULL, *lport = NULL, *sport = NULL;
uint16_t listen_port = 0;
union pico_address inaddr_link = {
0
}, inaddr_mcast = {
0
}, src[5] = {
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0 }},
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0x10}},
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0x01 }},
{.ip6 = { 0xff, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xe0, 0x01, 0x01, 0x01 }},
};
struct pico_ip_mreq mreq = ZERO_MREQ_IP6;
struct pico_ip_mreq_source mreq_source = ZERO_MREQ_SRC_IP6;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv6(laddr, &inaddr_link.ip6.addr[0]);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv6(maddr, &inaddr_mcast.ip6.addr[0]);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
/* unused at this moment */
/* send_port = short_be(atoi(sport)); */
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
/* end of parameter parsing */
printf("\n%s: multicast receive started. Receiving packets on [%s]:%d\n\n", __FUNCTION__, maddr, short_be(listen_port));
/* udpecho:bind_addr:listen_port[:sendto_port:datasize] */
new_arg = calloc(1, strlen(laddr) + 1 + strlen(lport) + 1 + strlen(sport) + strlen(",64:") + 1);
p = strcat(new_arg, laddr);
p = strcat(p + strlen(laddr), ",");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ",");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ",64,");
/* DAD needs to verify the link address before we can continue */
while(!pico_ipv6_link_get(&inaddr_link.ip6)) {
pico_stack_tick();
usleep(2000);
}
app_udpecho(new_arg);
memcpy(&mreq.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
memcpy( &mreq_source.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
memcpy(&mreq.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
memcpy(&mreq_source.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
memcpy(&mreq_source.mcast_source_addr, &src[0], sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_BLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_BLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_UNBLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_UNBLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_source_addr, &src[1], sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_source_addr, &src[2], sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
memcpy(&mreq_source.mcast_group_addr, &src[3], sizeof(struct pico_ip6));
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
return;
out:
fprintf(stderr, "mcastreceive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port[:send_port]\n");
exit(255);
}
#else
void app_mcastreceive_ipv6(char *arg)
{
printf("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast RECEIVE + ECHO ***/

View File

@@ -0,0 +1,140 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_socket.h>
extern void app_udpclient(char *arg);
/*** START Multicast SEND ***/
/*
* multicast send expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port
* link_addr: mcastsend picoapp IP address
* mcast_addr: multicast IP address to send to
* sendto_port: port number to send multicast traffic to
* listen_port: port number on which the mcastsend can receive data
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastsend_ipv6(char *arg)
{
int retval = 0;
char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
uint16_t sendto_port = 0;
struct pico_ip6 inaddr_link = {
0
}, inaddr_mcast = {
0
};
char *new_arg = NULL, *p = NULL, *nxt = arg;
struct pico_ip_mreq mreq = ZERO_MREQ_IP6;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv6(laddr, &inaddr_link.addr[0]);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv6(maddr, &inaddr_mcast.addr[0]);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
sendto_port = short_be(atoi(sport));
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
/* unused at this moment */
/* listen_port = short_be(atoi(lport)); */
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
picoapp_dbg("\n%s: mcastsend started. Sending packets to %s:%u\n\n", __FUNCTION__, maddr, short_be(sendto_port));
/* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(",64,10,5,") + 1);
p = strcat(new_arg, maddr);
p = strcat(p + strlen(maddr), ",");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ",");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ",64,10,5,");
/* DAD needs to verify the link address before we can continue */
while(!pico_ipv6_link_get(&inaddr_link)) {
pico_stack_tick();
usleep(2000);
}
app_udpclient(new_arg);
memcpy(&mreq.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
memcpy(&mreq.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
retval = 1;
}
if (new_arg)
free(new_arg);
if (lport)
free(lport);
if (maddr)
free(maddr);
if (sport)
free(sport);
if (laddr)
free(laddr);
if (retval)
exit(retval);
return;
out:
picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
exit(255);
}
#else
void app_mcastsend_ipv6(char *arg)
{
picoapp_dbg("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast SEND ***/

View File

@@ -0,0 +1,171 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_socket.h>
extern void app_udpecho(char *arg);
/*** START Multicast RECEIVE + ECHO ***/
/*
* multicast receive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port:sendto_port
* link_addr: mcastreceive picoapp IP address
* mcast_addr: multicast IP address to receive
* listen_port: port number on which the mcastreceive listens
* sendto_port: port number to echo multicast traffic to (echo to originating IP address)
*
* f.e.: ./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
extern struct udpecho_pas *udpecho_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastreceive(char *arg)
{
char *new_arg = NULL, *p = NULL, *nxt = arg;
char *laddr = NULL, *maddr = NULL, *lport = NULL, *sport = NULL;
uint16_t listen_port = 0;
union pico_address inaddr_link = {
0
}, inaddr_mcast = {
0
};
struct pico_ip_mreq mreq = ZERO_MREQ;
struct pico_ip_mreq_source mreq_source = ZERO_MREQ_SRC;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv4(laddr, &inaddr_link.ip4.addr);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv4(maddr, &inaddr_mcast.ip4.addr);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
/* unused at this moment */
/* send_port = short_be(atoi(sport)); */
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
/* end of parameter parsing */
printf("\n%s: multicast receive started. Receiving packets on %s:%d\n\n", __FUNCTION__, maddr, short_be(listen_port));
/* udpecho:bind_addr:listen_port[:sendto_port:datasize] */
new_arg = calloc(1, strlen(laddr) + 1 + strlen(lport) + 1 + strlen(sport) + strlen(":64:") + 1);
p = strcat(new_arg, laddr);
p = strcat(p + strlen(laddr), ":");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ":");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ":64:");
app_udpecho(new_arg);
mreq.mcast_group_addr = mreq_source.mcast_group_addr = inaddr_mcast;
mreq.mcast_link_addr = mreq_source.mcast_link_addr = inaddr_link;
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC100101);
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_BLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_BLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_UNBLOCK_SOURCE, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_UNBLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC10010A);
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
}
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC100101);
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
mreq_source.mcast_group_addr.ip4.addr = long_be(0XE0010101);
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
}
return;
out:
fprintf(stderr, "mcastreceive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port[:send_port]\n");
exit(255);
}
#else
void app_mcastreceive(char *arg)
{
printf("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast RECEIVE + ECHO ***/

View File

@@ -0,0 +1,129 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_socket.h>
extern void app_udpclient(char *arg);
/*** START Multicast SEND ***/
/*
* multicast send expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port
* link_addr: mcastsend picoapp IP address
* mcast_addr: multicast IP address to send to
* sendto_port: port number to send multicast traffic to
* listen_port: port number on which the mcastsend can receive data
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667
*/
extern struct udpclient_pas *udpclient_pas;
#ifdef PICO_SUPPORT_MCAST
void app_mcastsend(char *arg)
{
char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
uint16_t sendto_port = 0;
union pico_address inaddr_link = {
0
}, inaddr_mcast = {
0
};
char *new_arg = NULL, *p = NULL, *nxt = arg;
struct pico_ip_mreq mreq = ZERO_MREQ;
/* start of parameter parsing */
if (nxt) {
nxt = cpy_arg(&laddr, nxt);
if (laddr) {
pico_string_to_ipv4(laddr, &inaddr_link.ip4.addr);
} else {
goto out;
}
} else {
/* no arguments */
goto out;
}
if (nxt) {
nxt = cpy_arg(&maddr, nxt);
if (maddr) {
pico_string_to_ipv4(maddr, &inaddr_mcast.ip4.addr);
} else {
goto out;
}
} else {
/* missing multicast address */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
sendto_port = short_be(atoi(sport));
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
/* unused at this moment */
/* listen_port = short_be(atoi(lport)); */
} else {
/* incorrect listen_port */
goto out;
}
} else {
/* missing listen_port */
goto out;
}
picoapp_dbg("\n%s: mcastsend started. Sending packets to %08X:%u\n\n", __FUNCTION__, long_be(inaddr_mcast.addr), short_be(sendto_port));
/* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(":64:10:5:") + 1);
p = strcat(new_arg, maddr);
p = strcat(p + strlen(maddr), ":");
p = strcat(p + 1, sport);
p = strcat(p + strlen(sport), ":");
p = strcat(p + 1, lport);
p = strcat(p + strlen(lport), ":64:10:5:");
app_udpclient(new_arg);
free(new_arg);
mreq.mcast_group_addr = inaddr_mcast;
mreq.mcast_link_addr = inaddr_link;
if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
exit(1);
}
/* free strdups */
if (maddr)
free(maddr);
if (laddr)
free(laddr);
if (lport)
free(lport);
if (sport)
free(sport);
return;
out:
picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
exit(255);
}
#else
void app_mcastsend(char *arg)
{
picoapp_dbg("ERROR: PICO_SUPPORT_MCAST disabled\n");
return;
}
#endif
/*** END Multicast SEND ***/

View File

@@ -0,0 +1,31 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_nat.h>
/*** START NATBOX ***/
void app_natbox(char *arg)
{
char *dest = NULL;
struct pico_ip4 ipdst, pub_addr, priv_addr;
struct pico_ipv4_link *link;
cpy_arg(&dest, arg);
if (!dest) {
fprintf(stderr, "natbox needs the following format: natbox:dst_addr\n");
exit(255);
}
pico_string_to_ipv4(dest, &ipdst.addr);
link = pico_ipv4_link_get(&ipdst);
if (!link) {
fprintf(stderr, "natbox: Destination not found.\n");
exit(255);
}
pico_ipv4_nat_enable(link);
pico_string_to_ipv4("10.50.0.10", &pub_addr.addr);
pico_string_to_ipv4("10.40.0.08", &priv_addr.addr);
pico_ipv4_port_forward(pub_addr, short_be(5555), priv_addr, short_be(6667), PICO_PROTO_UDP, PICO_NAT_PORT_FORWARD_ADD);
fprintf(stderr, "natbox: started.\n");
}
/*** END NATBOX ***/

View File

@@ -0,0 +1,11 @@
/* NOOP */
#include <pico_stack.h>
void app_noop(void)
{
while(1) {
pico_stack_tick();
usleep(2000);
}
}
/* END NOOP */

View File

@@ -0,0 +1,138 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_icmp4.h>
#include <pico_icmp6.h>
/*** START PING ***/
#ifdef PICO_SUPPORT_PING
#define NUM_PING 10
void cb_ping(struct pico_icmp4_stats *s)
{
char host[30];
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size, host, s->seq,
s->ttl, (long unsigned int)s->time);
if (s->seq >= NUM_PING)
exit(0);
} else {
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
exit(1);
}
}
#ifdef PICO_SUPPORT_IPV6
void cb_ping6(struct pico_icmp6_stats *s)
{
char host[50];
pico_ipv6_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size, host, s->seq,
s->ttl, (long unsigned int)s->time);
if (s->seq >= NUM_PING)
exit(0);
} else {
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
exit(1);
}
}
#endif
void ping_abort_timer(pico_time now, void *_id)
{
int *id = (int *) _id;
printf("Ping: aborting...\n");
if (!IPV6_MODE)
pico_icmp4_ping_abort(*id);
#ifdef PICO_SUPPORT_IPV6
else
pico_icmp6_ping_abort(*id);
#endif
}
void app_ping(char *arg)
{
char *dest = NULL;
char *next = NULL;
char *abort = NULL;
char *delay = NULL;
char *asize = NULL;
int initial_delay = 0;
struct pico_ip6 dst;
static int id;
int timeout = 0;
int size = 64;
next = cpy_arg(&dest, arg);
if (!dest) {
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
exit(255);
}
pico_string_to_ipv6(dest, dst.addr);
if (next) {
next = cpy_arg(&asize, next);
size = atoi(asize);
free(asize);
if (size <= 0) {
size = 64; /* Default */
}
}
if (next) {
next = cpy_arg(&abort, next);
if (strlen(abort) > 0) {
printf("Got arg: '%s'\n", abort);
timeout = atoi(abort);
if (timeout < 0) {
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
exit(255);
}
printf("Aborting ping after %d seconds\n", timeout);
}
}
if (next) {
next = cpy_arg(&delay, next);
if (strlen(delay) > 0) {
initial_delay = atoi(delay);
if (initial_delay > 0) {
printf("Initial delay: %d seconds\n", initial_delay);
initial_delay = PICO_TIME_MS() + initial_delay * 1000;
while (PICO_TIME_MS() < initial_delay) {
pico_stack_tick();
usleep(10000);
}
}
}
free(delay);
}
printf("Starting ping.\n");
if (!IPV6_MODE)
id = pico_icmp4_ping(dest, NUM_PING, 1000, 10000, size, cb_ping);
#ifdef PICO_SUPPORT_IPV6
else
id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, size, cb_ping6, pico_ipv6_source_dev_find(&dst));
#endif
if (timeout > 0) {
printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
if (!pico_timer_add(timeout * 1000, ping_abort_timer, &id)) {
printf("Failed to set ping abort timeout, aborting ping\n");
ping_abort_timer((pico_time)0, &id);
exit(1);
}
}
/* free copied args */
if (dest)
free(dest);
if (abort)
free(abort);
}
#endif
/*** END PING ***/

View File

@@ -0,0 +1,72 @@
#include "utils.h"
#include <pico_slaacv4.h>
#include <pico_icmp4.h>
/*** START SLAACV4 ***/
void ping_callback_slaacv4(struct pico_icmp4_stats *s)
{
char host[30] = { };
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("SLAACV4: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host,
s->seq, (long unsigned int)s->time);
if (s->seq >= 3) {
dbg("SLAACV4: TEST SUCCESS!\n");
pico_slaacv4_unregisterip();
exit(0);
}
} else {
dbg("SLAACV4: ping %lu to %s error %d\n", s->seq, host, s->err);
dbg("SLAACV4: TEST FAILED!\n");
exit(1);
}
}
void slaacv4_cb(struct pico_ip4 *ip, uint8_t code)
{
char dst[16] = "169.254.22.5";
printf("SLAACV4 CALLBACK ip:0x%X code:%d \n", ip->addr, code);
if (code == 0)
{
#ifdef PICO_SUPPORT_PING
pico_icmp4_ping(dst, 3, 1000, 5000, 32, ping_callback_slaacv4);
#else
exit(0);
#endif
}
else
{
exit(255);
}
}
void app_slaacv4(char *arg)
{
char *sdev = NULL;
char *nxt = arg;
struct pico_device *dev = NULL;
if (!nxt)
exit(255);
while (nxt) {
if (nxt) {
nxt = cpy_arg(&sdev, nxt);
if(!sdev) {
exit(255);
}
}
}
dev = pico_get_device(sdev);
free(sdev);
if(dev == NULL) {
printf("%s: error getting device %s: %s\n", __FUNCTION__, dev->name, strerror(pico_err));
exit(255);
}
pico_slaacv4_claimip(dev, slaacv4_cb);
}
/*** END SLAACv4 ***/

View File

@@ -0,0 +1,59 @@
#include "utils.h"
#include <pico_sntp_client.h>
/*** START SNTP ***/
#ifdef PICO_SUPPORT_SNTP_CLIENT
void sntp_timeout(pico_time __attribute__((unused)) now, void *arg)
{
struct pico_timeval ptv;
struct timeval tv;
pico_sntp_gettimeofday(&ptv);
gettimeofday(&tv, NULL);
printf("Linux sec: %u, msec: %u\n", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec / 1000);
printf("Picotcp sec: %u, msec: %u\n", (unsigned int)ptv.tv_sec, (unsigned int)ptv.tv_msec);
printf("SNTP test succesfull!\n");
exit(0);
}
void cb_synced(pico_err_t status)
{
if(status == PICO_ERR_ENETDOWN) {
printf("SNTP: Cannot resolve ntp server name\n");
exit(1);
} else if (status == PICO_ERR_ETIMEDOUT) {
printf("SNTP: Timed out, did not receive ntp packet from server\n");
exit(1);
} else if (status == PICO_ERR_EINVAL) {
printf("SNTP: Conversion error\n");
exit(1);
} else if (status == PICO_ERR_ENOTCONN) {
printf("SNTP: Socket error\n");
exit(1);
} else if (status == PICO_ERR_NOERR) {
if (!pico_timer_add(2000, sntp_timeout, NULL)) {
printf("SNTP: Failed to start timeout timer, exiting program \n");
exit(1);
}
} else {
printf("SNTP: Invalid status received in cb_synced\n");
exit(1);
}
}
void app_sntp(char *servername)
{
struct pico_timeval tv;
printf("Starting SNTP query towards %s\n", servername);
if(pico_sntp_gettimeofday(&tv) == 0)
printf("Wrongly succesfull gettimeofday\n");
else
printf("Unsuccesfull gettimeofday (not synced)\n");
if(pico_sntp_sync(servername, &cb_synced) == 0)
printf("Succesfull sync call!\n");
else
printf("Error in sync\n");
}
#endif
/*** END SNTP ***/

View File

@@ -0,0 +1,320 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_socket.h>
/*** START TCP BENCH ***/
#define TCP_BENCH_TX 1
#define TCP_BENCH_RX 2
#define TCP_BENCH_TX_FOREVER 3
static char *buffer1;
static char *buffer0;
int tcpbench_mode = 0;
struct pico_socket *tcpbench_sock = NULL;
static pico_time tcpbench_time_start, tcpbench_time_end;
void cb_tcpbench(uint16_t ev, struct pico_socket *s)
{
static int closed = 0;
static unsigned long count = 0;
uint8_t recvbuf[1500];
uint16_t port;
char peer[200];
/* struct pico_socket *sock_a; */
static int tcpbench_wr_size = 0;
static int tcpbench_rd_size = 0;
int tcpbench_w = 0;
int tcpbench_r = 0;
double tcpbench_time = 0;
count++;
if (ev & PICO_SOCK_EV_RD) {
do {
/* read data, but discard */
tcpbench_r = pico_socket_read(s, recvbuf, 1500);
if (tcpbench_r > 0) {
tcpbench_rd_size += tcpbench_r;
}
} while (tcpbench_r > 0);
if (tcpbench_time_start == 0)
tcpbench_time_start = PICO_TIME_MS();
printf("tcpbench_rd_size = %d \r", tcpbench_rd_size);
}
if (ev & PICO_SOCK_EV_CONN) {
if (!IPV6_MODE) {
struct pico_ip4 orig;
if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
printf("tcpbench> Connection established with server.\n");
} else if (tcpbench_mode == TCP_BENCH_RX) {
/* sock_a = pico_socket_accept(s, &orig, &port); */
pico_socket_accept(s, &orig, &port);
pico_ipv4_to_string(peer, orig.addr);
printf("tcpbench> Connection established with %s:%d.\n", peer, short_be(port));
}
} else {
struct pico_ip6 orig;
if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
printf("tcpbench> Connection established with server.\n");
} else if (tcpbench_mode == TCP_BENCH_RX) {
/* sock_a = pico_socket_accept(s, &orig, &port); */
pico_socket_accept(s, &orig, &port);
#ifdef PICO_SUPPORT_IPV6
pico_ipv6_to_string(peer, orig.addr);
printf("tcpbench> Connection established with [%s]:%d.\n", peer, short_be(port));
#endif
}
}
}
if (ev & PICO_SOCK_EV_FIN) {
printf("tcpbench> Socket closed. Exit normally. \n");
if (tcpbench_mode == TCP_BENCH_RX) {
tcpbench_time_end = PICO_TIME_MS();
tcpbench_time = (tcpbench_time_end - tcpbench_time_start) / 1000.0; /* get number of seconds */
printf("tcpbench> received %d bytes in %lf seconds\n", tcpbench_rd_size, tcpbench_time);
printf("tcpbench> average read throughput %lf kbit/sec\n", ((tcpbench_rd_size * 8.0) / tcpbench_time) / 1000);
pico_socket_shutdown(s, PICO_SHUT_WR);
printf("tcpbench> Called shutdown write, ev = %d\n", ev);
}
if (!pico_timer_add(5000, deferred_exit, NULL)) {
printf("tcpbench> Failed to start exit timer, exiting now\n");
exit(1);
}
}
if (ev & PICO_SOCK_EV_ERR) {
printf("tcpbench> ---- Socket Error received: %s. Bailing out.\n", strerror(pico_err));
if (!pico_err == PICO_ERR_ECONNRESET) {
if (pico_timer_add(5000, deferred_exit, NULL)) {
printf("tcpbench> Failed to start exit timer, exiting now\n");
exit(1);
}
}
else {
printf("tcpbench> ---- Socket Error: '%s'. Was unexpected! Something went wrong.\n", strerror(pico_err));
exit(2);
}
}
if (ev & PICO_SOCK_EV_CLOSE) {
printf("tcpbench> event close\n");
if (tcpbench_mode == TCP_BENCH_RX) {
pico_socket_close(s);
printf("tcpbench> Called shutdown write, ev = %d\n", ev);
} else if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
pico_socket_close(s);
return;
}
}
if (ev & PICO_SOCK_EV_WR) {
if (((tcpbench_wr_size < TCPSIZ) && (tcpbench_mode == TCP_BENCH_TX)) || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
do {
tcpbench_w = pico_socket_write(tcpbench_sock, buffer0 + (tcpbench_wr_size % TCPSIZ), TCPSIZ - (tcpbench_wr_size % TCPSIZ));
if (tcpbench_w > 0) {
tcpbench_wr_size += tcpbench_w;
/* printf("tcpbench> SOCKET WRITTEN - %d\n",tcpbench_w); */
} else {
/* printf("pico_socket_write returned %d\n", tcpbench_w); */
}
if (tcpbench_time_start == 0)
tcpbench_time_start = PICO_TIME_MS();
} while(tcpbench_w > 0);
printf("tcpbench_wr_size = %d \r", tcpbench_wr_size);
} else {
if (!closed && tcpbench_mode == TCP_BENCH_TX) {
tcpbench_time_end = PICO_TIME_MS();
pico_socket_shutdown(s, PICO_SHUT_WR);
printf("tcpbench> TCPSIZ written\n");
printf("tcpbench> Called shutdown()\n");
tcpbench_time = (tcpbench_time_end - tcpbench_time_start) / 1000.0; /* get number of seconds */
printf("tcpbench> Transmitted %u bytes in %lf seconds\n", TCPSIZ, tcpbench_time);
printf("tcpbench> average write throughput %lf kbit/sec\n", ((TCPSIZ * 8.0) / tcpbench_time) / 1000);
closed = 1;
}
}
}
}
void app_tcpbench(char *arg)
{
struct pico_socket *s;
char *dport = NULL;
char *dest = NULL;
char *mode = NULL;
char *nagle = NULL;
int port = 0, i;
uint16_t port_be = 0;
char *nxt;
char *sport = NULL;
int nagle_off = 1;
union {
struct pico_ip4 ip4;
struct pico_ip6 ip6;
} inaddr_any = {
.ip4 = {0}, .ip6 = {{0}}
};
nxt = cpy_arg(&mode, arg);
if ((*mode == 't') || (*mode == 'f')) { /* TEST BENCH SEND MODE */
if (*mode == 't')
tcpbench_mode = TCP_BENCH_TX;
else
tcpbench_mode = TCP_BENCH_TX_FOREVER;
printf("tcpbench> TX\n");
nxt = cpy_arg(&dest, nxt);
if (!dest) {
fprintf(stderr, "tcpbench send needs the following format: tcpbench:tx:dst_addr[:dport][:n] -- 'n' is for nagle\n");
exit(255);
}
printf ("+++ Dest is %s\n", dest);
if (nxt) {
printf("Next arg: %s\n", nxt);
nxt = cpy_arg(&dport, nxt);
printf("Dport: %s\n", dport);
}
if (nxt) {
printf("Next arg: %s\n", nxt);
nxt = cpy_arg(&nagle, nxt);
printf("nagle: %s\n", nagle);
if (strlen(nagle) == 1 && nagle[0] == 'n') {
nagle_off = 0;
printf("Nagle algorithm enabled\n");
}
}
if (dport) {
port = atoi(dport);
port_be = short_be((uint16_t)port);
}
if (port == 0) {
port_be = short_be(5555);
}
buffer0 = malloc(TCPSIZ);
buffer1 = malloc(TCPSIZ);
printf("Buffer1 (%p)\n", buffer1);
for (i = 0; i < TCPSIZ; i++) {
char c = (i % 26) + 'a';
buffer0[i] = c;
}
memset(buffer1, 'a', TCPSIZ);
printf("tcpbench> Connecting to: %s:%d\n", dest, short_be(port_be));
if (!IPV6_MODE) {
struct pico_ip4 server_addr;
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpbench);
if (!s)
exit(1);
pico_socket_setoption(s, PICO_TCP_NODELAY, &nagle_off);
/* NOTE: used to set a fixed local port and address
local_port = short_be(6666);
pico_string_to_ipv4("10.40.0.11", &local_addr.addr);
pico_socket_bind(s, &local_addr, &local_port);*/
pico_string_to_ipv4(dest, &server_addr.addr);
pico_socket_connect(s, &server_addr, port_be);
} else {
struct pico_ip6 server_addr;
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpbench);
if (!s)
exit(1);
pico_socket_setoption(s, PICO_TCP_NODELAY, &nagle_off);
/* NOTE: used to set a fixed local port and address
local_port = short_be(6666);
pico_string_to_ipv4("10.40.0.11", &local_addr.addr);
pico_socket_bind(s, &local_addr, &local_port);*/
#ifdef PICO_SUPPORT_IPV6
pico_string_to_ipv6(dest, server_addr.addr);
pico_socket_connect(s, &server_addr, port_be);
#endif
}
} else if (*mode == 'r') { /* TEST BENCH RECEIVE MODE */
int ret;
tcpbench_mode = TCP_BENCH_RX;
printf("tcpbench> RX\n");
cpy_arg(&sport, nxt);
if (!sport) {
fprintf(stderr, "tcpbench receive needs the following format: tcpbench:rx[:dport]\n");
exit(255);
}
if (sport) {
printf("s-port is %s\n", sport);
port = atoi(sport);
port_be = short_be((uint16_t)port);
printf("tcpbench> Got port %d\n", port);
free(sport);
}
if (port == 0) {
port_be = short_be(5555);
}
printf("tcpbench> OPEN\n");
if (!IPV6_MODE)
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpbench);
else
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpbench);
if (!s)
exit(1);
printf("tcpbench> BIND\n");
if (!IPV6_MODE)
ret = pico_socket_bind(s, &inaddr_any.ip4, &port_be);
else
ret = pico_socket_bind(s, &inaddr_any.ip6, &port_be);
if (ret < 0) {
printf("tcpbench> BIND failed because %s\n", strerror(pico_err));
exit(1);
}
printf("tcpbench> LISTEN\n");
if (pico_socket_listen(s, 40) != 0)
exit(1);
printf("tcpbench> listening port %u ...\n", short_be(port_be));
} else {
printf("tcpbench> wrong mode argument\n");
exit(1);
}
tcpbench_sock = s;
/* free strdups */
if (dport)
free(dport);
if (dest)
free (dest);
if (mode)
free (mode);
if (nagle)
free (nagle);
return;
}
/*** END TCP BENCH ***/

View File

@@ -0,0 +1,197 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_socket.h>
/*** START TCP CLIENT ***/
static char *buffer1;
static char *buffer0;
void compare_results(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
{
#ifdef CONSISTENCY_CHECK /* TODO: Enable */
int i;
printf("Calculating result.... (%p)\n", buffer1);
if (memcmp(buffer0, buffer1, TCPSIZ) == 0)
exit(0);
for (i = 0; i < TCPSIZ; i++) {
if (buffer0[i] != buffer1[i]) {
fprintf(stderr, "Error at byte %d - %c!=%c\n", i, buffer0[i], buffer1[i]);
exit(115);
}
}
#endif
exit(0);
}
void cb_tcpclient(uint16_t ev, struct pico_socket *s)
{
static int w_size = 0;
static int r_size = 0;
static int closed = 0;
int r, w;
static unsigned long count = 0;
count++;
picoapp_dbg("tcpclient> wakeup %lu, event %u\n", count, ev);
if (ev & PICO_SOCK_EV_RD) {
do {
r = pico_socket_read(s, buffer1 + r_size, TCPSIZ - r_size);
if (r > 0) {
r_size += r;
picoapp_dbg("SOCKET READ - %d\n", r_size);
}
if (r < 0)
exit(5);
} while(r > 0);
}
if (ev & PICO_SOCK_EV_CONN) {
printf("Connection established with server.\n");
}
if (ev & PICO_SOCK_EV_FIN) {
printf("Socket closed. Exit normally. \n");
if (!pico_timer_add(2000, compare_results, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
}
if (ev & PICO_SOCK_EV_ERR) {
printf("Socket error received: %s. Bailing out.\n", strerror(pico_err));
exit(1);
}
if (ev & PICO_SOCK_EV_CLOSE) {
printf("Socket received close from peer - Wrong case if not all client data sent!\n");
pico_socket_close(s);
return;
}
if (ev & PICO_SOCK_EV_WR) {
if (w_size < TCPSIZ) {
do {
w = pico_socket_write(s, buffer0 + w_size, TCPSIZ - w_size);
if (w > 0) {
w_size += w;
picoapp_dbg("SOCKET WRITTEN - %d\n", w_size);
if (w < 0)
exit(5);
}
} while(w > 0);
} else {
#ifdef INFINITE_TCPTEST
w_size = 0;
return;
#endif
if (!closed) {
pico_socket_shutdown(s, PICO_SHUT_WR);
printf("Called shutdown()\n");
closed = 1;
}
}
}
}
void app_tcpclient(char *arg)
{
char *daddr = NULL, *dport = NULL;
char *nxt = arg;
uint16_t send_port = 0, listen_port = short_be(5555);
int i = 0, ret = 0, yes = 1;
struct pico_socket *s = NULL;
union pico_address dst = {
.ip4 = {0}, .ip6 = {{0}}
};
union pico_address inaddr_any = {
.ip4 = {0}, .ip6 = {{0}}
};
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&daddr, arg);
if (daddr) {
if (!IPV6_MODE)
pico_string_to_ipv4(daddr, &dst.ip4.addr);
#ifdef PICO_SUPPORT_IPV6
else
pico_string_to_ipv6(daddr, dst.ip6.addr);
#endif
} else {
goto out;
}
} else {
/* missing dest_addr */
goto out;
}
if (nxt) {
nxt = cpy_arg(&dport, nxt);
if (dport && atoi(dport)) {
send_port = short_be(atoi(dport));
} else {
goto out;
}
} else {
/* missing send_port */
goto out;
}
/* end of argument parsing */
buffer0 = malloc(TCPSIZ);
buffer1 = malloc(TCPSIZ);
printf("Buffer1 (%p)\n", buffer1);
for (i = 0; i < TCPSIZ; i++) {
char c = (i % 26) + 'a';
buffer0[i] = c;
}
memset(buffer1, 'a', TCPSIZ);
printf("Connecting to: %s:%d\n", daddr, short_be(send_port));
if (!IPV6_MODE)
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpclient);
else
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpclient);
if (!s) {
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
exit(1);
}
pico_socket_setoption(s, PICO_TCP_NODELAY, &yes);
if (!IPV6_MODE)
ret = pico_socket_bind(s, &inaddr_any.ip4, &listen_port);
else
ret = pico_socket_bind(s, &inaddr_any.ip6, &listen_port);
if (ret < 0) {
printf("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err));
exit(1);
}
if (!IPV6_MODE)
ret = pico_socket_connect(s, &dst.ip4, send_port);
else
ret = pico_socket_connect(s, &dst.ip6, send_port);
if (ret < 0) {
printf("%s: error connecting to %s:%u: %s\n", __FUNCTION__, daddr, short_be(send_port), strerror(pico_err));
exit(1);
}
return;
out:
fprintf(stderr, "tcpclient expects the following format: tcpclient:dest_addr:dest_port\n");
exit(255);
}
/*** END TCP CLIENT ***/

View File

@@ -0,0 +1,178 @@
#include "utils.h"
#include <pico_socket.h>
#include <pico_ipv4.h>
/*** START TCP ECHO ***/
#define BSIZE (1024 * 10)
static char recvbuf[BSIZE];
static int pos = 0, len = 0;
static int flag = 0;
int send_tcpecho(struct pico_socket *s)
{
int w, ww = 0;
if (len > pos) {
do {
w = pico_socket_write(s, recvbuf + pos, len - pos);
if (w > 0) {
pos += w;
ww += w;
if (pos >= len) {
pos = 0;
len = 0;
}
}
} while((w > 0) && (pos < len));
}
return ww;
}
void cb_tcpecho(uint16_t ev, struct pico_socket *s)
{
int r = 0;
picoapp_dbg("tcpecho> wakeup ev=%u\n", ev);
if (ev & PICO_SOCK_EV_RD) {
if (flag & PICO_SOCK_EV_CLOSE)
printf("SOCKET> EV_RD, FIN RECEIVED\n");
while (len < BSIZE) {
r = pico_socket_read(s, recvbuf + len, BSIZE - len);
if (r > 0) {
len += r;
flag &= ~(PICO_SOCK_EV_RD);
} else {
flag |= PICO_SOCK_EV_RD;
break;
}
}
if (flag & PICO_SOCK_EV_WR) {
flag &= ~PICO_SOCK_EV_WR;
send_tcpecho(s);
}
}
if (ev & PICO_SOCK_EV_CONN) {
uint32_t ka_val = 0;
struct pico_socket *sock_a = {
0
};
struct pico_ip4 orig = {
0
};
uint16_t port = 0;
char peer[30] = {
0
};
int yes = 1;
sock_a = pico_socket_accept(s, &orig, &port);
pico_ipv4_to_string(peer, orig.addr);
printf("Connection established with %s:%d.\n", peer, short_be(port));
pico_socket_setoption(sock_a, PICO_TCP_NODELAY, &yes);
/* Set keepalive options */
ka_val = 5;
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPCNT, &ka_val);
ka_val = 30000;
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPIDLE, &ka_val);
ka_val = 5000;
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPINTVL, &ka_val);
}
if (ev & PICO_SOCK_EV_FIN) {
printf("Socket closed. Exit normally. \n");
if (!pico_timer_add(2000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
}
if (ev & PICO_SOCK_EV_ERR) {
printf("Socket error received: %s. Bailing out.\n", strerror(pico_err));
exit(1);
}
if (ev & PICO_SOCK_EV_CLOSE) {
printf("Socket received close from peer.\n");
if (flag & PICO_SOCK_EV_RD) {
pico_socket_shutdown(s, PICO_SHUT_WR);
printf("SOCKET> Called shutdown write, ev = %d\n", ev);
}
}
if (ev & PICO_SOCK_EV_WR) {
r = send_tcpecho(s);
if (r == 0)
flag |= PICO_SOCK_EV_WR;
else
flag &= (~PICO_SOCK_EV_WR);
}
}
void app_tcpecho(char *arg)
{
char *nxt = arg;
char *lport = NULL;
uint16_t listen_port = 0;
int ret = 0, yes = 1;
struct pico_socket *s = NULL;
union {
struct pico_ip4 ip4;
struct pico_ip6 ip6;
} inaddr_any = {
.ip4 = {0}, .ip6 = {{0}}
};
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
goto out;
}
} else {
/* missing listen_port */
goto out;
}
/* end of argument parsing */
if (!IPV6_MODE)
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpecho);
else
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpecho);
if (!s) {
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
exit(1);
}
pico_socket_setoption(s, PICO_TCP_NODELAY, &yes);
if (!IPV6_MODE)
ret = pico_socket_bind(s, &inaddr_any.ip4, &listen_port);
else
ret = pico_socket_bind(s, &inaddr_any.ip6, &listen_port);
if (ret < 0) {
printf("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err));
exit(1);
}
if (pico_socket_listen(s, 40) != 0) {
printf("%s: error listening on port %u\n", __FUNCTION__, short_be(listen_port));
exit(1);
}
printf("Launching PicoTCP echo server\n");
return;
out:
fprintf(stderr, "tcpecho expects the following format: tcpecho:listen_port\n");
exit(255);
}
/*** END TCP ECHO ***/

View File

@@ -0,0 +1,485 @@
#include "utils.h"
#include <pico_stack.h>
#include <pico_tftp.h>
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <inttypes.h>
/* Let's use linux fs */
#include <fcntl.h>
#include <ctype.h>
/*** START TFTP ***/
#ifdef PICO_SUPPORT_TFTP
#define TFTP_MODE_SRV 0
#define TFTP_MODE_CLI 1
#define TFTP_MODE_PSH 2
#define TFTP_TX_COUNT 2000
#define TFTP_PAYLOAD_SIZE 512
unsigned char tftp_txbuf[TFTP_PAYLOAD_SIZE];
static uint16_t family;
struct command_t {
char operation;
char *filename;
union pico_address server_address;
struct command_t *next;
};
struct note_t {
char *filename;
int fd;
char direction;
int32_t filesize;
struct note_t *next;
};
struct note_t *clipboard = NULL;
struct note_t *add_note(const char *filename, int fd, char direction)
{
struct note_t *note = PICO_ZALLOC(sizeof(struct note_t));
note->filename = strdup(filename);
note->fd = fd;
note->direction = direction;
note->filesize = 0;
note->next = clipboard;
clipboard = note;
return note;
}
void del_note(struct note_t *note)
{
struct note_t *prev;
if (note == clipboard)
{
clipboard = clipboard->next;
if (note->filename)
free (note->filename);
PICO_FREE(note);
} else {
for (prev = clipboard; prev->next; prev = prev->next)
if (prev->next == note) {
prev->next = note->next;
if (note->filename)
free (note->filename);
PICO_FREE(note);
break;
}
}
}
struct command_t *add_command(struct command_t *commands, char operation,
char *filename, union pico_address *server_address)
{
struct command_t *command = PICO_ZALLOC(sizeof(struct command_t));
command->operation = operation;
command->filename = filename;
memcpy(&command->server_address, server_address, sizeof(union pico_address));
command->next = commands;
return command;
}
int32_t get_filesize(const char *filename)
{
int ret;
struct stat buf;
ret = stat(filename, &buf);
if (ret)
return -1;
return buf.st_size;
}
struct note_t *setup_transfer(char operation, const char *filename)
{
int fd;
printf("operation %c\n", operation);
fd = open(filename, (toupper(operation) == 'T') ? O_RDONLY : O_WRONLY | O_EXCL | O_CREAT, 0666);
if (fd < 0) {
perror("open");
fprintf(stderr, "Unable to handle file %s\n", filename);
return NULL;
}
return add_note(filename, fd, operation);
}
int cb_tftp_tx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
{
struct note_t *note = (struct note_t *) arg;
if (event != PICO_TFTP_EV_OK) {
fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
exit(1);
}
len = read(note->fd, tftp_txbuf, PICO_TFTP_PAYLOAD_SIZE);
if (len >= 0) {
note->filesize += len;
pico_tftp_send(session, tftp_txbuf, len);
if (len < PICO_TFTP_PAYLOAD_SIZE) {
printf("TFTP: file %s (%" PRId32 " bytes) TX transfer complete!\n", note->filename, note->filesize);
close(note->fd);
del_note(note);
}
} else {
perror("read");
fprintf(stderr, "Filesystem error reading file %s, cancelling current transfer\n", note->filename);
pico_tftp_abort(session, TFTP_ERR_EACC, "Error on read");
del_note(note);
}
if (!clipboard) {
if (!pico_timer_add(3000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
}
return len;
}
int cb_tftp_tx_opt(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
{
int ret;
int32_t filesize;
if (event == PICO_TFTP_EV_OPT) {
ret = pico_tftp_get_option(session, PICO_TFTP_OPTION_FILE, &filesize);
if (ret)
printf("TFTP: Option filesize is not used\n");
else
printf("TFTP: We expect to transmit %" PRId32 " bytes\n", filesize);
event = PICO_TFTP_EV_OK;
}
return cb_tftp_tx(session, event, block, len, arg);
}
int cb_tftp_rx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
{
struct note_t *note = (struct note_t *) arg;
int ret;
if (event != PICO_TFTP_EV_OK) {
fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
exit(1);
}
if (!note)
return 0;
note->filesize += len;
if (write(note->fd, block, len) < 0) {
perror("write");
fprintf(stderr, "Filesystem error writing file %s, cancelling current transfer\n", note->filename);
pico_tftp_abort(session, TFTP_ERR_EACC, "Error on write");
del_note(note);
} else {
if (len != PICO_TFTP_PAYLOAD_SIZE) {
printf("TFTP: file %s (%" PRId32 " bytes) RX transfer complete!\n", note->filename, note->filesize);
close(note->fd);
del_note(note);
}
}
if (!clipboard) {
if (!pico_timer_add(3000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
}
return len;
}
int cb_tftp_rx_opt(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
{
int ret;
int32_t filesize;
if (event == PICO_TFTP_EV_OPT) {
ret = pico_tftp_get_option(session, PICO_TFTP_OPTION_FILE, &filesize);
if (ret)
printf("TFTP: Option filesize is not used\n");
else
printf("TFTP: We expect to receive %" PRId32 " bytes\n", filesize);
return 0;
}
return cb_tftp_rx(session, event, block, len, arg);
}
struct pico_tftp_session *make_session_or_die(union pico_address *addr, uint16_t family)
{
struct pico_tftp_session *session;
session = pico_tftp_session_setup(addr, family);
if (!session) {
fprintf(stderr, "TFTP: Error in session setup\n");
exit(3);
}
return session;
}
struct note_t *transfer_prepare(struct pico_tftp_session **psession, char operation, const char *filename, union pico_address *addr, uint16_t family)
{
struct note_t *note;
note = setup_transfer(operation, filename);
*psession = make_session_or_die(addr, family);
return note;
}
void start_rx(struct pico_tftp_session *session, const char *filename, uint16_t port,
int (*rx_callback)(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg),
struct note_t *note)
{
if (pico_tftp_start_rx(session, port, filename, rx_callback, note)) {
fprintf(stderr, "TFTP: Error in initialization\n");
exit(1);
}
}
void start_tx(struct pico_tftp_session *session, const char *filename, uint16_t port,
int (*tx_callback)(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg),
struct note_t *note)
{
if (pico_tftp_start_tx(session, port, filename, tx_callback, note)) {
fprintf(stderr, "TFTP: Error in initialization\n");
exit(1);
}
}
void tftp_listen_cb(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len)
{
struct note_t *note;
struct pico_tftp_session *session;
printf("TFTP listen callback (BASIC) from remote port %" PRIu16 ".\n", short_be(port));
if (opcode == PICO_TFTP_RRQ) {
printf("Received TFTP get request for %s\n", filename);
note = transfer_prepare(&session, 't', filename, addr, family);
start_tx(session, filename, port, cb_tftp_tx, note);
} else if (opcode == PICO_TFTP_WRQ) {
printf("Received TFTP put request for %s\n", filename);
note = transfer_prepare(&session, 'r', filename, addr, family);
start_rx(session, filename, port, cb_tftp_rx, note);
}
}
void tftp_listen_cb_opt(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len)
{
struct note_t *note;
struct pico_tftp_session *session;
int options;
uint8_t timeout;
int32_t filesize;
int ret;
printf("TFTP listen callback (OPTIONS) from remote port %" PRIu16 ".\n", short_be(port));
/* declare the options we want to support */
ret = pico_tftp_parse_request_args(filename, len, &options, &timeout, &filesize);
if (ret)
pico_tftp_reject_request(addr, port, TFTP_ERR_EOPT, "Malformed request");
if (opcode == PICO_TFTP_RRQ) {
printf("Received TFTP get request for %s\n", filename);
note = transfer_prepare(&session, 'T', filename, addr, family);
if (options & PICO_TFTP_OPTION_TIME)
pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
if (options & PICO_TFTP_OPTION_FILE) {
ret = get_filesize(filename);
if (ret < 0) {
pico_tftp_reject_request(addr, port, TFTP_ERR_ENOENT, "File not found");
return;
}
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
}
start_tx(session, filename, port, cb_tftp_tx_opt, note);
} else { /* opcode == PICO_TFTP_WRQ */
printf("Received TFTP put request for %s\n", filename);
note = transfer_prepare(&session, 'R', filename, addr, family);
if (options & PICO_TFTP_OPTION_TIME)
pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
if (options & PICO_TFTP_OPTION_FILE)
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
start_rx(session, filename, port, cb_tftp_rx_opt, note);
}
}
void print_usage(int exit_code)
{
printf("\nUsage: tftp:OPTION:[OPTION]...\n"
"\nOtions can be repeated. Every option may be one of the following:\n"
"\ts\t\t\t starts the basic server (RFC1350)\n"
"\tS\t\t\t starts the server with option handling capability\n"
"\tt:file:ip\t\t PUT request (without options) for file to server ip\n"
"\tT:file:ip\t\t PUT request for file to server ip\n"
"\tr:file:ip\t\t GET request (without options) for file to server ip\n"
"\tR:file:ip\t\t GET request for file to server ip\n"
"Example:\n"
"\t\t tftp:S:T:firstFile:10.40.0.2:R:another.file:10.40.0.5:T:secondFile:10.40.0.2\n\n");
exit(exit_code);
}
struct command_t *parse_arguments_recursive(struct command_t *commands, char *arg)
{
char *next;
char *operation;
char *filename;
char *address;
static union pico_address remote_address;
int ret;
struct command_t *new_cmd = NULL;
if (!arg)
return commands;
next = cpy_arg(&operation, arg);
switch (*operation) {
case 'S':
case 's':
filename = address = NULL;
break;
case 'T':
case 'R':
case 't':
case 'r':
if (!next) {
fprintf(stderr, "Incomplete client command %s (filename componet is missing)\n", arg);
return NULL;
}
next = cpy_arg(&filename, next);
if (!next) {
fprintf(stderr, "Incomplete client command %s (address component is missing)\n", arg);
return NULL;
}
next = cpy_arg(&address, next);
if (!IPV6_MODE)
ret = pico_string_to_ipv4(address, &remote_address.ip4.addr);
else
ret = pico_string_to_ipv6(address, remote_address.ip6.addr);
if (ret < 0) {
fprintf(stderr, "Invalid IP address %s\n", address);
print_usage(2);
}
if (address)
free(address);
break;
default:
fprintf(stderr, "Invalid command %s\n", operation);
return NULL;
};
new_cmd = add_command(commands, *operation, filename, &remote_address);
free(operation);
return parse_arguments_recursive(new_cmd, next);
}
struct command_t *parse_arguments(char *arg)
{
struct command_t *reversed = parse_arguments_recursive(NULL, arg);
struct command_t *commands = NULL;
struct command_t *current;
if (!reversed) {
fprintf(stderr, "Wrong command line!\n");
print_usage(1);
}
while (reversed) {
current = reversed;
reversed = reversed->next;
current->next = commands;
commands = current;
}
return commands;
}
void app_tftp(char *arg)
{
struct command_t *commands, *old_cmd;
struct note_t *note;
struct pico_tftp_session *session;
int is_server_enabled = 0;
int filesize;
family = IPV6_MODE ? PICO_PROTO_IPV6 : PICO_PROTO_IPV4;
commands = parse_arguments(arg);
while (commands) {
if (toupper(commands->operation) != 'S')
note = transfer_prepare(&session, commands->operation, commands->filename, &commands->server_address, family);
switch (commands->operation) {
case 'S':
case 's':
if (!is_server_enabled) {
pico_tftp_listen(PICO_PROTO_IPV4, (commands->operation == 'S') ? tftp_listen_cb_opt : tftp_listen_cb);
is_server_enabled = 1;
}
break;
case 'T':
filesize = get_filesize(commands->filename);
if (filesize < 0) {
fprintf(stderr, "TFTP: unable to read size of file %s\n", commands->filename);
exit(3);
}
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx_opt, note);
break;
case 't':
start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx, note);
break;
case 'R':
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0);
start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx_opt, note);
break;
case 'r':
start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx, note);
}
old_cmd = commands;
commands = commands->next;
if (old_cmd->filename)
free(old_cmd->filename);
/* commands are allocated using PICO_ZALLOC, so use PICO_FREE */
PICO_FREE(old_cmd);
}
}
#endif
/* END TFTP */

View File

@@ -0,0 +1,290 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_socket.h>
/*** START UDP CLIENT ***/
/*
* udpclient expects the following format: udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops]
* dest_addr: IP address to send datagrams to
* sendto_port: port number to send datagrams to
* listen_port [OPTIONAL]: port number on which the udpclient listens
* datasize [OPTIONAL]: size of the data given to the socket in one go
* loops [OPTIONAL]: number of intervals in which data is send
* subloops [OPTIONAL]: number of sends in one interval
*
* REMARK: once an optional parameter is given, all optional parameters need a value!
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a udpclient:10.40.0.3:6667:6667:1400:100:10
*/
struct udpclient_pas *udpclient_pas;
static int exit_retry = 0;
static void request_exit_echo(pico_time now, void *arg)
{
struct pico_socket *s = (struct pico_socket *)arg;
char end[4] = "end";
pico_socket_send(s, end, 4);
if (exit_retry++ > 3) {
if (!pico_timer_add(1000, deferred_exit, udpclient_pas)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
} else {
if (!pico_timer_add(1000, request_exit_echo, s)) {
printf("Failed to start request_exit_echo timer, sending request now\n");
request_exit_echo((pico_time)0, NULL);
exit(1);
}
printf("%s: requested exit of echo\n", __FUNCTION__);
}
}
void udpclient_send(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
{
struct pico_socket *s = udpclient_pas->s;
char *buf = NULL;
int i = 0, w = 0;
static uint16_t loop = 0;
if (++loop > udpclient_pas->loops) {
if (!pico_timer_add(1000, request_exit_echo, s)) {
printf("Failed to start request_exit_echo timer, sending request now\n");
request_exit_echo((pico_time)0, NULL);
exit(1);
}
return;
} else {
buf = calloc(1, udpclient_pas->datasize);
if (!buf) {
printf("%s: no memory available\n", __FUNCTION__);
return;
}
memset(buf, '1', udpclient_pas->datasize);
picoapp_dbg("%s: performing loop %u\n", __FUNCTION__, loop);
for (i = 0; i < udpclient_pas->subloops; i++) {
w = pico_socket_send(s, buf, udpclient_pas->datasize);
if (w <= 0)
break;
}
picoapp_dbg("%s: written %u byte(s) in each of %u subloops\n", __FUNCTION__, udpclient_pas->datasize, i);
free(buf);
}
if (!pico_timer_add(100, udpclient_send, NULL)) {
printf("Failed to start send timer, sending exit request to echo and exiting\n");
request_exit_echo((pico_time)0, NULL);
exit(1);
}
}
void cb_udpclient(uint16_t ev, struct pico_socket *s)
{
char *recvbuf = NULL;
int r = 0;
if (ev & PICO_SOCK_EV_RD) {
recvbuf = calloc(1, udpclient_pas->datasize);
if (!recvbuf) {
printf("%s: no memory available\n", __FUNCTION__);
return;
}
do {
r = pico_socket_recv(s, recvbuf, udpclient_pas->datasize);
} while ( r > 0);
free(recvbuf);
}
if (ev == PICO_SOCK_EV_ERR) {
printf("Socket Error received. Bailing out.\n");
free(udpclient_pas);
exit(7);
}
}
void app_udpclient(char *arg)
{
char *daddr = NULL, *lport = NULL, *sport = NULL, *s_datasize = NULL, *s_loops = NULL, *s_subloops = NULL;
char *nxt = arg;
char sinaddr_any[40] = {
0
};
uint16_t listen_port = 0;
int ret = 0;
udpclient_pas = calloc(1, sizeof(struct udpclient_pas));
if (!udpclient_pas) {
printf("%s: no memory available\n", __FUNCTION__);
exit(255);
}
udpclient_pas->s = NULL;
udpclient_pas->loops = 100;
udpclient_pas->subloops = 10;
udpclient_pas->datasize = 1400;
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&daddr, arg);
if (daddr) {
if (!IPV6_MODE)
pico_string_to_ipv4(daddr, &udpclient_pas->dst.ip4.addr);
#ifdef PICO_SUPPORT_IPV6
else
pico_string_to_ipv6(daddr, udpclient_pas->dst.ip6.addr);
#endif
} else {
goto out;
}
} else {
/* missing dest_addr */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
udpclient_pas->sport = short_be(atoi(sport));
} else {
goto out;
}
} else {
/* missing send_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
goto out;
}
} else {
/* missing listen_port, use default */
listen_port = 0;
}
if (nxt) {
nxt = cpy_arg(&s_datasize, nxt);
if (s_datasize && atoi(s_datasize)) {
udpclient_pas->datasize = atoi(s_datasize);
} else {
goto out;
}
} else {
/* missing datasize, incomplete optional parameters? -> exit */
if (lport)
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_loops, nxt);
if (s_loops && atoi(s_loops)) {
udpclient_pas->loops = atoi(s_loops);
} else {
goto out;
}
} else {
/* missing loops, incomplete optional parameters? -> exit */
if (s_datasize)
goto out;
}
if (nxt) {
nxt = cpy_arg(&s_subloops, nxt);
if (s_subloops && atoi(s_subloops)) {
udpclient_pas->subloops = atoi(s_subloops);
} else {
goto out;
}
} else {
/* missing subloops, incomplete optional parameters? -> exit */
if (s_loops)
goto out;
}
/* end of argument parsing */
if (!IPV6_MODE)
pico_ipv4_to_string(sinaddr_any, inaddr_any.addr);
#ifdef PICO_SUPPORT_IPV6
else
pico_ipv6_to_string(sinaddr_any, inaddr6_any.addr);
#endif
if (!IPV6_MODE)
udpclient_pas->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpclient);
else
udpclient_pas->s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &cb_udpclient);
if (!udpclient_pas->s) {
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
free(udpclient_pas);
exit(1);
}
if (!IPV6_MODE)
ret = pico_socket_bind(udpclient_pas->s, &inaddr_any, &listen_port);
else
ret = pico_socket_bind(udpclient_pas->s, &inaddr6_any, &listen_port);
if (ret < 0) {
free(udpclient_pas);
printf("%s: error binding socket to %s:%u: %s\n", __FUNCTION__, sinaddr_any, short_be(listen_port), strerror(pico_err));
exit(1);
}
if (!IPV6_MODE)
ret = pico_socket_connect(udpclient_pas->s, &udpclient_pas->dst.ip4, udpclient_pas->sport);
else
ret = pico_socket_connect(udpclient_pas->s, &udpclient_pas->dst.ip6, udpclient_pas->sport);
if (ret < 0) {
printf("%s: error connecting to [%s]:%u: %s\n", __FUNCTION__, daddr, short_be(udpclient_pas->sport), strerror(pico_err));
free(udpclient_pas);
exit(1);
}
printf("\n%s: UDP client launched. Sending packets of %u bytes in %u loops and %u subloops to %s:%u\n\n",
__FUNCTION__, udpclient_pas->datasize, udpclient_pas->loops, udpclient_pas->subloops, daddr, short_be(udpclient_pas->sport));
if (!pico_timer_add(100, udpclient_send, NULL)) {
printf("Failed to start send timer, sending exit request to echo and exiting\n");
request_exit_echo((pico_time)0, NULL);
exit(1);
}
/* free strdups */
if (daddr)
free (daddr);
if (lport)
free (lport);
if (sport)
free (sport);
if (s_datasize)
free (s_datasize);
if (s_loops)
free (s_loops);
if (s_subloops)
free (s_subloops);
return;
out:
fprintf(stderr, "udpclient expects the following format: udpclient:dest_addr:dest_port[:listen_port:datasize:loops:subloops]\n");
free(udpclient_pas);
exit(255);
}
/*** END UDP CLIENT ***/

View File

@@ -0,0 +1,216 @@
#include "utils.h"
#include <pico_ipv4.h>
#include <pico_ipv6.h>
#include <pico_socket.h>
/**** START UDP ECHO ****/
/*
* udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]
* bind_addr: IP address to bind to
* listen_port: port number on which the udpecho listens
* sendto_port [OPTIONAL]: port number to echo datagrams to (echo to originating IP address)
* datasize [OPTIONAL]: max size of the data red from the socket in one go
*
* REMARK: once an optional parameter is given, all optional parameters need a value!
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.3:255.255.255.0: -a udpecho:10.40.0.3:6667:6667:1400
*/
static int udpecho_exit = 0;
struct udpecho_pas *udpecho_pas;
void cb_udpecho(uint16_t ev, struct pico_socket *s)
{
char *recvbuf = NULL;
uint16_t port = 0;
int r = 0;
union {
struct pico_ip4 ip4;
struct pico_ip6 ip6;
} peer;
if (udpecho_exit)
return;
if (ev == PICO_SOCK_EV_RD) {
recvbuf = calloc(1, udpecho_pas->datasize);
if (!recvbuf) {
printf("%s: no memory available\n", __FUNCTION__);
return;
}
do {
r = pico_socket_recvfrom(s, recvbuf, udpecho_pas->datasize, IPV6_MODE ? (void *)peer.ip6.addr : (void *)&peer.ip4.addr, &port);
/* printf("UDP recvfrom returned %d\n", r); */
if (r > 0) {
if (strncmp(recvbuf, "end", 3) == 0) {
printf("Client requested to exit... test successful.\n");
if (!pico_timer_add(1000, deferred_exit, udpecho_pas)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
udpecho_exit++;
}
pico_socket_sendto(s, recvbuf, r, IPV6_MODE ? (void *)peer.ip6.addr : (void *)&peer.ip4.addr, port);
}
} while (r > 0);
free(recvbuf);
}
if (ev == PICO_SOCK_EV_ERR) {
printf("Socket Error received. Bailing out.\n");
free(udpecho_pas);
exit(7);
}
picoapp_dbg("%s: received packet from %08X:%u\n", __FUNCTION__, long_be(peer), short_be(port));
}
void app_udpecho(char *arg)
{
char *baddr = NULL, *lport = NULL, *sport = NULL, *s_datasize = NULL;
char *nxt = arg;
uint16_t listen_port = 0;
struct pico_ip4 inaddr_bind = { };
struct pico_ip6 inaddr_bind6 = { };
int ret = 0;
udpecho_pas = calloc(1, sizeof(struct udpecho_pas));
if (!udpecho_pas) {
printf("%s: no memory available\n", __FUNCTION__);
exit(255);
}
udpecho_pas->s = NULL;
udpecho_pas->sendto_port = 0;
udpecho_pas->datasize = 5000;
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&baddr, nxt);
if (baddr) {
if (!IPV6_MODE)
pico_string_to_ipv4(baddr, &inaddr_bind.addr);
#ifdef PICO_SUPPORT_IPV6
else
pico_string_to_ipv6(baddr, inaddr_bind6.addr);
#endif
} else {
goto out;
}
} else {
/* missing bind_addr */
goto out;
}
if (nxt) {
nxt = cpy_arg(&lport, nxt);
if (lport && atoi(lport)) {
listen_port = short_be(atoi(lport));
} else {
listen_port = short_be(5555);
}
} else {
/* missing listen_port */
goto out;
}
if (nxt) {
nxt = cpy_arg(&sport, nxt);
if (sport && atoi(sport)) {
udpecho_pas->sendto_port = atoi(sport);
} else {
/* incorrect send_port */
goto out;
}
} else {
/* missing send_port, use default */
}
if (nxt) {
nxt = cpy_arg(&s_datasize, nxt);
if (s_datasize && atoi(s_datasize)) {
udpecho_pas->datasize = atoi(s_datasize);
} else {
/* incorrect datasize */
goto out;
}
} else {
/* missing datasize, incomplete optional parameters? -> exit */
if (sport)
goto out;
}
/* end of argument parsing */
if (!IPV6_MODE)
udpecho_pas->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpecho);
else
udpecho_pas->s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &cb_udpecho);
if (!udpecho_pas->s) {
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
free(udpecho_pas);
exit(1);
}
if (!IPV6_MODE)
ret = pico_socket_bind(udpecho_pas->s, &inaddr_bind, &listen_port);
else {
ret = pico_socket_bind(udpecho_pas->s, &inaddr_bind6, &listen_port);
printf("udpecho> Bound to [%s]:%d.\n", baddr, short_be(listen_port));
}
if (ret != 0) {
free(udpecho_pas);
if (!IPV6_MODE)
printf("%s: error binding socket to %08X:%u: %s\n", __FUNCTION__, long_be(inaddr_bind.addr), short_be(listen_port), strerror(pico_err));
else
printf("%s: error binding socket to [%s]:%u: %s\n", __FUNCTION__, baddr, short_be(listen_port), strerror(pico_err));
exit(1);
}
#ifdef PICOAPP_IPFILTER
{
struct pico_ip4 address, in_addr_netmask, in_addr;
/* struct pico_ipv4_link *link; */
int ret = 0;
address.addr = 0x0800280a;
in_addr_netmask.addr = 0x00FFFFFF;
in_addr.addr = 0x0000320a;
/* link = pico_ipv4_link_get(&address); */
printf("udpecho> IPFILTER ENABLED\n");
/*Adjust your IPFILTER*/
ret |= pico_ipv4_filter_add(NULL, 17, NULL, NULL, &in_addr, &in_addr_netmask, 0, 5555, 0, 0, FILTER_DROP);
if (ret < 0)
printf("Filter_add invalid argument\n");
}
#endif
printf("\n%s: UDP echo launched. Receiving packets of %u bytes on port %u\n\n", __FUNCTION__, udpecho_pas->datasize, short_be(listen_port));
/* free strdups */
if (baddr)
free (baddr);
if (lport)
free (lport);
if (sport)
free (sport);
if (s_datasize)
free (s_datasize);
return;
out:
fprintf(stderr, "udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]\n");
free(udpecho_pas);
exit(255);
}
/*** END UDP ECHO ***/

View File

@@ -0,0 +1,88 @@
#include "utils.h"
#include <pico_ipv6.h>
#include <pico_socket.h>
/**** START UDP ECHO ****/
/*
* udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]
* bind_addr: IP address to bind to
* listen_port: port number on which the udpecho listens
* sendto_port [OPTIONAL]: port number to echo datagrams to (echo to originating IP address)
* datasize [OPTIONAL]: max size of the data red from the socket in one go
*
* REMARK: once an optional parameter is given, all optional parameters need a value!
*
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.3:255.255.255.0: -a udpecho:10.40.0.3:6667:6667:1400
*/
void dummy_cb(uint16_t __attribute__((unused)) ev, struct pico_socket __attribute__((unused)) *s)
{
}
void app_sendto_test(char *arg)
{
char *nxt = arg;
char *dstaddr = NULL;
char *dstport = NULL;
struct pico_ip4 inaddr_dst = {};
struct pico_ip6 inaddr_dst6 = {};
uint16_t dport;
struct pico_socket *sock;
int ret;
/* start of argument parsing */
if (nxt) {
nxt = cpy_arg(&dstaddr, nxt);
if (dstaddr) {
if (!IPV6_MODE)
pico_string_to_ipv4(dstaddr, &inaddr_dst.addr);
#ifdef PICO_SUPPORT_IPV6
else
pico_string_to_ipv6(dstaddr, inaddr_dst6.addr);
#endif
} else {
goto out;
}
} else {
/* missing bind_addr */
goto out;
}
if (nxt) {
nxt = cpy_arg(&dstport, nxt);
if (dstport && atoi(dstport)) {
dport = short_be(atoi(dstport));
} else {
dport = short_be(5555);
}
} else {
/* missing listen_port */
goto out;
}
if (!IPV6_MODE)
sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &dummy_cb);
else
sock = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &dummy_cb);
ret = pico_socket_sendto(sock, "Testing", 7u, ((IPV6_MODE) ? (void *)(&inaddr_dst6) : (void *)(&inaddr_dst)), dport);
if (ret < 0)
printf("Failure in first pico_socket_send\n");
ret = pico_socket_sendto(sock, "Testing", 7u, ((IPV6_MODE) ? (void *)(&inaddr_dst6) : (void *)(&inaddr_dst)), dport);
if (ret < 0)
printf("Failure in second pico_socket_send\n");
ret = pico_socket_close(sock);
if (ret)
printf("Failure in pico_socket_close\n");
printf("\n%s: UDP sendto test launched. Sending packets to ip %s port %u\n\n", __FUNCTION__, dstaddr, short_be(dport));
return;
out:
fprintf(stderr, "udp_sendto_test expects the following format: udp_sendto_test:dest_addr:[dest_por]t\n");
exit(255);
}

View File

@@ -0,0 +1,151 @@
#include "utils.h"
#include <pico_ipv6.h>
#include <pico_socket.h>
/*** START UDP NAT CLIENT ***/
/* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0:10.40.0.10: -a udpnatclient:10.50.0.8:6667: */
static struct pico_ip4 udpnatclient_inaddr_dst;
static uint16_t udpnatclient_port_be;
void udpnatclient_send(pico_time __attribute__((unused)) now, void *arg)
{
int i, w;
struct pico_socket *s = (struct pico_socket *)arg;
char buf[1400] = { };
char end[4] = "end";
static int loop = 0;
for ( i = 0; i < 3; i++) {
w = pico_socket_send(s, buf, 1400);
}
if (++loop > 1000) {
udpnatclient_port_be = 0;
for (i = 0; i < 3; i++) {
w = pico_socket_send(s, end, 4);
if (w <= 0)
break;
printf("End!\n");
}
if (!pico_timer_add(1000, deferred_exit, NULL)) {
printf("Failed to start exit timer, exiting now\n");
exit(1);
}
return;
}
}
void cb_udpnatclient(uint16_t ev, struct pico_socket *s)
{
char recvbuf[1400];
int r = 0;
if (ev & PICO_SOCK_EV_RD) {
do {
r = pico_socket_recv(s, recvbuf, 1400);
} while(r > 0);
}
if (ev == PICO_SOCK_EV_ERR) {
printf("Socket Error received. Bailing out.\n");
exit(7);
}
/* Not closing to test port check */
/* pico_socket_close(s); */
}
void udpnatclient_open_socket(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
{
struct pico_socket *s = NULL;
static int loop;
if (!udpnatclient_port_be)
return;
loop++;
picoapp_dbg(">>>>> Loop %d\n", loop);
if (!(loop % 100))
printf("Created %d sockets\n", loop);
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpnatclient);
if (!s)
exit(1);
if (pico_socket_connect(s, &udpnatclient_inaddr_dst, udpnatclient_port_be) != 0)
{
printf("Error connecting\n");
exit(1);
}
picoapp_dbg("New socket with port %u\n", s->local_port);
if (!pico_timer_add(25, udpnatclient_send, s)) {
printf("Failed to start send timer, exiting now\n");
exit(1);
}
if (!pico_timer_add(25, udpnatclient_open_socket, 0)) {
printf("Failed to start open_socket timer, exiting now\n");
exit(1);
}
}
void app_udpnatclient(char *arg)
{
struct pico_socket *s;
char *daddr, *dport;
int port = 0;
uint16_t port_be = 0;
struct pico_ip4 inaddr_dst = ZERO_IP4;
char *nxt;
nxt = cpy_arg(&daddr, arg);
if (!daddr) {
fprintf(stderr, " udpnatclient expects the following format: udpnatclient:dest_addr[:dest_port]\n");
exit(255);
}
if (nxt) {
nxt = cpy_arg(&dport, nxt);
if (dport) {
port = atoi(dport);
if (port > 0)
port_be = short_be(port);
}
}
if (port == 0) {
port_be = short_be(5555);
}
printf("UDP NAT client started. Sending packets to %s:%d\n", daddr, short_be(port_be));
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpnatclient);
if (!s)
exit(1);
pico_string_to_ipv4(daddr, &inaddr_dst.addr);
if (pico_socket_connect(s, &inaddr_dst, port_be) != 0)
{
printf("Error binding the port \n");
exit(1);
}
picoapp_dbg("New socket with port %u\n", s->local_port);
udpnatclient_inaddr_dst = inaddr_dst;
udpnatclient_port_be = port_be;
if (!pico_timer_add(100, udpnatclient_send, s)) {
printf("Failed to start send timer, exiting now\n");
exit(1);
}
if (!pico_timer_add(1000, udpnatclient_open_socket, 0)) {
printf("Failed to start open_socket timer, exiting now\n");
exit(1);
}
}
/*** END UDP NAT CLIENT ***/

View File

@@ -0,0 +1,39 @@
#ifndef PICO_EXAMPLES_UTILS_H
#define PICO_EXAMPLES_UTILS_H
#include <pico_stack.h>
#define TCPSIZ (1024 * 1024 * 5)
extern struct pico_ip4 ZERO_IP4;
extern struct pico_ip_mreq ZERO_MREQ;
extern struct pico_ip_mreq_source ZERO_MREQ_SRC;
extern struct pico_ip6 ZERO_IP6;
extern struct pico_ip_mreq ZERO_MREQ_IP6;
extern struct pico_ip_mreq_source ZERO_MREQ_SRC_IP6;
#define picoapp_dbg(...) do {} while(0)
/* #define picoapp_dbg printf */
extern int IPV6_MODE;
extern struct pico_ip4 inaddr_any;
extern struct pico_ip6 inaddr6_any;
extern char *cpy_arg(char **dst, char *str);
extern void deferred_exit(pico_time now, void *arg);
struct udpclient_pas {
struct pico_socket *s;
uint8_t loops;
uint8_t subloops;
uint16_t datasize;
uint16_t sport;
union pico_address dst;
}; /* per application struct */
struct udpecho_pas {
struct pico_socket *s;
uint16_t sendto_port; /* big-endian */
uint16_t datasize;
}; /* per application struct */
#endif

104
kernel/picotcp/test/mkunits.sh Executable file
View File

@@ -0,0 +1,104 @@
#!/bin/bash
# By Daniele.
#set -x
filename=$1
if [ [x$1] == [x] ]; then
echo USAGE: $0 filename.c
exit 4
fi
#CMOCK="../CMock/lib/cmock.rb"
bname=`basename $filename`
cat $filename |grep static|grep \( | grep \) >/tmp/$bname
if (test -f ./test/unit/modunit_$bname); then
echo The destination file ./test/unit/modunit_$bname already exists. Exiting...
exit 0
fi
cat $filename |grep "\#include " > ./test/unit/modunit_$bname
MYSELF=`echo $bname | cut -d"." -f1`.h
INCLUDES=`cat $filename |grep "\#include \"" |grep -v $MYSELF| cut -d '"' -f 2`
echo includes are:
echo $INCLUDES
echo "#include \"$filename\"" >>./test/unit/modunit_$bname
echo "#include \"check.h\"" >>./test/unit/modunit_$bname
echo >> ./test/unit/modunit_$bname
echo >> ./test/unit/modunit_$bname
while read fn ; do
fname=`echo $fn | cut -d "(" -f 1| cut -d" " -f 3`
echo "START_TEST(tc_$fname)" >>./test/unit/modunit_$bname
echo "{" >>./test/unit/modunit_$bname
echo " /* TODO: test this: $fn */" >>./test/unit/modunit_$bname
echo "}" >>./test/unit/modunit_$bname
echo "END_TEST" >>./test/unit/modunit_$bname
done </tmp/$bname
echo >> ./test/unit/modunit_$bname
echo >> ./test/unit/modunit_$bname
echo "Suite *pico_suite(void)
{
Suite *s = suite_create(\"PicoTCP\");
" >> ./test/unit/modunit_$bname
while read fn ; do
fname=`echo $fn | cut -d "(" -f 1| cut -d" " -f 3`
echo " TCase *TCase_$fname = tcase_create(\"Unit test for $fname\");" >> ./test/unit/modunit_$bname
done </tmp/$bname
echo >> ./test/unit/modunit_$bname
echo >> ./test/unit/modunit_$bname
while read fn ; do
fname=`echo $fn | cut -d "(" -f 1| cut -d" " -f 3`
echo " tcase_add_test(TCase_$fname, tc_$fname);" >> ./test/unit/modunit_$bname
echo " suite_add_tcase(s, TCase_$fname);" >> ./test/unit/modunit_$bname
done </tmp/$bname
echo "return s;">> ./test/unit/modunit_$bname
echo "}">> ./test/unit/modunit_$bname
echo "
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}" >>./test/unit/modunit_$bname
echo Gernerated test ./test/unit/modunit_$bname
#echo Generating mocks...
#mkdir -p mocks
#
#CFILES=""
#for i in $INCLUDES; do
# ii=`find -name $i | grep -v build`
# ruby $CMOCK $ii
# CFILE=`basename $ii |cut -d "." -f 1`.c
# CFILES="$CFILES mocks/Mock$CFILE"
#done
ELF=`echo build/test/modunit_$bname | sed -e "s/\.c/.elf/g"`
echo
echo
MOCKS=$(gcc -I include/ -I modules/ -I. test/unit/modunit_$bname $CFILES -lcheck -pthread -lm -lrt -o $ELF 2>&1 |grep "undefined reference to" | sed -e "s/.*\`//g" | sed -e "s/'.*$//g" |sort | uniq)
for m in $MOCKS; do
decl=`grep -R $m * |grep -v ");" | grep -v Binary | cut -d ":" -f 2`
echo $decl >> ./test/unit/modunit_$bname
echo "{" >> ./test/unit/modunit_$bname
echo "/* TODO: MOCK ME! */">> ./test/unit/modunit_$bname
echo "}" >> ./test/unit/modunit_$bname
done
gcc -I include/ -I modules/ -I. test/unit/modunit_$bname $CFILES -lcheck -pthread -lm -lrt -o $ELF && echo "Successfully compiled $ELF"
#echo " /* TODO: MOCKS NEEDED: $MOCKS */ " >>./test/unit/modunit_$bname

View File

@@ -0,0 +1,68 @@
#!/bin/bash
sudo vde_switch -t pic0 -s /tmp/pic0.ctl -d
sudo vde_switch -s /tmp/pic1.ctl -d
sudo vde_switch -s /tmp/pic2.ctl -d
sudo vde_switch -s /tmp/pic3.ctl -d
sudo ifconfig pic0 10.40.0.254/16 up
./build/test/picoapp.elf \
--vde pic0:/tmp/pic0.ctl:10.40.0.8:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0: \
--vde pic1:/tmp/pic1.ctl:10.41.0.9:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic1.ctl:10.41.0.1:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic1.ctl:10.41.0.2:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic1.ctl:10.41.0.3:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic1.ctl:10.41.0.10:255.255.0.0: \
--vde pic1:/tmp/pic2.ctl:10.42.0.10:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic2.ctl:10.42.0.1:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic2.ctl:10.42.0.2:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic1.ctl:10.42.0.3:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic2.ctl:10.42.0.11:255.255.0.0: \
--vde pic1:/tmp/pic3.ctl:10.43.0.11:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic3.ctl:10.43.0.1:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic3.ctl:10.43.0.2:255.255.0.0: \
-a olsr: &
./build/test/picoapp.elf \
--vde pic0:/tmp/pic3.ctl:10.43.0.3:255.255.0.0: \
-a olsr: &
sleep 5
sudo killall olsrd
sudo olsrd -i pic0

26
kernel/picotcp/test/perf.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
THRESHOLD=300
sh ./test/vde_sock_start_user.sh
sleep 2
(iperf -s >/tmp/iperf.log)&
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.50.0.2:255.255.255.0:10.50.0.1: --app iperfc:10.50.0.1: &>/dev/null
killall iperf
RES=`cat /tmp/iperf.log |grep Mbits |sed -e "s/.*Bytes//g" |sed -e "s/^[ ]*//g"`
SPEED=`echo $RES | cut -d " " -f 1`
UNITS=`echo $RES | cut -d " " -f 2`
if [ ["$UNITS"] != ["Mbits/sec"] ]; then
echo "Wrong test result units: expected Mbits/sec, got $UNITS"
exit 1
fi
if (test $SPEED -lt $THRESHOLD); then
echo "Speed too low: expected $THRESHOLD MBits/s, got $SPEED $UNITS"
exit 2
fi
echo Test result: $SPEED $UNITS
rm -f /tmp/iperf.log
exit 0

View File

@@ -0,0 +1,29 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "pico_faulty.h"
/* #warning "COMPILING for MEMORY TESTS!" */
uint32_t mm_failure_count = 0;
uint32_t cur_mem, max_mem;
static int called_atexit = 0;
void memory_stats(void)
{
fprintf(stderr, " ################ MAX MEMORY USED in this test: %u\n", max_mem);
}
int pico_set_mm_failure(uint32_t nxt)
{
if (!called_atexit) {
atexit(memory_stats);
called_atexit++;
}
mm_failure_count = nxt;
return 0;
}

View File

@@ -0,0 +1,134 @@
/*********************************************************************
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
Do not redistribute without a written permission by the Copyright
holders.
*********************************************************************/
/* This is a test implementation, with a faulty memory manager,
* intended to increase test coverage
* Warning: not intended for production!
*
*/
#ifndef PICO_SUPPORT_POSIX
#define PICO_SUPPORT_POSIX
#define PICO_FAULTY
#define MEM_LIMIT (0)
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#include <stdlib.h>
extern uint32_t mm_failure_count;
int pico_set_mm_failure(uint32_t nxt);
extern uint32_t max_mem;
extern uint32_t cur_mem;
/*
#define TIME_PRESCALE
*/
#define dbg printf
#define stack_fill_pattern(...) do {} while(0)
#define stack_count_free_words(...) do {} while(0)
#define stack_get_free_words() (0)
static inline void mem_stat_store(void)
{
char fname_mod[] = "/tmp/pico-mem-report-%hu.txt";
char fname[200];
char buffer[20];
int fd;
snprintf(fname, 200, fname_mod, getpid());
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0660);
if (fd < 0) {
return;
}
snprintf(buffer, 20, "%d\n", max_mem);
write(fd, buffer, strlen(buffer));
close(fd);
}
static inline void *pico_zalloc(size_t x)
{
uint32_t *ptr;
if (mm_failure_count > 0) {
if (--mm_failure_count == 0) {
fprintf(stderr, "Malloc failed, for test purposes\n");
return NULL;
}
}
ptr = (uint32_t *)calloc(x + sizeof(uint32_t), 1);
*ptr = (uint32_t)x; /* store size of alloc */
cur_mem += (uint32_t)x;
#ifndef DISABLE_MM_STATS
if (cur_mem > max_mem) {
max_mem = cur_mem;
if ((MEM_LIMIT > 0) && (max_mem > MEM_LIMIT))
abort();
mem_stat_store();
}
#endif
return (void*)(ptr + 1);
}
static inline void pico_free(void *x)
{
uint32_t *ptr = (uint32_t*)(((uint8_t *)x) - sizeof(uint32_t)); /* fetch size of the alloc */
cur_mem -= *ptr;
free(ptr);
}
/* time prescaler */
#ifdef TIME_PRESCALE
extern int32_t prescale_time;
#endif
static inline uint32_t PICO_TIME(void)
{
struct timeval t;
gettimeofday(&t, NULL);
#ifdef TIME_PRESCALE
return (prescale_time < 0) ? (uint32_t)(t.tv_sec / 1000 << (-prescale_time)) : \
(uint32_t)(t.tv_sec / 1000 >> prescale_time);
#else
return (uint32_t)t.tv_sec;
#endif
}
static inline uint32_t PICO_TIME_MS(void)
{
struct timeval t;
gettimeofday(&t, NULL);
#ifdef TIME_PRESCALER
uint32_t tmp = ((t.tv_sec * 1000) + (t.tv_usec / 1000));
return (prescale_time < 0) ? (uint32_t)(tmp / 1000 << (-prescale_time)) : \
(uint32_t)(tmp / 1000 >> prescale_time);
#else
return (uint32_t)((t.tv_sec * 1000) + (t.tv_usec / 1000));
#endif
}
static inline void PICO_IDLE(void)
{
usleep(5000);
}
void memory_stats(void);
#endif /* PICO_SUPPORT_POSIX */

View File

@@ -0,0 +1,757 @@
/* PicoTCP Test application */
#include <poll.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/types.h>
#include <unistd.h>
#include "utils.h"
#include "pico_stack.h"
#include "pico_config.h"
#include "pico_dev_vde.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_socket.h"
#include "pico_dev_tun.h"
#include "pico_dev_tap.h"
#include "pico_nat.h"
#include "pico_icmp4.h"
#include "pico_icmp6.h"
#include "pico_dns_client.h"
#include "pico_dev_loop.h"
#include "pico_dhcp_client.h"
#include "pico_dhcp_server.h"
#include "pico_ipfilter.h"
#include "pico_olsr.h"
#include "pico_sntp_client.h"
#include "pico_mdns.h"
#include "pico_tftp.h"
#include "pico_dev_radiotest.h"
#include "pico_dev_radio_mgr.h"
#include <poll.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#ifdef FAULTY
#include "pico_faulty.h"
#endif
void app_udpecho(char *args);
void app_tcpecho(char *args);
void app_udpclient(char *args);
void app_tcpclient(char *args);
void app_tcpbench(char *args);
void app_natbox(char *args);
void app_udpdnsclient(char *args);
void app_udpnatclient(char *args);
void app_mcastsend(char *args);
void app_mcastreceive_ipv6(char *args);
void app_mcastsend_ipv6(char *args);
void app_mcastreceive(char *args);
void app_ping(char *args);
void app_dhcp_server(char *args);
void app_dhcp_client(char *args);
void app_dns_sd(char *arg, struct pico_ip4 addr);
void app_mdns(char *arg, struct pico_ip4 addr);
void app_sntp(char *args);
void app_tftp(char *args);
void app_slaacv4(char *args);
void app_udpecho(char *args);
void app_sendto_test(char *args);
void app_noop(void);
struct pico_ip4 ZERO_IP4 = {
0
};
struct pico_ip_mreq ZERO_MREQ = {
.mcast_group_addr = {{0}},
.mcast_link_addr = {{0}}
};
struct pico_ip_mreq_source ZERO_MREQ_SRC = {
.mcast_group_addr.ip4 = {0},
.mcast_link_addr.ip4 = {0},
.mcast_source_addr.ip4 = {0}
};
struct pico_ip6 ZERO_IP6 = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
struct pico_ip_mreq ZERO_MREQ_IP6 = {
.mcast_group_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
.mcast_link_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}
};
struct pico_ip_mreq_source ZERO_MREQ_SRC_IP6 = {
.mcast_group_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
.mcast_link_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }},
.mcast_source_addr.ip6 = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}
};
/* #define INFINITE_TCPTEST */
#define picoapp_dbg(...) do {} while(0)
/* #define picoapp_dbg printf */
/* #define PICOAPP_IPFILTER 1 */
int IPV6_MODE;
struct pico_ip4 inaddr_any = {
0
};
struct pico_ip6 inaddr6_any = {{0}};
char *cpy_arg(char **dst, char *str);
void deferred_exit(pico_time __attribute__((unused)) now, void *arg)
{
if (arg) {
free(arg);
arg = NULL;
}
printf("%s: quitting\n", __FUNCTION__);
exit(0);
}
/** From now on, parsing the command line **/
#define NXT_MAC(x) ++ x[5]
/* Copy a string until the separator,
terminate it and return the next index,
or NULL if it encounters a EOS */
char *cpy_arg(char **dst, char *str)
{
char *p, *nxt = NULL;
char *start = str;
char *end = start + strlen(start);
char sep = ':';
if (IPV6_MODE)
sep = ',';
p = str;
while (p) {
if ((*p == sep) || (*p == '\0')) {
*p = (char)0;
nxt = p + 1;
if ((*nxt == 0) || (nxt >= end))
nxt = 0;
printf("dup'ing %s\n", start);
*dst = strdup(start);
break;
}
p++;
}
return nxt;
}
static void __wakeup(uint16_t __attribute__((unused)) ev, struct pico_socket __attribute__((unused)) *s)
{
}
static void usage(char *arg0)
{
printf("Usage: %s [--vde name:sock:address:netmask[:gateway]] [--vde ...] [--tun name:address:netmask[:gateway]] [--tun ...] [--app name[:args]]\n\n\n", arg0);
printf("\tall arguments can be repeated, e.g. to run on multiple links or applications\n");
printf("\t* --app arguments must be at the end *\n");
exit(255);
}
#define IF_APPNAME(x) if(strcmp(x, name) == 0)
int main(int argc, char **argv)
{
unsigned char macaddr[6] = {
0, 0, 0, 0xa, 0xb, 0x0
};
uint16_t *macaddr_low = (uint16_t *) (macaddr + 2);
struct pico_device *dev = NULL;
struct pico_ip4 addr4 = {
0
};
struct pico_ip4 bcastAddr = ZERO_IP4;
struct option long_options[] = {
{"help", 0, 0, 'h'},
{"vde", 1, 0, 'v'},
{"barevde", 1, 0, 'b'},
{"tun", 1, 0, 't'},
{"tap", 1, 0, 'T'},
{"route", 1, 0, 'r'},
{"app", 1, 0, 'a'},
{"dns", 1, 0, 'd'},
{"loop", 0, 0, 'l'},
{0, 0, 0, 0}
};
int option_idx = 0;
int c;
char *app = NULL, *p = argv[0];
/* parse till we find the name of the executable */
while (p) {
if (*p == '/')
app = p + 1;
else if (*p == '\0')
break;
else
{} /* do nothing */
p++;
}
if (strcmp(app, "picoapp6.elf") == 0)
IPV6_MODE = 1;
*macaddr_low = (uint16_t)(*macaddr_low ^ (uint16_t)((uint16_t)getpid() & (uint16_t)0xFFFFU));
printf("My macaddr base is: %02x %02x\n", macaddr[2], macaddr[3]);
printf("My macaddr is: %02x %02x %02x %02x %02x %02x\n", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
#ifdef PICO_SUPPORT_MM
pico_mem_init(128 * 1024);
#endif
pico_stack_init();
/* Parse args */
while(1) {
c = getopt_long(argc, argv, "6:v:b:t:T:a:r:hl", long_options, &option_idx);
if (c < 0)
break;
switch(c) {
case 'h':
usage(argv[0]);
break;
case 'T':
{
char *nxt, *name = NULL, *addr = NULL, *nm = NULL, *gw = NULL;
struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
do {
nxt = cpy_arg(&name, optarg);
if (!nxt) break;
nxt = cpy_arg(&addr, nxt);
if (!nxt) break;
nxt = cpy_arg(&nm, nxt);
if (!nxt) break;
cpy_arg(&gw, nxt);
} while(0);
if (!nm) {
fprintf(stderr, "Tun: bad configuration...\n");
exit(1);
}
dev = pico_tap_create(name);
if (!dev) {
perror("Creating tap");
exit(1);
}
pico_string_to_ipv4(addr, &ipaddr.addr);
pico_string_to_ipv4(nm, &netmask.addr);
pico_ipv4_link_add(dev, ipaddr, netmask);
bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
if (gw && *gw) {
pico_string_to_ipv4(gw, &gateway.addr);
printf("Adding default route via %08x\n", gateway.addr);
pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
}
#ifdef PICO_SUPPORT_IPV6
if (IPV6_MODE) {
struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
pico_string_to_ipv6(addr, ipaddr6.addr);
pico_string_to_ipv6(nm, netmask6.addr);
pico_ipv6_link_add(dev, ipaddr6, netmask6);
if (gw && *gw) {
pico_string_to_ipv6(gw, gateway6.addr);
pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
}
pico_ipv6_dev_routing_enable(dev);
}
#endif
}
break;
case 't':
{
char *nxt, *name = NULL, *addr = NULL, *nm = NULL, *gw = NULL;
struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
do {
nxt = cpy_arg(&name, optarg);
if (!nxt) break;
nxt = cpy_arg(&addr, nxt);
if (!nxt) break;
nxt = cpy_arg(&nm, nxt);
if (!nxt) break;
cpy_arg(&gw, nxt);
} while(0);
if (!nm) {
fprintf(stderr, "Tun: bad configuration...\n");
exit(1);
}
dev = pico_tun_create(name);
if (!dev) {
perror("Creating tun");
exit(1);
}
pico_string_to_ipv4(addr, &ipaddr.addr);
pico_string_to_ipv4(nm, &netmask.addr);
pico_ipv4_link_add(dev, ipaddr, netmask);
bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
if (gw && *gw) {
pico_string_to_ipv4(gw, &gateway.addr);
printf("Adding default route via %08x\n", gateway.addr);
pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
}
#ifdef PICO_SUPPORT_IPV6
if (IPV6_MODE) {
struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
pico_string_to_ipv6(addr, ipaddr6.addr);
pico_string_to_ipv6(nm, netmask6.addr);
pico_ipv6_link_add(dev, ipaddr6, netmask6);
if (gw && *gw) {
pico_string_to_ipv6(gw, gateway6.addr);
pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
}
pico_ipv6_dev_routing_enable(dev);
}
#endif
}
break;
case 'v':
{
char *nxt, *name = NULL, *sock = NULL, *addr = NULL, *nm = NULL, *gw = NULL, *addr6 = NULL, *nm6 = NULL, *gw6 = NULL, *loss_in = NULL, *loss_out = NULL;
struct pico_ip4 ipaddr, netmask, gateway, zero = ZERO_IP4;
uint32_t i_pc = 0, o_pc = 0;
printf("+++ OPTARG %s\n", optarg);
do {
nxt = cpy_arg(&name, optarg);
if (!nxt) break;
nxt = cpy_arg(&sock, nxt);
if (!nxt) break;
if (!IPV6_MODE) {
nxt = cpy_arg(&addr, nxt);
if (!nxt) break;
nxt = cpy_arg(&nm, nxt);
if (!nxt) break;
nxt = cpy_arg(&gw, nxt);
if (!nxt) break;
nxt = cpy_arg(&loss_in, nxt);
if (!nxt) break;
nxt = cpy_arg(&loss_out, nxt);
if (!nxt) break;
} else {
nxt = cpy_arg(&addr6, nxt);
if (!nxt) break;
printf("addr6: %s\n", addr6);
nxt = cpy_arg(&nm6, nxt);
if (!nxt) break;
nxt = cpy_arg(&gw6, nxt);
if (!nxt) break;
nxt = cpy_arg(&loss_in, nxt);
if (!nxt) break;
nxt = cpy_arg(&loss_out, nxt);
if (!nxt) break;
}
} while(0);
if (!nm && !nm6) {
fprintf(stderr, "Vde: bad configuration...\n");
exit(1);
}
macaddr[4] ^= (uint8_t)(getpid() >> 8);
macaddr[5] ^= (uint8_t) (getpid() & 0xFF);
dev = pico_vde_create(sock, name, macaddr);
NXT_MAC(macaddr);
if (!dev) {
perror("Creating vde");
exit(1);
}
printf("Vde created.\n");
if (!IPV6_MODE) {
pico_string_to_ipv4(addr, &ipaddr.addr);
pico_string_to_ipv4(nm, &netmask.addr);
pico_ipv4_link_add(dev, ipaddr, netmask);
addr4 = ipaddr;
bcastAddr.addr = (ipaddr.addr) | (~netmask.addr);
if (gw && *gw) {
pico_string_to_ipv4(gw, &gateway.addr);
pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
}
}
#ifdef PICO_SUPPORT_IPV6
if (IPV6_MODE) {
struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}}, gateway6 = {{0}}, zero6 = {{0}};
printf("SETTING UP IPV6 ADDRESS\n");
pico_string_to_ipv6(addr6, ipaddr6.addr);
pico_string_to_ipv6(nm6, netmask6.addr);
pico_ipv6_link_add(dev, ipaddr6, netmask6);
if (gw6 && *gw6) {
pico_string_to_ipv6(gw6, gateway6.addr);
pico_ipv6_route_add(zero6, zero6, gateway6, 1, NULL);
}
pico_ipv6_dev_routing_enable(dev);
}
#endif
if (loss_in && (strlen(loss_in) > 0)) {
i_pc = (uint32_t)atoi(loss_in);
}
if (loss_out && (strlen(loss_out) > 0)) {
o_pc = (uint32_t)atoi(loss_out);
}
if (i_pc || o_pc) {
printf(" ---------- >Setting vde packet loss %u:%u\n", i_pc, o_pc);
pico_vde_set_packetloss(dev, i_pc, o_pc);
}
}
break;
case '6':
{
char *nxt, *name = NULL, *area0 = NULL, *area1 = NULL, *dump = NULL;
const char pan_addr[] = "2aaa:abcd::0";
uint8_t n_id, n_area0, n_area1;
struct pico_ip6 pan;
/* Copy required command line arguments */
nxt = cpy_arg(&name, optarg);
if (!nxt)
goto check;
nxt = cpy_arg(&area0, nxt);
if (!nxt)
goto check;
nxt = cpy_arg(&area1, nxt);
if (!nxt)
goto check;
/* Check required arguments */
check: if (!name || !area0 || !area1) {
fprintf(stderr, "Usage: -6,id,area\n");
exit(1);
}
n_id = (uint8_t) atoi(name);
n_area0 = (uint8_t) atoi(area0);
n_area1 = (uint8_t) atoi(area1);
if (nxt) {
nxt = cpy_arg(&dump, nxt);
}
printf("%d:%d:%d\n", n_id, n_area0, n_area1);
if (!n_id) {
printf("Starting radio-network...\n");
pico_radio_mgr_start();
} else {
dev = pico_radiotest_create(n_id, n_area0, n_area1, 0, dump);
if (!dev) {
exit(1);
}
printf("Radiotest created.\n");
/* Add a routable link */
pico_string_to_ipv6(pan_addr, pan.addr);
pico_ipv6_link_add_local(dev, &pan);
/* Enable routing on first device */
if (n_id == 1) {
pico_ipv6_dev_routing_enable(dev);
}
}
break;
}
case 'b':
{
char *nxt, *name = NULL, *sock = NULL;
printf("+++ OPTARG %s\n", optarg);
do {
nxt = cpy_arg(&name, optarg);
if (!nxt) break;
nxt = cpy_arg(&sock, nxt);
} while(0);
if (!sock) {
fprintf(stderr, "Vde: bad configuration...\n");
exit(1);
}
macaddr[4] ^= (uint8_t)(getpid() >> 8);
macaddr[5] ^= (uint8_t)(getpid() & 0xFF);
dev = pico_vde_create(sock, name, macaddr);
NXT_MAC(macaddr);
if (!dev) {
if (sock)
free(sock);
if (name)
free(name);
perror("Creating vde");
exit(1);
}
if (sock)
free(sock);
if (name)
free(name);
printf("Vde created.\n");
}
break;
case 'l':
{
struct pico_ip4 ipaddr, netmask;
dev = pico_loop_create();
if (!dev) {
perror("Creating loop");
exit(1);
}
pico_string_to_ipv4("127.0.0.1", &ipaddr.addr);
pico_string_to_ipv4("255.0.0.0", &netmask.addr);
pico_ipv4_link_add(dev, ipaddr, netmask);
printf("Loopback created\n");
#ifdef PICO_SUPPORT_IPV6
if (IPV6_MODE) {
struct pico_ip6 ipaddr6 = {{0}}, netmask6 = {{0}};
pico_string_to_ipv6("::1", ipaddr6.addr);
pico_string_to_ipv6("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", netmask6.addr);
pico_ipv6_link_add(dev, ipaddr6, netmask6);
}
pico_ipv6_dev_routing_enable(dev);
#endif
}
break;
case 'r':
{
char *nxt, *addr, *nm, *gw;
struct pico_ip4 ipaddr, netmask, gateway;
/* XXX adjust for IPv6 */
addr = NULL, nm = NULL, gw = NULL;
printf("+++ ROUTEOPTARG %s\n", optarg);
do {
nxt = cpy_arg(&addr, optarg);
if (!nxt) break;
nxt = cpy_arg(&nm, nxt);
if (!nxt) break;
nxt = cpy_arg(&gw, nxt);
} while(0);
if (!addr || !nm || !gw) {
fprintf(stderr, "--route expects addr:nm:gw:\n");
usage(argv[0]);
}
pico_string_to_ipv4(addr, &ipaddr.addr);
pico_string_to_ipv4(nm, &netmask.addr);
pico_string_to_ipv4(gw, &gateway.addr);
if (pico_ipv4_route_add(ipaddr, netmask, gateway, 1, NULL) == 0)
fprintf(stderr, "ROUTE ADDED *** to %s via %s\n", addr, gw);
else
fprintf(stderr, "ROUTE ADD: ERROR %s \n", strerror(pico_err));
break;
}
case 'd':
{
/* Add a DNS nameserver IP address */
char *straddr;
struct pico_ip4 ipaddr;
printf("DNS nameserver address = %s\n", optarg);
cpy_arg(&straddr, optarg);
pico_string_to_ipv4(straddr, &ipaddr.addr);
pico_dns_client_nameserver(&ipaddr, PICO_DNS_NS_ADD);
break;
}
case 'a':
{
char *name = NULL, *args = NULL;
printf("+++ OPTARG %s\n", optarg);
args = cpy_arg(&name, optarg);
printf("+++ NAME: %s ARGS: %s\n", name, args);
IF_APPNAME("udpecho") {
app_udpecho(args);
} else IF_APPNAME("tcpecho") {
app_tcpecho(args);
} else IF_APPNAME("udpclient") {
app_udpclient(args);
} else IF_APPNAME("tcpclient") {
app_tcpclient(args);
} else IF_APPNAME("tcpbench") {
app_tcpbench(args);
} else IF_APPNAME("natbox") {
app_natbox(args);
} else IF_APPNAME("udpdnsclient") {
app_udpdnsclient(args);
} else IF_APPNAME("udpnatclient") {
app_udpnatclient(args);
} else IF_APPNAME("mcastsend") {
#ifndef PICO_SUPPORT_MCAST
return 0;
#endif
app_mcastsend(args);
} else IF_APPNAME("mcastreceive") {
#ifndef PICO_SUPPORT_MCAST
return 0;
#endif
app_mcastreceive(args);
}
else IF_APPNAME("mcastsend_ipv6") {
#ifndef PICO_SUPPORT_MCAST
return 0;
#endif
app_mcastsend_ipv6(args);
} else IF_APPNAME("mcastreceive_ipv6") {
#ifndef PICO_SUPPORT_MCAST
return 0;
#endif
app_mcastreceive_ipv6(args);
}
#ifdef PICO_SUPPORT_PING
else IF_APPNAME("ping") {
app_ping(args);
}
#endif
else IF_APPNAME("dhcpserver") {
#ifndef PICO_SUPPORT_DHCPD
return 0;
#else
app_dhcp_server(args);
#endif
} else IF_APPNAME("dhcpclient") {
#ifndef PICO_SUPPORT_DHCPC
return 0;
#else
app_dhcp_client(args);
#endif
} else IF_APPNAME("dns_sd") {
#ifndef PICO_SUPPORT_DNS_SD
return 0;
#else
app_dns_sd(args, addr4);
#endif
} else IF_APPNAME("mdns") {
#ifndef PICO_SUPPORT_MDNS
return 0;
#else
app_mdns(args, addr4);
#endif
#ifdef PICO_SUPPORT_SNTP_CLIENT
} else IF_APPNAME("sntp") {
app_sntp(args);
#endif
} else IF_APPNAME("bcast") {
struct pico_ip4 any = {
.addr = 0xFFFFFFFFu
};
struct pico_socket *s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &__wakeup);
pico_socket_sendto(s, "abcd", 5u, &any, 1000);
pico_socket_sendto(s, "abcd", 5u, &bcastAddr, 1000);
#ifdef PICO_SUPPORT_TFTP
} else IF_APPNAME("tftp") {
app_tftp(args);
#endif
} else IF_APPNAME("noop") {
app_noop();
#ifdef PICO_SUPPORT_OLSR
} else IF_APPNAME("olsr") {
dev = pico_get_device("pic0");
if(dev) {
pico_olsr_add(dev);
}
dev = pico_get_device("pic1");
if(dev) {
pico_olsr_add(dev);
}
app_noop();
#endif
} else IF_APPNAME("slaacv4") {
#ifndef PICO_SUPPORT_SLAACV4
return 0;
#else
app_slaacv4(args);
#endif
} else IF_APPNAME("udp_sendto_test") {
app_sendto_test(args);
} else {
fprintf(stderr, "Unknown application %s\n", name);
usage(argv[0]);
}
}
break;
}
}
if (!dev) {
printf("nodev");
usage(argv[0]);
}
#ifdef FAULTY
atexit(memory_stats);
#endif
printf("%s: launching PicoTCP loop\n", __FUNCTION__);
while(1) {
pico_stack_tick();
usleep(2000);
}
}

193
kernel/picotcp/test/ppp.c Normal file
View File

@@ -0,0 +1,193 @@
#include <pico_stack.h>
#include <pico_dev_ppp.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <pico_icmp4.h>
#include <pico_ipv4.h>
#include <pico_md5.h>
#include <pico_socket.h>
#ifdef PICO_SUPPORT_POLARSSL
#include <polarssl/md5.h>
#endif
#ifdef PICO_SUPPORT_CYASSL
#include <cyassl/ctaocrypt/md5.h>
#endif
#define MODEM "/dev/ttyUSB0"
#define SPEED 236800
/* #define APN "gprs.base.be" */
#define APN "web.be"
#define PASSWD "web"
#define USERNAME "altran"
/* #define DEBUG_FLOW */
static int fd = -1;
static int idx;
static int ping_on = 0;
static struct pico_device *ppp = NULL;
static void sigusr1_hdl(int signo)
{
fprintf(stderr, "SIGUSR1: Connecting!\n");
if (ppp)
pico_ppp_connect(ppp);
}
static void sigusr2_hdl(int signo)
{
fprintf(stderr, "SIGUSR2/SIGINT: Disconnecting!\n");
if (ppp)
pico_ppp_disconnect(ppp);
if (signo == SIGINT)
exit(0);
}
#ifdef PICO_SUPPORT_POLARSSL
static void md5sum(uint8_t *dst, const uint8_t *src, size_t len)
{
md5(src, len, dst);
}
#endif
#ifdef PICO_SUPPORT_CYASSL
static void md5sum(uint8_t *dst, const uint8_t *src, size_t len)
{
Md5 md5;
InitMd5(&md5);
Md5Update(&md5, src, len);
Md5Final(&md5, dst);
}
#endif
int modem_read(struct pico_device *dev, void *data, int len)
{
int r;
r = read(fd, data, len);
#ifdef DEBUG_FLOW
if (r > 0) {
printf(" <<< ");
for(idx = 0; idx < r; idx++) {
printf(" %02x", ((uint8_t*)data)[idx]);
}
printf("\n");
}
#endif
return r;
}
int modem_write(struct pico_device *dev, const void *data, int len)
{
int r;
#ifdef DEBUG_FLOW
printf(" >>> ");
for(idx = 0; idx < len; idx++) {
printf(" %02x", ((uint8_t*)data)[idx]);
}
printf("\n");
#endif
r = write(fd, data, len);
return r;
}
int modem_set_speed(struct pico_device *dev, uint32_t speed)
{
struct termios term;
if (tcgetattr(fd, &term) != 0)
return 6;
if (cfsetspeed(&term, B115200) != 0)
return 7;
if (tcsetattr(fd, TCSANOW, &term) != 0)
return 8;
printf("Speed set to 115200.\n");
return 0;
}
void cb_ping(struct pico_icmp4_stats *s)
{
char host[30];
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("%lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host, s->seq, s->time);
} else {
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
}
}
static void cb_sock(uint16_t ev, struct pico_socket *s)
{
}
static void ping(void)
{
struct pico_socket *s;
struct pico_ip4 dst;
pico_string_to_ipv4("80.68.95.85", &dst.addr);
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, cb_sock);
pico_socket_connect(s, &dst, short_be(80));
pico_icmp4_ping("80.68.95.85", 10, 1000, 4000, 8, cb_ping);
}
int main(int argc, const char *argv[])
{
const char *path = MODEM;
const char *apn = APN;
const char *passwd = PASSWD;
const char *username = USERNAME;
if (argc > 1)
path = argv[1];
if (argc > 2)
apn = argv[2];
if (argc > 3)
passwd = argv[3];
fd = open(path, O_RDWR);
if (fd < 0)
return 1;
fcntl(fd, F_SETFL, O_NONBLOCK);
signal(SIGUSR1, sigusr1_hdl);
signal(SIGUSR2, sigusr2_hdl);
signal(SIGINT, sigusr2_hdl);
pico_stack_init();
#if defined PICO_SUPPORT_POLARSSL || defined PICO_SUPPORT_CYASSL
pico_register_md5sum(md5sum);
#endif
ppp = pico_ppp_create();
if (!ppp)
return 2;
pico_ppp_set_serial_read(ppp, modem_read);
pico_ppp_set_serial_write(ppp, modem_write);
pico_ppp_set_serial_set_speed(ppp, modem_set_speed);
pico_ppp_set_apn(ppp, apn);
pico_ppp_set_password(ppp, passwd);
pico_ppp_set_username(ppp, username);
pico_ppp_connect(ppp);
while(1 < 2) {
pico_stack_tick();
usleep(1000);
if (ppp->link_state(ppp) && !ping_on) {
ping_on++;
ping();
}
}
}

View File

@@ -0,0 +1,36 @@
#!/usr/bin/python
# dhcp.py
# Butterfly-like topology test for dhcp
# One DHCP server, serving on two interface
# Eigth DHCP clients, four on each network
#
# s1----@ @----r1
# s2-----\__ DHCP __/-----r2
# s3-----/ \-----r3
# s4----@ @----r4
#
from topology import *
T = Topology()
net1 = Network(T, "pyt1")
net2 = Network(T, "pyt2")
server = Host(T, net1, net2, args="dhcpserver:eth1:172.16.1.2:255.255.255.0:64:128:eth2:172.16.2.2:255.255.255.0:64:128")
s1 = Host(T, net1, args="dhcpclient:eth1")
s2 = Host(T, net1, args="dhcpclient:eth1")
s3 = Host(T, net1, args="dhcpclient:eth1")
s4 = Host(T, net1, args="dhcpclient:eth1")
r1 = Host(T, net2, args="dhcpclient:eth1")
r2 = Host(T, net2, args="dhcpclient:eth1")
r3 = Host(T, net2, args="dhcpclient:eth1")
r4 = Host(T, net2, args="dhcpclient:eth1")
raw_input("Press enter to continue ...")
start(T)
wait(server)
cleanup()

View File

@@ -0,0 +1,48 @@
#!/usr/bin/python
# fairness.py
# A complex test for butterly-like topology,
# using 3 TCP connections and 3 ping flows.
#
# s1---. .---r1
# s2----\ /
# s3-----\__.R1---R2.__/__.--r2
# s4-----/ \
# s5----/ \_.--r3
# s6---^
#
from topology import *
T = Topology()
net1 = Network(T)
net2 = Network(T)
net3 = Network(T)
#router1 = Host(T, net1, net2, "natbox:172.16.2.1:")
#router2 = Host(T, net2, net3, "natbox:172.16.3.1:")
router1 = Host(T, net1, net2)
router2 = Host(T, net2, net3)
send1 = Host(T, net1, args="tcpbench:t:172.16.3.2:")
send2 = Host(T, net1, args="tcpbench:t:172.16.3.3:")
send3 = Host(T, net1, args="tcpbench:t:172.16.3.4:")
send4 = Host(T, net1, args="ping:172.16.3.2:")
send5 = Host(T, net1, args="ping:172.16.3.3:")
send6 = Host(T, net1, args="ping:172.16.3.4:")
recv1 = Host(T, net3, args="tcpbench:r:")
recv2 = Host(T, net3, args="tcpbench:r:")
recv3 = Host(T, net3, args="tcpbench:r:")
recv4 = Host(T, net3, args="tcpbench:r:")
sleep(1)
start(T)
wait(send1)
wait(send2)
wait(send3)
cleanup()

View File

@@ -0,0 +1,47 @@
#!/usr/bin/python
# fairness.py
# A complex test for butterly-like topology,
# using 3 TCP connections and 3 ping flows.
#
# Bottleneck of 4 Mbit/300 ms overall delay is added.
#
# s1---. .---r1
# s2----\ /
# s3-----\__.R1---R2.__/__.--r2
# s4-----/ \
# s5----/ \_.--r3
# s6---^
#
from topology import *
T = Topology()
net1 = Network(T)
net2 = Network(T)
net3 = Network(T)
router1 = Host(T, net1, net2, delay2="150", bw2="20M")
router2 = Host(T, net2, net3)
send1 = Host(T, net1, args="tcpbench:t:172.16.3.2:")
send2 = Host(T, net1, args="tcpbench:t:172.16.3.3:")
send3 = Host(T, net1, args="tcpbench:t:172.16.3.4:")
send4 = Host(T, net1, args="ping:172.16.3.2:")
send5 = Host(T, net1, args="ping:172.16.3.3:")
send6 = Host(T, net1, args="ping:172.16.3.4:")
recv1 = Host(T, net3, args="tcpbench:r:")
recv2 = Host(T, net3, args="tcpbench:r:")
recv3 = Host(T, net3, args="tcpbench:r:")
sleep(1)
start(T)
wait(send1)
wait(send2)
wait(send3)
cleanup()

View File

@@ -0,0 +1,47 @@
#!/usr/bin/python
# fairness.py
# A complex test for butterly-like topology,
# using 3 TCP connections and 3 ping flows.
#
# Bottleneck of 4 Mbit/300 ms overall delay is added.
#
# s1---. .---r1
# s2----\ /
# s3-----\__.R1---R2.__/__.--r2
# s4-----/ \
# s5----/ \_.--r3
# s6---^
#
from topology import *
T = Topology()
net1 = Network(T)
net2 = Network(T, "pyt0")
net3 = Network(T)
router1 = Host(T, net1, net2, delay2="150", bw2="4M")
router2 = Host(T, net2, net3)
send1 = Host(T, net1, args="tcpbench:t:172.16.3.2:")
send2 = Host(T, net1, args="tcpbench:t:172.16.3.3:")
send3 = Host(T, net1, args="tcpbench:t:172.16.3.4:")
send4 = Host(T, net1, args="ping:172.16.3.2:")
send5 = Host(T, net1, args="ping:172.16.3.3:")
send6 = Host(T, net1, args="ping:172.16.3.4:")
recv1 = Host(T, net3, args="tcpbench:r:")
recv2 = Host(T, net3, args="tcpbench:r:")
recv3 = Host(T, net3, args="tcpbench:r:")
sleep(1)
start(T)
wait(send1)
wait(send2)
wait(send3)
cleanup()

View File

@@ -0,0 +1,60 @@
#!/usr/bin/python
#
# fragmentation.py
#
# Fragmentation test with PicoTCP sending and Linux receiving
#
# (sender) (Receiver)
# PicoTCP ------------------------ Linux
#
# An udpclient is started which will give DATASIZE bytes in one go
# to the socket. This data will be fragmented and send over to the
# Linux, where it is reassembled and received in one piece.
#
from topology import *
import socket, random, string
SRC_ADDR = ''
DST_ADDR = '172.16.1.1'
SRC_PORT = 6667
SENDTO_PORT = 6667
LISTEN_PORT = 6667
DATASIZE = 4000
LOOPS = 4
SUBLOOPS = 1
UDPCLIENT = "udpclient:" + str(DST_ADDR) + ":" + str(SENDTO_PORT) + ":" + str(LISTEN_PORT) + ":" + str(DATASIZE) + ":" + str(LOOPS) + ":" + str(SUBLOOPS)
print UDPCLIENT
T = Topology()
net1 = Network(T, "pyt0")
h1 = Host(T, net1, args=UDPCLIENT)
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_udp.bind((SRC_ADDR, SRC_PORT))
s_udp.settimeout(5);
raw_input("Press enter to continue ...")
start(T)
while True:
data, addr = s_udp.recvfrom(DATASIZE)
#print data
if len(data) == DATASIZE:
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ fragmentation test IS successful +++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(0)
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ fragmentation test NOT successful ++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(1)

View File

@@ -0,0 +1,135 @@
#PicoTCP topology test environment.
#Guidelines to prepare test scenarios.
#
#The interface is simple, it has three objects:
# * Topology
# * Network
# * Host
#
#And a handful of helping routines, such as:
# * start()
# * loop()
# * sleep()
# * wait()
#
#
########################################################################
#== Create a test scenario ==#
########################################################################
# Every script file will start with: "#!/usr/bin/python" in the first
# line, and will have execution permissions. This script is an exception
# because it is not intended to be run, as it is in fact a walkthrough to
# all the functionalities.
# Importing the topology objects is mandatory, so add:
from topology import *
# A Topology must be created to use all other objects:
T = Topology()
# Now, we can create "Network" objects. The networks will have address
# 172.16.X.0/24, where 'X' is the order of creation, starting from 1.
#
network1 = Network(T)
network2 = Network(T)
# The two networks are separated and using different address pools:
#
# ## ### ## ## ## ### ## ##
# # network1 # # network2 #
# # 172.16.1.0 # # 172.16.2.0 #
# ## ## ###### ## ## ######
#
# If you are running your test as root, you can also add a tun-tap connection
# to the network, which will be automatically configured:
networkLocal = Network(T,'tap0')
# In the same way ad networks, you can create a PicoTCP Host that connects to a
# network as follows:
host1_1 = Host(T, network1)
# Also, you can specify a role for the application/host, by using picoapp's
# args format for '--app'. For example, the machine below will ping the previously
# created one:
host1_2 = Host(T, network1, args ="ping:172.16.1.1:")
#
# ## ### ## ## ## ### ## ##
# host1.1--# network1 # # network2 #
# # 172.16.1.0 # # 172.16.2.0 #
# ## ## ###### ## ## ######
# /
# host1.2___/
# (ping host1.1)
#
# At this point, a picoTCP host with two network cards can connect
# the two networks like this:
router1 = Host(T, network1, network2)
#
# ## ### ## ## router1 ## ### ## ##
# host1.1--# network1 #__/ \__ # network2 #
# # 172.16.1.0 # # 172.16.2.0 #
# ## ## ###### ## ## ######
# /
# host1.2___/
# (ping host1.1)
# Now, we can attach an host to the second network too:
# Connection to the host can be an emulated channel, i.e.
# it is possible to add bidirectional delay and limited
# bandwidth in the link between the host and the network:
#
host2_2 = Host(network2, delay1="100", bw1="500K")
#
# ## ### ## ## router1 ## ### ## ##
# host1.1--# network1 #__/ \__ # network2 #
# # 172.16.1.0 # # 172.16.2.0 #
# ## ## ###### ## ## ######
# / *
# host1.2.__/ \._*_*_host2.2
# (ping host1.1)
## Since the routes will be automatically added before the test starts,
# all the hosts in the networks will be reachable to each other:
# all the picoapps will have their static routes populated automatically
# by the topology tool, no matter how complex the network is. The only
# requirement is that all the networks share at least one router.
#
# For this reason, we can create a host that pings across the network:
host1_4 = Host(T, network1, args="ping:172.16.2.2:")
#
# host1.4.
# (ping 2.2) \
# \## ### ## ## router1 ## ### ## ##
# host1.1--# network1 #__/ \__ # network2 #
# # 172.16.1.0 # # 172.16.2.0 #
# ## ## ###### ## ## ######
# / *
# host1.2.__/ \._*_*_host2.2
# (ping host1.1)
########################################################################
#== Start the test ==#
########################################################################
# All the host will be connected and activated when you call:
start()
# At this point you may want to define your exit strategy. Valid commands
# are:
loop() # Loop forever, until the test is interrupted (e.g. by ctrl+c)
sleep(N) # Sleep N seconds
wait(host1_4) # Wait for application running on host 1.4, and return only if
# it has terminated
########################################################################
#== End the test ==#
########################################################################
# Always call:
cleanup()

View File

@@ -0,0 +1,13 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
h2 = Host(T, net1, args="httpd")
sleep(1)
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,64 @@
#!/usr/bin/python
# multicast_recv.py
#
# Multicast test with PicoTCP receiving and Linux sending
#
# (sender) (Receiver)
# Linux ------------------------ PicoTCP
# mcast to 224.7.7.7
#
from topology import *
import socket, random, string
IF_ADDR = '172.16.1.1'
LINK_ADDR = '172.16.1.2'
MCAST_ADDR = '224.7.7.7'
SRC_PORT = 5555
LISTEN_PORT = 6667
SENDTO_PORT = 6667
MCASTRECV = "mcastreceive:" + str(LINK_ADDR) + ":" + str(MCAST_ADDR) + ":" + str(LISTEN_PORT) + ":" + str(SENDTO_PORT)
print MCASTRECV
T = Topology()
net1 = Network(T, "pyt0")
h1 = Host(T, net1, args=MCASTRECV)
# sending socket
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_udp.bind((IF_ADDR, SRC_PORT))
s_udp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s_udp.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
s_udp.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(str(IF_ADDR)))
# receiving socket
s_udp_recv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_udp_recv.bind((IF_ADDR, LISTEN_PORT))
s_udp_recv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s_udp_recv.settimeout(5);
raw_input("Press enter to continue ...")
start(T)
sleep(1)
while True:
s_udp.sendto("multicast test succeeded", (str(MCAST_ADDR), LISTEN_PORT))
data = s_udp_recv.recv(4096)
#print data
if 'succeeded' in data:
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ multicast_recv test IS successful +++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(0)
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ multicast_recv test NOT successful ++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(1)

View File

@@ -0,0 +1,58 @@
#!/usr/bin/python
#
# multicast_send.py
#
# Multicast test with PicoTCP sending and Linux receiving
#
# (sender) (Receiver)
# PicoTCP ------------------------ Linux
# mcast to 224.7.7.7
#
from topology import *
import socket, random, string, struct
IF_ADDR = '172.16.1.1'
LINK_ADDR = '172.16.1.2'
MCAST_ADDR = '224.7.7.7'
LISTEN_PORT = 6667
SENDTO_PORT = 6667
MCASTSEND = "mcastsend:" + str(LINK_ADDR) + ":" + str(MCAST_ADDR) + ":" + str(SENDTO_PORT) + ":" + str(LISTEN_PORT)
print MCASTSEND
T = Topology()
net1 = Network(T, "pyt0")
h1 = Host(T, net1, args=MCASTSEND)
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_udp.bind((MCAST_ADDR, LISTEN_PORT))
s_udp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s_udp.settimeout(5);
mreq = struct.pack("=4s4s", socket.inet_aton(str(MCAST_ADDR)), socket.inet_aton(str(IF_ADDR)))
s_udp.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
raw_input("Press enter to continue ...")
start(T)
sleep(1)
while True:
data = s_udp.recv(4096)
#print data
if 'end' in data:
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ multicast_send test IS successful +++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(0)
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ multicast_send test NOT successful ++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(1)

View File

@@ -0,0 +1,14 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
#h1 = Host(T, net1)
h2 = Host(T, net1, args="noop")
sleep(1)
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,14 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T)
h1 = Host(T, net1)
h2 = Host(T, net1, args="ping:172.16.1.1:")
sleep(1)
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,14 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T)
h1 = Host(T, net1, delay1="200")
h2 = Host(T, net1, args="ping:172.16.1.1:")
sleep(1)
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,14 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
#h1 = Host(T, net1)
h2 = Host(T, net1, args="ping:172.16.1.1:")
sleep(1)
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,17 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, 'nat0')
net2 = Network(T)
h1 = Host(T, net1, args="ping:172.16.2.1:")
h2 = Host(T, net2)
router1 = Host(T, net1, net2, args="natbox:172.16.2.2:")
sleep(1)
start(T)
wait(h1)
cleanup()

View File

@@ -0,0 +1,62 @@
#!/usr/bin/python
#
# reassemby.py
#
# Reassemly test with PicoTCP receiving and Linux sending
#
# (receiver) (Sender)
# PicoTCP ------------------------ Linux
#
# An udpecho is started which will receive DATASIZE bytes in one go
# from the socket. The Linux will send DATASIZE bytes in one go to the
# udpecho, this data will be sent fragmented. The udpecho is to reassemble
# this data and echo it back.
#
from topology import *
import socket, random, string
SRC_ADDR = ''
LINK_ADDR = '172.16.1.2'
SRC_PORT = 5555
LISTEN_PORT = 6667
SENDTO_PORT = 5555
DATASIZE = 3400
UDPECHO = "udpecho:" + str(LINK_ADDR) + ":" + str(LISTEN_PORT) + ":" + str(SENDTO_PORT) + ":" + str(DATASIZE)
print UDPECHO
T = Topology()
net1 = Network(T, "pyt0")
h1 = Host(T, net1, args=UDPECHO)
str_send = ''.join(random.choice(string.ascii_lowercase) for x in range(DATASIZE))
#print str_send
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_udp.bind((SRC_ADDR, SRC_PORT))
s_udp.settimeout(5);
raw_input("Press enter to continue ...")
start(T)
while True:
s_udp.sendto(str_send, (LINK_ADDR, LISTEN_PORT))
data = s_udp.recv(DATASIZE)
#print len(data)
if len(data) == DATASIZE:
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ reassembly test IS successful +++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(0)
print '\n\n'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '+++++ reassembly test NOT successful ++++'
print '+++++++++++++++++++++++++++++++++++++++++++++'
print '\n\n'
cleanup()
exit(1)

View File

@@ -0,0 +1,18 @@
#!/usr/bin/python
#
from topology import *
T = Topology()
net1 = Network(T, "vde0")
send1 = Host(T, net1, args="tcpbench:t:172.16.1.3:7770:")
recv1 = Host(T, net1, args="tcpbench:r:7770:", delay1="30", loss1="1")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
wait(send1)
cleanup()

View File

@@ -0,0 +1,17 @@
#!/usr/bin/python
#
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
send1 = Host(T, net1, args="tcpbench:t:172.16.1.3:7770:")
recv1 = Host(T, net1, args="tcpbench:r:7770:")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
wait(send1)
cleanup()

View File

@@ -0,0 +1,17 @@
#!/usr/bin/python
#
from topology import *
T = Topology()
net1 = Network(T)
send1 = Host(T, net1, args="tcpbench:t:172.16.1.2:7770:")
recv1 = Host(T, net1, args="tcpbench:r:7770:")
sleep(1)
#raw_input("Press enter to continue ...")
start(T)
wait(send1)
cleanup()

View File

@@ -0,0 +1,14 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
h2 = Host(T, net1, args="tcpbench:r:6660:")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
wait(h2)
cleanup()

View File

@@ -0,0 +1,15 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
#h1 = Host(T, net1)
h3 = Host(T, net1, args="tcpbench:t:172.16.1.1:6660:")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
wait(h3)
cleanup()

View File

@@ -0,0 +1,16 @@
#!/usr/bin/python
from topology import *
T = Topology()
net1 = Network(T, "pyt0")
#h1 = Host(T, net1)
h2 = Host(T, net1, args="tcpecho:8888", delay1="20", loss1="0.01")
#h3 = Host(T, net1, args="tcpbench:t:172.16.1.1:")
sleep(1)
start(T)
#wait(h3)
wait(h2)
cleanup()

View File

@@ -0,0 +1,223 @@
#!/usr/bin/python
# Python classes definition for the picoTCP
# topology test environment
#
# Copyright (c) 2013-2017 Altran Intelligent Systems. See LICENSE for usage.
import sys, os, subprocess, time, re
def test_tuntap():
if not os.geteuid()==0:
sys.exit("\nOnly root can use real devices contained in this script\n")
class Topology:
def __init__(self):
self.nets = []
self.nodes = []
self.nextn = 1
self.hosts = []
class Network:
def __init__(self, topology, real=''):
self.n = topology.nextn
topology.nextn += 1
self.nodes = []
self.topology = topology
self.topology.nets.append(self)
self.sock = "/tmp/topology/net"+`self.n`
self.nextn = 1
vdecmd = ["vde_switch", "-x" , "-s", self.sock, "-m", self.sock+".mgmt"]
if real != '':
test_tuntap()
vdecmd.append('-t')
vdecmd.append(real)
vdecmd.append('-x')
self.pop = subprocess.Popen(vdecmd, stdin=subprocess.PIPE)
self.hosts = []
print ""
print vdecmd
print "Created network "+self.sock
if real != '':
subprocess.call(["ifconfig",real,"172.16."+`self.n`+".1", "netmask", "255.255.255.0", "up"])
self.nextn = 2
class Node:
def __init__(self,topology, network = None):
if (network is None):
network = Network(topology)
self.net = network
self.n = network.nextn
network.nextn += 1
self.net.nodes.append(self)
self.topology = topology
self.topology.nodes.append(self)
class Host:
def add_routes(self, topology):
for eth in [self.eth1, self.eth2]:
if eth and not self.args.startswith("dhcpclient"):
net = eth.net
for h in topology.hosts:
if h.eth1 and h.eth2:
dst=""
gw=""
routing=False
if (h.eth2.net.n == net.n) and (self not in h.eth1.net.hosts):
if h.eth1.net.n > net.n or h.nat == False:
print "FOUND route to net "+`h.eth1.net.n`
dst_net = h.eth1.net.n
gw_net = h.eth2.net.n
gw_n = h.eth2.n
routing=True
elif (h.eth1.net.n == net.n) and (self not in h.eth2.net.hosts):
if h.eth2.net.n > net.n or h.nat == False:
print "FOUND route to net "+`h.eth2.net.n`
dst_net = h.eth2.net.n
gw_net = h.eth1.net.n
gw_n = h.eth1.n
routing=True
if (routing):
dst = "172.16."+`dst_net`+".0"
gw = "172.16."+`gw_net`+"."+`gw_n`
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
if (routing and gw_net > dst_net and h.nat == False):
dst_net -= 1
while(dst_net > 0):
dst = "172.16."+`dst_net`+".0"
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
dst_net -= 1
elif (routing and gw_net != None and gw_net < dst_net):
dst_net += 1
while(dst_net < net.topology.nextn):
dst = "172.16."+`dst_net`+".0"
self.routes.append("-r")
self.routes.append(dst+":255.255.255.0:"+gw+":")
dst_net += 1
def parse_options(self, eth, delay, bw, loss):
if (delay != "" or bw != ""):
mysock = eth.net.sock + "__" + `eth.n`
wirecmd = ['wirefilter', '-v']
wirecmd.append(mysock +":" + eth.net.sock)
if (delay != ''):
wirecmd.append("-d")
wirecmd.append(delay)
if (bw != ''):
wirecmd.append("-b")
wirecmd.append(bw)
if (loss != ''):
wirecmd.append("-l")
wirecmd.append(loss)
print wirecmd
subprocess.Popen(['vde_switch', '-s', mysock], stdin=subprocess.PIPE)
subprocess.Popen(wirecmd, stdin=subprocess.PIPE)
else:
mysock = eth.net.sock
return mysock
def __init__(self, topology, net1=None, net2=None, gw=None, args="tcpecho:5555", delay1="", bw1="", delay2="", bw2="", loss1="", loss2=""):
if net1:
self.eth1 = Node(topology, net1)
net1.hosts.append(self)
else:
self.eth1 = None
if net2:
self.eth2 = Node(topology, net2)
net2.hosts.append(self)
else:
self.eth2 = None
self.cmd = ["./build/test/picoapp.elf"]
self.gw = gw
if args.startswith("nat"):
self.nat = True
else:
self.nat = False
if (net1):
mysock = self.parse_options(self.eth1, delay1, bw1, loss1)
if (args.startswith("dhcpclient")):
self.cmd.append("--barevde")
vdeline = "eth1:"+mysock+':'
else:
self.cmd.append("--vde")
vdeline = "eth1:"+mysock+':'+"172.16."+`self.eth1.net.n`+"."+`self.eth1.n`+":255.255.255.0:"
if (self.gw and re.search("172\.16\."+`self.eth1.net`, self.gw)):
vdeline +=self.gw+":"
self.cmd.append(vdeline)
if (net2):
mysock = self.parse_options(self.eth2, delay2, bw2, loss2)
if (args.startswith("dhcpclient")):
self.cmd.append("--barevde")
vdeline = "eth2:"+mysock+':'
else:
self.cmd.append("--vde")
vdeline = "eth2:"+mysock+':'+"172.16."+`self.eth2.net.n`+"."+`self.eth2.n`+":255.255.255.0:"
if (self.gw and re.search("172\.16\."+`self.eth2.net`+".", self.gw)):
vdeline +=self.gw+":"
self.cmd.append(vdeline)
self.args = args
self.pop = None
topology.hosts.append(self)
self.routes = []
def start(self):
if self.pop:
return
for r in self.routes:
self.cmd.append(r)
self.cmd.append("-a")
self.cmd.append(self.args)
print self.cmd
self.pop = subprocess.Popen(self.cmd)
def cleanup():
try:
subprocess.call(["killall","vde_switch"])
subprocess.call(["killall","picoapp.elf"])
subprocess.call(["killall","wirefilter"])
os.unlink("/tmp/topology")
except:
pass
def loop():
while(True):
time.sleep(1)
sys.exit(0)
def sleep(n):
time.sleep(n)
def wait(x):
if (x is None):
print("start failed: "+x.cmd)
sys.exit(1)
while (x.pop.poll() == None):
time.sleep(1)
print "Goodbye"
sys.exit(0)
def start(T):
print "Calculating routes.."
for n in T.nets:
for h in n.hosts:
h.add_routes(T)
print "Done!"
print "Starting up..."
for n in T.nets:
for h in n.hosts:
h.start()
try:
os.mkdir("/tmp/topology/")
except:
pass
cleanup()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/python
from topology import *
'''
Add route to 172.16.0.0/16 gw 172.16.1.2 on your host machine.
Should result in something like:
~$ traceroute 172.16.8.2
traceroute to 172.16.8.2 (172.16.8.2), 30 hops max, 60 byte packets
1 172.16.1.2 (172.16.1.2) 0.481 ms 0.473 ms 0.467 ms
2 172.16.2.2 (172.16.2.2) 4.680 ms 4.702 ms 4.700 ms
3 172.16.3.2 (172.16.3.2) 8.759 ms 8.768 ms 8.766 ms
4 172.16.4.2 (172.16.4.2) 10.791 ms 10.789 ms 10.786 ms
5 172.16.5.2 (172.16.5.2) 12.826 ms 12.825 ms 12.821 ms
6 172.16.6.2 (172.16.6.2) 14.844 ms 17.858 ms 17.857 ms
7 172.16.7.2 (172.16.7.2) 17.858 ms 14.000 ms 13.999 ms
8 172.16.8.2 (172.16.8.2) 18.032 ms 18.029 ms 18.023 ms
'''
T = Topology()
net1 = Network(T, 'nat0')
net2 = Network(T)
net3 = Network(T)
net4 = Network(T)
net5 = Network(T)
net6 = Network(T)
net7 = Network(T)
net8 = Network(T)
router1 = Host(T, net1, net2)
router2 = Host(T, net2, net3)
router3 = Host(T, net3, net4)
router4 = Host(T, net4, net5)
router5 = Host(T, net5, net6)
router6 = Host(T, net6, net7)
router7 = Host(T, net7, net8)
h1 = Host(T, net8)
sleep(1)
start(T)
loop()
cleanup()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/python
from topology import *
'''
Add route to 172.16.0.0/16 gw 172.16.1.2 on your host machine.
Should result in something like:
~$ traceroute 172.16.8.2
traceroute to 172.16.8.2 (172.16.8.2), 30 hops max, 60 byte packets
1 172.16.1.2 (172.16.1.2) 0.481 ms 0.473 ms 0.467 ms
2 172.16.2.2 (172.16.2.2) 4.680 ms 4.702 ms 4.700 ms
3 172.16.3.2 (172.16.3.2) 8.759 ms 8.768 ms 8.766 ms
4 172.16.4.2 (172.16.4.2) 10.791 ms 10.789 ms 10.786 ms
5 172.16.5.2 (172.16.5.2) 12.826 ms 12.825 ms 12.821 ms
6 172.16.6.2 (172.16.6.2) 14.844 ms 17.858 ms 17.857 ms
7 172.16.7.2 (172.16.7.2) 17.858 ms 14.000 ms 13.999 ms
8 172.16.8.2 (172.16.8.2) 18.032 ms 18.029 ms 18.023 ms
'''
T = Topology()
net1 = Network(T, 'nat0')
net2 = Network(T)
net3 = Network(T)
net4 = Network(T)
net5 = Network(T)
net6 = Network(T)
net7 = Network(T)
net8 = Network(T)
router1 = Host(T, net1, net2, args="natbox:172.16.2.1")
router2 = Host(T, net2, net3, args="natbox:172.16.3.1")
router3 = Host(T, net3, net4, args="natbox:172.16.4.1")
router4 = Host(T, net4, net5, args="natbox:172.16.5.1")
router5 = Host(T, net5, net6, args="natbox:172.16.6.1")
router6 = Host(T, net6, net7, args="natbox:172.16.7.1")
router7 = Host(T, net7, net8, args="natbox:172.16.8.1")
h1 = Host(T, net8)
sleep(1)
start(T)
loop()
cleanup()

View File

@@ -0,0 +1,16 @@
#!/usr/bin/python
#
from topology import *
T = Topology()
net1 = Network(T,"udp0")
echo = Host(T, net1, args="udpecho:172.16.1.2:7770:7770:1400:")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
wait(echo)
cleanup()

View File

@@ -0,0 +1,34 @@
#!/usr/bin/python
from topology import *
import zmq
import sys
T = Topology()
net1 = Network(T, "pyt0")
#h1 = Host(T, net1)
h2 = Host(T, net1, args="zeromq_prod:")
sleep(1)
raw_input("Press enter to continue ...")
start(T)
# Zeromq part
ctx = zmq.Context()
z = ctx.socket(zmq.SUB)
z.setsockopt(zmq.SUBSCRIBE, "")
z.connect("tcp://172.16.1.2:1207")
print "In the loop..."
for i in range(20):
if z.poll(20000) == 0:
print "Timeout!!!"
cleanup()
sys.exit(1)
else:
msg = z.recv()
print "Recvd msg len=%d content: %s" % (len(msg), msg)
cleanup()

View File

@@ -0,0 +1,244 @@
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <inttypes.h>
#include "pico_stack.h"
#include "pico_config.h"
#include "pico_ipv4.h"
#include "pico_icmp4.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_device.h"
#include "pico_dev_vde.h"
#include "pico_tftp.h"
static struct pico_device *pico_dev;
int32_t get_filesize(const char *filename)
{
int ret;
struct stat buf;
ret = stat(filename, &buf);
if (ret)
return -1;
return buf.st_size;
}
void start_rx(struct pico_tftp_session *session, int *synchro, const char *filename, int options)
{
int ret;
int fd;
int32_t len;
uint8_t buf[PICO_TFTP_PAYLOAD_SIZE];
int left = 1000;
int countdown = 0;
printf("Start receiving file %s with options set to %d\n", filename, options);
if (options) {
ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0);
if (ret) {
fprintf(stderr, "Error in pico_tftp_set_option\n");
exit(1);
}
}
ret = pico_tftp_app_start_rx(session, filename);
if (ret) {
fprintf(stderr, "Error in pico_tftp_app_start_rx\n");
exit(1);
}
fd = open(filename, O_WRONLY | O_EXCL | O_CREAT, 0664);
if (!fd) {
fprintf(stderr, "Error in open\n");
countdown = 1;
}
for(; left; left -= countdown) {
usleep(2000); /* PICO_IDLE(); */
pico_stack_tick();
if (countdown)
continue;
if (*synchro) {
len = pico_tftp_get(session, buf, PICO_TFTP_PAYLOAD_SIZE);
if (len < 0) {
fprintf(stderr, "Failure in pico_tftp_get\n");
close(fd);
countdown = 1;
continue;
}
ret = write(fd, buf, len);
if (ret < 0) {
fprintf(stderr, "Error in write\n");
pico_tftp_abort(session, TFTP_ERR_EXCEEDED, "File write error");
close(fd);
countdown = 1;
continue;
}
printf("Written %" PRId32 " bytes to file (synchro=%d)\n", len, *synchro);
if (len != PICO_TFTP_PAYLOAD_SIZE) {
close(fd);
printf("Transfer complete!\n");
countdown = 1;
}
}
}
}
void start_tx(struct pico_tftp_session *session, int *synchro, const char *filename, int options)
{
int ret;
int fd;
int32_t len;
uint8_t buf[PICO_TFTP_PAYLOAD_SIZE];
int left = 1000;
int countdown = 0;
printf("Start sending file %s with options set to %d\n", filename, options);
if (options) {
ret = get_filesize(filename);
if (ret < 0) {
fprintf(stderr, "Error in get_filesize\n");
exit(1);
}
ret = pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
if (ret) {
fprintf(stderr, "Error in pico_tftp_set_option\n");
exit(1);
}
}
ret = pico_tftp_app_start_tx(session, filename);
if (ret) {
fprintf(stderr, "Error in pico_tftp_app_start_rx\n");
exit(1);
}
fd = open(filename, O_RDONLY, 0444);
if (!fd) {
fprintf(stderr, "Error in open\n");
pico_tftp_abort(session, TFTP_ERR_EACC, "Error opening file");
countdown = 1;
}
for(; left; left -= countdown) {
usleep(2000); /* PICO_IDLE(); */
pico_stack_tick();
if (countdown)
continue;
if (*synchro) {
ret = read(fd, buf, PICO_TFTP_PAYLOAD_SIZE);
if (ret < 0) {
fprintf(stderr, "Error in read\n");
pico_tftp_abort(session, TFTP_ERR_EACC, "File read error");
close(fd);
countdown = 1;
continue;
}
printf("Read %" PRId32 " bytes from file (synchro=%d)\n", len, *synchro);
len = pico_tftp_put(session, buf, ret);
if (len < 0) {
fprintf(stderr, "Failure in pico_tftp_put\n");
close(fd);
countdown = 1;
continue;
}
if (len != PICO_TFTP_PAYLOAD_SIZE) {
close(fd);
printf("Transfer complete!\n");
countdown = 1;
}
}
}
}
void usage(const char *text)
{
fprintf(stderr, "%s\nArguments must be <filename> <mode>\n"
"<mode> can be:\n"
"\tg => GET request without options\n"
"\tG => GET request WITH options\n"
"\tp => PUT request without options\n"
"\tP => PUT request WITH options\n\n",
text);
exit(1);
}
int main(int argc, char**argv)
{
struct pico_ip4 my_ip;
union pico_address server_address;
struct pico_ip4 netmask;
struct pico_tftp_session *session;
int synchro;
int options = 0;
void (*operation)(struct pico_tftp_session *session, int *synchro, const char *filename, int options);
unsigned char macaddr[6] = {
0, 0, 0, 0xa, 0xb, 0x0
};
uint16_t *macaddr_low = (uint16_t *) (macaddr + 2);
*macaddr_low = *macaddr_low ^ (uint16_t)((uint16_t)getpid() & (uint16_t)0xFFFFU);
macaddr[4] ^= (uint8_t)(getpid() >> 8);
macaddr[5] ^= (uint8_t) (getpid() & 0xFF);
pico_string_to_ipv4("10.40.0.10", &my_ip.addr);
pico_string_to_ipv4("255.255.255.0", &netmask.addr);
pico_string_to_ipv4("10.40.0.2", &server_address.ip4.addr);
if (argc != 3) {
usage("Invalid number or arguments");
}
switch (argv[2][0]) {
case 'G':
options = 1;
case 'g':
operation = start_rx;
break;
case 'P':
options = 1;
case 'p':
operation = start_tx;
break;
default:
usage("Invalid mode");
}
printf("%s start!\n", argv[0]);
pico_stack_init();
pico_dev = (struct pico_device *) pico_vde_create("/tmp/vde_switch", "tap0", macaddr);
if(!pico_dev) {
fprintf(stderr, "Error creating pico device, got enough privileges? Exiting...\n");
exit(1);
}
pico_ipv4_link_add(pico_dev, my_ip, netmask);
printf("Starting picoTCP loop\n");
session = pico_tftp_app_setup(&server_address, short_be(PICO_TFTP_PORT), PICO_PROTO_IPV4, &synchro);
if (!session) {
fprintf(stderr, "Error in pico_tftp_app_setup\n");
exit(1);
}
printf("synchro %d\n", synchro);
operation(session, &synchro, argv[1], options);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,556 @@
#include "pico_addressing.h"
#include "pico_ipv6_nd.h"
#include "pico_stack.h"
#include "pico_frame.h"
#include "pico_ipv6.h"
#include "pico_6lowpan.h"
#include "modules/pico_802154.c"
#include "check.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*******************************************************************************
* MACROS
******************************************************************************/
#define STARTING() \
printf("*********************** STARTING %s ***\n", __func__); \
fflush(stdout)
#define TRYING(s, ...) \
printf("Trying %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define CHECKING(i) \
printf("Checking the results of test %2d in %s...", (i)++, \
__func__); \
fflush(stdout)
#define FAIL_UNLESS(cond, s, ...) \
if ((cond)) { \
printf(" SUCCESS\n"); \
} else { \
printf(" FAILED\n"); \
} \
fail_unless((cond), s, ##__VA_ARGS__)
#define FAIL_IF(cond, s, ...) \
if (!(cond)) { \
printf(" SUCCESS\n"); \
} else { \
printf(" FAILED\n"); \
} \
fail_if((cond), s, ##__VA_ARGS__)
#define ENDING(i) \
printf("*********************** ENDING %s *** NUMBER OF TESTS: %d\n",\
__func__, ((i)-1)); \
fflush(stdout)
#define DBG(s, ...) \
printf(s, ##__VA_ARGS__); \
fflush(stdout)
/*******************************************************************************
* HELPER FUNCTIONS
******************************************************************************/
static void dbg_addr_ext(const char *msg, uint8_t a[SIZE_6LOWPAN_EXT])
{
DBG("%s: (64-bit extended address): ", msg);
DBG("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
}
/*******************************************************************************
* ADDRESSES
******************************************************************************/
START_TEST(tc_swap)
{
int test = 1;
uint8_t a = 5;
uint8_t b = 1;
STARTING();
// TEST 1
TRYING("With a = %d and b = %d\n", a, b);
pico_swap(&a, &b);
CHECKING(test);
FAIL_IF(1 != a && b != 5, "Failed swapping numbers\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_to_ietf)
{
int test = 1;
struct pico_802154 a = {
.addr.data = { 1,2,3,4,5,6,7,8 },
.mode = AM_6LOWPAN_EXT
};
uint8_t buf[] = {8,7,6,5,4,3,2,1};
STARTING();
// TEST 1
TRYING("Extended address mode\n");
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
CHECKING(test);
FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT),
"Failed converting to IETF endianness\n");
// TEST 2
TRYING("Short address mode\n");
a.mode = AM_6LOWPAN_SHORT;
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
CHECKING(test);
FAIL_UNLESS(a.addr._short.addr == short_be(0x0708),
"Failed converting short to IETF endianness\n");
// TEST 3
TRYING("Wrong address mode\n");
a.mode = AM_6LOWPAN_NONE;
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
buf[0] = 7;
buf[1] = 8;
CHECKING(test);
FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT),
"Should've done nothing\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_ll_src)
{
int test = 1;
struct pico_ip6 ip = {
.addr = {0,0,0,0,0,0,0,0, 3,2,3,4,5,6,7,8}
};
struct pico_ip6 ip2 = {
.addr = {0,0,0,0,0,0,0,0, 0,0,0,0xff,0xfe,0,0x12,0x34}
};
struct pico_6lowpan_info info = {
.addr_short.addr = short_be(0x1234),
.addr_ext.addr = {3,2,3,4,5,6,7,8}
};
struct pico_device dev;
struct pico_802154 addr;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer;
STARTING();
dev.eth = (struct pico_ethdev *)&info;
f->net_hdr = f->buffer;
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
// TEST 3
TRYING("With an IPv6 address that is derived from MAC short address\n");
info.addr_short.addr = short_be(0x1234);
hdr->src = ip2;
addr = addr_802154_ll_src(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've returned device's short address \n");
CHECKING(test);
FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr,
"Should've copied the short address from the device\n");
// TEST 4
TRYING("With an IPv6 address that is derived from MAC extended address\n");
ip.addr[8] = 1;
hdr->src = ip;
addr = addr_802154_ll_src(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned device's extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(info.addr_ext.addr, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied device's extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_ll_dst)
{
int test = 1;
struct pico_ip6 ip;
struct pico_ip6 local;
struct pico_ip6 local2;
struct pico_802154 addr;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer;
struct pico_device dev;
uint8_t buf[] = {3,2,3,4,5,6,7,8};
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", ip.addr);
pico_string_to_ipv6("fe80:0:0:0:0102:0304:0506:0708", local.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0ff:fe00:1234", local2.addr);
STARTING();
f->net_hdr = f->buffer;
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
// TEST 1
TRYING("With a MCAST IPv6 address, should return 0xFFFF\n");
hdr->dst = ip;
addr = addr_802154_ll_dst(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've set address mode to SHORT\n");
CHECKING(test);
FAIL_UNLESS(short_be(ADDR_802154_BCAST) == addr.addr._short.addr,
"Should've set address to BCAST\n");
// TEST 2
TRYING("With a link local IPv6 address derived from an extended L2 address\n");
hdr->dst = local;
addr = addr_802154_ll_dst(f);
dbg_addr_ext("After:", addr.addr._ext.addr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've set address mode to EXTENDED\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(buf, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended address from the IP address\n");
// TEST 3
TRYING("With a link local IPv6 address derived from a short L2 address\n");
hdr->dst = local2;
addr = addr_802154_ll_dst(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've set address mode to SHORT\n");
CHECKING(test);
FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr,
"Should've copied the short address from the IP address\n");
/* TODO: Test getting address from neighbour table */
ENDING(test);
}
END_TEST
/*******************************************************************************
* FRAME
******************************************************************************/
/* Frame (123 bytes) */
static uint8_t pkt[] = {
0x41, 0xcc, 0xa6, 0xff, 0xff, 0x8a, /* A..... */
0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0x88, /* ........ */
0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0xc1, /* ........ */
0x09, 0x00, 0x02, 0x42, 0xfa, 0x40, 0x04, 0x01, /* ...B.@.. */
0xf0, 0xb1, 0x01, 0x06, 0x6f, 0xaf, 0x48, 0x65, /* ....o.He */
0x6c, 0x6c, 0x6f, 0x20, 0x30, 0x30, 0x36, 0x20, /* llo 006 */
0x30, 0x78, 0x46, 0x46, 0x33, 0x43, 0x0a, 0x00, /* 0xFF3C.. */
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* ........ */
0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, /* ...... ! */
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* "#$%&'() */
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, /* *+,-./01 */
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, /* :;<=>?@A */
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, /* BCDEFGHI */
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, /* JKLMNOPQ */
0x52, 0x53, 0x54, 0x68, 0x79 /* RSThy */
};
START_TEST(tc_dst_am)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine AM of destination addr from buffer \n");
ret = dst_am((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == ret,
"Should've returned the AM of an extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_src_am)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine AM of source addr from buffer \n");
ret = src_am((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == ret,
"Should've returned the AM of an extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_hdr_len)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine length of the header from buffer\n");
ret = frame_802154_hdr_len((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(21 == ret,
"Should've returned the correct length of the header\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_src)
{
int test = 1;
struct pico_802154_hdr *hdr;
struct pico_802154 addr;
uint8_t src[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88};
STARTING();
hdr = (struct pico_802154_hdr *)pkt;
// TEST 1
TRYING("To receive the source address from a mapped buffer\n");
addr = frame_802154_src(hdr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned an extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(src, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended source address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_dst)
{
int test = 1;
struct pico_802154_hdr *hdr;
struct pico_802154 addr;
uint8_t dst[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a};
STARTING();
hdr = (struct pico_802154_hdr *)pkt;
// TEST 1
TRYING("To receive the source address from a mapped buffer\n");
addr = frame_802154_dst(hdr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned an extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(dst, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended source address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_format)
{
int test = 1;
struct pico_802154 src = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_6lowpan_short pan = { .addr = short_be(0xffff) };
uint8_t buf[127] = {0};
int i = 0;
STARTING();
// TEST 1
TRYING("To format a frame like sample capture\n");
frame_802154_format(buf, 166, FCF_INTRA_PAN, FCF_NO_ACK_REQ,
FCF_NO_SEC, pan, src, dst);
printf("Buffer:");
for (i = 0; i < 21; i++) {
if (i % 8 != 0)
printf("%02x ", buf[i]);
else {
printf("\n%02x ", buf[i]);
}
}
printf("\n");
CHECKING(test);
FAIL_UNLESS(21 == frame_802154_hdr_len((struct pico_802154_hdr *)buf),
"Failed to correctly set the frame header, the length isn't right\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(pkt, buf, 21),
"Failed to correctly format IEEE802.15.4 frame\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_process_out)
{
int i = 0;
int ret = 0;
int test = 1;
struct pico_802154 src = {
.addr.data = {3,2,3,4,5,6,7,8},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_frame *f = pico_frame_alloc(0);
struct pico_6lowpan_info info = {
.addr_short.addr = short_be(0x1234),
.addr_ext.addr = {3,2,3,4,5,6,7,8},
.pan_id.addr = short_be(0x1234)
};
struct pico_device dev;
uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00,
0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x03};
dev.eth = (struct pico_ethdev *)&info;
dev.q_out = PICO_ZALLOC(sizeof(struct pico_queue));
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
STARTING();
pico_stack_init();
// TEST 1
TRYING("Trying with bare frame\n");
f->src.pan = src;
f->dst.pan = dst;
ret = pico_802154_process_out(f);
printf("Buffer:");
for (i = 0; i < 21; i++) {
if (i % 8 != 0)
printf("%02x ", f->datalink_hdr[i]);
else {
printf("\n%02x ", f->datalink_hdr[i]);
}
}
printf("\n");
CHECKING(test);
FAIL_UNLESS(0 < ret, "Shouldn't have returned an error\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(buf, f->datalink_hdr, 21),
"Frame isn't correctly formatted\n");
pico_frame_discard(f);
ENDING(test);
}
END_TEST
START_TEST(tc_802154_process_in)
{
int ret = 0;
int test = 1;
struct pico_802154 src = {
.addr.data = {3,2,3,4,5,6,7,8},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_frame *f = pico_frame_alloc(22);
uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00,
0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x03,0x60};
memcpy(f->buffer, buf, 22);
f->src.pan = src;
f->dst.pan = dst;
STARTING();
pico_stack_init();
TRYING("Apply processing function on predefined buffer\n");
ret = pico_802154_process_in(f);
CHECKING(test);
FAIL_UNLESS(0 < ret, "Should not return failure\n");
}
END_TEST
static Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_swap = tcase_create("Unit test for pico_swap");
TCase *TCase_802154_to_ietf = tcase_create("Unit test for 802154_to_ietf");
TCase *TCase_802154_ll_src = tcase_create("Unit test for 802154_ll_src");
TCase *TCase_802154_ll_dst = tcase_create("Unit test for 802154_ll_dst");
TCase *TCase_802154_hdr_len = tcase_create("Unit test for 802154_hdr_len");
TCase *TCase_src_am = tcase_create("Unit test for src_am");
TCase *TCase_dst_am = tcase_create("Unit test for dst_am");
TCase *TCase_802154_src = tcase_create("Unit test for 802154_src");
TCase *TCase_802154_dst = tcase_create("Unit test for 802154_dst");
TCase *TCase_802154_format = tcase_create("Unit test for 802154_format");
TCase *TCase_802154_process_out = tcase_create("Unit test for 802154_process_out");
TCase *TCase_802154_process_in = tcase_create("Unit test for 802154_process_in");
/*******************************************************************************
* ADDRESSES
******************************************************************************/
tcase_add_test(TCase_swap, tc_swap);
suite_add_tcase(s, TCase_swap);
tcase_add_test(TCase_802154_to_ietf, tc_802154_to_ietf);
suite_add_tcase(s, TCase_802154_to_ietf);
tcase_add_test(TCase_802154_ll_src, tc_802154_ll_src);
suite_add_tcase(s, TCase_802154_ll_src);
tcase_add_test(TCase_802154_ll_dst, tc_802154_ll_dst);
suite_add_tcase(s, TCase_802154_ll_dst);
/*******************************************************************************
* FRAME
******************************************************************************/
tcase_add_test(TCase_802154_hdr_len, tc_802154_hdr_len);
suite_add_tcase(s, TCase_802154_hdr_len);
tcase_add_test(TCase_src_am, tc_src_am);
suite_add_tcase(s, TCase_src_am);
tcase_add_test(TCase_dst_am, tc_dst_am);
suite_add_tcase(s, TCase_dst_am);
tcase_add_test(TCase_802154_src, tc_802154_src);
suite_add_tcase(s, TCase_802154_src);
tcase_add_test(TCase_802154_dst, tc_802154_dst);
suite_add_tcase(s, TCase_802154_dst);
tcase_add_test(TCase_802154_format, tc_802154_format);
suite_add_tcase(s, TCase_802154_format);
tcase_add_test(TCase_802154_process_out, tc_802154_process_out);
suite_add_tcase(s, TCase_802154_process_out);
tcase_add_test(TCase_802154_process_in, tc_802154_process_in);
suite_add_tcase(s, TCase_802154_process_in);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,545 @@
#include <pico_stack.h>
#include <pico_tree.h>
#include <pico_socket.h>
#include <pico_aodv.h>
#include <pico_device.h>
#include <pico_ipv4.h>
#include "modules/pico_aodv.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_aodv_node_compare)
{
struct pico_aodv_node a, b;
a.dest.ip4.addr = long_be(1);
b.dest.ip4.addr = long_be(2);
fail_if(aodv_node_compare(&a, &b) >= 0);
a.dest.ip4.addr = long_be(3);
fail_if(aodv_node_compare(&a, &b) <= 0);
b.dest.ip4.addr = long_be(3);
fail_if(aodv_node_compare(&a, &b) != 0);
}
END_TEST
START_TEST(tc_aodv_dev_cmp)
{
struct pico_device a, b;
a.hash = 1;
b.hash = 2;
fail_if(aodv_dev_cmp(&a, &b) >= 0);
a.hash = 3;
fail_if(aodv_dev_cmp(&a, &b) <= 0);
b.hash = 3;
fail_if(aodv_dev_cmp(&a, &b) != 0);
}
END_TEST
START_TEST(tc_get_node_by_addr)
{
struct pico_aodv_node a;
union pico_address test;
a.dest.ip4.addr = long_be(10);
test.ip4.addr = long_be(10);
pico_tree_insert(&aodv_nodes, &a);
fail_if(get_node_by_addr(&test) != &a);
pico_tree_delete(&aodv_nodes, &a);
fail_if(get_node_by_addr(&test) != NULL);
}
END_TEST
static int set_bcast_link_called = 0;
void pico_ipv4_route_set_bcast_link(struct pico_ipv4_link *link)
{
IGNORE_PARAMETER(link);
set_bcast_link_called++;
}
START_TEST(tc_pico_aodv_set_dev)
{
struct pico_device *dev = NULL;
pico_aodv_set_dev(dev);
fail_if(set_bcast_link_called != 1);
}
END_TEST
START_TEST(tc_aodv_peer_refresh)
{
/* TODO: test this: static int aodv_peer_refresh(struct pico_aodv_node *node, uint32_t seq) */
struct pico_aodv_node node;
memset(&node, 0, sizeof(node));
node.dseq = 0xFFFF;
fail_if(aodv_peer_refresh(&node, 10) != 0); /* should succeed, because SYNC flag is not yet set... */
fail_if((node.flags & PICO_AODV_NODE_SYNC) == 0); /* Flag should be set after last call... */
fail_if(aodv_peer_refresh(&node, 5) == 0); /* should FAIL, because seq number is lower... */
fail_if(aodv_peer_refresh(&node, 10) == 0); /* should FAIL, because seq number is still the same... */
fail_if(aodv_peer_refresh(&node, 15) != 0); /* should succeed, because seq number is now bigger... */
fail_if(node.dseq != 15);
}
END_TEST
static int called_route_add = 0;
static uint32_t route_add_gw = 0u;
static int route_add_metric = 0;
int pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link)
{
IGNORE_PARAMETER(link);
IGNORE_PARAMETER(netmask);
IGNORE_PARAMETER(address);
called_route_add++;
route_add_gw = gateway.addr;
route_add_metric = metric;
return 0;
}
START_TEST(tc_aodv_elect_route)
{
struct pico_aodv_node node;
union pico_address gateway;
memset(&node, 0, sizeof(node));
gateway.ip4.addr = 0x55555555;
called_route_add = 0;
aodv_elect_route(&node, NULL, 150, NULL);
fail_if(called_route_add != 1); /* Not active, should succeed */
fail_if(route_add_gw != 0u);
fail_if(route_add_metric != 1);
called_route_add = 0;
route_add_metric = 0;
route_add_gw = 0u;
node.flags = PICO_AODV_NODE_ROUTE_DOWN | PICO_AODV_NODE_ROUTE_UP;
aodv_elect_route(&node, &gateway, 150, NULL);
fail_if(called_route_add != 0); /* Already active, existing metric is lower */
called_route_add = 0;
route_add_metric = 0;
route_add_gw = 0u;
node.metric = 22;
aodv_elect_route(&node, &gateway, 15, NULL);
fail_if(called_route_add != 1); /* Already active, existing metric is higher */
fail_if(route_add_metric != 16);
fail_if(route_add_gw != 0x55555555);
}
END_TEST
START_TEST(tc_aodv_peer_new)
{
union pico_address addr;
struct pico_aodv_node *new;
addr.ip4.addr = 0x44444444;
new = aodv_peer_new(&addr);
fail_if(!new);
fail_if(!get_node_by_addr(&addr));
pico_set_mm_failure(1);
new = aodv_peer_new(&addr);
fail_if(new);
}
END_TEST
START_TEST(tc_aodv_peer_eval)
{
union pico_address addr;
struct pico_aodv_node *node = NULL;
/* Case 0: Creation */
addr.ip4.addr = 0x11224433;
node = aodv_peer_eval(&addr, 0, 0);
fail_if(!node);
fail_if((node->flags & PICO_AODV_NODE_SYNC) != 0); /* Not synced! */
/* Case 1: retrieve, unsynced */
node->metric = 42;
node = aodv_peer_eval(&addr, 0, 0); /* Should get existing node! */
fail_if(!node);
fail_if(node->metric != 42);
fail_if((node->flags & PICO_AODV_NODE_SYNC) != 0); /* Not synced! */
/* Case 2: new node, invalid allocation */
addr.ip4.addr = 0x11224455;
pico_set_mm_failure(1);
node = aodv_peer_eval(&addr, long_be(10), 1);
fail_if(node);
/* Case 3: existing node, setting the new sequence */
addr.ip4.addr = 0x11224433;
node = aodv_peer_eval(&addr, long_be(10), 1); /* Should get existing node! */
fail_if(node->metric != 42);
fail_if((node->flags & PICO_AODV_NODE_SYNC) == 0);
fail_if(node->dseq != 10);
}
END_TEST
START_TEST(tc_aodv_lifetime)
{
struct pico_aodv_node node;
pico_time now = PICO_TIME_MS();
memset(&node, 0, sizeof(node));
fail_if(aodv_lifetime(&node) == 0);
fail_if(node.last_seen < now);
node.last_seen = now - AODV_ACTIVE_ROUTE_TIMEOUT;
fail_if(aodv_lifetime(&node) != 0);
}
END_TEST
static uint8_t sent_pkt_type = 0xFF;
static uint32_t dest_addr = 0;
static int pico_socket_sendto_called = 0;
static int pico_socket_sendto_extended_called = 0;
uint32_t expected_dseq = 0;
int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
{
uint8_t *pkt = (uint8_t *)(uintptr_t)buf;
printf("Sendto called!\n");
pico_socket_sendto_called++;
fail_if(remote_port != short_be(PICO_AODV_PORT));
fail_if (s != aodv_socket);
fail_if(pkt[0] > 4);
fail_if(pkt[0] < 1);
sent_pkt_type = pkt[0];
dest_addr = ((union pico_address *)dst)->ip4.addr;
if (sent_pkt_type == AODV_TYPE_RREQ) {
/* struct pico_aodv_rreq *req = (struct pico_aodv_rreq *)(uintptr_t)buf; */
fail_if(len != sizeof(struct pico_aodv_rreq));
}
else if (sent_pkt_type == AODV_TYPE_RREP) {
struct pico_aodv_rrep *rep = (struct pico_aodv_rrep *)(uintptr_t)buf;
fail_if(len != sizeof(struct pico_aodv_rrep));
fail_if(rep->dest != 0x11111111);
fail_if(rep->orig != 0x22222222);
printf("rep->dseq= %08x, exp: %08x\n", rep->dseq, expected_dseq);
fail_if(rep->dseq != expected_dseq);
}
return len;
}
int pico_socket_sendto_extended(struct pico_socket *s, const void *buf, const int len,
void *dst, uint16_t remote_port, struct pico_msginfo *msginfo)
{
IGNORE_PARAMETER(msginfo);
pico_socket_sendto_extended_called++;
return pico_socket_sendto(s, buf, len, dst, remote_port);
}
START_TEST(tc_aodv_send_reply)
{
struct pico_aodv_node node;
struct pico_aodv_rreq req;
struct pico_msginfo info;
union pico_address addr;
addr.ip4.addr = 0x22222222;
memset(&node, 0, sizeof(node));
memset(&req, 0, sizeof(req));
memset(&info, 0, sizeof(info));
req.dest = 0x11111111;
req.orig = addr.ip4.addr;
req.dseq = 99;
aodv_send_reply(&node, &req, 1, &info);
fail_if(pico_socket_sendto_called != 0); /* Call should have no effect, due to non-existing origin node */
/* Creating origin... */
fail_if(aodv_peer_new(&addr) == NULL);
aodv_send_reply(&node, &req, 0, &info);
fail_if(pico_socket_sendto_called != 0); /* Call should have no effect, node non-local, non sync'd */
expected_dseq = long_be(pico_aodv_local_id + 1);
aodv_send_reply(&node, &req, 1, &info);
fail_if(pico_socket_sendto_called != 1); /* Call should succeed */
pico_socket_sendto_called = 0;
node.flags = PICO_AODV_NODE_SYNC;
node.dseq = 42;
expected_dseq = long_be(42);
aodv_send_reply(&node, &req, 0, &info);
fail_if(pico_socket_sendto_called != 1); /* Call should succeed */
pico_socket_sendto_called = 0;
}
END_TEST
static struct pico_ipv4_link global_link;
struct pico_ipv4_link *pico_ipv4_link_by_dev(struct pico_device *dev)
{
IGNORE_PARAMETER(dev);
if (!global_link.address.addr)
return NULL;
printf("Setting link!\n");
return &global_link;
}
static struct pico_device global_dev;
static int link_find_success = 0;
struct pico_device *pico_ipv4_link_find(struct pico_ip4 *ip4)
{
IGNORE_PARAMETER(ip4);
if (link_find_success)
return &global_dev;
return NULL;
}
static int timer_set = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(arg);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(expire);
printf("Timer set!\n");
timer_set++;
return (uint32_t ) 0x99999999;
}
START_TEST(tc_aodv_send_req)
{
struct pico_aodv_node node;
struct pico_device d;
aodv_socket = NULL;
memset(&node, 0, sizeof(node));
node.flags = PICO_AODV_NODE_ROUTE_DOWN | PICO_AODV_NODE_ROUTE_UP;
fail_if(aodv_send_req(&node) != 0); /* Should fail: node already active */
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
node.flags = 0;
fail_if(aodv_send_req(&node) != 0); /* Should fail: no devices in tree */
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
pico_tree_insert(&aodv_devices, &d);
fail_if(aodv_send_req(&node) != -1); /* Should fail: aodv_socket == NULL */
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
/* No valid link, timer is set, call does not send packets */
aodv_socket = (struct pico_socket*) 1;
global_link.address.addr = 0;
fail_if(aodv_send_req(&node) != 0);
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
fail_if(timer_set != 1);
timer_set = 0;
/* One valid link, timer is set, one packet is sent */
global_link.address.addr = 0xFEFEFEFE;
fail_if(aodv_send_req(&node) != 1);
fail_if(pico_socket_sendto_called != 1);
fail_if(pico_socket_sendto_extended_called != 1);
fail_if(timer_set != 1);
pico_socket_sendto_called = 0;
pico_socket_sendto_extended_called = 0;
timer_set = 0;
}
END_TEST
START_TEST(tc_aodv_reverse_path_discover)
{
struct pico_aodv_node node;
memset(&node, 0, sizeof(node));
aodv_reverse_path_discover(0, &node);
}
END_TEST
START_TEST(tc_aodv_recv_valid_rreq)
{
struct pico_aodv_node node;
struct pico_aodv_rreq req;
struct pico_msginfo info;
union pico_address addr;
memset(&node, 0, sizeof(node));
memset(&req, 0, sizeof(req));
memset(&info, 0, sizeof(info));
addr.ip4.addr = 0x22222222;
link_find_success = 0;
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called > 0);
/* link not local, but active node, set to send reply, no timer */
link_find_success = 0;
fail_if(aodv_peer_new(&addr) == NULL);
global_link.address.addr = 0x44444444;
req.orig = addr.ip4.addr;
req.dest = 0x11111111;
node.flags = PICO_AODV_NODE_SYNC | PICO_AODV_NODE_ROUTE_UP | PICO_AODV_NODE_ROUTE_DOWN;
node.dseq = 42;
expected_dseq = long_be(42);
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called < 1);
fail_if(timer_set > 0);
pico_socket_sendto_called = 0;
/* link local, active node. Full send + set timer. */
link_find_success = 1;
expected_dseq = long_be(pico_aodv_local_id + 1);
aodv_peer_new(&addr);
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called < 1);
fail_if(timer_set < 1);
}
END_TEST
START_TEST(tc_aodv_parse_rreq)
{
/* TODO: test this: static void aodv_parse_rreq(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rrep)
{
/* TODO: test this: static void aodv_parse_rrep(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rerr)
{
/* TODO: test this: static void aodv_parse_rerr(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rack)
{
aodv_parse_rack(NULL, NULL, 0, NULL);
}
END_TEST
START_TEST(tc_pico_aodv_parse)
{
}
END_TEST
START_TEST(tc_pico_aodv_socket_callback)
{
/* TODO: test this: static void pico_aodv_socket_callback(uint16_t ev, struct pico_socket *s) */
}
END_TEST
START_TEST(tc_aodv_make_rreq)
{
/* TODO: test this: static void aodv_make_rreq(struct pico_aodv_node *node, struct pico_aodv_rreq *req) */
}
END_TEST
START_TEST(tc_aodv_retrans_rreq)
{
/* TODO: test this: static void aodv_retrans_rreq(pico_time now, void *arg) */
}
END_TEST
START_TEST(tc_pico_aodv_expired)
{
/* TODO: test this: static void pico_aodv_expired(struct pico_aodv_node *node) */
}
END_TEST
START_TEST(tc_pico_aodv_collector)
{
/* TODO: test this: static void pico_aodv_collector(pico_time now, void *arg) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_aodv_node_compare = tcase_create("Unit test for aodv_node_compare");
TCase *TCase_aodv_dev_cmp = tcase_create("Unit test for aodv_dev_cmp");
TCase *TCase_get_node_by_addr = tcase_create("Unit test for get_node_by_addr");
TCase *TCase_pico_aodv_set_dev = tcase_create("Unit test for pico_aodv_set_dev");
TCase *TCase_aodv_peer_refresh = tcase_create("Unit test for aodv_peer_refresh");
TCase *TCase_aodv_elect_route = tcase_create("Unit test for aodv_elect_route");
TCase *TCase_aodv_peer_new = tcase_create("Unit test for aodv_peer_new");
TCase *TCase_aodv_peer_eval = tcase_create("Unit test for aodv_peer_eval");
TCase *TCase_aodv_lifetime = tcase_create("Unit test for aodv_lifetime");
TCase *TCase_aodv_send_reply = tcase_create("Unit test for aodv_send_reply");
TCase *TCase_aodv_send_req = tcase_create("Unit test for aodv_send_req");
TCase *TCase_aodv_reverse_path_discover = tcase_create("Unit test for aodv_reverse_path_discover");
TCase *TCase_aodv_recv_valid_rreq = tcase_create("Unit test for aodv_recv_valid_rreq");
TCase *TCase_aodv_parse_rreq = tcase_create("Unit test for aodv_parse_rreq");
TCase *TCase_aodv_parse_rrep = tcase_create("Unit test for aodv_parse_rrep");
TCase *TCase_aodv_parse_rerr = tcase_create("Unit test for aodv_parse_rerr");
TCase *TCase_aodv_parse_rack = tcase_create("Unit test for aodv_parse_rack");
TCase *TCase_pico_aodv_parse = tcase_create("Unit test for pico_aodv_parse");
TCase *TCase_pico_aodv_socket_callback = tcase_create("Unit test for pico_aodv_socket_callback");
TCase *TCase_aodv_make_rreq = tcase_create("Unit test for aodv_make_rreq");
TCase *TCase_aodv_retrans_rreq = tcase_create("Unit test for aodv_retrans_rreq");
TCase *TCase_pico_aodv_expired = tcase_create("Unit test for pico_aodv_expired");
TCase *TCase_pico_aodv_collector = tcase_create("Unit test for pico_aodv_collector");
tcase_add_test(TCase_aodv_node_compare, tc_aodv_node_compare);
suite_add_tcase(s, TCase_aodv_node_compare);
tcase_add_test(TCase_aodv_dev_cmp, tc_aodv_dev_cmp);
suite_add_tcase(s, TCase_aodv_dev_cmp);
tcase_add_test(TCase_get_node_by_addr, tc_get_node_by_addr);
suite_add_tcase(s, TCase_get_node_by_addr);
tcase_add_test(TCase_pico_aodv_set_dev, tc_pico_aodv_set_dev);
suite_add_tcase(s, TCase_pico_aodv_set_dev);
tcase_add_test(TCase_aodv_peer_refresh, tc_aodv_peer_refresh);
suite_add_tcase(s, TCase_aodv_peer_refresh);
tcase_add_test(TCase_aodv_elect_route, tc_aodv_elect_route);
suite_add_tcase(s, TCase_aodv_elect_route);
tcase_add_test(TCase_aodv_peer_new, tc_aodv_peer_new);
suite_add_tcase(s, TCase_aodv_peer_new);
tcase_add_test(TCase_aodv_peer_eval, tc_aodv_peer_eval);
suite_add_tcase(s, TCase_aodv_peer_eval);
tcase_add_test(TCase_aodv_lifetime, tc_aodv_lifetime);
suite_add_tcase(s, TCase_aodv_lifetime);
tcase_add_test(TCase_aodv_send_reply, tc_aodv_send_reply);
suite_add_tcase(s, TCase_aodv_send_reply);
tcase_add_test(TCase_aodv_send_req, tc_aodv_send_req);
suite_add_tcase(s, TCase_aodv_send_req);
tcase_add_test(TCase_aodv_reverse_path_discover, tc_aodv_reverse_path_discover);
suite_add_tcase(s, TCase_aodv_reverse_path_discover);
tcase_add_test(TCase_aodv_recv_valid_rreq, tc_aodv_recv_valid_rreq);
suite_add_tcase(s, TCase_aodv_recv_valid_rreq);
tcase_add_test(TCase_aodv_parse_rreq, tc_aodv_parse_rreq);
suite_add_tcase(s, TCase_aodv_parse_rreq);
tcase_add_test(TCase_aodv_parse_rrep, tc_aodv_parse_rrep);
suite_add_tcase(s, TCase_aodv_parse_rrep);
tcase_add_test(TCase_aodv_parse_rerr, tc_aodv_parse_rerr);
suite_add_tcase(s, TCase_aodv_parse_rerr);
tcase_add_test(TCase_aodv_parse_rack, tc_aodv_parse_rack);
suite_add_tcase(s, TCase_aodv_parse_rack);
tcase_add_test(TCase_pico_aodv_parse, tc_pico_aodv_parse);
suite_add_tcase(s, TCase_pico_aodv_parse);
tcase_add_test(TCase_pico_aodv_socket_callback, tc_pico_aodv_socket_callback);
suite_add_tcase(s, TCase_pico_aodv_socket_callback);
tcase_add_test(TCase_aodv_make_rreq, tc_aodv_make_rreq);
suite_add_tcase(s, TCase_aodv_make_rreq);
tcase_add_test(TCase_aodv_retrans_rreq, tc_aodv_retrans_rreq);
suite_add_tcase(s, TCase_aodv_retrans_rreq);
tcase_add_test(TCase_pico_aodv_expired, tc_pico_aodv_expired);
suite_add_tcase(s, TCase_pico_aodv_expired);
tcase_add_test(TCase_pico_aodv_collector, tc_pico_aodv_collector);
suite_add_tcase(s, TCase_pico_aodv_collector);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,97 @@
#include "modules/pico_dev_loop.c"
#include "check.h"
static int called = 0;
static int fail = 0;
Suite *pico_suite(void);
int pico_device_init(struct pico_device __attribute__((unused)) *dev, const char __attribute__((unused)) *name, const uint8_t __attribute__((unused)) *mac)
{
if (fail)
return -1;
return 0;
}
void pico_device_destroy(struct pico_device *dev)
{
dev = dev;
}
int32_t pico_stack_recv(struct pico_device __attribute__((unused)) *dev, uint8_t __attribute__((unused)) *buffer, uint32_t __attribute__((unused)) len)
{
called = 1;
return 1;
}
START_TEST(tc_pico_loop_send)
{
uint8_t buf[LOOP_MTU + 1] = {};
fail_if(pico_loop_send(NULL, buf, LOOP_MTU + 1) != 0);
/* First send: OK */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != LOOP_MTU);
/* Second: buffer busy */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != 0);
}
END_TEST
START_TEST(tc_pico_loop_poll)
{
uint8_t buf[LOOP_MTU + 1] = {};
fail_if(pico_loop_poll(NULL, 0) != 0);
called = 0;
/* First send: OK */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != LOOP_MTU);
fail_if(pico_loop_poll(NULL, 1) != 0);
fail_if(called == 0);
}
END_TEST
START_TEST(tc_pico_loop_create)
{
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_loop_create (1)\n");
pico_set_mm_failure(1);
fail_if(pico_loop_create() != NULL);
#endif
fail = 1;
fail_if(pico_loop_create() != NULL);
fail = 0;
fail_if(pico_loop_create() == NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_loop_send = tcase_create("Unit test for pico_loop_send");
TCase *TCase_pico_loop_poll = tcase_create("Unit test for pico_loop_poll");
TCase *TCase_pico_loop_create = tcase_create("Unit test for pico_loop_create");
tcase_add_test(TCase_pico_loop_send, tc_pico_loop_send);
suite_add_tcase(s, TCase_pico_loop_send);
tcase_add_test(TCase_pico_loop_poll, tc_pico_loop_poll);
suite_add_tcase(s, TCase_pico_loop_poll);
tcase_add_test(TCase_pico_loop_create, tc_pico_loop_create);
suite_add_tcase(s, TCase_pico_loop_create);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
#include "pico_config.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_socket.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_dns_client.h"
#include "pico_tree.h"
#include "pico_udp.h"
#include "modules/pico_dns_client.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_pico_dns_client_callback)
{
struct pico_socket *s = pico_udp_open();
s->proto = &pico_proto_udp;
fail_if(!s);
/* Test with ERR */
pico_dns_client_callback(PICO_SOCK_EV_ERR, s);
/* Test with failing RD */
pico_dns_client_callback(PICO_SOCK_EV_RD, s);
}
END_TEST
START_TEST(tc_pico_dns_client_retransmission)
{
/* TODO: test this: static void pico_dns_client_retransmission(pico_time now, void *arg); */
}
END_TEST
START_TEST(tc_dns_ns_cmp)
{
/* TODO: test this: static int dns_ns_cmp(void *ka, void *kb) */
}
END_TEST
START_TEST(tc_dns_query_cmp)
{
/* TODO: test this: static int dns_query_cmp(void *ka, void *kb) */
}
END_TEST
START_TEST(tc_pico_dns_client_del_ns)
{
/* TODO: test this: static int pico_dns_client_del_ns(struct pico_ip4 *ns_addr) */
}
END_TEST
START_TEST(tc_pico_dns_ns)
{
/* TODO: test this: static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr) */
}
END_TEST
START_TEST(tc_pico_dns_client_del_query)
{
/* TODO: test this: static int pico_dns_client_del_query(uint16_t id) */
}
END_TEST
START_TEST(tc_pico_dns_query)
{
/* TODO: test this: static struct pico_dns_query *pico_dns_client_find_query(uint16_t id) */
}
END_TEST
START_TEST(tc_pico_dns_client_strlen)
{
/* TODO: test this: static uint16_t pico_dns_client_strlen(const char *url) */
}
END_TEST
START_TEST(tc_pico_dns_client_seek)
{
/* TODO: test this: static char *pico_dns_client_seek(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_mirror)
{
/* TODO: test this: static int8_t pico_dns_client_mirror(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_prefix)
{
/* TODO: test this: static int pico_dns_client_query_prefix(struct pico_dns_prefix *pre) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_suffix)
{
/* TODO: test this: static int pico_dns_client_query_suffix(struct pico_dns_query_suffix *suf, uint16_t type, uint16_t class) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_domain)
{
/* TODO: test this: static int pico_dns_client_query_domain(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_answer_domain)
{
/* TODO: test this: static int pico_dns_client_answer_domain(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_prefix)
{
/* TODO: test this: static int pico_dns_client_check_prefix(struct pico_dns_prefix *pre) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_qsuffix)
{
/* TODO: test this: static int pico_dns_client_check_qsuffix(struct pico_dns_query_suffix *suf, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_asuffix)
{
/* TODO: test this: static int pico_dns_client_check_asuffix(struct pico_dns_answer_suffix *suf, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_seek_suffix)
{
/* TODO: test this: static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_prefix *pre, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_send)
{
/* TODO: test this: static int pico_dns_client_send(struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_user_callback)
{
/* TODO: test this: static int pico_dns_client_user_callback(struct pico_dns_answer_suffix *asuffix, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_getaddr_init)
{
/* TODO: test this: static int pico_dns_client_getaddr_init(const char *url, uint16_t proto, void (*callback)(char *, void *), void *arg) */
}
END_TEST
START_TEST(tc_pico_dns_ipv6_set_ptr)
{
/* TODO: test this: static void pico_dns_ipv6_set_ptr(const char *ip, char *dst) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_dns_client_callback = tcase_create("Unit test for pico_dns_client_callback");
TCase *TCase_pico_dns_client_retransmission = tcase_create("Unit test for pico_dns_client_retransmission");
TCase *TCase_dns_ns_cmp = tcase_create("Unit test for dns_ns_cmp");
TCase *TCase_dns_query_cmp = tcase_create("Unit test for dns_query_cmp");
TCase *TCase_pico_dns_client_del_ns = tcase_create("Unit test for pico_dns_client_del_ns");
TCase *TCase_pico_dns_ns = tcase_create("Unit test for pico_dns_ns");
TCase *TCase_pico_dns_client_del_query = tcase_create("Unit test for pico_dns_client_del_query");
TCase *TCase_pico_dns_query = tcase_create("Unit test for pico_dns_query");
TCase *TCase_pico_dns_client_strlen = tcase_create("Unit test for pico_dns_client_strlen");
TCase *TCase_pico_dns_client_seek = tcase_create("Unit test for pico_dns_client_seek");
TCase *TCase_pico_dns_client_mirror = tcase_create("Unit test for pico_dns_client_mirror");
TCase *TCase_pico_dns_client_query_prefix = tcase_create("Unit test for pico_dns_client_query_prefix");
TCase *TCase_pico_dns_client_query_suffix = tcase_create("Unit test for pico_dns_client_query_suffix");
TCase *TCase_pico_dns_client_query_domain = tcase_create("Unit test for pico_dns_client_query_domain");
TCase *TCase_pico_dns_client_answer_domain = tcase_create("Unit test for pico_dns_client_answer_domain");
TCase *TCase_pico_dns_client_check_prefix = tcase_create("Unit test for pico_dns_client_check_prefix");
TCase *TCase_pico_dns_client_check_qsuffix = tcase_create("Unit test for pico_dns_client_check_qsuffix");
TCase *TCase_pico_dns_client_check_asuffix = tcase_create("Unit test for pico_dns_client_check_asuffix");
TCase *TCase_pico_dns_client_seek_suffix = tcase_create("Unit test for pico_dns_client_seek_suffix");
TCase *TCase_pico_dns_client_send = tcase_create("Unit test for pico_dns_client_send");
TCase *TCase_pico_dns_client_user_callback = tcase_create("Unit test for pico_dns_client_user_callback");
TCase *TCase_pico_dns_client_getaddr_init = tcase_create("Unit test for pico_dns_client_getaddr_init");
TCase *TCase_pico_dns_ipv6_set_ptr = tcase_create("Unit test for pico_dns_ipv6_set_ptr");
tcase_add_test(TCase_pico_dns_client_callback, tc_pico_dns_client_callback);
suite_add_tcase(s, TCase_pico_dns_client_callback);
tcase_add_test(TCase_pico_dns_client_retransmission, tc_pico_dns_client_retransmission);
suite_add_tcase(s, TCase_pico_dns_client_retransmission);
tcase_add_test(TCase_dns_ns_cmp, tc_dns_ns_cmp);
suite_add_tcase(s, TCase_dns_ns_cmp);
tcase_add_test(TCase_dns_query_cmp, tc_dns_query_cmp);
suite_add_tcase(s, TCase_dns_query_cmp);
tcase_add_test(TCase_pico_dns_client_del_ns, tc_pico_dns_client_del_ns);
suite_add_tcase(s, TCase_pico_dns_client_del_ns);
tcase_add_test(TCase_pico_dns_ns, tc_pico_dns_ns);
suite_add_tcase(s, TCase_pico_dns_ns);
tcase_add_test(TCase_pico_dns_client_del_query, tc_pico_dns_client_del_query);
suite_add_tcase(s, TCase_pico_dns_client_del_query);
tcase_add_test(TCase_pico_dns_query, tc_pico_dns_query);
suite_add_tcase(s, TCase_pico_dns_query);
tcase_add_test(TCase_pico_dns_client_strlen, tc_pico_dns_client_strlen);
suite_add_tcase(s, TCase_pico_dns_client_strlen);
tcase_add_test(TCase_pico_dns_client_seek, tc_pico_dns_client_seek);
suite_add_tcase(s, TCase_pico_dns_client_seek);
tcase_add_test(TCase_pico_dns_client_mirror, tc_pico_dns_client_mirror);
suite_add_tcase(s, TCase_pico_dns_client_mirror);
tcase_add_test(TCase_pico_dns_client_query_prefix, tc_pico_dns_client_query_prefix);
suite_add_tcase(s, TCase_pico_dns_client_query_prefix);
tcase_add_test(TCase_pico_dns_client_query_suffix, tc_pico_dns_client_query_suffix);
suite_add_tcase(s, TCase_pico_dns_client_query_suffix);
tcase_add_test(TCase_pico_dns_client_query_domain, tc_pico_dns_client_query_domain);
suite_add_tcase(s, TCase_pico_dns_client_query_domain);
tcase_add_test(TCase_pico_dns_client_answer_domain, tc_pico_dns_client_answer_domain);
suite_add_tcase(s, TCase_pico_dns_client_answer_domain);
tcase_add_test(TCase_pico_dns_client_check_prefix, tc_pico_dns_client_check_prefix);
suite_add_tcase(s, TCase_pico_dns_client_check_prefix);
tcase_add_test(TCase_pico_dns_client_check_qsuffix, tc_pico_dns_client_check_qsuffix);
suite_add_tcase(s, TCase_pico_dns_client_check_qsuffix);
tcase_add_test(TCase_pico_dns_client_check_asuffix, tc_pico_dns_client_check_asuffix);
suite_add_tcase(s, TCase_pico_dns_client_check_asuffix);
tcase_add_test(TCase_pico_dns_client_seek_suffix, tc_pico_dns_client_seek_suffix);
suite_add_tcase(s, TCase_pico_dns_client_seek_suffix);
tcase_add_test(TCase_pico_dns_client_send, tc_pico_dns_client_send);
suite_add_tcase(s, TCase_pico_dns_client_send);
tcase_add_test(TCase_pico_dns_client_user_callback, tc_pico_dns_client_user_callback);
suite_add_tcase(s, TCase_pico_dns_client_user_callback);
tcase_add_test(TCase_pico_dns_client_getaddr_init, tc_pico_dns_client_getaddr_init);
suite_add_tcase(s, TCase_pico_dns_client_getaddr_init);
tcase_add_test(TCase_pico_dns_ipv6_set_ptr, tc_pico_dns_ipv6_set_ptr);
suite_add_tcase(s, TCase_pico_dns_ipv6_set_ptr);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,403 @@
#include "pico_config.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_socket.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_dns_common.h"
#include "pico_tree.h"
#include "pico_dev_mock.c"
#include "modules/pico_dns_sd.c"
#include "check.h"
Suite *pico_suite(void);
void callback( pico_mdns_rtree *tree, char *str, void *arg);
int dns_sd_init(void);
char text[] = "textvers";
char text2[] = "pass";
char text3[] = "color";
char value[] = "1";
char value3[] = "";
void callback( pico_mdns_rtree *tree,
char *str,
void *arg )
{
kv_vector vector = {
0
};
/* This doesn't even gets called, tests exit before possible callback */
IGNORE_PARAMETER(str);
IGNORE_PARAMETER(arg);
IGNORE_PARAMETER(tree);
fail_unless(pico_dns_sd_register_service("Hello World!",
"_kerberos._udp",
88, &vector, 120,
callback, NULL) == 0,
"dns_sd_register_service failed!\n");
}
int dns_sd_init()
{
struct mock_device *mock = NULL;
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
mock = pico_mock_create(NULL);
if (!mock)
return -1;
pico_ipv4_link_add(mock->dev, local, netmask);
/* Try to initialise the mDNS module right */
return pico_dns_sd_init("host.local", local, callback, NULL);
}
START_TEST(tc_dns_sd_kv_vector_strlen)
{
kv_vector pairs = {
0
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
fail_unless(pico_dns_sd_kv_vector_strlen(&pairs) == 23,
"dns_sd_kv_vector_strlen returned wrong length!\n");
pico_dns_sd_kv_vector_erase(&pairs);
}
END_TEST
START_TEST(tc_dns_sd_srv_record_create)
{
struct pico_mdns_record *record = NULL;
uint8_t buf[19] = {
0, 0, 0, 0, 0, 80,
5, 'h', 'i', 't', 'e', 'x',
5, 'l', 'o', 'c', 'a', 'l',
0
};
record = pico_dns_sd_srv_record_create("test.local", 0, 0, 80,
"hitex.local", 10,
PICO_MDNS_RECORD_UNIQUE);
fail_unless(strcmp(record->record->rname, "\4test\5local") == 0,
"Name of SRV record not correct!\n");
fail_unless(short_be(record->record->rsuffix->rtype) == 33,
"Type of SRV record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rclass) == 0x8001,
"Class of SRV record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rdlength) == 19,
"rdlength of SRV record not correctly set!\n");
fail_unless(long_be(record->record->rsuffix->rttl) == 10,
"TTL of SRV record not correctly set!\n");
fail_unless(memcmp(record->record->rdata, buf, 19) == 0,
"Rdata of TXT record not correctly set!\n");
pico_mdns_record_delete((void **)&record);
}
END_TEST
START_TEST(tc_dns_sd_txt_record_create)
{
struct pico_mdns_record *record = NULL;
kv_vector pairs = {
0
};
uint8_t buf[23] = {
10, 't', 'e', 'x', 't', 'v', 'e', 'r', 's', '=', '1',
4, 'p', 'a', 's', 's',
6, 'c', 'o', 'l', 'o', 'r', '='
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
record = pico_dns_sd_txt_record_create("test.local", pairs, 10,
PICO_MDNS_RECORD_UNIQUE);
fail_unless(strcmp(record->record->rname, "\4test\5local") == 0,
"Name of TXT record not correct!\n");
fail_unless(short_be(record->record->rsuffix->rtype) == 16,
"Type of TXT record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rclass) == 0x8001,
"Class of TXT record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rdlength) == 23,
"rdlength of TXT record not correctly set!\n");
fail_unless(long_be(record->record->rsuffix->rttl) == 10,
"TTL of TXT record not correctly set!\n");
fail_unless(memcmp(record->record->rdata, buf, 23) == 0,
"Rdata of TXT record not correctly set!\n");
pico_mdns_record_delete((void **)&record);
}
END_TEST
START_TEST(tc_dns_sd_kv_create)
{
key_value_pair_t *pair = NULL;
pair = pico_dns_sd_kv_create("textvers", "1");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "1") == 0,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair->value);
PICO_FREE(pair);
pair = pico_dns_sd_kv_create("textvers", NULL);
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(pair->value == NULL,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair);
pair = pico_dns_sd_kv_create("textvers", "");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "") == 0,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair->value);
PICO_FREE(pair);
}
END_TEST
START_TEST(tc_dns_sd_kv_delete)
{
key_value_pair_t *pair = NULL;
pair = pico_dns_sd_kv_create("textvers", "1");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "1") == 0,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
pair = pico_dns_sd_kv_create("textvers", NULL);
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(pair->value == NULL,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
pair = pico_dns_sd_kv_create("textvers", "");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "") == 0,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_check_type_format)
{
fail_unless(pico_dns_sd_check_type_format("_http._tcp") == 0,
"dns_sd_check_type_format failed with correct format!\n");
fail_unless(pico_dns_sd_check_type_format("_printer._sub._http._tcp")
== 0,
"dns_sd_check_type_format failed with subtype!\n");
/* Test too long subtype */
fail_unless(pico_dns_sd_check_type_format(
"1234567891123456789212345678931234567894123456789512345678961234._sub._http._tcp"), "dns_sd_check_type_format failed with too big subtype!\n");
/* Test too long service type with subtype */
fail_unless(pico_dns_sd_check_type_format(
"printer._sub.0123456789112345678._tcp"),
"dns_sd_check_type_format failed with too big sn w/ sub!\n");
/* Test too long service type with subtype */
fail_unless(pico_dns_sd_check_type_format("0123456789112345678._tcp"),
"dns_sd_check_type_format failed with too big sn!\n");
}
END_TEST
START_TEST(tc_dns_sd_check_instance_name_format)
{
/* Test too long name */
fail_unless(pico_dns_sd_check_instance_name_format(
"1234567891123456789212345678931234567894123456789512345678961234"),
"dns_sd_check_instance_name_format failed with too big name!\n");
fail_unless(pico_dns_sd_check_instance_name_format("Hello World!") == 0,
"dns_sd_check_instance_name_format failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_create_service_url)
{
char *service_url = NULL;
service_url = pico_dns_sd_create_service_url("Hello World!", "_http._tcp");
fail_unless(strcmp(service_url, "Hello World!._http._tcp.local") == 0,
"dns_sd_create_service_url failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_init)
{
pico_stack_init();
fail_unless(dns_sd_init() == 0,
"dns_sd_init failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_register_service)
{
pico_stack_init();
dns_sd_init();
}
END_TEST
START_TEST(tc_dns_sd_browse_service)
{
/* Not implemented in code */
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_add)
{
kv_vector pairs = {
0
};
char *key = NULL;
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
key = pico_dns_sd_kv_vector_get(&pairs, 2)->key;
fail_unless(strcmp("color", key) == 0,
"dns_sd_kv_vector_add failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_get)
{
kv_vector pairs = {
0
};
char *key = NULL;
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
key = pico_dns_sd_kv_vector_get(&pairs, 2)->key;
fail_unless(strcmp("color", key) == 0,
"dns_sd_kv_vector_get failed!\n");
fail_unless(pico_dns_sd_kv_vector_get(&pairs, 3) == NULL,
"dns_sd_kv_vector_get failed @ OOB!\n");
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_erase)
{
kv_vector pairs = {
0
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
pico_dns_sd_kv_vector_erase(&pairs);
fail_unless(pairs.pairs == NULL,
"dns_sd_kv_vector_erase failed!\n");
fail_unless(pairs.count == 0,
"dns_sd_kv_vector_erase failed!\n");
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
/* Key-Value pair vector plain creation function */
TCase *TCase_dns_sd_kv_vector_strlen = tcase_create("Unit test for dns_sd_kv_vector_strlen");
/* DNS utility functions */
TCase *TCase_dns_sd_srv_record_create = tcase_create("Unit test for dns_sd_srv_record_create");
TCase *TCase_dns_sd_txt_record_create = tcase_create("Unit test for dns_sd_txt_record_create");
/* Key-Value pair creation */
TCase *TCase_dns_sd_kv_create = tcase_create("Unit test for dns_sd_kv_create");
TCase *TCase_dns_sd_kv_delete = tcase_create("Unit test for dns_sd_kv_delete");
/* Utility functions */
TCase *TCase_dns_sd_check_type_format = tcase_create("Unit test for dns_sd_check_type_format");
TCase *TCase_dns_sd_check_instance_name_format = tcase_create("Unit test for dns_sd_check_instance_name_format");
TCase *TCase_dns_sd_create_service_url = tcase_create("Unit test for dns_sd_create_service_url");
/* DNS SD API functions */
TCase *TCase_dns_sd_init = tcase_create("Unit test for dns_sd_init");
TCase *TCase_dns_sd_register_service = tcase_create("Unit test for dns_sd_register_service");
TCase *TCase_dns_sd_browse_service = tcase_create("Unit test for dns_sd_browse_service");
/* Key-Value vector functions */
TCase *TCase_dns_sd_kv_vector_add = tcase_create("Unit test for dns_sd_kv_vector_add");
TCase *TCase_dns_sd_kv_vector_get = tcase_create("Unit test for dns_sd_kv_vector_get");
TCase *TCase_dns_sd_kv_vector_erase = tcase_create("Unit test for dns_sd_kv_vector_erase");
/* Key-Value pair vector plain creation function */
tcase_add_test(TCase_dns_sd_kv_vector_strlen, tc_dns_sd_kv_vector_strlen);
suite_add_tcase(s, TCase_dns_sd_kv_vector_strlen);
/* DNS utility functions */
tcase_add_test(TCase_dns_sd_srv_record_create, tc_dns_sd_srv_record_create);
suite_add_tcase(s, TCase_dns_sd_srv_record_create);
tcase_add_test(TCase_dns_sd_txt_record_create, tc_dns_sd_txt_record_create);
suite_add_tcase(s, TCase_dns_sd_txt_record_create);
/* Key-Value pair creation */
tcase_add_test(TCase_dns_sd_kv_create, tc_dns_sd_kv_create);
suite_add_tcase(s, TCase_dns_sd_kv_create);
tcase_add_test(TCase_dns_sd_kv_delete, tc_dns_sd_kv_delete);
suite_add_tcase(s, TCase_dns_sd_kv_delete);
/* Utility functions */
tcase_add_test(TCase_dns_sd_check_type_format, tc_dns_sd_check_type_format);
suite_add_tcase(s, TCase_dns_sd_check_type_format);
tcase_add_test(TCase_dns_sd_check_instance_name_format, tc_dns_sd_check_instance_name_format);
suite_add_tcase(s, TCase_dns_sd_check_instance_name_format);
tcase_add_test(TCase_dns_sd_create_service_url, tc_dns_sd_create_service_url);
suite_add_tcase(s, TCase_dns_sd_create_service_url);
/* DNS SD API functions */
tcase_add_test(TCase_dns_sd_init, tc_dns_sd_init);
suite_add_tcase(s, TCase_dns_sd_init);
tcase_add_test(TCase_dns_sd_register_service, tc_dns_sd_register_service);
suite_add_tcase(s, TCase_dns_sd_register_service);
tcase_add_test(TCase_dns_sd_browse_service, tc_dns_sd_browse_service);
suite_add_tcase(s, TCase_dns_sd_browse_service);
/* Key-Value vector functions */
tcase_add_test(TCase_dns_sd_kv_vector_add, tc_dns_sd_kv_vector_add);
suite_add_tcase(s, TCase_dns_sd_kv_vector_add);
tcase_add_test(TCase_dns_sd_kv_vector_get, tc_dns_sd_kv_vector_get);
suite_add_tcase(s, TCase_dns_sd_kv_vector_get);
tcase_add_test(TCase_dns_sd_kv_vector_erase, tc_dns_sd_kv_vector_erase);
suite_add_tcase(s, TCase_dns_sd_kv_vector_erase);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,315 @@
//#include "pico_config.h"
#include "pico_stack.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_icmp4.h"
#include "pico_icmp6.h"
#include "pico_arp.h"
#include "pico_ethernet.h"
#include "modules/pico_ethernet.c"
#include "check.h"
#define STARTING() \
printf("*********************** STARTING %s ***\n", __func__); \
fflush(stdout)
#define TRYING(s, ...) \
printf("Trying %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define CHECKING(i) \
printf("Checking the results of test %2d in %s...", (i)++, \
__func__); \
fflush(stdout)
#define SUCCESS() \
printf(" SUCCES\n"); \
fflush(stdout)
#define BREAKING(s, ...) \
printf("Breaking %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define ENDING(i) \
printf("*********************** ENDING %s *** N TESTS: %d\n", \
__func__, ((i)-1)); \
fflush(stdout)
#define DBG(s, ...) \
printf(s, ##__VA_ARGS__); \
fflush(stdout)
Suite *pico_suite(void);
START_TEST(tc_destination_is_bcast)
{
/* test this: static int destination_is_bcast(struct pico_frame *f) */
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer;
struct pico_ipv4_hdr *h4 = NULL;
/* Test parameters */
int ret = 0, count = 0;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
STARTING();
TRYING("With wrong protocol -> IPv6\n");
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since IPv6 frame\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With right protocol -> IPv4\n");
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not a mcast address\n");
SUCCESS();
BREAKING();
ret = destination_is_bcast(NULL);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_destination_is_mcast)
{
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_ip6 mcast = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_ip4 addr4 = {0};
struct pico_ip4 mcast4 = {0};
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer;
struct pico_ipv4_hdr *h4 = (struct pico_ipv4_hdr *)f->buffer;
/* Test parameters */
int ret = 0, count = 0;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
STARTING();
pico_string_to_ipv4("232.1.1.0", &(mcast4.addr)); /* 0 */
pico_string_to_ipv4("10.20.0.1", &(addr4.addr));
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", (mcast.addr)); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", (addr.addr)); /* 0 */
TRYING("With IPv6 unicast addr\n");
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not an IPv6 multicast\n");
SUCCESS();
TRYING("With IPv6 multicast addr\n");
memcpy(h->dst.addr, mcast.addr, PICO_SIZE_IP6);
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(1 == ret, "Should've returned 1 since an IPv6 multicast\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With IPv4 unicast addr\n");
h4->dst = addr4;
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not an IPv4 mcast address\n");
SUCCESS();
TRYING("With IPv4 multicast addr\n");
h4->dst = mcast4;
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(1 == ret, "Should've returned 1 since an IPv4 multicast\n");
SUCCESS();
BREAKING();
ret = destination_is_bcast(NULL);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_ipv4_ethernet_receive)
{
/* test this: static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f) */
struct pico_frame *f = NULL;
struct pico_ipv4_hdr *h4 = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With IPv4 frame\n");
ret = pico_ipv4_ethernet_receive(f);
CHECKING(count);
fail_unless(ret > 0, "Was correct frame should've returned size of frame\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv4.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_ipv6_ethernet_receive)
{
/* test this: static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f) */
struct pico_frame *f = NULL;
struct pico_ipv6_hdr *h = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
h = (struct pico_ipv6_hdr *)f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x40; /* Ipv6 */
TRYING("With wrong network type\n");
ret = pico_ipv6_ethernet_receive(f);
CHECKING(count);
fail_unless(ret == -1, "Wrong type should've returned an error\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
h = (struct pico_ipv6_hdr *)f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60;
TRYING("With correct network type\n");
ret = pico_ipv6_ethernet_receive(f);
CHECKING(count);
fail_unless(ret == (int32_t)f->buffer_len, "Was correct frame, should've returned success\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv6.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_eth_receive)
{
struct pico_frame *f = NULL;
struct pico_eth_hdr *eth = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
/* ETHERNET PROTOCOL : IPV6 */
eth->proto = PICO_IDETH_IPV6;
TRYING("With wrong network type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == -1, "Wrong type should've returned an error\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x60; /* Ipv6 */
/* ETHERNET PROTOCOL : IPV6 */
eth->proto = PICO_IDETH_IPV6;
TRYING("With correct network type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == (int32_t)f->buffer_len, "Was correct frame, should've returned success\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv6.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
TRYING("With wrong frame type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == -1, "should've returned -1 wrong ethernet protocol\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
eth->proto = PICO_IDETH_IPV4;
TRYING("With IPv4 frame\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret > 0, "Was correct frame should've returned size of frame\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv4.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_destination_is_bcast = tcase_create("Unit test for destination_is_bcast");
TCase *TCase_destination_is_mcast = tcase_create("Unit test for destination_is_mcast");
TCase *TCase_pico_ipv4_ethernet_receive = tcase_create("Unit test for pico_ipv4_ethernet_receive");
TCase *TCase_pico_ipv6_ethernet_receive = tcase_create("Unit test for pico_ipv6_ethernet_receive");
TCase *TCase_pico_eth_receive = tcase_create("Unit test for pico_eth_receive");
tcase_add_test(TCase_destination_is_bcast, tc_destination_is_bcast);
suite_add_tcase(s, TCase_destination_is_bcast);
tcase_add_test(TCase_destination_is_mcast, tc_destination_is_mcast);
suite_add_tcase(s, TCase_destination_is_mcast);
tcase_add_test(TCase_pico_ipv4_ethernet_receive, tc_pico_ipv4_ethernet_receive);
suite_add_tcase(s, TCase_pico_ipv4_ethernet_receive);
tcase_add_test(TCase_pico_ipv6_ethernet_receive, tc_pico_ipv6_ethernet_receive);
suite_add_tcase(s, TCase_pico_ipv6_ethernet_receive);
tcase_add_test(TCase_pico_eth_receive, tc_pico_eth_receive);
suite_add_tcase(s, TCase_pico_eth_receive);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,274 @@
#include "pico_config.h"
#include "pico_protocol.h"
#include "pico_frame.h"
#include "stack/pico_frame.c"
#include "check.h"
volatile pico_err_t pico_err;
#define FRAME_SIZE 1000
Suite *pico_suite(void);
START_TEST(tc_pico_frame_alloc_discard)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
/* Test consistency */
fail_if(!f);
fail_if(!f->buffer);
fail_if(!f->usage_count);
fail_if(*f->usage_count != 1);
fail_if(f->start != f->buffer);
fail_if(f->len != f->buffer_len);
fail_if(f->len != FRAME_SIZE);
pico_frame_discard(f);
/* Test empty discard */
pico_frame_discard(NULL);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_alloc (1)\n");
pico_set_mm_failure(1);
f = pico_frame_alloc(FRAME_SIZE);
fail_if(f);
printf("Testing with faulty memory in frame_alloc (2)\n");
pico_set_mm_failure(2);
f = pico_frame_alloc(FRAME_SIZE);
fail_if(f);
printf("Testing with faulty memory in frame_do_alloc, with external buffer, failing to allocate usage_count \n");
pico_set_mm_failure(2);
f = pico_frame_do_alloc(FRAME_SIZE, 1, 1);
fail_if(f);
#endif
printf("Testing frame_do_alloc, with invalid flags combination\n");
f = pico_frame_do_alloc(FRAME_SIZE, 0, 1);
fail_if(f);
}
END_TEST
START_TEST(tc_pico_frame_grow_head)
{
struct pico_frame *f = pico_frame_alloc(3);
struct pico_frame *f2 = pico_frame_alloc(0);
int ret = 0;
uint8_t buf[6] = { 0, 0, 0, 'a', 'b', 'c'};
/* I don't care about usage_count, it's tested 'pico_frame_grow' */
fail_if(pico_frame_grow_head(f, 2) == 0);
/* Check for dereferencing OOB */
fail_if(pico_frame_grow_head(f2, 2) == -1);
f2->net_hdr[0] = 1;
f->net_hdr = f->buffer;
f->net_len = 3;
f->net_hdr[0] = 'a';
f->net_hdr[1] = 'b';
f->net_hdr[2] = 'c';
/* Try to grow head */
ret = pico_frame_grow_head(f, 6);
fail_if(ret != 0);
fail_unless(0 == memcmp(f->buffer, buf, f->buffer_len));
fail_unless(3 == f->net_hdr - f->buffer);
f->datalink_hdr = f->net_hdr - 3;
f->datalink_hdr[0] = 1;
}
END_TEST
START_TEST(tc_pico_frame_grow)
{
struct pico_frame *f = pico_frame_alloc(3);
struct pico_frame *f2 = pico_frame_alloc(0);
fail_if(f->buffer_len != 3);
/* Ensure that the usage_count starts at byte 4, for good alignment */
fail_if(((void*)f->usage_count - (void *)f->buffer) != 4);
((uint8_t *)f->buffer)[0] = 'a';
((uint8_t *)f->buffer)[1] = 'b';
((uint8_t *)f->buffer)[2] = 'c';
*f->usage_count = 12;
/* First, the failing cases. */
fail_if(pico_frame_grow(NULL, 30) == 0);
fail_if(pico_frame_grow(f, 2) == 0);
f->flags = 0;
/* Check for dereferencing OOB */
fail_if(pico_frame_grow(f2, 3) != 0);
f2->net_hdr[0] = 1;
f2->net_hdr[1] = 2;
pico_set_mm_failure(1);
fail_if(pico_frame_grow(f, 21) == 0);
/* Now, the good one. */
fail_if(pico_frame_grow(f, 21) != 0);
fail_if(f->buffer_len != 21);
fail_if(((void *)f->usage_count - (void *)f->buffer) != 24);
fail_if(((uint8_t *)f->buffer)[0] != 'a');
fail_if(((uint8_t *)f->buffer)[1] != 'b');
fail_if(((uint8_t *)f->buffer)[2] != 'c');
fail_if(*f->usage_count != 12);
*f->usage_count = 1;
pico_frame_discard(f);
f = pico_frame_alloc_skeleton(10, 1);
fail_if(!f);
fail_if(f->buffer);
fail_if(!f->flags);
f->buffer = PICO_ZALLOC(10);
fail_if(pico_frame_grow(f, 22) != 0);
fail_if (f->flags);
pico_frame_discard(f);
}
END_TEST
START_TEST(tc_pico_frame_copy)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
struct pico_frame *c1, *c2, *c3;
(void)c3;
fail_if(!f);
fail_if(!f->buffer);
fail_if(*f->usage_count != 1);
/* First copy */
c1 = pico_frame_copy(f);
fail_if(!c1);
fail_if(!c1->buffer);
fail_if(!c1->usage_count);
fail_if (c1->buffer != f->buffer);
fail_if(c1->usage_count != f->usage_count);
fail_if(*c1->usage_count != 2);
fail_if(*f->usage_count != 2);
fail_if(c1->start != c1->buffer);
fail_if(c1->len != c1->buffer_len);
fail_if(c1->len != FRAME_SIZE);
/* Second copy */
c2 = pico_frame_copy(f);
fail_if (c2->buffer != f->buffer);
fail_if(c2->usage_count != f->usage_count);
fail_if(*c2->usage_count != 3);
fail_if(*f->usage_count != 3);
fail_if(c2->start != c2->buffer);
fail_if(c2->len != c2->buffer_len);
fail_if(c2->len != FRAME_SIZE);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_copy (1)\n");
pico_set_mm_failure(1);
c3 = pico_frame_copy(f);
fail_if(c3);
fail_if(!f);
#endif
/* Discard 1 */
pico_frame_discard(c1);
fail_if(*f->usage_count != 2);
/* Discard 2 */
pico_frame_discard(c2);
fail_if(*f->usage_count != 1);
pico_frame_discard(f);
}
END_TEST
START_TEST(tc_pico_frame_deepcopy)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
struct pico_frame *dc = pico_frame_deepcopy(f);
fail_if(*f->usage_count != 1);
fail_if(*dc->usage_count != 1);
fail_if(dc->buffer == f->buffer);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_deepcopy (1)\n");
pico_set_mm_failure(1);
dc = pico_frame_deepcopy(f);
fail_if(dc);
fail_if(!f);
#endif
}
END_TEST
START_TEST(tc_pico_is_digit)
{
fail_if(pico_is_digit('a'));
fail_if(pico_is_digit('Z'));
fail_if(pico_is_digit('\0'));
fail_if(pico_is_digit('\n'));
fail_if(pico_is_digit('0' - 1));
fail_if(pico_is_digit('9' + 1));
fail_unless(pico_is_digit('0'));
fail_unless(pico_is_digit('9'));
}
END_TEST
START_TEST(tc_pico_is_hex)
{
fail_if(pico_is_hex('g'));
fail_if(pico_is_hex('Z'));
fail_if(pico_is_hex('\0'));
fail_if(pico_is_hex('\n'));
fail_if(pico_is_hex('0' - 1));
fail_if(pico_is_hex('f' + 1));
fail_if(pico_is_hex('F' + 1));
fail_unless(pico_is_hex('0'));
fail_unless(pico_is_hex('f'));
fail_unless(pico_is_hex('A'));
fail_unless(pico_is_hex('F'));
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico_frame.c");
TCase *TCase_pico_frame_alloc_discard = tcase_create("Unit test for pico_frame_alloc_discard");
TCase *TCase_pico_frame_copy = tcase_create("Unit test for pico_frame_copy");
TCase *TCase_pico_frame_grow = tcase_create("Unit test for pico_frame_grow");
TCase *TCase_pico_frame_grow_head = tcase_create("Unit test for pico_frame_grow_head");
TCase *TCase_pico_frame_deepcopy = tcase_create("Unit test for pico_frame_deepcopy");
TCase *TCase_pico_is_digit = tcase_create("Unit test for pico_is_digit");
TCase *TCase_pico_is_hex = tcase_create("Unit test for pico_is_hex");
tcase_add_test(TCase_pico_frame_alloc_discard, tc_pico_frame_alloc_discard);
tcase_add_test(TCase_pico_frame_copy, tc_pico_frame_copy);
tcase_add_test(TCase_pico_frame_grow, tc_pico_frame_grow);
tcase_add_test(TCase_pico_frame_grow_head, tc_pico_frame_grow_head);
tcase_add_test(TCase_pico_frame_deepcopy, tc_pico_frame_deepcopy);
tcase_add_test(TCase_pico_is_digit, tc_pico_is_digit);
tcase_add_test(TCase_pico_is_hex, tc_pico_is_hex);
suite_add_tcase(s, TCase_pico_frame_alloc_discard);
suite_add_tcase(s, TCase_pico_frame_copy);
suite_add_tcase(s, TCase_pico_frame_grow);
suite_add_tcase(s, TCase_pico_frame_grow_head);
suite_add_tcase(s, TCase_pico_frame_deepcopy);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,192 @@
#include "pico_hotplug_detection.h"
#include "pico_tree.h"
#include "pico_device.h"
#include "modules/pico_hotplug_detection.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void cb_one(struct pico_device *dev, int event);
void cb_two(struct pico_device *dev, int event);
int link_state_a(struct pico_device *self);
int link_state_b(struct pico_device *self);
/* stubs for timer */
static int8_t timer_active = 0;
void (*timer_cb_function)(pico_time, void *);
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(arg);
timer_active++;
timer_cb_function = timer;
return 123;
}
void pico_timer_cancel(uint32_t id)
{
timer_active--;
fail_if(id != 123);
}
/* callbacks for testing */
uint32_t cb_one_cntr = 0;
int cb_one_last_event = 0;
void cb_one(struct pico_device *dev, int event)
{
IGNORE_PARAMETER(dev);
cb_one_cntr++;
cb_one_last_event = event;
}
uint32_t cb_two_cntr = 0;
int cb_two_last_event = 0;
void cb_two(struct pico_device *dev, int event)
{
IGNORE_PARAMETER(dev);
cb_two_cntr++;
cb_two_last_event = event;
}
/* link state functions for the testing devices */
int state_a = 0;
int link_state_a(struct pico_device *self)
{
IGNORE_PARAMETER(self);
return state_a;
}
int state_b = 0;
int link_state_b(struct pico_device *self)
{
IGNORE_PARAMETER(self);
return state_b;
}
START_TEST(tc_pico_hotplug_reg_dereg)
{
/* create some devices */
struct pico_device *dev_a, *dev_b;
dev_a = pico_null_create("dummy1");
dev_b = pico_null_create("dummy2");
dev_a->link_state = &link_state_a;
dev_b->link_state = &link_state_b;
/* add some function pointers to be called */
pico_hotplug_register(dev_a, &cb_one);
fail_unless(timer_active == 1);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
fail_unless(timer_active == 1);
/* remove function pointers */
pico_hotplug_deregister(dev_a, &cb_one);
pico_hotplug_deregister(dev_a, &cb_two);
pico_hotplug_deregister(dev_b, &cb_two);
/* check that our tree is empty at the end */
fail_unless(pico_tree_empty(&Hotplug_device_tree));
/* register functions multiple times */
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
/* remove function pointers once */
pico_hotplug_deregister(dev_a, &cb_one);
pico_hotplug_deregister(dev_a, &cb_two);
fail_unless(timer_active == 1);
pico_hotplug_deregister(dev_b, &cb_two);
fail_unless(timer_active == 0);
/* check that our tree is empty at the end */
fail_unless(pico_tree_empty(&Hotplug_device_tree));
}
END_TEST
START_TEST(tc_pico_hotplug_callbacks)
{
/* create some devices */
struct pico_device *dev_a, *dev_b;
dev_a = pico_null_create("dummy1");
dev_b = pico_null_create("dummy2");
dev_a->link_state = &link_state_a;
dev_b->link_state = &link_state_b;
/* add some function pointers to be called */
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
fail_unless(timer_active == 1);
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 1);
fail_unless(cb_two_cntr == 2);
state_a = 1;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 2);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_UP );
fail_unless(cb_two_cntr == 3);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_UP );
state_b = 1;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 2);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_UP );
fail_unless(cb_two_cntr == 4);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_UP );
state_a = 0;
state_b = 0;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 3);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_DOWN );
fail_unless(cb_two_cntr == 6);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_DOWN );
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_hotplug_reg_dereg = tcase_create("Unit test for pico_hotplug_reg_dereg");
TCase *TCase_pico_hotplug_callbacks = tcase_create("Unit test for pico_hotplug_callbacks");
tcase_add_test(TCase_pico_hotplug_reg_dereg, tc_pico_hotplug_reg_dereg);
suite_add_tcase(s, TCase_pico_hotplug_reg_dereg);
tcase_add_test(TCase_pico_hotplug_callbacks, tc_pico_hotplug_callbacks);
suite_add_tcase(s, TCase_pico_hotplug_callbacks);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,359 @@
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_igmp.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void mock_callback(struct igmp_timer *t);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
void mock_callback(struct igmp_timer *t)
{
IGNORE_PARAMETER(t);
}
static int mcast_filter_cmp(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
if (a->ip4.addr < b->ip4.addr)
return -1;
if (a->ip4.addr > b->ip4.addr)
return 1;
return 0;
}
static int mcast_sources_cmp(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
if (a->ip4.addr < b->ip4.addr)
return -1;
if (a->ip4.addr > b->ip4.addr)
return 1;
return 0;
}
static PICO_TREE_DECLARE(_MCASTFilter, mcast_filter_cmp);
START_TEST(tc_pico_igmp_report_expired)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct pico_ip4 zero = {0};
t->mcast_link = zero;
t->mcast_group = zero;
/* void function, just check for side effects */
pico_igmp_report_expired(t);
}
END_TEST
START_TEST(tc_igmpt_type_compare)
{
struct igmp_timer a;
struct igmp_timer b;
a.type = 1;
b.type = 2;
fail_if(igmpt_type_compare(&a, &b) != -1);
fail_if(igmpt_type_compare(&b, &a) != 1);
fail_if(igmp_timer_cmp(&b, &a) != 1);
}
END_TEST
START_TEST(tc_pico_igmp_state_change)
{
struct pico_ip4 mcast_link, mcast_group;
pico_string_to_ipv4("192.168.1.1", &mcast_link.addr);
pico_string_to_ipv4("224.7.7.7", &mcast_group.addr);
fail_if(pico_igmp_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
fail_if(pico_igmp_state_change(&mcast_link, &mcast_group, 0, NULL, PICO_IGMP_STATE_CREATE) != 0);
}
END_TEST
START_TEST(tc_pico_igmp_timer_expired)
{
struct igmp_timer *t, *s;
t = PICO_ZALLOC(sizeof(struct igmp_timer));
t->stopped = IGMP_TIMER_STOPPED;
t->type = 0;
pico_string_to_ipv4("192.168.1.1", &t->mcast_link.addr);
pico_string_to_ipv4("244.7.7.7", &t->mcast_group.addr);
/* void function, just check for side effects */
pico_igmp_timer_expired(0, (void *)t);
pico_tree_insert(&IGMPTimers, t);
s = PICO_ZALLOC(sizeof(struct igmp_timer));
memcpy(s,t,sizeof(struct igmp_timer)); // t will be freed next test
pico_igmp_timer_expired(0, (void *)t); /* t is freed here */
s->stopped++;
s->start = PICO_TIME_MS()*2;
s->type++;
pico_tree_insert(&IGMPTimers, s);
t = PICO_ZALLOC(sizeof(struct igmp_timer));
memcpy(t,s,sizeof(struct igmp_timer)); // s will be freed next test
pico_igmp_timer_expired(0, (void *)s); /* s is freed here */
t->callback = mock_callback;
pico_igmp_timer_expired(0, (void *)t);
}
END_TEST
START_TEST(tc_pico_igmp_v2querier_expired)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct pico_ip4 addr = {0};
struct pico_device *dev = pico_null_create("dummy2");
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_frame));
t->f = f;
pico_string_to_ipv4("192.168.1.1", &(addr.addr));
/* void function, just check for side effects */
/* No link */
pico_igmp_v2querier_expired(t);
f->dev = dev;
pico_ipv4_link_add(dev, addr, addr);
pico_igmp_v2querier_expired(t);
}
END_TEST
START_TEST(tc_pico_igmp_delete_parameter)
{
struct mcast_parameters p;
fail_if(pico_igmp_delete_parameter(&p) != -1);
}
END_TEST
START_TEST(tc_pico_igmp_process_in)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv4_link *link;
uint8_t i, j, _i, _j;
int result;
struct pico_mcast_group g;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv4("192.168.1.1", &p->mcast_link.ip4.addr);
pico_string_to_ipv4("244.7.7.7", &p->mcast_group.ip4.addr);
/* no link */
fail_if(pico_igmp_generate_report(p) != -1);
pico_ipv4_link_add(dev, p->mcast_link.ip4, p->mcast_link.ip4);
link = pico_ipv4_link_get(&p->mcast_link.ip4);
link->mcast_compatibility = PICO_IGMPV2;
g.mcast_addr.ip4 = p->mcast_group.ip4;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp;
/* No mcastsources tree */
link->mcast_compatibility = PICO_IGMPV3;
fail_if(pico_igmp_generate_report(p) != -1);
pico_tree_insert(link->MCASTGroups, &g);
pico_tree_insert(&IGMPParameters, p);
link->mcast_compatibility = 99;
fail_if(pico_igmp_generate_report(p) != -1);
link->mcast_compatibility = PICO_IGMPV2;
fail_if(pico_igmp_generate_report(p) != 0);
link->mcast_compatibility = PICO_IGMPV3;
for(_j = 0; _j < 3; _j++) { /* FILTER */
(_j == 2) ? (result = -1) : (result = 0);
for(_i = 0; _i < 3; _i++) { /* FILTER */
if(_i == 2) result = -1;
for(i = 0; i < 3; i++) { /* STATES */
for(j = 0; j < 6; j++) { /* EVENTS */
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = _i;
g.filter_mode = _j;
if(p->event == IGMP_EVENT_DELETE_GROUP || p->event == IGMP_EVENT_QUERY_RECV)
p->event++;
fail_if(pico_igmp_generate_report(p) != result);
p->state = i;
p->event = j;
if(result != -1 && p->f) /* in some combinations, no frame is created */
fail_if(pico_igmp_process_in(NULL, p->f) != 0);
}
}
}
}
}
END_TEST
START_TEST(tc_pico_igmp_find_parameter)
{
struct pico_ip4 mcast_link, mcast_group;
struct mcast_parameters test = {
0
};
fail_if(pico_igmp_find_parameter(NULL, NULL) != NULL);
pico_string_to_ipv4("192.168.1.1", &mcast_link.addr);
fail_if(pico_igmp_find_parameter(&mcast_link, NULL) != NULL);
pico_string_to_ipv4("192.168.1.2", &mcast_group.addr);
fail_if(pico_igmp_find_parameter(&mcast_link, &mcast_group) != NULL);
test.mcast_link.ip4 = mcast_link;
test.mcast_group.ip4 = mcast_group;
pico_tree_insert(&IGMPParameters, &test);
fail_if(pico_igmp_find_parameter(&mcast_link, &mcast_group) == NULL);
}
END_TEST
START_TEST(tc_pico_igmp_compatibility_mode)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip4 addr;
struct pico_ipv4_hdr *hdr;
struct igmp_message *query;
uint8_t ihl = 24;
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, sizeof(struct igmpv3_report) + sizeof(struct igmpv3_group_record) + (0 * sizeof(struct pico_ip4)));
pico_string_to_ipv4("192.168.1.2", &addr.addr);
hdr = (struct pico_ipv4_hdr *) f->net_hdr;
ihl = (uint8_t)((hdr->vhl & 0x0F) * 4); /* IHL is in 32bit words */
query = (struct igmp_message *) f->transport_hdr;
/* No link */
fail_if(pico_igmp_compatibility_mode(f) != -1);
pico_ipv4_link_add(dev, addr, addr);
f->dev = dev;
/* Igmpv3 query */
hdr->len = short_be((uint16_t)(12 + ihl));
fail_if(pico_igmp_compatibility_mode(f) != 0);
/* Igmpv2 query */
hdr->len = short_be((uint16_t)(8 + ihl));
query->max_resp_time = 0;
fail_if(pico_igmp_compatibility_mode(f) == 0);
query->max_resp_time = 1;
fail_if(pico_igmp_compatibility_mode(f) != 0);
/* Invalid Query */
hdr->len = short_be((uint16_t)(9 + ihl));
fail_if(pico_igmp_compatibility_mode(f) == 0);
}
END_TEST
START_TEST(tc_pico_igmp_analyse_packet)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ip4 addr;
struct igmp_message *igmp;
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, sizeof(struct igmp_message));
pico_string_to_ipv4("192.168.1.1", &addr.addr);
/* No link */
fail_if(pico_igmp_analyse_packet(f) != NULL);
pico_ipv4_link_add(dev, addr, addr);
f->dev = dev;
igmp = (struct igmp_message *) (f->transport_hdr);
igmp->type = 0;
/* wrong type */
fail_if(pico_igmp_analyse_packet(f) != NULL);
/* all correct */
igmp->type = IGMP_TYPE_MEM_QUERY;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V1;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V2;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V3;
fail_if(pico_igmp_analyse_packet(f) == NULL);
}
END_TEST
START_TEST(tc_pico_igmp_discard)
{
/* TODO */
}
END_TEST
START_TEST(tc_srst)
{
struct mcast_parameters p;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ipv4_link *link;
pico_string_to_ipv4("192.168.1.1", &p.mcast_link.ip4.addr);
/* no link */
fail_if(srst(&p) != -1);
pico_ipv4_link_add(dev, p.mcast_link.ip4, p.mcast_link.ip4);
link = pico_ipv4_link_get(&p.mcast_link.ip4);
/* Not supported protocol for this call */
link->mcast_compatibility = PICO_IGMPV2;
fail_if(srst(&p) != -1);
link->mcast_compatibility = PICO_IGMPV3;
fail_if(srst(&p) != -1);
}
END_TEST
START_TEST(tc_stcl)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct mcast_parameters p;
pico_string_to_ipv4("192.168.1.10", &t->mcast_link.addr);
pico_string_to_ipv4("244.7.7.7", &t->mcast_group.addr);
p.mcast_link.ip4 = t->mcast_link;
p.mcast_group.ip4 = t->mcast_group;
t->type = IGMP_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(stcl(&p) != -1);
pico_igmp_timer_start(t);
fail_if(stcl(&p) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_igmp_report_expired = tcase_create("Unit test for pico_igmp_report_expired");
TCase *TCase_igmpt_type_compare = tcase_create("Unit test for igmpt_type_compare");
TCase *TCase_pico_igmp_analyse_packet = tcase_create("Unit test for pico_igmp_analyse_packet");
TCase *TCase_pico_igmp_discard = tcase_create("Unit test for pico_igmp_discard");
TCase *TCase_pico_igmp_compatibility_mode = tcase_create("Unit test for pico_igmp_compatibility");
TCase *TCase_pico_igmp_state_change = tcase_create("Unit test for pico_igmp_state_change");
TCase *TCase_pico_igmp_process_in = tcase_create("Unit test for pico_igmp_process_in");
TCase *TCase_pico_igmp_timer_expired = tcase_create("Unit test for pico_igmp_timer_expired");
TCase *TCase_pico_igmp_delete_parameter = tcase_create("Unit test for pico_igmp_delete_parameter");
TCase *TCase_pico_igmp_find_parameter = tcase_create("Unit test for pico_igmp_find_parameter");
TCase *TCase_stcl = tcase_create("Unit test for stcl");
TCase *TCase_srst = tcase_create("Unit test for srst");
TCase *TCase_pico_igmp_v2querier_expired = tcase_create("Unit test for pico_igmp_v2_querier_expired");
tcase_add_test(TCase_pico_igmp_report_expired, tc_pico_igmp_report_expired);
suite_add_tcase(s, TCase_pico_igmp_report_expired);
tcase_add_test(TCase_igmpt_type_compare, tc_igmpt_type_compare);
suite_add_tcase(s, TCase_igmpt_type_compare);
tcase_add_test(TCase_pico_igmp_analyse_packet, tc_pico_igmp_analyse_packet);
suite_add_tcase(s, TCase_pico_igmp_analyse_packet);
tcase_add_test(TCase_pico_igmp_discard, tc_pico_igmp_discard);
suite_add_tcase(s, TCase_pico_igmp_discard);
tcase_add_test(TCase_pico_igmp_compatibility_mode, tc_pico_igmp_compatibility_mode);
suite_add_tcase(s, TCase_pico_igmp_compatibility_mode);
suite_add_tcase(s, TCase_pico_igmp_state_change);
tcase_add_test(TCase_pico_igmp_state_change, tc_pico_igmp_state_change);
suite_add_tcase(s, TCase_pico_igmp_process_in);
tcase_add_test(TCase_pico_igmp_process_in, tc_pico_igmp_process_in);
suite_add_tcase(s, TCase_pico_igmp_timer_expired);
tcase_add_test(TCase_pico_igmp_timer_expired, tc_pico_igmp_timer_expired);
suite_add_tcase(s, TCase_pico_igmp_delete_parameter);
tcase_add_test(TCase_pico_igmp_delete_parameter, tc_pico_igmp_delete_parameter);
suite_add_tcase(s, TCase_pico_igmp_find_parameter);
tcase_add_test(TCase_pico_igmp_find_parameter, tc_pico_igmp_find_parameter);
suite_add_tcase(s, TCase_stcl);
tcase_add_test(TCase_stcl, tc_stcl);
suite_add_tcase(s, TCase_srst);
tcase_add_test(TCase_srst, tc_srst);
suite_add_tcase(s, TCase_pico_igmp_v2querier_expired);
tcase_add_test(TCase_pico_igmp_v2querier_expired, tc_pico_igmp_v2querier_expired);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,321 @@
#include "pico_ipv4.h"
#include "pico_config.h"
#include "pico_icmp4.h"
#include "pico_stack.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_device.h"
#include "pico_ipfilter.h"
#include "pico_tcp.h"
#include "pico_udp.h"
#include "pico_tree.h"
#include "modules/pico_ipfilter.c"
#include "check.h"
Suite *pico_suite(void);
int pico_icmp4_packet_filtered(struct pico_frame *f)
{
(void)f;
return 0;
}
void pico_frame_discard(struct pico_frame *f)
{
(void)f;
}
volatile pico_err_t pico_err;
START_TEST(tc_ipfilter)
{
uint32_t r;
struct filter_node a = {
0
}, b = {
0
};
fail_if(filter_compare(&a, &b) != 0);
/* a is rule, matching packet b */
a.filter_id = 1;
/* check that rule is matched properly */
fail_if(filter_match_packet_find_rule(&a, &b) != &a);
/* a has a out port that does not match packet */
b.out_port = 8;
a.out_port = 7;
fail_if(filter_compare(&a, &b) == 0);
/* a matches all ports */
a.out_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a has a in port that does not match packet */
b.in_port = 8;
a.in_port = 7;
fail_if(filter_compare(&a, &b) == 0);
/* a matches all ports */
a.in_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/* a matches port exactly */
a.in_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all out addresses */
b.out_addr = 0x010000a0;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match b via 8-bit netmask */
a.out_addr = 0x000000c0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) == 0);
/* a does not match b at all*/
a.out_addr = 0x020000b0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b via 8-bit netmask */
a.out_addr = 0x000000a0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) != 0);
/* a matches b exactly */
a.out_addr = 0x010000a0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all in addresses */
b.in_addr = 0x010000a0;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match b via 8-bit netmask */
a.in_addr = 0x000000c0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) == 0);
/* a does not match b at all*/
a.in_addr = 0x020000b0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b via 8-bit netmask */
a.in_addr = 0x000000a0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) != 0);
/* a matches b exactly */
a.in_addr = 0x010000a0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all protocols */
b.proto = 4u;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match protocol */
a.proto = 5u;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b's protocol */
a.proto = b.proto;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all devices */
b.fdev = (struct pico_device *) &b;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match device */
a.fdev = (struct pico_device *)&a;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b's device */
a.fdev = b.fdev;
fail_if(filter_compare(&a, &b) != 0);
/*** SAME TEST DUPLICATED WITH INVERTED ORDER OF PARAMETERS ***/
memset(&a, 0, sizeof(struct filter_node));
memset(&b, 0, sizeof(struct filter_node));
a.filter_id = 2;
/* check that rule is matched properly */
fail_if(filter_match_packet_find_rule(&b, &a) != &a);
/* a has a out port that does not match packet */
b.out_port = 8;
a.out_port = 7;
fail_if(filter_compare(&b, &a) == 0);
/* a matches all ports */
a.out_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a has a in port that does not match packet */
b.in_port = 8;
a.in_port = 7;
fail_if(filter_compare(&b, &a) == 0);
/* a matches all ports */
a.in_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/* a matches port exactly */
a.in_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all out addresses */
b.out_addr = 0x010000a0;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match b via 8-bit netmask */
a.out_addr = 0x000000c0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) == 0);
/* a does not match b at all*/
a.out_addr = 0x020000b0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b via 8-bit netmask */
a.out_addr = 0x000000a0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) != 0);
/* a matches b exactly */
a.out_addr = 0x010000a0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all in addresses */
b.in_addr = 0x010000a0;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match b via 8-bit netmask */
a.in_addr = 0x000000c0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) == 0);
/* a does not match b at all*/
a.in_addr = 0x020000b0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b via 8-bit netmask */
a.in_addr = 0x000000a0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) != 0);
/* a matches b exactly */
a.in_addr = 0x010000a0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all protocols */
b.proto = 4u;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match protocol */
a.proto = 5u;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b's protocol */
a.proto = b.proto;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all devices */
b.fdev = (struct pico_device *)&b;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match device */
a.fdev = (struct pico_device *)&a;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b's device */
a.fdev = b.fdev;
fail_if(filter_compare(&b, &a) != 0);
/*********** TEST ADD FILTER **************/
/*
uint32_t pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto,
struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask,
struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask,
uint16_t out_port, uint16_t in_port, int8_t priority,
uint8_t tos, enum filter_action action)
*/
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, MAX_PRIORITY + 1, 0, FILTER_DROP);
fail_if(r > 0);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, MIN_PRIORITY - 1, 0, FILTER_PRIORITY);
fail_if(r > 0);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, FILTER_COUNT);
fail_if(r > 0);
#ifdef FAULTY
pico_set_mm_failure(1);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, FILTER_DROP);
fail_if(r > 0);
fail_if(pico_err != PICO_ERR_ENOMEM);
#endif
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("IPfilter module");
TCase *TCase_ipfilter = tcase_create("Unit test for ipfilter");
tcase_add_test(TCase_ipfilter, tc_ipfilter);
suite_add_tcase(s, TCase_ipfilter);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,289 @@
#include "pico_config.h"
#include "pico_tree.h"
#include "pico_ipv6_nd.h"
#include "pico_icmp6.h"
#include "pico_ipv6.h"
#include "pico_stack.h"
#include "pico_device.h"
#include "pico_eth.h"
#include "pico_addressing.h"
#include "modules/pico_ipv6_nd.c"
#include "check.h"
#ifdef PICO_SUPPORT_IPV6
#undef PICO_TIME
#undef PICO_TIME_MS
#define PICO_TIME_MS (0)
#define PICO_TIME (0)
Suite *pico_suite(void);
START_TEST(tc_pico_nd_new_expire_time)
{
struct pico_ipv6_neighbor n = {
0
};
struct pico_device d = { {0} };
/* TODO: how to test these time values */
n.dev = &d;
d.hostvars.retranstime = 666;
n.state = PICO_ND_STATE_INCOMPLETE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_REACHABLE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_STALE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_PROBE;
pico_nd_new_expire_time(&n);
}
END_TEST
START_TEST(tc_pico_nd_queue)
{
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
int i;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *) f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
fail_if(!f);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
pico_ipv6_nd_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
pico_ipv6_nd_postpone(f);
fail_if(frames_queued_v6[0]->buffer != f->buffer);
pico_ipv6_nd_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
}
END_TEST
START_TEST(tc_pico_nd_discover)
{
/* TODO: test this: static void pico_nd_discover(struct pico_ipv6_neighbor *n) */
}
END_TEST
START_TEST(tc_neigh_options)
{
/* TODO: test this: static int neigh_options(struct pico_frame *f, struct pico_icmp6_opt_lladdr *opt, uint8_t expected_opt) */
}
END_TEST
START_TEST(tc_neigh_adv_complete)
{
/* TODO: test this: static int neigh_adv_complete(struct pico_ipv6_neighbor *n, struct pico_icmp6_opt_lladdr *opt) */
}
END_TEST
START_TEST(tc_neigh_adv_reconfirm_router_option)
{
/* TODO: test this: static void neigh_adv_reconfirm_router_option(struct pico_ipv6_neighbor *n, unsigned int isRouter) */
}
END_TEST
START_TEST(tc_neigh_adv_reconfirm)
{
/* TODO: test this: static int neigh_adv_reconfirm(struct pico_ipv6_neighbor *n, struct pico_icmp6_opt_lladdr *opt, struct pico_icmp6_hdr *hdr) */
}
END_TEST
START_TEST(tc_neigh_adv_check_solicited)
{
/* TODO: test this: static void neigh_adv_check_solicited(struct pico_icmp6_hdr *ic6, struct pico_ipv6_neighbor *n) */
}
END_TEST
START_TEST(tc_neigh_adv_process)
{
/* TODO: test this: static int neigh_adv_process(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ipv6_neighbor)
{
/* TODO: test this: static struct pico_ipv6_neighbor *neighbor_from_sol_new(struct pico_ip6 *ip, struct pico_icmp6_opt_lladdr *opt, struct pico_device *dev) */
}
END_TEST
START_TEST(tc_neighbor_from_sol)
{
/* TODO: test this: static void neighbor_from_sol(struct pico_ip6 *ip, struct pico_icmp6_opt_lladdr *opt, struct pico_device *dev) */
}
END_TEST
START_TEST(tc_neigh_sol_process)
{
/* TODO: test this: static int neigh_sol_process(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_icmp6_initial_checks)
{
/* TODO: test this: static int icmp6_initial_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_mcast_validity_checks)
{
/* TODO: test this: static int neigh_adv_mcast_validity_check(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_sol_mcast_validity_checks)
{
/* TODO: test this: static int neigh_sol_mcast_validity_check(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_validity_checks)
{
/* TODO: test this: static int neigh_adv_validity_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_sol_validity_checks)
{
/* TODO: test this: static int neigh_sol_validity_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_checks)
{
/* TODO: test this: static int neigh_adv_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_router_sol_recv)
{
/* TODO: test this: static int pico_nd_router_sol_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_router_adv_recv)
{
/* TODO: test this: static int pico_nd_router_adv_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_neigh_sol_recv)
{
/* TODO: test this: static int pico_nd_neigh_sol_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_neigh_adv_recv)
{
/* TODO: test this: static int pico_nd_neigh_adv_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_redirect_recv)
{
/* TODO: test this: static int pico_nd_redirect_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ipv6_nd_timer_callback)
{
/* TODO: test this: static void pico_ipv6_nd_timer_callback(pico_time now, void *arg) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_nd_new_expire_time = tcase_create("Unit test for pico_nd_new_expire_time");
TCase *TCase_pico_nd_discover = tcase_create("Unit test for pico_nd_discover");
TCase *TCase_neigh_options = tcase_create("Unit test for neigh_options");
TCase *TCase_neigh_adv_complete = tcase_create("Unit test for neigh_adv_complete");
TCase *TCase_neigh_adv_reconfirm_router_option = tcase_create("Unit test for neigh_adv_reconfirm_router_option");
TCase *TCase_neigh_adv_reconfirm = tcase_create("Unit test for neigh_adv_reconfirm");
TCase *TCase_neigh_adv_check_solicited = tcase_create("Unit test for neigh_adv_check_solicited");
TCase *TCase_neigh_adv_process = tcase_create("Unit test for neigh_adv_process");
TCase *TCase_pico_ipv6_neighbor = tcase_create("Unit test for pico_ipv6_neighbor");
TCase *TCase_neighbor_from_sol = tcase_create("Unit test for neighbor_from_sol");
TCase *TCase_neigh_sol_process = tcase_create("Unit test for neigh_sol_process");
TCase *TCase_icmp6_initial_checks = tcase_create("Unit test for icmp6_initial_checks");
TCase *TCase_neigh_sol_mcast_validity_checks = tcase_create("Unit test for neigh_sol_mcast_validity_checks");
TCase *TCase_neigh_sol_validity_checks = tcase_create("Unit test for neigh_sol_validity_checks");
TCase *TCase_neigh_adv_checks = tcase_create("Unit test for neigh_adv_checks");
TCase *TCase_neigh_adv_validity_checks = tcase_create("Unit test for neigh_adv_validity_checks");
TCase *TCase_neigh_adv_mcast_validity_checks = tcase_create("Unit test for neigh_adv_mcast_validity_checks");
TCase *TCase_pico_nd_router_sol_recv = tcase_create("Unit test for pico_nd_router_sol_recv");
TCase *TCase_pico_nd_router_adv_recv = tcase_create("Unit test for pico_nd_router_adv_recv");
TCase *TCase_pico_nd_neigh_sol_recv = tcase_create("Unit test for pico_nd_neigh_sol_recv");
TCase *TCase_pico_nd_neigh_adv_recv = tcase_create("Unit test for pico_nd_neigh_adv_recv");
TCase *TCase_pico_nd_redirect_recv = tcase_create("Unit test for pico_nd_redirect_recv");
TCase *TCase_pico_ipv6_nd_timer_callback = tcase_create("Unit test for pico_ipv6_nd_timer_callback");
TCase *TCase_pico_nd_queue = tcase_create("Unit test for pico_ipv6_nd: queue for pending frames");
tcase_add_test(TCase_pico_nd_new_expire_time, tc_pico_nd_new_expire_time);
suite_add_tcase(s, TCase_pico_nd_new_expire_time);
tcase_add_test(TCase_pico_nd_discover, tc_pico_nd_discover);
suite_add_tcase(s, TCase_pico_nd_discover);
tcase_add_test(TCase_neigh_options, tc_neigh_options);
suite_add_tcase(s, TCase_neigh_options);
tcase_add_test(TCase_neigh_adv_complete, tc_neigh_adv_complete);
suite_add_tcase(s, TCase_neigh_adv_complete);
tcase_add_test(TCase_neigh_adv_reconfirm_router_option, tc_neigh_adv_reconfirm_router_option);
suite_add_tcase(s, TCase_neigh_adv_reconfirm_router_option);
tcase_add_test(TCase_neigh_adv_reconfirm, tc_neigh_adv_reconfirm);
suite_add_tcase(s, TCase_neigh_adv_reconfirm);
tcase_add_test(TCase_neigh_adv_check_solicited, tc_neigh_adv_check_solicited);
suite_add_tcase(s, TCase_neigh_adv_check_solicited);
tcase_add_test(TCase_neigh_adv_process, tc_neigh_adv_process);
suite_add_tcase(s, TCase_neigh_adv_process);
tcase_add_test(TCase_pico_ipv6_neighbor, tc_pico_ipv6_neighbor);
suite_add_tcase(s, TCase_pico_ipv6_neighbor);
tcase_add_test(TCase_neighbor_from_sol, tc_neighbor_from_sol);
suite_add_tcase(s, TCase_neighbor_from_sol);
tcase_add_test(TCase_neigh_sol_process, tc_neigh_sol_process);
suite_add_tcase(s, TCase_neigh_sol_process);
tcase_add_test(TCase_icmp6_initial_checks, tc_icmp6_initial_checks);
suite_add_tcase(s, TCase_icmp6_initial_checks);
tcase_add_test(TCase_neigh_adv_mcast_validity_checks, tc_neigh_adv_mcast_validity_checks);
suite_add_tcase(s, TCase_neigh_adv_mcast_validity_checks);
tcase_add_test(TCase_neigh_sol_mcast_validity_checks, tc_neigh_sol_mcast_validity_checks);
suite_add_tcase(s, TCase_neigh_sol_mcast_validity_checks);
tcase_add_test(TCase_neigh_adv_validity_checks, tc_neigh_adv_validity_checks);
suite_add_tcase(s, TCase_neigh_adv_validity_checks);
tcase_add_test(TCase_neigh_sol_validity_checks, tc_neigh_sol_validity_checks);
suite_add_tcase(s, TCase_neigh_sol_validity_checks);
tcase_add_test(TCase_neigh_adv_checks, tc_neigh_adv_checks);
suite_add_tcase(s, TCase_neigh_adv_checks);
tcase_add_test(TCase_pico_nd_router_sol_recv, tc_pico_nd_router_sol_recv);
suite_add_tcase(s, TCase_pico_nd_router_sol_recv);
tcase_add_test(TCase_pico_nd_router_adv_recv, tc_pico_nd_router_adv_recv);
suite_add_tcase(s, TCase_pico_nd_router_adv_recv);
tcase_add_test(TCase_pico_nd_neigh_sol_recv, tc_pico_nd_neigh_sol_recv);
suite_add_tcase(s, TCase_pico_nd_neigh_sol_recv);
tcase_add_test(TCase_pico_nd_neigh_adv_recv, tc_pico_nd_neigh_adv_recv);
suite_add_tcase(s, TCase_pico_nd_neigh_adv_recv);
tcase_add_test(TCase_pico_nd_redirect_recv, tc_pico_nd_redirect_recv);
suite_add_tcase(s, TCase_pico_nd_redirect_recv);
tcase_add_test(TCase_pico_ipv6_nd_timer_callback, tc_pico_ipv6_nd_timer_callback);
suite_add_tcase(s, TCase_pico_ipv6_nd_timer_callback);
tcase_add_test(TCase_pico_nd_queue, tc_pico_nd_queue);
suite_add_tcase(s, TCase_pico_nd_queue);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}
#else
int main(void)
{
return 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,584 @@
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_mld.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void mock_callback(struct mld_timer *t);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
void mock_callback(struct mld_timer *t)
{
IGNORE_PARAMETER(t);
}
static int mcast_filter_cmp_ipv6(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6));
}
static int mcast_sources_cmp_ipv6(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6));
}
static PICO_TREE_DECLARE(_MCASTFilter, mcast_filter_cmp_ipv6);
START_TEST(tc_pico_mld_fill_hopbyhop)
{
struct pico_ipv6_hbhoption *hbh = NULL;
/* Not-null case tested by unit_ipv6.c */
fail_if(pico_mld_fill_hopbyhop(hbh) != NULL);
}
END_TEST
START_TEST(tc_pico_mld_check_hopbyhop)
{
struct pico_ipv6_hbhoption *hbh = NULL;
struct pico_ipv6_hbhoption _hbh;
uint8_t *p;
uint8_t options[8] = {
PICO_PROTO_ICMP6, 0, PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT, \
PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT_DATALEN, 0, 0, 1, 0
};
int i = 0;
int test = 0;
fail_if(pico_mld_check_hopbyhop(hbh) != -1);
_hbh.type = 1;
_hbh.len = 0;
fail_if(pico_mld_check_hopbyhop(&_hbh) != -1);
_hbh.type = PICO_PROTO_ICMP6;
_hbh.len = 1;
fail_if(pico_mld_check_hopbyhop(&_hbh) != -1);
hbh = (struct pico_ipv6_hbhoption *) PICO_ZALLOC(sizeof(struct pico_ipv6_hbhoption) + 7);
hbh->type = PICO_PROTO_ICMP6;
hbh->len = 0;
for(test = 0; test < 7; test++) {
p = (uint8_t *)hbh + sizeof(struct pico_ipv6_hbhoption);
for(i = 0; i < 6; i++ ) {
if(i != test)
*(p++) = options[i + 2];
else
*(p++) = 9;
}
if(test != 6)
fail_if(pico_mld_check_hopbyhop(hbh) != -1);
else
fail_if(pico_mld_check_hopbyhop(hbh) != 0);
}
}
END_TEST
START_TEST(tc_pico_mld_v1querier_expired)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct pico_ip6 addr = {{0}};
struct pico_device *dev = pico_null_create("dummy2");
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_frame));
t->f = f;
pico_string_to_ipv6("AAAA::109", addr.addr);
/* void function, just check for side effects */
/* No link */
pico_mld_v1querier_expired(t);
f->dev = dev;
pico_ipv6_link_add(dev, addr, addr);
pico_mld_v1querier_expired(t);
}
END_TEST
START_TEST(tc_pico_mld_send_report)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip6 addr;
struct pico_ipv6_link *link;
struct mcast_parameters p;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
pico_string_to_ipv6("AAAA::110", addr.addr);
p.mcast_link.ip6 = addr;
/* No link */
fail_if(pico_mld_send_report(&p, f) != -1);
link = pico_ipv6_link_add(dev, addr, addr);
p.event = 0;
link->mcast_compatibility = PICO_MLDV1;
fail_if(pico_mld_send_report(&p, f) != 0);
link->mcast_compatibility = 99;
fail_if(pico_mld_send_report(&p, f) != -1);
}
END_TEST
START_TEST(tc_pico_mld_report_expired)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct pico_ip6 zero = {0};
t->mcast_link = zero;
t->mcast_group = zero;
/* void function, just check for side effects */
pico_mld_report_expired(t);
}
END_TEST
START_TEST(tc_pico_mld_delete_parameter)
{
struct mcast_parameters p;
fail_if(pico_mld_delete_parameter(&p) != -1);
}
END_TEST
START_TEST(tc_mldt_type_compare)
{
struct mld_timer a;
struct mld_timer b;
a.type = 1;
b.type = 2;
fail_if(mldt_type_compare(&a, &b) != -1);
fail_if(mldt_type_compare(&b, &a) != 1);
fail_if(mld_timer_cmp(&b, &a) != 1);
}
END_TEST
START_TEST(tc_pico_mld_is_checksum_valid)
{
struct pico_frame *f;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
fail_if(pico_mld_is_checksum_valid(f) == 1);
}
END_TEST
START_TEST(tc_pico_mld_find_parameter)
{
struct pico_ip6 mcast_link, mcast_group;
struct mcast_parameters test = {
0
};
fail_if(pico_mld_find_parameter(NULL, NULL) != NULL);
pico_string_to_ipv6("AAAA::111", mcast_link.addr);
fail_if(pico_mld_find_parameter(&mcast_link, NULL) != NULL);
pico_string_to_ipv6("AAAA::211", mcast_group.addr);
fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) != NULL);
test.mcast_link.ip6 = mcast_link;
test.mcast_group.ip6 = mcast_group;
pico_tree_insert(&MLDParameters, &test);
fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) == NULL);
pico_tree_delete(&MLDParameters, &test);
}
END_TEST
START_TEST(tc_pico_mld_timer_expired)
{
struct mld_timer *t, *s;
t = PICO_ZALLOC(sizeof(struct mld_timer));
t->stopped = MLD_TIMER_STOPPED;
t->type = 0;
pico_string_to_ipv6("AAAA::112", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::112", t->mcast_group.addr);
/* void function, just check for side effects */
pico_mld_timer_expired(0, (void *)t);
pico_tree_insert(&MLDTimers, t);
s = PICO_ZALLOC(sizeof(struct mld_timer));
memcpy(s, t, sizeof(struct mld_timer)); /* t will be freed next test */
pico_mld_timer_expired(0, (void *)t); /* will be freed */
s->stopped++;
s->start = PICO_TIME_MS() * 2;
s->type++;
pico_tree_insert(&MLDTimers, s);
t = PICO_ZALLOC(sizeof(struct mld_timer));
memcpy(t, s, sizeof(struct mld_timer)); /* s will be freed next test */
pico_mld_timer_expired(0, (void *)s); /* s will be freed */
t->mld_callback = mock_callback;
pico_mld_timer_expired(0, (void *)t); /* t will be freed */
}
END_TEST
START_TEST(tc_pico_mld_send_done)
{
struct mcast_parameters p;
fail_if(pico_mld_send_done(&p, NULL) != 0);
}
END_TEST
START_TEST(tc_mld_stsdifs)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::113", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(mld_stsdifs(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* no timer */
fail_if(mld_stsdifs(p) != -1);
t->type = MLD_TIMER_GROUP_REPORT;
t->mcast_link = p->mcast_link.ip6;
t->mcast_group = p->mcast_group.ip6;
pico_tree_insert(&MLDTimers, t);
fail_if(mld_stsdifs(p) != 0);
/* set flag */
pico_mld_flag = 1;
fail_if(mld_stsdifs(p) != 0);
}
END_TEST
START_TEST(tc_mld_srsf)
{
struct mcast_parameters *p;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::114", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
fail_if(mld_srsf(p) != -1);
}
END_TEST
START_TEST(tc_mld_srst)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
struct pico_mcast_group g;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::99", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = 0;
g.filter_mode = 0;
g.mcast_addr = p->mcast_group;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp_ipv6;
pico_tree_insert(&MLDParameters, p);
/* no link */
fail_if(mld_srst(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* invalid proto */
fail_if(mld_srst(p) != -1);
link->mcast_compatibility = PICO_MLDV2;
pico_tree_insert(link->MCASTGroups, &g);
fail_if(mld_srst(p) != 0);
pico_tree_delete(&MLDParameters, p);
}
END_TEST
START_TEST(tc_mld_mrsrrt)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::115", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(mld_mrsrrt(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* wrong proto */
fail_if(mld_mrsrrt(p) != -1);
link->mcast_compatibility = PICO_MLDV2;
p->f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
fail_if(mld_mrsrrt(p) != -1);
}
END_TEST
START_TEST(tc_pico_mld_process_in)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
uint8_t i, j, _i, _j;
int result = 0;
struct pico_mcast_group g;
struct mldv2_report *report;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::101", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(pico_mld_generate_report(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
pico_string_to_ipv6("AAAA::100", p->mcast_group.ip6.addr);
fail_if(pico_mld_generate_report(p) != -1);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
link->mcast_compatibility = PICO_MLDV1;
g.mcast_addr = p->mcast_group;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp_ipv6;
/* No mcastsources tree */
link->mcast_compatibility = PICO_MLDV2;
fail_if(pico_mld_generate_report(p) != -1);
pico_tree_insert(link->MCASTGroups, &g);
pico_tree_insert(&MLDParameters, p);
link->mcast_compatibility = 99;
fail_if(pico_mld_generate_report(p) != -1);
link->mcast_compatibility = PICO_MLDV1;
fail_if(pico_mld_generate_report(p) != 0);
link->mcast_compatibility = PICO_MLDV2;
for(_j = 0; _j < 3; _j++) { /* FILTER */
(_j == 2) ? (result = -1) : (result = 0);
for(_i = 0; _i < 3; _i++) { /* FILTER */
if(_i == 2) result = -1;
for(i = 0; i < 3; i++) { /* STATES */
for(j = 0; j < 6; j++) { /* EVENTS */
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = _i;
g.filter_mode = _j;
if(p->event == MLD_EVENT_DELETE_GROUP || p->event == MLD_EVENT_QUERY_RECV)
p->event++;
fail_if(pico_mld_generate_report(p) != result);
p->state = i;
p->event = j;
if(result != -1 && p->f) { /* in some combinations, no frame is created */
report = (struct mldv2_report *)(p->f->transport_hdr + MLD_ROUTER_ALERT_LEN);
report->crc = short_be(pico_icmp6_checksum(p->f));
fail_if(pico_mld_process_in(p->f) != 0);
}
}
}
}
}
pico_tree_delete(&MLDParameters, p);
}
END_TEST
START_TEST(tc_mld_rtimrtct)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::102", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::102", t->mcast_group.addr);
p.mcast_link.ip6 = t->mcast_link;
p.mcast_group.ip6 = t->mcast_group;
t->type = MLD_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(mld_rtimrtct(&p) != -1);
pico_mld_timer_start(t);
fail_if(mld_rtimrtct(&p) != 0);
}
END_TEST
START_TEST(tc_mld_stcl)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::103", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::103", t->mcast_group.addr);
p.mcast_link.ip6 = t->mcast_link;
p.mcast_group.ip6 = t->mcast_group;
t->type = MLD_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(mld_stcl(&p) != -1);
pico_mld_timer_start(t);
fail_if(mld_stcl(&p) != 0);
}
END_TEST
START_TEST(tc_pico_mld_compatibility_mode)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip6 addr;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
pico_string_to_ipv6("AAAA::104", addr.addr);
/* No link */
fail_if(pico_mld_compatibility_mode(f) != -1);
pico_ipv6_link_add(dev, addr, addr);
f->dev = dev;
/* MLDv2 query */
f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) != 0);
/* MLDv1 query */
f->buffer_len = 24 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) != 0);
/* Invalid Query */
f->buffer_len = 25 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) == 0);
/* MLDv2 query + timer amready running */
f->dev = dev;
f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN + PICO_SIZE_ETHHDR;
fail_if(pico_mld_compatibility_mode(f) != -1);
}
END_TEST
START_TEST(tc_pico_mld_timer_reset)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
pico_string_to_ipv6("AAAA::105", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::105", t->mcast_group.addr);
t->type = 0;
fail_if(pico_mld_timer_reset(t) != -1);
}
END_TEST
START_TEST(tc_pico_mld_state_change)
{
struct pico_ip6 mcast_link, mcast_group;
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::106", mcast_link.addr);
pico_string_to_ipv6("AAAA::106", mcast_group.addr);
p.mcast_link.ip6 = mcast_link;
p.mcast_group.ip6 = mcast_group;
fail_if(pico_mld_state_change(NULL, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != -1);
/* All host group */
pico_string_to_ipv6("FF01:0:0:0:0:0:0:1", mcast_group.addr);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != 0);
pico_string_to_ipv6("AAAA::107", mcast_group.addr);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
pico_tree_insert(&MLDParameters, &p);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
pico_tree_delete(&MLDParameters, &p);
}
END_TEST
START_TEST(tc_pico_mld_analyse_packet)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ip6 addr;
struct pico_ip6 local;
struct pico_ipv6_hdr *ip6;
struct pico_ipv6_hbhoption *hbh;
struct pico_icmp6_hdr *mld;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mld_message) + MLD_ROUTER_ALERT_LEN);
pico_string_to_ipv6("AAAA::108", addr.addr);
pico_string_to_ipv6("FE80::1", local.addr);
/* No link */
fail_if(pico_mld_analyse_packet(f) != NULL);
pico_ipv6_link_add(dev, addr, addr);
ip6 = (struct pico_ipv6_hdr *) f->net_hdr;
ip6->hop = 99;
/* Incorrect hop */
fail_if(pico_mld_analyse_packet(f) != NULL);
ip6->hop = 1;
hbh = (struct pico_ipv6_hbhoption *) f->transport_hdr;
pico_mld_fill_hopbyhop(hbh);
hbh->type = 99;
/* incorrect hop by hop */
fail_if(pico_mld_analyse_packet(f) != NULL);
pico_mld_fill_hopbyhop(hbh);
ip6->src = addr;
/* Not link local */
fail_if(pico_mld_analyse_packet(f) != NULL);
memcpy(&ip6->src, PICO_IP6_ANY, sizeof(struct pico_ip6));
fail_if(pico_mld_analyse_packet(f) != NULL);
ip6->src = local;
mld = (struct pico_icmp6_hdr *) (f->transport_hdr + MLD_ROUTER_ALERT_LEN);
mld->type = 0;
/* wrong type */
fail_if(pico_mld_analyse_packet(f) != NULL);
/* all correct */
mld->type = PICO_MLD_QUERY;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_REPORT;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_DONE;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_REPORTV2;
fail_if(pico_mld_analyse_packet(f) == NULL);
}
END_TEST
START_TEST(tc_pico_mld_discard)
{
mld_discard(NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_mld_fill_hopbyhop = tcase_create("Unit test for pico_mld_fill_hopbyhop");
TCase *TCase_pico_mld_check_hopbyhop = tcase_create("Unit test for pico_mld_check_hopbyhop");
TCase *TCase_pico_mld_report_expired = tcase_create("Unit test for pico_mld_report_expired");
TCase *TCase_mldt_type_compare = tcase_create("Unit test for mldt_type_compare");
TCase *TCase_pico_mld_analyse_packet = tcase_create("Unit test for pico_mld_analyse_packet");
TCase *TCase_pico_mld_discard = tcase_create("Unit test for pico_mld_discard");
TCase *TCase_pico_mld_compatibility_mode = tcase_create("Unit test for pico_mld_compatibility");
TCase *TCase_pico_mld_v1querier_expired = tcase_create("Unit test for pico_mld_v1querier_expired");
TCase *TCase_pico_mld_delete_parameter = tcase_create("Unit test for pico_mld_delete_parameter");
TCase *TCase_pico_mld_timer_expired = tcase_create("Unit test for pico_mld_timer_expired");
TCase *TCase_pico_mld_timer_reset = tcase_create("Unit test for pico_mld_timer_reset");
TCase *TCase_pico_mld_send_done = tcase_create("Unit test for pico_mld_send_done");
TCase *TCase_pico_mld_is_checksum_valid = tcase_create("Unit test for pico_mld_is_checksum");
TCase *TCase_pico_mld_find_parameter = tcase_create("Unit test for pico_mld_find_parameter");
TCase *TCase_pico_mld_state_change = tcase_create("Unit test for pico_mld_state_change");
TCase *TCase_mld_srst = tcase_create("Unit test for pico_mld_srst");
TCase *TCase_mld_stcl = tcase_create("Unit test for pico_mld_stcl");
TCase *TCase_pico_mld_process_in = tcase_create("Unit test for pico_mld_process_in");
TCase *TCase_pico_mld_send_report = tcase_create("Unit test for pico_mld_send_report");
TCase *TCase_mld_stsdifs = tcase_create("Unit test for mld_stsdifs");
TCase *TCase_mld_srsf = tcase_create("Unit test for mld_srsf");
TCase *TCase_mld_rtimrtct = tcase_create("Unit test for mld_rtimrtct");
TCase *TCase_mld_mrsrrt = tcase_create("Unit test for mld_mrsrrt");
tcase_add_test(TCase_pico_mld_fill_hopbyhop, tc_pico_mld_fill_hopbyhop);
suite_add_tcase(s, TCase_pico_mld_fill_hopbyhop);
tcase_add_test(TCase_pico_mld_check_hopbyhop, tc_pico_mld_check_hopbyhop);
suite_add_tcase(s, TCase_pico_mld_check_hopbyhop);
tcase_add_test(TCase_pico_mld_report_expired, tc_pico_mld_report_expired);
suite_add_tcase(s, TCase_pico_mld_report_expired);
tcase_add_test(TCase_mldt_type_compare, tc_mldt_type_compare);
suite_add_tcase(s, TCase_mldt_type_compare);
tcase_add_test(TCase_pico_mld_analyse_packet, tc_pico_mld_analyse_packet);
suite_add_tcase(s, TCase_pico_mld_analyse_packet);
tcase_add_test(TCase_pico_mld_discard, tc_pico_mld_discard);
suite_add_tcase(s, TCase_pico_mld_discard);
tcase_add_test(TCase_pico_mld_compatibility_mode, tc_pico_mld_compatibility_mode);
suite_add_tcase(s, TCase_pico_mld_compatibility_mode);
tcase_add_test(TCase_pico_mld_v1querier_expired, tc_pico_mld_v1querier_expired);
suite_add_tcase(s, TCase_pico_mld_v1querier_expired);
tcase_add_test(TCase_pico_mld_delete_parameter, tc_pico_mld_delete_parameter);
suite_add_tcase(s, TCase_pico_mld_delete_parameter);
tcase_add_test(TCase_pico_mld_timer_expired, tc_pico_mld_timer_expired);
suite_add_tcase(s, TCase_pico_mld_timer_expired);
tcase_add_test(TCase_pico_mld_timer_reset, tc_pico_mld_timer_reset);
suite_add_tcase(s, TCase_pico_mld_timer_reset);
tcase_add_test(TCase_pico_mld_send_done, tc_pico_mld_send_done);
suite_add_tcase(s, TCase_pico_mld_send_done);
tcase_add_test(TCase_pico_mld_is_checksum_valid, tc_pico_mld_is_checksum_valid);
suite_add_tcase(s, TCase_pico_mld_is_checksum_valid);
tcase_add_test(TCase_pico_mld_find_parameter, tc_pico_mld_find_parameter);
suite_add_tcase(s, TCase_pico_mld_find_parameter);
tcase_add_test(TCase_pico_mld_state_change, tc_pico_mld_state_change);
suite_add_tcase(s, TCase_pico_mld_state_change);
tcase_add_test(TCase_mld_srst, tc_mld_srst);
suite_add_tcase(s, TCase_mld_srst);
tcase_add_test(TCase_mld_stcl, tc_mld_stcl);
suite_add_tcase(s, TCase_mld_stcl);
tcase_add_test(TCase_pico_mld_process_in, tc_pico_mld_process_in);
suite_add_tcase(s, TCase_pico_mld_process_in);
tcase_add_test(TCase_pico_mld_send_report, tc_pico_mld_send_report);
suite_add_tcase(s, TCase_pico_mld_send_report);
tcase_add_test(TCase_mld_stsdifs, tc_mld_stsdifs);
suite_add_tcase(s, TCase_mld_stsdifs);
tcase_add_test(TCase_mld_srsf, tc_mld_srsf);
suite_add_tcase(s, TCase_mld_srsf);
tcase_add_test(TCase_mld_rtimrtct, tc_mld_rtimrtct);
suite_add_tcase(s, TCase_mld_rtimrtct);
tcase_add_test(TCase_mld_mrsrrt, tc_mld_mrsrrt);
suite_add_tcase(s, TCase_mld_mrsrrt);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,229 @@
#include "pico_protocol.h"
#include "pico_tree.h"
#include "stack/pico_protocol.c"
#include "check.h"
Suite *pico_suite(void);
volatile pico_err_t pico_err = 0;
static int protocol_passby = 0;
static struct pico_frame f = {
.next = NULL
};
static struct pico_queue q = {
0
};
static struct pico_tree_node NODE_IN = {
0
};
static struct pico_tree_node NODE_OUT = {
0
};
#define KEY_IN 0x0D01
#define KEY_OUT 0x0D00
START_TEST(tc_pico_proto_cmp)
{
struct pico_protocol a = {
.hash = 0
};
struct pico_protocol b = {
.hash = 1
};
fail_if(pico_proto_cmp(&a, &b) >= 0);
a.hash = 1;
fail_if(pico_proto_cmp(&a, &b) != 0);
a.hash = 2;
fail_if(pico_proto_cmp(&a, &b) <= 0);
}
END_TEST
static int modunit_proto_loop_cb_in(struct pico_protocol *self, struct pico_frame *p)
{
if (!p)
protocol_passby = -1; /* Error! */
if (!self)
protocol_passby = -1; /* Error! */
if (protocol_passby != 0) /* Ensure that we are called only once. */
protocol_passby = -1;
protocol_passby = KEY_IN;
return 1; /* One frame processed! */
}
static int modunit_proto_loop_cb_out(struct pico_protocol *self, struct pico_frame *p)
{
if (!p)
protocol_passby = -1; /* Error! */
if (!self)
protocol_passby = -1; /* Error! */
if (protocol_passby != 0) /* Ensure that we are called only once. */
protocol_passby = -1;
protocol_passby = KEY_OUT;
return 1; /* One frame processed! */
}
START_TEST(tc_proto_loop_in)
{
struct pico_protocol p = {
.process_in = modunit_proto_loop_cb_in, .q_in = &q
};
protocol_passby = 0;
pico_enqueue(p.q_in, &f);
fail_if(proto_loop_in(&p, 1) != 0);
fail_if(protocol_passby != KEY_IN);
/* Try to dequeue from empty queue, get same loop_score */
protocol_passby = 0;
fail_if(proto_loop_in(&p, 1) != 1);
fail_if(protocol_passby != 0);
}
END_TEST
START_TEST(tc_proto_loop_out)
{
struct pico_protocol p = {
.process_out = modunit_proto_loop_cb_out, .q_out = &q
};
protocol_passby = 0;
pico_enqueue(p.q_out, &f);
fail_if(proto_loop_out(&p, 1) != 0);
fail_if(protocol_passby != KEY_OUT);
/* Try to dequeue from empty queue, get same loop_score */
protocol_passby = 0;
fail_if(proto_loop_out(&p, 1) != 1);
fail_if(protocol_passby != 0);
}
END_TEST
START_TEST(tc_proto_loop)
{
struct pico_protocol p = {
.process_in = modunit_proto_loop_cb_in,
.process_out = modunit_proto_loop_cb_out,
.q_in = &q,
.q_out = &q
};
protocol_passby = 0;
pico_enqueue(p.q_in, &f);
fail_if(proto_loop(&p, 1, PICO_LOOP_DIR_IN) != 0);
fail_if(protocol_passby != KEY_IN);
protocol_passby = 0;
pico_enqueue(p.q_out, &f);
fail_if(proto_loop(&p, 1, PICO_LOOP_DIR_OUT) != 0);
fail_if(protocol_passby != KEY_OUT);
}
END_TEST
START_TEST(tc_pico_tree_node)
{
struct pico_proto_rr rr = {
0
};
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
fail_unless(roundrobin_init(&rr, PICO_LOOP_DIR_IN) == &NODE_IN);
fail_unless(roundrobin_init(&rr, PICO_LOOP_DIR_OUT) == &NODE_OUT);
}
END_TEST
START_TEST(tc_roundrobin_end)
{
struct pico_proto_rr rr;
roundrobin_end(&rr, PICO_LOOP_DIR_IN, &NODE_IN);
fail_if(rr.node_in != &NODE_IN);
roundrobin_end(&rr, PICO_LOOP_DIR_OUT, &NODE_OUT);
fail_if(rr.node_out != &NODE_OUT);
}
END_TEST
START_TEST(tc_pico_protocol_generic_loop)
{
struct pico_proto_rr rr = {
0
};
int ret = 0;
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
ret = pico_protocol_generic_loop(&rr, 0, PICO_LOOP_DIR_IN);
fail_if(ret != 0);
pico_protocols_loop(0);
}
END_TEST
START_TEST(tc_proto_layer_rr_reset)
{
struct pico_proto_rr rr;
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
proto_layer_rr_reset(&rr);
fail_if(rr.node_in != NULL);
fail_if(rr.node_out != NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico_protocol.c");
TCase *TCase_pico_proto_cmp = tcase_create("Unit test for pico_proto_cmp");
TCase *TCase_proto_loop_in = tcase_create("Unit test for proto_loop_in");
TCase *TCase_proto_loop_out = tcase_create("Unit test for proto_loop_out");
TCase *TCase_proto_loop = tcase_create("Unit test for proto_loop");
TCase *TCase_pico_tree_node = tcase_create("Unit test for pico_tree_node");
TCase *TCase_roundrobin_end = tcase_create("Unit test for roundrobin_end");
TCase *TCase_pico_protocol_generic_loop = tcase_create("Unit test for pico_protocol_generic_loop");
TCase *TCase_proto_layer_rr_reset = tcase_create("Unit test for proto_layer_rr_reset");
tcase_add_test(TCase_pico_proto_cmp, tc_pico_proto_cmp);
suite_add_tcase(s, TCase_pico_proto_cmp);
tcase_add_test(TCase_proto_loop_in, tc_proto_loop_in);
suite_add_tcase(s, TCase_proto_loop_in);
tcase_add_test(TCase_proto_loop_out, tc_proto_loop_out);
suite_add_tcase(s, TCase_proto_loop_out);
tcase_add_test(TCase_proto_loop, tc_proto_loop);
suite_add_tcase(s, TCase_proto_loop);
tcase_add_test(TCase_pico_tree_node, tc_pico_tree_node);
suite_add_tcase(s, TCase_pico_tree_node);
tcase_add_test(TCase_roundrobin_end, tc_roundrobin_end);
suite_add_tcase(s, TCase_roundrobin_end);
tcase_add_test(TCase_pico_protocol_generic_loop, tc_pico_protocol_generic_loop);
suite_add_tcase(s, TCase_pico_protocol_generic_loop);
tcase_add_test(TCase_proto_layer_rr_reset, tc_proto_layer_rr_reset);
suite_add_tcase(s, TCase_proto_layer_rr_reset);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,428 @@
#include "pico_sntp_client.h"
#include "modules/pico_sntp_client.c"
#include "check.h"
#include "pico_socket.h"
/* Mocking functions, variables, ... */
volatile pico_time pico_tick = 0ull;
volatile pico_err_t pico_err = 0;
Suite *pico_suite(void);
void cb_synced(pico_err_t status);
/* Used in pico_sntp_sync_start */
struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s))
{
struct pico_socket *sock = PICO_ZALLOC(sizeof(struct pico_socket));
(void) net;
(void) proto;
(void) wakeup;
fail_unless (sock != NULL);
return sock;
}
/* Used in pico_sntp_sync_start */
int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
{
(void) s;
(void) local_addr;
(void) port;
return 0;
}
/* Used in pico_sntp_sync_start */
int pico_socket_close(struct pico_socket *s)
{
(void) s;
return 0;
}
/* Used in pico_sntp_send */
int8_t pico_socket_del(struct pico_socket *s)
{
(void) s;
return 0;
}
/* Used in dnsCallback */
int pico_string_to_ipv4(const char *ipstr, uint32_t *ip)
{
(void) ipstr;
(void) ip;
return 0;
}
/* Used in dnsCallback */
int pico_string_to_ipv6(const char *ipstr, uint8_t *ip)
{
(void) ipstr;
(void) ip;
return 0;
}
/* Used in pico_sntp_sync_start_ipv4 */
int pico_ipv4_to_string(char* ipbuf, const uint32_t ip)
{
(void) ipbuf;
(void) ip;
return 0;
}
/* Used in pico_sntp_sync_start_ipv6 */
int pico_ipv6_to_string(char* ipbuf, const uint8_t ip[PICO_SIZE_IP6])
{
(void) ipbuf;
(void) ip;
return 0;
}
/* Used in pico_sntp_client_wakeup */
int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
{
(void) s;
(void) buf;
(void) len;
(void) orig;
(void) remote_port;
return 0;
}
/* Used in pico_sntp_send */
int pico_socket_sendto(struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port)
{
(void) s;
(void) buf;
(void) len;
(void) dst;
(void) remote_port;
return 0;
}
/* Used in pico_sntp_sync_start_dns_ipv4, not tested */
int pico_dns_client_getaddr(const char *url, void (*callback)(char *ip, void *arg), void *arg)
{
(void) url;
(void) callback;
(void) arg;
return 0;
}
/* Used in pico_sntp_sync_start_dns_ipv6, not tested */
int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *), void *arg)
{
(void) url;
(void) callback;
(void) arg;
return 0;
}
/* Used in pico_sntp_parse */
void cb_synced(pico_err_t status)
{
(void) status;
}
/* Used in pico_sntp_send */
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
(void) expire;
(void) timer;
(void) arg;
return ++timers_added;
}
/* Used in pico_sntp_cleanup */
void pico_timer_cancel(uint32_t t)
{
IGNORE_PARAMETER(t);
}
START_TEST(tc_timestamp_convert)
{
struct pico_sntp_ts ts;
struct pico_timeval tv;
pico_time delay = 0ull;
int ret = 0;
/* Input is all zero */
ts.sec = long_be(0ul);
ts.frac = long_be(0ul);
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == -1);
ck_assert(tv.tv_sec == 0);
ck_assert(tv.tv_msec == 0);
/* Minimum input*/
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(4310344ul); /* MIN value: 1msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000000);
fail_unless(tv.tv_msec == 1);
/* Intermediate input */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(3865470566ul); /* value: 899msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000000);
fail_unless(tv.tv_msec == 900);
/* Maximum input */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(4294967295ul); /* MAX value: 999msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000001);
fail_unless(tv.tv_msec == 0);
/* Intermediate input with delay */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(3865470566ul); /* value: 899msec */
delay = 200ull;
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000001);
fail_unless(tv.tv_msec == 100);
}
END_TEST
START_TEST(tc_pico_sntp_cleanup)
{
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
pico_sntp_cleanup(ck, PICO_ERR_NOERR);
}
END_TEST
START_TEST(tc_pico_sntp_parse)
{
/* TODO: test this: static void pico_sntp_parse(char *buf, struct sntp_server_ns_cookie *ck) */
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
struct pico_sntp_header header = {
0
};
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
header.mode = 4; /* server mode */
header.vn = 4; /* sntp version 4 */
header.stratum = 1; /* primary reference */
header.trs_ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
header.trs_ts.frac = long_be(3865470566ul); /* value: 899msec */
fail_if(pico_sntp_parse((char *) &header, NULL) == 0);
fail_if(pico_sntp_parse((char *) &header, ck) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_client_wakeup)
{
/* TODO: test this: static void pico_sntp_client_wakeup(uint16_t ev, struct pico_socket *s) */
uint16_t event = PICO_SOCK_EV_ERR;
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
ck->cb_synced = cb_synced;
printf("Started wakeup unit test\n");
pico_sntp_client_wakeup(event, sock);
}
END_TEST
START_TEST(tc_sntp_receive_timeout)
{
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
sntp_receive_timeout(0ull, ck);
}
END_TEST
START_TEST(tc_pico_sntp_send)
{
/* TODO: test this: static void pico_sntp_send(struct pico_socket *sock, union pico_address *dst) */
struct pico_socket sock = {
0
};
union pico_address dst;
struct sntp_server_ns_cookie ck = {
0
};
sock.priv = &ck;
pico_sntp_send(&sock, &dst);
}
END_TEST
START_TEST(tc_dnsCallback)
{
/* TODO: test this: static void dnsCallback(char *ip, void *arg) */
char ip[] = "198.123.30.132";
struct sntp_server_ns_cookie *ck;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
dnsCallback(ip, ck);
}
END_TEST
START_TEST(tc_pico_sntp_sync)
{
const char *sntp_server= "ntp.nasa.gov";
fail_if(pico_sntp_sync(NULL, cb_synced) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync(sntp_server, NULL) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_ip)
{
union pico_address sntp_addr = { .ip4.addr = 0ul };
fail_if(pico_sntp_sync_ip(NULL, cb_synced) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync_ip(&sntp_addr, NULL) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync_ip(&sntp_addr, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start)
{
struct sntp_server_ns_cookie ck = { 0 };
union pico_address sntp_addr = { .ip4.addr= 0ul };
fail_if(pico_sntp_sync_start(&ck, &sntp_addr) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_dns_ipv4)
{
const char *sntp_server = "ntp.nasa.gov";
fail_if(pico_sntp_sync_start_dns_ipv4(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_dns_ipv6)
{
const char *sntp_server = "ntp.nasa.gov";
fail_if(pico_sntp_sync_start_dns_ipv6(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_ipv4)
{
union pico_address sntp_addr = { .ip4.addr = 0};
fail_if(pico_sntp_sync_start_ipv4(&sntp_addr, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_ipv6)
{
union pico_address sntp_addr = { .ip6.addr = { 0 } };
fail_if(pico_sntp_sync_start_ipv6(&sntp_addr, cb_synced) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_timestamp_convert = tcase_create("Unit test for pico_timeval");
TCase *TCase_pico_sntp_cleanup = tcase_create("Unit test for pico_sntp_cleanup");
TCase *TCase_pico_sntp_send = tcase_create("Unit test for pico_sntp_send");
TCase *TCase_pico_sntp_parse = tcase_create("Unit test for pico_sntp_parse");
TCase *TCase_pico_sntp_client_wakeup = tcase_create("Unit test for pico_sntp_client_wakeup");
TCase *TCase_sntp_receive_timeout = tcase_create("Unit test for sntp_receive_timeout");
TCase *TCase_dnsCallback = tcase_create("Unit test for dnsCallback");
TCase *TCase_pico_sntp_sync = tcase_create("Unit test for pico_sntp_sync");
TCase *TCase_pico_sntp_sync_ip = tcase_create("Unit test for pico_sntp_sync_ip");
TCase *TCase_pico_sntp_sync_start = tcase_create("Unit test for pico_sntp_sync_start");
TCase *TCase_pico_sntp_sync_start_dns_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv4");
TCase *TCase_pico_sntp_sync_start_dns_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv6");
TCase *TCase_pico_sntp_sync_start_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_ipv4");
TCase *TCase_pico_sntp_sync_start_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_ipv6");
tcase_add_test(TCase_timestamp_convert, tc_timestamp_convert);
suite_add_tcase(s, TCase_timestamp_convert);
tcase_add_test(TCase_pico_sntp_cleanup, tc_pico_sntp_cleanup);
suite_add_tcase(s, TCase_pico_sntp_cleanup);
tcase_add_test(TCase_pico_sntp_parse, tc_pico_sntp_parse);
suite_add_tcase(s, TCase_pico_sntp_parse);
tcase_add_test(TCase_pico_sntp_client_wakeup, tc_pico_sntp_client_wakeup);
suite_add_tcase(s, TCase_pico_sntp_client_wakeup);
tcase_add_test(TCase_sntp_receive_timeout, tc_sntp_receive_timeout);
suite_add_tcase(s, TCase_sntp_receive_timeout);
tcase_add_test(TCase_pico_sntp_send, tc_pico_sntp_send);
suite_add_tcase(s, TCase_pico_sntp_send);
tcase_add_test(TCase_dnsCallback, tc_dnsCallback);
suite_add_tcase(s, TCase_dnsCallback);
tcase_add_test(TCase_pico_sntp_sync, tc_pico_sntp_sync);
suite_add_tcase(s, TCase_pico_sntp_sync);
tcase_add_test(TCase_pico_sntp_sync_ip, tc_pico_sntp_sync_ip);
suite_add_tcase(s, TCase_pico_sntp_sync_ip);
tcase_add_test(TCase_pico_sntp_sync_start, tc_pico_sntp_sync_start);
suite_add_tcase(s, TCase_pico_sntp_sync_start);
tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv4, tc_pico_sntp_sync_start_dns_ipv4);
suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv4);
tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv6, tc_pico_sntp_sync_start_dns_ipv6);
suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv6);
tcase_add_test(TCase_pico_sntp_sync_start_ipv4, tc_pico_sntp_sync_start_ipv4);
suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv4);
tcase_add_test(TCase_pico_sntp_sync_start_ipv6, tc_pico_sntp_sync_start_ipv6);
suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv6);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,145 @@
#include "pico_config.h"
#include "pico_frame.h"
#include "pico_device.h"
#include "pico_protocol.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_dns_client.h"
#include "pico_eth.h"
#include "pico_arp.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_icmp4.h"
#include "pico_igmp.h"
#include "pico_udp.h"
#include "pico_tcp.h"
#include "pico_socket.h"
#include "heap.h"
#include "stack/pico_stack.c"
#include "check.h"
Suite *pico_suite(void);
void fake_timer(pico_time __attribute__((unused)) now, void __attribute__((unused)) *n);
START_TEST(tc_pico_ll_receive)
{
/* TODO: test this: static int32_t pico_ll_receive(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ll_check_bcast)
{
/* TODO: test this: static void pico_ll_check_bcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_destination_is_bcast)
{
/* TODO: test this: static int destination_is_bcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_destination_is_mcast)
{
/* TODO: test this: static int destination_is_mcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_eth)
{
/* TODO: test this: static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac) */
}
END_TEST
START_TEST(tc_pico_ethsend_local)
{
/* TODO: test this: static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr, int *ret) */
}
END_TEST
START_TEST(tc_pico_ethsend_bcast)
{
/* TODO: test this: static int32_t pico_ethsend_bcast(struct pico_frame *f, int *ret) */
}
END_TEST
START_TEST(tc_pico_ethsend_dispatch)
{
/* TODO: test this: static int32_t pico_ethsend_dispatch(struct pico_frame *f, int *ret) */
}
END_TEST
START_TEST(tc_calc_score)
{
/* TODO: test this: static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret) */
}
END_TEST
#ifdef PICO_FAULTY
void fake_timer(pico_time __attribute__((unused)) now, void __attribute__((unused)) *n)
{
}
#endif
START_TEST(tc_stack_generic)
{
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_stack_init (11)\n");
pico_set_mm_failure(13);
fail_if(pico_stack_init() != -1);
#endif
pico_stack_init();
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_timer_add (1)\n");
pico_set_mm_failure(1);
fail_if(pico_timer_add(0, fake_timer, NULL) != 0);
#endif
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_ll_receive = tcase_create("Unit test for pico_ll_receive");
TCase *TCase_pico_ll_check_bcast = tcase_create("Unit test for pico_ll_check_bcast");
TCase *TCase_destination_is_bcast = tcase_create("Unit test for destination_is_bcast");
TCase *TCase_destination_is_mcast = tcase_create("Unit test for destination_is_mcast");
TCase *TCase_pico_eth = tcase_create("Unit test for pico_eth");
TCase *TCase_pico_ethsend_local = tcase_create("Unit test for pico_ethsend_local");
TCase *TCase_pico_ethsend_bcast = tcase_create("Unit test for pico_ethsend_bcast");
TCase *TCase_pico_ethsend_dispatch = tcase_create("Unit test for pico_ethsend_dispatch");
TCase *TCase_calc_score = tcase_create("Unit test for calc_score");
TCase *TCase_stack_generic = tcase_create("GENERIC stack initialization unit test");
tcase_add_test(TCase_pico_ll_receive, tc_pico_ll_receive);
suite_add_tcase(s, TCase_pico_ll_receive);
tcase_add_test(TCase_pico_ll_check_bcast, tc_pico_ll_check_bcast);
suite_add_tcase(s, TCase_pico_ll_check_bcast);
tcase_add_test(TCase_destination_is_bcast, tc_destination_is_bcast);
suite_add_tcase(s, TCase_destination_is_bcast);
tcase_add_test(TCase_destination_is_mcast, tc_destination_is_mcast);
suite_add_tcase(s, TCase_destination_is_mcast);
tcase_add_test(TCase_pico_eth, tc_pico_eth);
suite_add_tcase(s, TCase_pico_eth);
tcase_add_test(TCase_pico_ethsend_local, tc_pico_ethsend_local);
suite_add_tcase(s, TCase_pico_ethsend_local);
tcase_add_test(TCase_pico_ethsend_bcast, tc_pico_ethsend_bcast);
suite_add_tcase(s, TCase_pico_ethsend_bcast);
tcase_add_test(TCase_pico_ethsend_dispatch, tc_pico_ethsend_dispatch);
suite_add_tcase(s, TCase_pico_ethsend_dispatch);
tcase_add_test(TCase_calc_score, tc_calc_score);
suite_add_tcase(s, TCase_calc_score);
tcase_add_test(TCase_stack_generic, tc_stack_generic);
suite_add_tcase(s, TCase_stack_generic);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,59 @@
#include "modules/pico_strings.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_get_string_terminator_position)
{
char buf[6] = "unit";
get_string_terminator_position(NULL,0);
fail_if(get_string_terminator_position(buf,2) != 0);
fail_if(get_string_terminator_position(buf,6) != &buf[4]);
}
END_TEST
START_TEST(tc_pico_strncasecmp)
{
fail_if(pico_strncasecmp("unit","UNIT",4) != 0);
fail_if(pico_strncasecmp("unit1","UNIT2",5) != -1);
fail_if(pico_strncasecmp("unit2","UNIT1",5) != 1);
}
END_TEST
START_TEST(tc_num2string)
{
char buf[20];
fail_if(num2string(-1,NULL,1) != -1);
fail_if(num2string(1,NULL,1) != -1);
fail_if(num2string(1,buf,1) != -1);
fail_if(num2string(1,buf,3) != 2);
fail_if(num2string(11,buf,3) != 3);
fail_if(num2string(112,buf,4) != 4);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_get_string_terminator_position = tcase_create("Unit test for get_string_terminator_position");
TCase *TCase_num2string = tcase_create("Unit test for num2string");
TCase *TCase_pico_strncasecmp = tcase_create("Unit test for pico_strncasecmp");
tcase_add_test(TCase_get_string_terminator_position, tc_get_string_terminator_position);
suite_add_tcase(s, TCase_get_string_terminator_position);
tcase_add_test(TCase_num2string,tc_num2string);
suite_add_tcase(s, TCase_num2string);
tcase_add_test(TCase_pico_strncasecmp,tc_pico_strncasecmp);
suite_add_tcase(s, TCase_pico_strncasecmp);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,863 @@
#include "pico_tcp.h"
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_tcp.c"
#include "check.h"
Suite *pico_suite(void);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
START_TEST(tc_input_segment_compare)
{
struct tcp_input_segment A = {
.seq = 0xFFFFFFFF
};
struct tcp_input_segment B = {
.seq = 0xFFFFFFFe
};
struct tcp_input_segment a = {
.seq = 0x01
};
struct tcp_input_segment b = {
.seq = 0x02
};
fail_if(input_segment_compare(&A, &B) <= 0);
fail_if(input_segment_compare(&a, &b) >= 0);
fail_if(input_segment_compare(&A, &b) >= 0);
fail_if(input_segment_compare(&A, &A) != 0);
}
END_TEST
START_TEST(tc_tcp_input_segment)
{
/* TODO: test this: static struct tcp_input_segment *segment_from_frame(struct pico_frame *f) */
struct pico_frame *f = pico_frame_alloc(60);
struct tcp_input_segment *seg;
fail_if(!f);
f->payload = f->start;
f->payload_len = 60;
f->transport_hdr = f->payload;
f->transport_len = (uint16_t)(f->payload_len - 40);
memset(f->payload, 'c', f->payload_len);
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xdeadbeef);
seg = segment_from_frame(f);
fail_if(!seg);
fail_if(seg->seq != 0xdeadbeef);
fail_if(seg->payload_len != f->payload_len);
fail_if(memcmp(seg->payload, f->payload, f->payload_len) != 0);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in segment_from_frame (1)\n");
pico_set_mm_failure(1);
seg = segment_from_frame(f);
fail_if(seg);
printf("Testing with faulty memory in segment_from_frame (2)\n");
pico_set_mm_failure(2);
seg = segment_from_frame(f);
fail_if(seg);
#endif
printf("Testing segment_from_frame with empty payload\n");
f->payload_len = 0;
seg = segment_from_frame(f);
fail_if(seg);
}
END_TEST
START_TEST(tc_segment_compare)
{
/* TODO: test this: static int segment_compare(void *ka, void *kb) */
struct pico_frame *a = pico_frame_alloc(40);
struct pico_frame *b = pico_frame_alloc(60);
a->transport_hdr = a->start;
b->transport_hdr = b->start;
((struct pico_tcp_hdr *)((b)->transport_hdr))->seq = long_be(0xaa00);
((struct pico_tcp_hdr *)((a)->transport_hdr))->seq = long_be(0xffffaa00);
fail_if(segment_compare(a, b) >= 0);
fail_if(segment_compare(a, a) != 0);
}
END_TEST
START_TEST(tc_tcp_discard_all_segments)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV4);
struct pico_frame *f = pico_frame_alloc(80);
struct tcp_input_segment *is;
fail_if(!t);
fail_if(!f);
printf("Testing enqueuing bogus frame\n");
f->buffer_len = 0;
fail_if(pico_enqueue_segment(&t->tcpq_out, f) >= 0);
f->buffer_len = 80;
f->transport_hdr = f->start;
f->transport_len = (uint16_t)(f->buffer_len - 40);
f->payload = f->start + 40;
f->payload_len = 40;
memset(f->payload, 'c', f->payload_len);
is = segment_from_frame(f);
fail_if(!is);
is->payload_len = 0;
fail_if(pico_enqueue_segment(&t->tcpq_in, is) >= 0);
is->payload_len = 40;
/* Successfull cases */
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
/* Fail because size exceeded. Must return 0. */
t->tcpq_out.max_size = 50;
t->tcpq_in.max_size = 50;
fail_if(pico_enqueue_segment(&t->tcpq_out, f) != 0);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) != 0);
#ifdef PICO_FAULTY
/* Fail because the tree cannot allocate a new node. Should return 0 */
printf("Testing with faulty memory (1)\n");
pico_set_mm_failure(1);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) > 0);
pico_set_mm_failure(1);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) > 0);
printf("Testing input segment conversion with faulty mm(1)\n");
pico_set_mm_failure(1);
is = segment_from_frame(f);
fail_if(is);
printf("Testing input segment conversion with faulty mm(2)\n");
pico_set_mm_failure(2);
is = segment_from_frame(f);
fail_if(is);
#endif
/* Discard all segments */
fail_if(t->tcpq_out.size == 0);
fail_if(t->tcpq_out.frames == 0);
tcp_discard_all_segments(&t->tcpq_out);
fail_if(t->tcpq_out.size != 0);
fail_if(t->tcpq_out.frames != 0);
fail_if(t->tcpq_in.size == 0);
fail_if(t->tcpq_in.frames == 0);
fail_if(pico_tcp_queue_in_is_empty(&t->sock));
tcp_discard_all_segments(&t->tcpq_in);
fail_if(t->tcpq_in.size != 0);
fail_if(t->tcpq_in.frames != 0);
fail_unless(pico_tcp_queue_in_is_empty(&t->sock));
/* Testing next_segment with NULLS */
fail_if(next_segment(NULL, NULL) != NULL);
}
END_TEST
START_TEST(tc_release_until)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV6);
struct pico_frame *f;
uint32_t i = 0;
int ret = 0;
struct tcp_input_segment *is;
fail_if(!t);
ret = release_until(&t->tcpq_out, 0);
fail_unless(ret == 0);
/* Test with output queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
printf("inserting frame seq = %08x len = %d\n", 0xaa00 + f->buffer_len * i, f->buffer_len);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
}
ret = release_until(&t->tcpq_out, 0xaa00 + f->buffer_len * 30);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test with input queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
f->payload = f->start;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
is = segment_from_frame(f);
fail_if(!is);
printf("inserting Input frame seq = %08x len = %d\n", long_be(is->seq), is->payload_len);
fail_if(!is);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
}
ret = release_until(&t->tcpq_in, 0xaa00 + f->buffer_len * 30);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
}
END_TEST
START_TEST(tc_release_all_until)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV4);
struct pico_frame *f;
uint32_t i = 0;
int ret = 0;
struct tcp_input_segment *is;
pico_time tm;
fail_if(!t);
ret = release_all_until(&t->tcpq_out, 0, &tm);
fail_unless(ret == 0);
/* Test with output queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
printf("inserting frame seq = %08x len = %d\n", 0xaa00 + f->buffer_len * i, f->buffer_len);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
}
ret = release_all_until(&t->tcpq_out, 0xaa00 + f->buffer_len * 30, &tm);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test with input queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
f->payload = f->start;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
is = segment_from_frame(f);
fail_if(!is);
printf("inserting Input frame seq = %08x len = %d\n", long_be(is->seq), is->payload_len);
fail_if(!is);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
}
ret = release_all_until(&t->tcpq_in, 0xaa00 + f->buffer_len * 30, &tm);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test enqueue_segment with NULL segment */
fail_if(pico_enqueue_segment(NULL, NULL) != -1);
}
END_TEST
START_TEST(tc_tcp_send_fin)
{
/* TODO: test this: static void tcp_send_fin(struct pico_socket_tcp *t); */
}
END_TEST
START_TEST(tc_pico_tcp_process_out)
{
/* TODO: test this: static int pico_tcp_process_out(struct pico_protocol *self, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_paws)
{
pico_paws();
/* Nothing to test for a random function...*/
}
END_TEST
START_TEST(tc_tcp_add_options)
{
/* TODO: test this: static void tcp_add_options(struct pico_socket_tcp *ts, struct pico_frame *f, uint16_t flags, uint16_t optsiz) */
struct pico_socket_tcp ts = { };
struct pico_frame *f = pico_frame_alloc(100);
uint16_t flags = 0;
uint16_t optsiz = 50;
uint8_t *frame_opt_buff;
int i;
struct tcp_sack_block *a, *b, *c;
uint32_t al = 0xa0,
ar = 0xaf,
bl = 0xb0,
br = 0xbf,
cl = 0xc0,
cr = 0xcf;
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
frame_opt_buff = f->transport_hdr + PICO_SIZE_TCPHDR;
/* Window scale only */
printf("Testing window scale option\n");
ts.wnd_scale = 66;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[2] != 66);
for (i = 3; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
/* MSS + SACK_OK + WS + TIMESTAMPS */
printf("Testing full SYN options\n");
flags = PICO_TCP_SYN;
ts.wnd_scale = 66;
ts.mss = 0xAA88;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_MSS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_MSS);
fail_if(frame_opt_buff[2] != 0xAA);
fail_if(frame_opt_buff[3] != 0x88);
fail_if(frame_opt_buff[4] != PICO_TCP_OPTION_SACK_OK);
fail_if(frame_opt_buff[5] != PICO_TCPOPTLEN_SACK_OK);
fail_if(frame_opt_buff[6] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[7] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[8] != 66);
fail_if(frame_opt_buff[9] != PICO_TCP_OPTION_TIMESTAMP);
fail_if(frame_opt_buff[10] != PICO_TCPOPTLEN_TIMESTAMP);
/* Timestamps: up to byte 18 */
for (i = 19; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
/* Testing SACKs */
printf("Testing full SACK options\n");
a = PICO_ZALLOC(sizeof (struct tcp_sack_block));
b = PICO_ZALLOC(sizeof (struct tcp_sack_block));
c = PICO_ZALLOC(sizeof (struct tcp_sack_block));
a->left = al;
a->right = ar;
a->next = b;
b->left = bl;
b->right = br;
b->next = c;
c->left = cl;
c->right = cr;
c->next = NULL;
ts.sack_ok = 1;
ts.sacks = a;
flags = PICO_TCP_ACK;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[2] != 66);
fail_if(frame_opt_buff[3] != PICO_TCP_OPTION_SACK);
fail_if(frame_opt_buff[4] != PICO_TCPOPTLEN_SACK + 6 * (sizeof(uint32_t)));
fail_if(memcmp(frame_opt_buff + 5, &al, 4) != 0);
fail_if(memcmp(frame_opt_buff + 9, &ar, 4) != 0);
fail_if(memcmp(frame_opt_buff + 13, &bl, 4) != 0);
fail_if(memcmp(frame_opt_buff + 17, &br, 4) != 0);
fail_if(memcmp(frame_opt_buff + 21, &cl, 4) != 0);
fail_if(memcmp(frame_opt_buff + 25, &cr, 4) != 0);
fail_if(ts.sacks != NULL);
for (i = 29; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
}
END_TEST
START_TEST(tc_tcp_options_size_frame)
{
/* TODO: test this: static uint16_t tcp_options_size_frame(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_add_options_frame)
{
/* TODO: test this: static void tcp_add_options_frame(struct pico_socket_tcp *ts, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_send_ack)
{
/* TODO: test this: static void tcp_send_ack(struct pico_socket_tcp *t); */
}
END_TEST
START_TEST(tc_tcp_set_space)
{
/* TODO: test this: static void tcp_set_space(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_options_size)
{
/* TODO: test this: static uint16_t tcp_options_size(struct pico_socket_tcp *t, uint16_t flags) */
}
END_TEST
START_TEST(tc_tcp_process_sack)
{
/* TODO: test this: static void tcp_process_sack(struct pico_socket_tcp *t, uint32_t start, uint32_t end) */
}
END_TEST
START_TEST(tc_tcp_rcv_sack)
{
/* TODO: test this: static void tcp_rcv_sack(struct pico_socket_tcp *t, uint8_t *opt, int len) */
}
END_TEST
START_TEST(tc_tcp_parse_options)
{
/* TODO: test this: static void tcp_parse_options(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_send)
{
/* TODO: test this: static int tcp_send(struct pico_socket_tcp *ts, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_sock_stats)
{
/* TODO: test this: static void sock_stats(uint32_t when, void *arg) */
}
END_TEST
START_TEST(tc_initconn_retry)
{
/* TODO: test this: static void initconn_retry(pico_time when, void *arg) */
}
END_TEST
START_TEST(tc_tcp_send_synack)
{
/* TODO: test this: static int tcp_send_synack(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_send_empty)
{
/* TODO: test this: static void tcp_send_empty(struct pico_socket_tcp *t, uint16_t flags, int is_keepalive) */
}
END_TEST
START_TEST(tc_tcp_send_probe)
{
/* TODO: test this: static void tcp_send_probe(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_send_rst)
{
/* TODO: test this: static int tcp_send_rst(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_nosync_rst)
{
/* TODO: test this: static int tcp_nosync_rst(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_sack_prepare)
{
/* TODO: test this: static void tcp_sack_prepare(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_data_in)
{
/* TODO: test this: static int tcp_data_in(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack_advance_una)
{
/* TODO: test this: static int tcp_ack_advance_una(struct pico_socket_tcp *t, struct pico_frame *f, pico_time *timestamp) */
}
END_TEST
START_TEST(tc_time_diff)
{
/* TODO: test this: static uint16_t time_diff(pico_time a, pico_time b) */
}
END_TEST
START_TEST(tc_tcp_rtt)
{
/* TODO: test this: static void tcp_rtt(struct pico_socket_tcp *t, uint32_t rtt) */
}
END_TEST
START_TEST(tc_tcp_congestion_control)
{
/* TODO: test this: static void tcp_congestion_control(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_add_retransmission_timer)
{
/* TODO: test this: static void add_retransmission_timer(struct pico_socket_tcp *t, pico_time next_ts); */
}
END_TEST
START_TEST(tc_tcp_first_timeout)
{
/* TODO: test this: static void tcp_first_timeout(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_rto_xmit)
{
/* TODO: test this: static int tcp_rto_xmit(struct pico_socket_tcp *t, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_next_zerowindow_probe)
{
/* TODO: test this: static void tcp_next_zerowindow_probe(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_is_allowed_to_send)
{
/* TODO: test this: static int tcp_is_allowed_to_send(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_retrans_timeout)
{
/* TODO: test this: static void tcp_retrans_timeout(pico_time val, void *sock) */
}
END_TEST
START_TEST(tc_tcp_retrans)
{
/* TODO: test this: static int tcp_retrans(struct pico_socket_tcp *t, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack_dbg)
{
/* TODO: test this: static void tcp_ack_dbg(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack)
{
/* TODO: test this: static int tcp_ack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_finwaitack)
{
/* TODO: test this: static int tcp_finwaitack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_deltcb)
{
/* TODO: test this: static void tcp_deltcb(pico_time when, void *arg) */
}
END_TEST
START_TEST(tc_tcp_finwaitfin)
{
/* TODO: test this: static int tcp_finwaitfin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_closewaitack)
{
/* TODO: test this: static int tcp_closewaitack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_lastackwait)
{
/* TODO: test this: static int tcp_lastackwait(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_syn)
{
/* TODO: test this: static int tcp_syn(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_set_init_point)
{
/* TODO: test this: static void tcp_set_init_point(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_synack)
{
/* TODO: test this: static int tcp_synack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_first_ack)
{
/* TODO: test this: static int tcp_first_ack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_closewait)
{
/* TODO: test this: static int tcp_closewait(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_fin)
{
/* TODO: test this: static int tcp_fin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_rcvfin)
{
/* TODO: test this: static int tcp_rcvfin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_finack)
{
/* TODO: test this: static int tcp_finack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_force_closed)
{
/* TODO: test this: static void tcp_force_closed(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_wakeup_pending)
{
/* TODO: test this: static void tcp_wakeup_pending(struct pico_socket *s, uint16_t ev) */
}
END_TEST
START_TEST(tc_tcp_rst)
{
/* TODO: test this: static int tcp_rst(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_halfopencon)
{
/* TODO: test this: static int tcp_halfopencon(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_closeconn)
{
/* TODO: test this: static int tcp_closeconn(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_invalid_flags)
{
/* TODO: test this: static uint8_t invalid_flags(struct pico_socket *s, uint8_t flags) */
}
END_TEST
START_TEST(tc_checkLocalClosing)
{
/* TODO: test this: static int checkLocalClosing(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_checkRemoteClosing)
{
/* TODO: test this: static int checkRemoteClosing(struct pico_socket *s) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_input_segment_compare = tcase_create("Unit test for input_segment_compare");
TCase *TCase_tcp_input_segment = tcase_create("Unit test for tcp_input_segment");
TCase *TCase_segment_compare = tcase_create("Unit test for segment_compare");
TCase *TCase_tcp_discard_all_segments = tcase_create("Unit test for tcp_discard_all_segments");
TCase *TCase_release_until = tcase_create("Unit test for release_until");
TCase *TCase_release_all_until = tcase_create("Unit test for release_all_until");
TCase *TCase_tcp_send_fin = tcase_create("Unit test for tcp_send_fin");
TCase *TCase_pico_tcp_process_out = tcase_create("Unit test for pico_tcp_process_out");
TCase *TCase_pico_paws = tcase_create("Unit test for pico_paws");
TCase *TCase_tcp_add_options = tcase_create("Unit test for tcp_add_options");
TCase *TCase_tcp_options_size_frame = tcase_create("Unit test for tcp_options_size_frame");
TCase *TCase_tcp_add_options_frame = tcase_create("Unit test for tcp_add_options_frame");
TCase *TCase_tcp_send_ack = tcase_create("Unit test for tcp_send_ack");
TCase *TCase_tcp_set_space = tcase_create("Unit test for tcp_set_space");
TCase *TCase_tcp_options_size = tcase_create("Unit test for tcp_options_size");
TCase *TCase_tcp_process_sack = tcase_create("Unit test for tcp_process_sack");
TCase *TCase_tcp_rcv_sack = tcase_create("Unit test for tcp_rcv_sack");
TCase *TCase_tcp_parse_options = tcase_create("Unit test for tcp_parse_options");
TCase *TCase_tcp_send = tcase_create("Unit test for tcp_send");
TCase *TCase_sock_stats = tcase_create("Unit test for sock_stats");
TCase *TCase_initconn_retry = tcase_create("Unit test for initconn_retry");
TCase *TCase_tcp_send_synack = tcase_create("Unit test for tcp_send_synack");
TCase *TCase_tcp_send_empty = tcase_create("Unit test for tcp_send_empty");
TCase *TCase_tcp_send_probe = tcase_create("Unit test for tcp_send_probe");
TCase *TCase_tcp_send_rst = tcase_create("Unit test for tcp_send_rst");
TCase *TCase_tcp_nosync_rst = tcase_create("Unit test for tcp_nosync_rst");
TCase *TCase_tcp_sack_prepare = tcase_create("Unit test for tcp_sack_prepare");
TCase *TCase_tcp_data_in = tcase_create("Unit test for tcp_data_in");
TCase *TCase_tcp_ack_advance_una = tcase_create("Unit test for tcp_ack_advance_una");
TCase *TCase_time_diff = tcase_create("Unit test for time_diff");
TCase *TCase_tcp_rtt = tcase_create("Unit test for tcp_rtt");
TCase *TCase_tcp_congestion_control = tcase_create("Unit test for tcp_congestion_control");
TCase *TCase_add_retransmission_timer = tcase_create("Unit test for add_retransmission_timer");
TCase *TCase_tcp_first_timeout = tcase_create("Unit test for tcp_first_timeout");
TCase *TCase_tcp_rto_xmit = tcase_create("Unit test for tcp_rto_xmit");
TCase *TCase_tcp_next_zerowindow_probe = tcase_create("Unit test for tcp_next_zerowindow_probe");
TCase *TCase_tcp_is_allowed_to_send = tcase_create("Unit test for tcp_is_allowed_to_send");
TCase *TCase_tcp_retrans_timeout = tcase_create("Unit test for tcp_retrans_timeout");
TCase *TCase_tcp_retrans = tcase_create("Unit test for tcp_retrans");
TCase *TCase_tcp_ack_dbg = tcase_create("Unit test for tcp_ack_dbg");
TCase *TCase_tcp_ack = tcase_create("Unit test for tcp_ack");
TCase *TCase_tcp_finwaitack = tcase_create("Unit test for tcp_finwaitack");
TCase *TCase_tcp_deltcb = tcase_create("Unit test for tcp_deltcb");
TCase *TCase_tcp_finwaitfin = tcase_create("Unit test for tcp_finwaitfin");
TCase *TCase_tcp_closewaitack = tcase_create("Unit test for tcp_closewaitack");
TCase *TCase_tcp_lastackwait = tcase_create("Unit test for tcp_lastackwait");
TCase *TCase_tcp_syn = tcase_create("Unit test for tcp_syn");
TCase *TCase_tcp_set_init_point = tcase_create("Unit test for tcp_set_init_point");
TCase *TCase_tcp_synack = tcase_create("Unit test for tcp_synack");
TCase *TCase_tcp_first_ack = tcase_create("Unit test for tcp_first_ack");
TCase *TCase_tcp_closewait = tcase_create("Unit test for tcp_closewait");
TCase *TCase_tcp_fin = tcase_create("Unit test for tcp_fin");
TCase *TCase_tcp_rcvfin = tcase_create("Unit test for tcp_rcvfin");
TCase *TCase_tcp_finack = tcase_create("Unit test for tcp_finack");
TCase *TCase_tcp_force_closed = tcase_create("Unit test for tcp_force_closed");
TCase *TCase_tcp_wakeup_pending = tcase_create("Unit test for tcp_wakeup_pending");
TCase *TCase_tcp_rst = tcase_create("Unit test for tcp_rst");
TCase *TCase_tcp_halfopencon = tcase_create("Unit test for tcp_halfopencon");
TCase *TCase_tcp_closeconn = tcase_create("Unit test for tcp_closeconn");
TCase *TCase_invalid_flags = tcase_create("Unit test for invalid_flags");
TCase *TCase_checkLocalClosing = tcase_create("Unit test for checkLocalClosing");
TCase *TCase_checkRemoteClosing = tcase_create("Unit test for checkRemoteClosing");
tcase_add_test(TCase_input_segment_compare, tc_input_segment_compare);
suite_add_tcase(s, TCase_input_segment_compare);
tcase_add_test(TCase_tcp_input_segment, tc_tcp_input_segment);
suite_add_tcase(s, TCase_tcp_input_segment);
tcase_add_test(TCase_segment_compare, tc_segment_compare);
suite_add_tcase(s, TCase_segment_compare);
tcase_add_test(TCase_tcp_discard_all_segments, tc_tcp_discard_all_segments);
suite_add_tcase(s, TCase_tcp_discard_all_segments);
tcase_add_test(TCase_release_until, tc_release_until);
suite_add_tcase(s, TCase_release_until);
tcase_add_test(TCase_release_all_until, tc_release_all_until);
suite_add_tcase(s, TCase_release_all_until);
tcase_add_test(TCase_tcp_send_fin, tc_tcp_send_fin);
suite_add_tcase(s, TCase_tcp_send_fin);
tcase_add_test(TCase_pico_tcp_process_out, tc_pico_tcp_process_out);
suite_add_tcase(s, TCase_pico_tcp_process_out);
tcase_add_test(TCase_pico_paws, tc_pico_paws);
suite_add_tcase(s, TCase_pico_paws);
tcase_add_test(TCase_tcp_add_options, tc_tcp_add_options);
suite_add_tcase(s, TCase_tcp_add_options);
tcase_add_test(TCase_tcp_options_size_frame, tc_tcp_options_size_frame);
suite_add_tcase(s, TCase_tcp_options_size_frame);
tcase_add_test(TCase_tcp_add_options_frame, tc_tcp_add_options_frame);
suite_add_tcase(s, TCase_tcp_add_options_frame);
tcase_add_test(TCase_tcp_send_ack, tc_tcp_send_ack);
suite_add_tcase(s, TCase_tcp_send_ack);
tcase_add_test(TCase_tcp_set_space, tc_tcp_set_space);
suite_add_tcase(s, TCase_tcp_set_space);
tcase_add_test(TCase_tcp_options_size, tc_tcp_options_size);
suite_add_tcase(s, TCase_tcp_options_size);
tcase_add_test(TCase_tcp_process_sack, tc_tcp_process_sack);
suite_add_tcase(s, TCase_tcp_process_sack);
tcase_add_test(TCase_tcp_rcv_sack, tc_tcp_rcv_sack);
suite_add_tcase(s, TCase_tcp_rcv_sack);
tcase_add_test(TCase_tcp_parse_options, tc_tcp_parse_options);
suite_add_tcase(s, TCase_tcp_parse_options);
tcase_add_test(TCase_tcp_send, tc_tcp_send);
suite_add_tcase(s, TCase_tcp_send);
tcase_add_test(TCase_sock_stats, tc_sock_stats);
suite_add_tcase(s, TCase_sock_stats);
tcase_add_test(TCase_initconn_retry, tc_initconn_retry);
suite_add_tcase(s, TCase_initconn_retry);
tcase_add_test(TCase_tcp_send_synack, tc_tcp_send_synack);
suite_add_tcase(s, TCase_tcp_send_synack);
tcase_add_test(TCase_tcp_send_empty, tc_tcp_send_empty);
suite_add_tcase(s, TCase_tcp_send_empty);
tcase_add_test(TCase_tcp_send_probe, tc_tcp_send_probe);
suite_add_tcase(s, TCase_tcp_send_probe);
tcase_add_test(TCase_tcp_send_rst, tc_tcp_send_rst);
suite_add_tcase(s, TCase_tcp_send_rst);
tcase_add_test(TCase_tcp_nosync_rst, tc_tcp_nosync_rst);
suite_add_tcase(s, TCase_tcp_nosync_rst);
tcase_add_test(TCase_tcp_sack_prepare, tc_tcp_sack_prepare);
suite_add_tcase(s, TCase_tcp_sack_prepare);
tcase_add_test(TCase_tcp_data_in, tc_tcp_data_in);
suite_add_tcase(s, TCase_tcp_data_in);
tcase_add_test(TCase_tcp_ack_advance_una, tc_tcp_ack_advance_una);
suite_add_tcase(s, TCase_tcp_ack_advance_una);
tcase_add_test(TCase_time_diff, tc_time_diff);
suite_add_tcase(s, TCase_time_diff);
tcase_add_test(TCase_tcp_rtt, tc_tcp_rtt);
suite_add_tcase(s, TCase_tcp_rtt);
tcase_add_test(TCase_tcp_congestion_control, tc_tcp_congestion_control);
suite_add_tcase(s, TCase_tcp_congestion_control);
tcase_add_test(TCase_add_retransmission_timer, tc_add_retransmission_timer);
suite_add_tcase(s, TCase_add_retransmission_timer);
tcase_add_test(TCase_tcp_first_timeout, tc_tcp_first_timeout);
suite_add_tcase(s, TCase_tcp_first_timeout);
tcase_add_test(TCase_tcp_rto_xmit, tc_tcp_rto_xmit);
suite_add_tcase(s, TCase_tcp_rto_xmit);
tcase_add_test(TCase_tcp_next_zerowindow_probe, tc_tcp_next_zerowindow_probe);
suite_add_tcase(s, TCase_tcp_next_zerowindow_probe);
tcase_add_test(TCase_tcp_is_allowed_to_send, tc_tcp_is_allowed_to_send);
suite_add_tcase(s, TCase_tcp_is_allowed_to_send);
tcase_add_test(TCase_tcp_retrans_timeout, tc_tcp_retrans_timeout);
suite_add_tcase(s, TCase_tcp_retrans_timeout);
tcase_add_test(TCase_tcp_retrans, tc_tcp_retrans);
suite_add_tcase(s, TCase_tcp_retrans);
tcase_add_test(TCase_tcp_ack_dbg, tc_tcp_ack_dbg);
suite_add_tcase(s, TCase_tcp_ack_dbg);
tcase_add_test(TCase_tcp_ack, tc_tcp_ack);
suite_add_tcase(s, TCase_tcp_ack);
tcase_add_test(TCase_tcp_finwaitack, tc_tcp_finwaitack);
suite_add_tcase(s, TCase_tcp_finwaitack);
tcase_add_test(TCase_tcp_deltcb, tc_tcp_deltcb);
suite_add_tcase(s, TCase_tcp_deltcb);
tcase_add_test(TCase_tcp_finwaitfin, tc_tcp_finwaitfin);
suite_add_tcase(s, TCase_tcp_finwaitfin);
tcase_add_test(TCase_tcp_closewaitack, tc_tcp_closewaitack);
suite_add_tcase(s, TCase_tcp_closewaitack);
tcase_add_test(TCase_tcp_lastackwait, tc_tcp_lastackwait);
suite_add_tcase(s, TCase_tcp_lastackwait);
tcase_add_test(TCase_tcp_syn, tc_tcp_syn);
suite_add_tcase(s, TCase_tcp_syn);
tcase_add_test(TCase_tcp_set_init_point, tc_tcp_set_init_point);
suite_add_tcase(s, TCase_tcp_set_init_point);
tcase_add_test(TCase_tcp_synack, tc_tcp_synack);
suite_add_tcase(s, TCase_tcp_synack);
tcase_add_test(TCase_tcp_first_ack, tc_tcp_first_ack);
suite_add_tcase(s, TCase_tcp_first_ack);
tcase_add_test(TCase_tcp_closewait, tc_tcp_closewait);
suite_add_tcase(s, TCase_tcp_closewait);
tcase_add_test(TCase_tcp_fin, tc_tcp_fin);
suite_add_tcase(s, TCase_tcp_fin);
tcase_add_test(TCase_tcp_rcvfin, tc_tcp_rcvfin);
suite_add_tcase(s, TCase_tcp_rcvfin);
tcase_add_test(TCase_tcp_finack, tc_tcp_finack);
suite_add_tcase(s, TCase_tcp_finack);
tcase_add_test(TCase_tcp_force_closed, tc_tcp_force_closed);
suite_add_tcase(s, TCase_tcp_force_closed);
tcase_add_test(TCase_tcp_wakeup_pending, tc_tcp_wakeup_pending);
suite_add_tcase(s, TCase_tcp_wakeup_pending);
tcase_add_test(TCase_tcp_rst, tc_tcp_rst);
suite_add_tcase(s, TCase_tcp_rst);
tcase_add_test(TCase_tcp_halfopencon, tc_tcp_halfopencon);
suite_add_tcase(s, TCase_tcp_halfopencon);
tcase_add_test(TCase_tcp_closeconn, tc_tcp_closeconn);
suite_add_tcase(s, TCase_tcp_closeconn);
tcase_add_test(TCase_invalid_flags, tc_invalid_flags);
suite_add_tcase(s, TCase_invalid_flags);
tcase_add_test(TCase_checkLocalClosing, tc_checkLocalClosing);
suite_add_tcase(s, TCase_checkLocalClosing);
tcase_add_test(TCase_checkRemoteClosing, tc_checkRemoteClosing);
suite_add_tcase(s, TCase_checkRemoteClosing);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,375 @@
#include <pico_defines.h>
#include <pico_stack.h>
#include <pico_socket.h>
#include <pico_tftp.h>
#include "modules/pico_tftp.c"
#include "check.h"
Suite *pico_suite(void);
int tftp_user_cb(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg);
/* MOCKS */
static int called_pico_socket_close = 0;
static uint16_t expected_opcode = 0;
static int called_user_cb = 0;
static int called_sendto = 0;
static uint32_t called_pico_timer_add = 0;
static int called_pico_timer_cancel = 0;
static struct pico_socket example_socket;
static struct pico_tftp_session example_session;
int pico_socket_close(struct pico_socket *s)
{
fail_if(s != example_session.socket);
called_pico_socket_close++;
return 0;
}
int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
{
const struct pico_tftp_hdr *h = (const struct pico_tftp_hdr *)buf;
fail_if(s != &example_socket);
fail_if(short_be(h->opcode) != expected_opcode);
fail_if(len <= 0);
(void)dst;
(void)remote_port;
called_sendto++;
return 0;
}
int tftp_user_cb(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg)
{
(void)session;
(void)err;
(void)block;
(void)len;
(void)arg;
called_user_cb++;
return 0;
}
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
(void)expire;
(void)timer;
(void)arg;
return ++called_pico_timer_add;
}
void pico_timer_cancel(uint32_t t)
{
(void)t;
called_pico_timer_cancel++;
}
/* TESTS */
/* START_TEST(tc_check_opcode) */
/* { */
/* / * TODO: test this: static int check_opcode(struct pico_tftp_hdr *th) * / */
/* struct pico_tftp_hdr th; */
/* th.opcode = 0; */
/* fail_unless(check_opcode(&th) == -1); */
/* th.opcode = short_be(PICO_TFTP_RRQ); */
/* fail_unless(check_opcode(&th) == 0); */
/* th.opcode = short_be(0xFF); */
/* fail_unless(check_opcode(&th) == -1); */
/* } */
/* END_TEST */
START_TEST(tc_find_session_by_socket)
{
tftp_sessions = (struct pico_tftp_session *)PICO_ZALLOC(sizeof(struct pico_tftp_session));
tftp_sessions->socket = &example_socket;
tftp_sessions->next = (struct pico_tftp_session *)PICO_ZALLOC(sizeof(struct pico_tftp_session));
tftp_sessions->socket = NULL;
tftp_sessions->next = NULL;
fail_if(find_session_by_socket(&example_socket) != tftp_sessions->next);
}
END_TEST
START_TEST(tc_tftp_finish)
{
tftp_sessions = 0;
/* Test case: client */
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_finish(&example_session);
fail_if(!called_pico_socket_close);
/* Test eval_finish() len is 5*/
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_eval_finish(&example_session, 5);
fail_if(example_session.state != TFTP_STATE_CLOSING);
fail_if(!called_pico_socket_close);
/* Test eval_finish() len is PICO_TFTP_TOTAL_BLOCK_SIZE */
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_eval_finish(&example_session, PICO_TFTP_TOTAL_BLOCK_SIZE);
fail_if(called_pico_socket_close);
}
END_TEST
START_TEST(tc_tftp_send_ack)
{
example_session.socket = &example_socket;
#ifdef PICO_FAULTY
/* send_ack must not segfault when out of memory */
pico_set_mm_failure(1);
tftp_send_ack(&example_session);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_ACK;
tftp_send_ack(&example_session);
fail_if(called_sendto < 1);
}
END_TEST
START_TEST(tc_tftp_send_req)
{
/* Not needed. The tftp_send_rx_req and tftp_send_tx_req cover this. */
}
END_TEST
START_TEST(tc_tftp_send_rx_req)
{
char filename[14] = "some filename";
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
called_sendto = 0;
#ifdef PICO_FAULTY
example_session.callback = tftp_user_cb;
/* send_req must call error cb when out of memory */
pico_set_mm_failure(1);
tftp_send_rx_req(&example_session, NULL, 0, filename);
fail_if(called_user_cb < 1);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_RRQ;
tftp_send_rx_req(&example_session, NULL, 0, NULL);
fail_if(called_sendto > 0); /* Calling with filename = NULL: not good */
tftp_send_rx_req(&example_session, NULL, 0, filename);
fail_if(called_sendto < 0);
}
END_TEST
START_TEST(tc_tftp_send_tx_req)
{
char filename[14] = "some filename";
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
called_sendto = 0;
#ifdef PICO_FAULTY
example_session.callback = tftp_user_cb;
/* send_req must call error cb when out of memory */
pico_set_mm_failure(1);
tftp_send_tx_req(&example_session, NULL, 0, filename);
fail_if(called_user_cb < 1);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_WRQ;
tftp_send_tx_req(&example_session, NULL, 0, NULL);
fail_if(called_sendto > 0); /* Calling with filename = NULL: not good */
tftp_send_tx_req(&example_session, NULL, 0, filename);
fail_if(called_sendto < 0);
}
END_TEST
START_TEST(tc_tftp_send_error)
{
char longtext[1024];
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
/* Sending empty msg */
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, NULL);
fail_if(called_sendto < 1);
/* Sending some msg */
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, "some text here");
fail_if(called_sendto < 1);
/* sending some very long msg */
memset(longtext, 'a', 1023);
longtext[1023] = (char)0;
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, longtext);
fail_if(called_sendto < 1);
}
END_TEST
START_TEST(tc_tftp_send_data)
{
example_session.state = 0;
example_session.socket = &example_socket;
called_sendto = 0;
expected_opcode = PICO_TFTP_DATA;
tftp_send_data(&example_session, (const uint8_t*)"buffer", strlen("buffer"));
fail_if(called_sendto < 1);
fail_if(example_session.state != TFTP_STATE_WAIT_LAST_ACK);
}
END_TEST
START_TEST(tc_pico_tftp_abort)
{
int ret;
server.listen_socket = NULL;
/*first case: no session and no listening socket*/
ret = pico_tftp_abort(NULL, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
/*second case: no session but listening socket*/
server.listen_socket = example_session.socket = &example_socket;
pico_tftp_abort(NULL, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
/*tirdh case: session non into list*/
ret = pico_tftp_abort(&example_session, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
}
END_TEST
/* Receiving functions */
START_TEST(tc_tftp_data)
{
/* TODO: test this: static void tftp_data(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_ack)
{
/* TODO: test this: static void tftp_ack(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_timeout)
{
/* TODO: test this: static void tftp_timeout(pico_time t) */
}
END_TEST
START_TEST(tc_tftp_req)
{
/* TODO: test this: static void tftp_req(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_data_err)
{
/* TODO: test this: static void tftp_data_err(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_fsm_timeout)
{
/* TODO: test this: static void tftp_fsm_timeout(pico_time now, void *arg) */
}
END_TEST
START_TEST(tc_tftp_receive)
{
/* TODO: test this: static void tftp_receive(uint8_t *block, uint32_t r, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_cb)
{
/* TODO: test this: static void tftp_cb(uint16_t ev, struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tftp_socket_open)
{
/* TODO: test this: static int tftp_socket_open(uint16_t family, union pico_address *a, uint16_t port) */
fail_if(tftp_socket_open(0xFFFF, 21) != NULL);
fail_if(tftp_socket_open(0xFFFF, 0xFFFF) != NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
/* TCase *TCase_check_opcode = tcase_create("Unit test for check_opcode"); */
TCase *TCase_find_session_by_socket = tcase_create("Unit test for find_session_by_socket");
TCase *TCase_tftp_finish = tcase_create("Unit test for tftp_finish");
TCase *TCase_tftp_send_ack = tcase_create("Unit test for tftp_send_ack");
TCase *TCase_tftp_send_req = tcase_create("Unit test for tftp_send_req");
TCase *TCase_tftp_send_rx_req = tcase_create("Unit test for tftp_send_rx_req");
TCase *TCase_tftp_send_tx_req = tcase_create("Unit test for tftp_send_tx_req");
TCase *TCase_tftp_send_error = tcase_create("Unit test for tftp_send_error");
TCase *TCase_tftp_send_data = tcase_create("Unit test for tftp_send_data");
TCase *Tcase_pico_tftp_abort = tcase_create("Unit test for pico_tftp_abort");
TCase *TCase_tftp_data = tcase_create("Unit test for tftp_data");
TCase *TCase_tftp_ack = tcase_create("Unit test for tftp_ack");
TCase *TCase_tftp_timeout = tcase_create("Unit test for tftp_timeout");
TCase *TCase_tftp_req = tcase_create("Unit test for tftp_req");
TCase *TCase_tftp_data_err = tcase_create("Unit test for tftp_data_err");
TCase *TCase_tftp_fsm_timeout = tcase_create("Unit test for tftp_fsm_timeout");
TCase *TCase_tftp_receive = tcase_create("Unit test for tftp_receive");
TCase *TCase_tftp_cb = tcase_create("Unit test for tftp_cb");
TCase *TCase_tftp_socket_open = tcase_create("Unit test for tftp_socket_open");
/* tcase_add_test(TCase_check_opcode, tc_check_opcode); */
/* suite_add_tcase(s, TCase_check_opcode); */
tcase_add_test(TCase_find_session_by_socket, tc_find_session_by_socket);
suite_add_tcase(s, TCase_find_session_by_socket);
tcase_add_test(TCase_tftp_finish, tc_tftp_finish);
suite_add_tcase(s, TCase_tftp_finish);
tcase_add_test(TCase_tftp_send_ack, tc_tftp_send_ack);
suite_add_tcase(s, TCase_tftp_send_ack);
tcase_add_test(TCase_tftp_send_req, tc_tftp_send_req);
suite_add_tcase(s, TCase_tftp_send_req);
tcase_add_test(TCase_tftp_send_rx_req, tc_tftp_send_rx_req);
suite_add_tcase(s, TCase_tftp_send_rx_req);
tcase_add_test(TCase_tftp_send_tx_req, tc_tftp_send_tx_req);
suite_add_tcase(s, TCase_tftp_send_tx_req);
tcase_add_test(TCase_tftp_send_error, tc_tftp_send_error);
suite_add_tcase(s, TCase_tftp_send_error);
tcase_add_test(TCase_tftp_send_data, tc_tftp_send_data);
suite_add_tcase(s, TCase_tftp_send_data);
tcase_add_test(TCase_tftp_data, tc_tftp_data);
suite_add_tcase(s, Tcase_pico_tftp_abort);
tcase_add_test(Tcase_pico_tftp_abort, tc_pico_tftp_abort);
suite_add_tcase(s, TCase_tftp_data);
tcase_add_test(TCase_tftp_ack, tc_tftp_ack);
suite_add_tcase(s, TCase_tftp_ack);
tcase_add_test(TCase_tftp_timeout, tc_tftp_timeout);
suite_add_tcase(s, TCase_tftp_timeout);
tcase_add_test(TCase_tftp_req, tc_tftp_req);
suite_add_tcase(s, TCase_tftp_req);
tcase_add_test(TCase_tftp_data_err, tc_tftp_data_err);
suite_add_tcase(s, TCase_tftp_data_err);
tcase_add_test(TCase_tftp_fsm_timeout, tc_tftp_fsm_timeout);
suite_add_tcase(s, TCase_tftp_fsm_timeout);
tcase_add_test(TCase_tftp_receive, tc_tftp_receive);
suite_add_tcase(s, TCase_tftp_receive);
tcase_add_test(TCase_tftp_cb, tc_tftp_cb);
suite_add_tcase(s, TCase_tftp_cb);
tcase_add_test(TCase_tftp_socket_open, tc_tftp_socket_open);
suite_add_tcase(s, TCase_tftp_socket_open);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,84 @@
#include "pico_frame.h"
#include "pico_queue.h"
#include "stack/pico_frame.c"
#include "pico_stack.h"
#include "check.h"
Suite *pico_suite(void);
struct pico_queue q1 = {
0
}, q2 = {
0
};
START_TEST(tc_q)
{
struct pico_frame *f0 = pico_frame_alloc(100);
struct pico_frame *f1 = pico_frame_alloc(100);
struct pico_frame *f2 = pico_frame_alloc(100);
struct pico_frame *f3 = pico_frame_alloc(100);
struct pico_frame *f4 = pico_frame_alloc(100);
pico_queue_protect(&q1);
q1.max_frames = 4;
q2.max_size = 4 * 100;
fail_if (pico_enqueue(&q1, pico_frame_copy(f0)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f1)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f2)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f3)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f4)) >= 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f0)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f1)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f2)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f3)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f4)) >= 0);
fail_if((pico_dequeue(&q1))->buffer != f0->buffer);
fail_if((pico_dequeue(&q1))->buffer != f1->buffer);
fail_if((pico_dequeue(&q1))->buffer != f2->buffer);
fail_if((pico_dequeue(&q1))->buffer != f3->buffer);
fail_if(pico_queue_peek(&q1) != NULL);
fail_if(pico_dequeue(&q1) != NULL);
fail_if(q1.size != 0);
fail_if(q1.frames != 0);
pico_queue_empty(&q2);
fail_if(q2.size != 0);
fail_if(q2.frames != 0);
fail_if(pico_queue_peek(&q2) != NULL);
fail_if(pico_dequeue(&q2) != NULL);
pico_queue_deinit(&q1);
pico_queue_deinit(&q2);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("Packet Queues");
TCase *TCase_q = tcase_create("Unit test for pico_queue.c");
tcase_add_test(TCase_q, tc_q);
suite_add_tcase(s, TCase_q);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,59 @@
#include "pico_tcp.c"
#include <check.h>
Suite *pico_suite(void);
START_TEST(tc_seq_compare)
{
uint32_t big_a = 0xFFFFFF0alu;
uint32_t big_b = 0xFFFFFF0blu;
uint32_t small_a = 0xalu;
uint32_t small_b = 0xblu;
uint32_t under_thresh = 0x7ffffffflu;
uint32_t over_thresh = 0x80000000lu;
uint32_t zero = 0lu;
fail_if(pico_seq_compare(small_a, small_b) >= 0);
fail_if(pico_seq_compare(small_b, small_a) <= 0);
fail_if(pico_seq_compare(over_thresh, under_thresh) <= 0);
fail_if(pico_seq_compare(under_thresh, over_thresh) >= 0);
fail_if(pico_seq_compare(small_a, big_b) <= 0);
fail_if(pico_seq_compare(big_b, small_a) >= 0);
fail_if(pico_seq_compare(small_a, zero) <= 0);
fail_if(pico_seq_compare(zero, small_a) >= 0);
fail_if(pico_seq_compare(big_a, zero) >= 0);
fail_if(pico_seq_compare(zero, big_a) <= 0);
fail_if(pico_seq_compare(big_a, big_b) >= 0);
fail_if(pico_seq_compare(big_b, big_a) <= 0);
fail_if(pico_seq_compare(big_a, big_a) != 0);
fail_if(pico_seq_compare(zero, zero) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico tcp sequence numbers");
TCase *TCase_seq_compare = tcase_create("Unit test for pico_seq_compare");
tcase_add_test(TCase_seq_compare, tc_seq_compare);
suite_add_tcase(s, TCase_seq_compare);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@@ -0,0 +1,213 @@
#include "pico_ethernet.c"
static struct pico_frame *init_frame(struct pico_device *dev)
{
struct pico_frame *f = pico_frame_alloc(PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR);
f->net_hdr = f->buffer + PICO_SIZE_ETHHDR;
f->datalink_hdr = f->buffer;
f->dev = dev;
return f;
}
START_TEST (arp_update_max_arp_reqs_test)
{
pico_stack_init();
max_arp_reqs = 0;
usleep((PICO_ARP_INTERVAL + 1) * 1000);
pico_stack_tick();
fail_unless(max_arp_reqs > 0);
max_arp_reqs = PICO_ARP_MAX_RATE;
usleep((PICO_ARP_INTERVAL + 1) * 1000);
pico_stack_tick();
fail_unless(max_arp_reqs == PICO_ARP_MAX_RATE);
}
END_TEST
START_TEST (arp_compare_test)
{
struct pico_arp a, b;
char ipstr[] = "192.168.1.1";
memset(&a, 0, sizeof(a));
pico_string_to_ipv4(ipstr, &b.ipv4.addr);
fail_unless(arp_compare(&a, &b) == -1);
fail_unless(arp_compare(&b, &a) == 1);
fail_unless(arp_compare(&a, &a) == 0);
}
END_TEST
START_TEST (arp_lookup_test)
{
struct pico_ip4 ip;
struct pico_eth *eth = NULL;
char ipstr[] = "192.168.1.1";
struct pico_arp entry;
eth = pico_arp_lookup(&ip);
fail_unless(eth == NULL);
pico_string_to_ipv4(ipstr, &ip.addr);
entry.ipv4 = ip;
pico_stack_init();
fail_unless(pico_arp_add_entry(&entry) == 0);
entry.arp_status = PICO_ARP_STATUS_STALE;
eth = pico_arp_lookup(&ip);
fail_unless(eth == NULL);
pico_tree_delete(&arp_tree, &entry);
}
END_TEST
START_TEST (arp_expire_test)
{
struct pico_arp entry;
entry.arp_status = PICO_ARP_STATUS_REACHABLE;
entry.timestamp = 0;
arp_expire(PICO_ARP_TIMEOUT, &entry);
fail_unless(entry.arp_status == PICO_ARP_STATUS_STALE);
}
END_TEST
START_TEST(tc_pico_arp_queue)
{
struct pico_ip4 addr = {
.addr = 0xaabbccdd
};
int i;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
struct pico_ipv4_hdr *h = (struct pico_ipv4_hdr *) f->buffer;
fail_if(!f);
f->net_hdr = (uint8_t *)h;
h->dst.addr = addr.addr;
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued[i] != NULL);
}
pico_arp_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued[i] != NULL);
}
pico_arp_postpone(f);
fail_if(frames_queued[0]->buffer != f->buffer);
pico_arp_unreachable(&addr);
PICO_FREE(f);
}
END_TEST
START_TEST (arp_receive_test)
{
struct mock_device *mock;
struct pico_frame *f = NULL;
struct pico_arp_hdr *ah = NULL;
struct pico_eth_hdr *eh = NULL;
uint8_t macaddr1[6] = {
0, 0, 0, 0xa, 0xb, 0xf
};
uint8_t macaddr2[6] = {
0, 0, 0, 0xc, 0xd, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 ip1 = {
.addr = long_be(0x0A2800AA)
};
struct pico_ip4 ip2 = {
.addr = long_be(0x0A2800AB)
};
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, ip1, netmask), "add link to mock device failed");
/* Normal ARP request */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
eh = (struct pico_eth_hdr *) f->datalink_hdr;
ah = (struct pico_arp_hdr *) f->net_hdr;
memcpy(eh->saddr, macaddr2, PICO_SIZE_ETH);
memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH);
eh->proto = PICO_IDETH_ARP;
ah->htype = PICO_ARP_HTYPE_ETH;
ah->ptype = PICO_IDETH_IPV4;
ah->hsize = PICO_SIZE_ETH;
ah->psize = PICO_SIZE_IP4;
ah->opcode = PICO_ARP_REQUEST;
memcpy(ah->s_mac, macaddr2, PICO_SIZE_ETH);
ah->src.addr = ip2.addr;
ah->dst.addr = ip1.addr;
fail_unless(pico_arp_receive(f) == 0);
/* net_hdr is a nullpointer */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
f->net_hdr = NULL;
fail_unless(pico_arp_receive(f) == -1);
/* wrong hardware type */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->htype = 0;
fail_unless(pico_arp_receive(f) == -1);
/* wrong protocol type */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->ptype = 0;
fail_unless(pico_arp_receive(f) == -1);
/* source mac address is multicast */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->s_mac[0] = 0x01;
fail_unless(pico_arp_receive(f) == -1);
pico_ipv4_link_del(mock->dev, ip1);
}
END_TEST
START_TEST (arp_get_test)
{
struct pico_frame *f = NULL;
struct mock_device *mock;
struct pico_ipv4_hdr *hdr = NULL;
struct pico_eth *eth = NULL;
uint8_t macaddr[6] = {
0, 0, 0xa, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 ip = {
.addr = long_be(0x0A28000B)
};
mock = pico_mock_create(macaddr);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, ip, netmask), "add link to mock device failed");
f = pico_frame_alloc(PICO_SIZE_ETHHDR + sizeof(struct pico_ipv4_hdr));
f->net_hdr = f->start + PICO_SIZE_ETHHDR;
f->datalink_hdr = f->start;
f->dev = mock->dev;
hdr = (struct pico_ipv4_hdr *) f->net_hdr;
hdr->dst.addr = ip.addr;
eth = pico_arp_get(f);
fail_unless(eth == &mock->dev->eth->mac);
pico_ipv4_link_del(mock->dev, ip);
}
END_TEST

View File

@@ -0,0 +1,554 @@
static struct pico_dhcp_client_cookie*dhcp_client_ptr;
void callback_dhcpclient(void*cli, int code);
int generate_dhcp_msg(uint8_t *buf, uint32_t *len, uint8_t type);
void callback_dhcpclient(void*cli, int code)
{
struct pico_ip4 gateway;
char gw_txt_addr[30];
IGNORE_PARAMETER(cli);
if(code == PICO_DHCP_SUCCESS) {
gateway = pico_dhcp_get_gateway(&dhcp_client_ptr);
pico_ipv4_to_string(gw_txt_addr, gateway.addr);
}
printf("callback happened with code %d!\n", code);
}
int generate_dhcp_msg(uint8_t *buf, uint32_t *len, uint8_t type)
{
if(type == DHCP_MSG_TYPE_DISCOVER) {
uint8_t buffer[] = {
0x01, 0x01, 0x06, 0x00, 0x0c, 0x10,
0x53, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x0a, 0x0b, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x01, 0x37, 0x07, 0x01,
0x1c, 0x02, 0x03, 0x0c, 0x3a, 0x3b, 0x39, 0x02, 0x02, 0x40, 0xff, 0x00
};
*len = sizeof(buffer);
memcpy(&(buf[0]), buffer, *len);
}else if(type == DHCP_MSG_TYPE_OFFER) {
return 1;
}else if(type == DHCP_MSG_TYPE_REQUEST) {
uint32_t i = 0;
uint8_t buffer1[] = {
/* 0x63,0x82,0x53,0x63,// MAGIC COOCKIE */
/* 0x35,0x01,0x03, // DHCP REQUEST */
/* 0x36,0x04,0x00,0x00,0x00,0x00 // SERVER ID */
0x32, 0x04, buf[0x3a], buf[0x3b], buf[0x3c], buf[0x3e], /* requested ip */
0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, /* Parameter list */
0x3d, 0x07, 0x01, buf[0x06], buf[0x07], buf[0x08], buf[0x09], buf[0x0a], buf[0x0b], /* Client id */
0xff
};
buf[0x02a] = 0x01; /* change to boot request */
buf[0x11c] = 0x03; /* request */
memcpy(&(buf[0x123]), &(buffer1[0]), sizeof(buffer1));
*len = sizeof(buffer1) + 0x123;
for(i = *len; i < 0x150; i++) {
buf[i + 10] = 0x00;
}
return 0;
}else if(type == DHCP_MSG_TYPE_ACK) {
return 1;
}
return 0;
}
START_TEST (test_dhcp_server_api)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is not in arp table yet
* Status : Done
************************************************************************/
struct mock_device *mock;
uint8_t macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
uint8_t buf[600] = {
0
};
/* Declaration test 1 */
struct pico_dhcp_server_setting s1 = {
0
};
/* Declaration test 2 */
struct pico_dhcp_server_setting s2 = {
0
};
printf("*********************** starting %s * \n", __func__);
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
/* test 0 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 0 statements */
fail_unless(pico_dhcp_server_initiate(NULL), "DHCP_SERVER> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 1 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Store data in settings */
s1.server_ip.addr = long_be(0x0A28000F); /* make sure this IP is not assigned */
/* Test 1 statements */
fail_unless(pico_dhcp_server_initiate(&s1), "DHCP_SERVER> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 2 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Store data in settings */
s2.server_ip = serverip;
/* Test 2 statements */
fail_if(pico_dhcp_server_initiate(&s2), "DHCP_SERVER> failed after correct parameter");
}
END_TEST
START_TEST (test_dhcp)
{
/************************************************************************
* Check if all states (offer, bound) are changed correctly
* and if response messages are replied correctly
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
uint8_t macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint8_t macaddr2[6] = {
0xc6, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_ip4 *stored_ipv4 = NULL;
uint32_t len = 0;
int network_read = 0;
uint8_t *buf;
uint8_t printbufactive = 0;
buf = PICO_ZALLOC(600);
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
/*Initiate test setup*/
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr2);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_unless(dn == NULL, "DCHP SERVER -> negotiation data available befor discover msg recvd");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
tick_it(3);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if state is changed and reply is received */
network_read = pico_mock_network_read(mock, buf, BUFLEN);
fail_unless(network_read > 0, "received msg on network of %u bytes", network_read);
printbuf(&(buf[0]), (uint32_t)network_read, "DHCP-OFFER msg", printbufactive);
fail_unless(buf[0x011c] == 0x02, "No DHCP offer received after discovery");
fail_unless(dn->state == PICO_DHCP_STATE_OFFER, "DCHP SERVER -> negotiation state not changed to OFFER");
/*change offer to request*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_REQUEST), "DHCP_SERVER->failed to generate buffer");
printbuf(&(buf[0x2a]), len - 0x2a, "request buffer", printbufactive);
/* simulate reception of a offer packet */
pico_dhcp_server_recv(&sock, &(buf[0x2a]), len - 0x2a);
fail_unless(dn->state == PICO_DHCP_STATE_BOUND, "DCHP SERVER -> negotiation state not changed to BOUND");
tick_it(3);
/* check if state is changed and reply is received */
do {
network_read = pico_mock_network_read(mock, buf, BUFLEN);
} while (buf[0] == 0x33);
printf("Received message: %d bytes\n", network_read);
fail_unless(network_read > 0, "received msg on network of %d bytes", network_read);
printbuf(&(buf[0]), (uint32_t)network_read, "DHCP-ACK msg", printbufactive);
fail_unless(buf[0x11c] == 0x05, "No DHCP ACK received after discovery");
}
END_TEST
START_TEST (test_dhcp_server_ipninarp)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is not in arp table yet
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_ip4 *stored_ipv4 = NULL;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint32_t len = 0;
uint8_t buf[600] = {
0
};
uint8_t printbufactive = 0;
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
/*Initiate test setup*/
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_unless(dn == NULL, "DCHP SERVER -> negotiation data available before discover msg recvd");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if new ip is in ARP cache */
fail_if(pico_arp_reverse_lookup(&dn->hwaddr) == NULL, "DCHP SERVER -> new address is not inserted in ARP");
}
END_TEST
START_TEST (test_dhcp_server_ipinarp)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is allready in arp table
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 ipv4address = {
.addr = long_be(0x0a280067)
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_ip4 *stored_ipv4 = NULL;
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_eth *arp_resp = NULL;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint32_t len = 0;
uint8_t buf[600] = {
0
};
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
/*Initiate test setup*/
pico_stack_init();
pico_arp_create_entry(&(macaddr1[0]), ipv4address, s.dev);
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if new ip is in ARP cache */
arp_resp = pico_arp_lookup(&ipv4address);
fail_if(arp_resp == NULL, "DCHP SERVER -> address unavailable in arp cache");
}
END_TEST
#if 0
START_TEST (test_dhcp_client)
{
struct mock_device*mock;
uint32_t dhcp_hdr_offset = PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR + PICO_UDPHDR_SIZE;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 address = {
0
};
struct pico_ip4 yiaddr = {
.addr = long_be(0xC0A8000A)
};
struct pico_ip4 gateway = {
0
};
struct pico_ip4 router = {
.addr = long_be(0xC0A800FE)
};
uint8_t buf[BUFLEN] = {
0
};
uint8_t offer_buf1[] = {
0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0x00, 0x01
};
uint8_t offer_buf2[] = {
0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x3a, 0x04, 0x00, 0x00, 0x07, 0x08, 0x3b, 0x04, 0x00, 0x00, 0x0c, 0x4e, 0x33, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x36, 0x04, 0xc0, 0xa8, 0x00, 0x01, 0xff
};
uint8_t routeropt_buf[] = {
PICO_DHCPOPT_ROUTER, 0x04, 0xC0, 0xA8, 0x00, 0xFE, 0xFF
};
int type = 0;
uint8_t printbufactive = 0;
uint32_t len = 0;
uint32_t xid = 0;
struct pico_dhcp_client_cookie *cli = NULL;
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* initiate negotiation -> change state to */
pico_dhcp_initiate_negotiation(mock->dev, &callback_dhcpclient, &xid);
cli = get_cookie_by_xid(xid);
dhcp_client_ptr = cli;
fail_if(cli == NULL, "initiate fail");
fail_unless(cli->state == DHCPSTATE_DISCOVER, "Not in discover state after init negotiate");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* push discover msg on network */
tick_it(3);
/* read discover message from network */
len = pico_mock_network_read(mock, buf, BUFLEN );
fail_unless(len, "No msg received on network!");
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
fail_unless(buf[0x011c] == 0x01, "No DHCP Discover received after initiate negotiation");
mock_print_protocol(buf);
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* check API access functions */
address = pico_dhcp_get_address(cli);
fail_unless(address.addr == 0, "Client address gets value at init -> should get it from dhcp server");
gateway = pico_dhcp_get_gateway(cli);
fail_unless(gateway.addr == 0, "Gateway gets value at init -> should get it from dhcp server ");
/* Change received discovery msg to offer offer msg */
buf[0x2a] = 0x02;
memcpy(&(buf[0x3a]), &(offer_buf1[0]), sizeof(offer_buf1));
memcpy(&(buf[0x3a]), &(yiaddr.addr), sizeof(struct pico_ip4));
memcpy(&(buf[0x116]), &(offer_buf2[0]), sizeof(offer_buf2));
memcpy(&(buf[0x13b]), &(routeropt_buf[0]), sizeof(routeropt_buf));
memcpy(&(buf[0x13d]), &(router.addr), sizeof(struct pico_ip4));
printbuf(&(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset, "DHCP-OFFER message", printbufactive);
/* generate dhcp type from msg */
type = pico_dhcp_verify_and_identify_type(&(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset, cli);
fail_if(type == 0, "unkown DHCP type");
/* simulate reception of a DHCP server offer */
pico_dhcp_state_machine(type, cli, &(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset);
fail_if(cli->state == DHCPSTATE_DISCOVER, "still in discover state after dhcp server offer");
fail_unless(cli->state == DHCPSTATE_REQUEST, "not in REQUEST state after dhcp server offer");
address = pico_dhcp_get_address(cli);
fail_unless(address.addr == yiaddr.addr, "Client address incorrect => yiaddr or pico_dhcp_get_address incorrect");
gateway = pico_dhcp_get_gateway(cli);
fail_unless(gateway.addr == router.addr, "Gateway incorrect! => routeroption or pico_dhcp_get_gateway incorrect");
tick_it(3);
len = pico_mock_network_read(mock, buf, BUFLEN);
fail_unless(len, "received msg on network of %d bytes", len);
printbuf(&(buf[0]), len, "DHCP-REQUEST packet", printbufactive);
fail_unless(buf[0x011c] == 0x03, "No DHCP request received after offer");
}
END_TEST
#endif
START_TEST (test_dhcp_client_api)
{
/************************************************************************
* Check API of pico_dhcp_initiate_negotiation
* Status : Done
************************************************************************/
/* Declaration test 0 */
uint32_t xid0 = 0;
struct pico_dhcp_client_cookie *cli0 = NULL;
/* Declaration test 1 */
uint32_t xid1 = 0;
struct pico_dhcp_client_cookie *cli1 = NULL;
printf("*********************** starting %s * \n", __func__);
/* test 0 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 0 statements */
pico_dhcp_initiate_negotiation(NULL, NULL, &xid0);
cli0 = pico_dhcp_client_find_cookie(xid0);
fail_unless(cli0 == NULL, "DHCP_CLIENT> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 1 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 1 statements */
pico_dhcp_initiate_negotiation(NULL, &callback_dhcpclient, &xid1);
cli1 = pico_dhcp_client_find_cookie(xid1);
fail_unless(cli1 == NULL, "DHCP_CLIENT> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
#if 0
/* not testable since we do not have a stub for the pico_socket_sendto */
/* Declaration test 2 */
uint32_t xid2 = 0;
struct pico_dhcp_client_cookie *cli2 = NULL;
struct pico_device *dev2;
struct mock_device *mock2 = NULL;
/* test 2 */
/* Create device */
dev2 = pico_null_create("dummy");
mock2 = pico_mock_create(NULL);
fail_if(mock2 == NULL, "No device created");
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 2 statements */
xid2 = pico_dhcp_initiate_negotiation(dev2, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
xid2 = pico_dhcp_initiate_negotiation(mock2->dev, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
xid2 = pico_dhcp_initiate_negotiation(dev2, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
#endif
}
END_TEST

View File

@@ -0,0 +1,88 @@
void cb_dns(char *ip, void *arg);
void cb_dns(char *ip, void *arg)
{
if (!ip) {
/* Error occured */
printf("DNS error getaddr\n");
return;
}
/* Do something */
printf("DNS -> %s\n", ip);
PICO_FREE(ip);
if (arg)
PICO_FREE(arg);
}
START_TEST (test_dns)
{
int ret;
char url[] = "www.google.com";
char ip[] = "8.8.4.4";
struct pico_ip4 ns;
ns.addr = long_be(0x0a00280a); /* 10.40.0.10 */
pico_stack_init();
printf("START DNS TEST\n");
/* testing nameserver API */
ret = pico_dns_client_nameserver(NULL, PICO_DNS_NS_ADD);
fail_if(ret == 0, "dns> dns_client_nameserver add error");
ret = pico_dns_client_nameserver(NULL, PICO_DNS_NS_DEL);
fail_if(ret == 0, "dns> dns_client_nameserver del error");
ret = pico_dns_client_nameserver(NULL, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(NULL, 0xFF);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL); /* delete non added ns */
fail_if(ret == 0, "dns> dns_client_nameserver del error");
ret = pico_dns_client_nameserver(&ns, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one */
fail_if(ret < 0, "dns> dns_client_nameserver add error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL);
fail_if(ret < 0, "dns> dns_client_nameserver del error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one */
fail_if(ret < 0, "dns> dns_client_nameserver add error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one again */
fail_if(ret < 0, "dns> dns_client_nameserver add double failed");
/* testing getaddr API */
/* not testable since we do not have a stub for the pico_socket_send */
/* ret = pico_dns_client_getaddr(url, cb_dns, NULL); / * ask correct one * / */
/* fail_if(ret < 0, "dns> dns_client_getaddr: %s",strerror(pico_err)); */
ret = pico_dns_client_getaddr(NULL, cb_dns, NULL);
fail_if(ret == 0, "dns> dns_client_getaddr: no url");
ret = pico_dns_client_getaddr(url, NULL, NULL);
fail_if(ret == 0, "dns> dns_client_getaddr: no cb");
/* testing getname API */
/* not testable since we do not have a stub for the pico_socket_send */
/* ret = pico_dns_client_getname(ip, cb_dns, NULL); / * ask correct one * / */
/* fail_if(ret < 0, "dns> dns_client_getname: %s",strerror(pico_err)); */
ret = pico_dns_client_getname(NULL, cb_dns, NULL);
fail_if(ret == 0, "dns> dns_client_getname: no ip");
ret = pico_dns_client_getname(ip, NULL, NULL);
fail_if(ret == 0, "dns> dns_client_getname: no cb");
}
END_TEST

View File

@@ -0,0 +1,401 @@
#include "pico_icmp4.h"
#define NUM_PING 1
int ping_test_var = 0;
void cb_ping(struct pico_icmp4_stats *s);
void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s);
void cb_ping(struct pico_icmp4_stats *s)
{
char host[30];
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("%lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host, s->seq, s->time);
if (s->seq == NUM_PING) {
ping_test_var++;
}
fail_if (s->seq > NUM_PING);
} else {
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
exit(1);
}
}
START_TEST (test_icmp4_ping)
{
struct pico_ip4 local = {
0
};
struct pico_ip4 remote = {
0
};
struct pico_ip4 netmask = {
0
};
struct mock_device *mock = NULL;
char local_address[] = {
"192.168.1.102"
};
char remote_address[] = {
"192.168.1.103"
};
uint16_t interval = 1000;
uint16_t timeout = 5000;
uint8_t size = 48;
int bufferlen = 80;
uint8_t buffer[bufferlen];
int len;
uint8_t temp_buf[4];
printf("*********************** starting %s * \n", __func__);
pico_string_to_ipv4(local_address, &(local.addr));
pico_string_to_ipv4("255.255.255.0", &(netmask.addr));
pico_string_to_ipv4(remote_address, &(remote.addr));
pico_string_to_ipv4("255.255.255.0", &(netmask.addr));
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
fail_if(pico_icmp4_ping(local_address, NUM_PING, interval, timeout, size, cb_ping) < 0);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_if(ping_test_var != 1);
pico_icmp4_ping(remote_address, NUM_PING, interval, timeout, size, cb_ping);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* get the packet from the mock_device */
memset(buffer, 0, (size_t)bufferlen);
len = pico_mock_network_read(mock, buffer, bufferlen);
fail_if(len < 20);
/* inspect it */
fail_unless(mock_ip_protocol(mock, buffer, len) == 1);
fail_unless(mock_icmp_type(mock, buffer, len) == 8);
fail_unless(mock_icmp_code(mock, buffer, len) == 0);
fail_unless(pico_checksum(buffer + 20, (uint32_t)(len - 20)) == 0);
/* cobble up a reply */
buffer[20] = 0; /* type 0 : reply */
memcpy(temp_buf, buffer + 12, 4);
memcpy(buffer + 12, buffer + 16, 4);
memcpy(buffer + 16, temp_buf, 4);
/* using the mock-device because otherwise I have to put everything in a pico_frame correctly myself. */
pico_mock_network_write(mock, buffer, len);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(ping_test_var == 2);
/* repeat but make it an invalid reply... */
pico_icmp4_ping(remote_address, NUM_PING, interval, timeout, size, cb_ping);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* get the packet from the mock_device */
memset(buffer, 0, (size_t)bufferlen);
len = pico_mock_network_read(mock, buffer, bufferlen);
/* inspect it */
fail_unless(mock_ip_protocol(mock, buffer, len) == 1);
fail_unless(mock_icmp_type(mock, buffer, len) == 8);
fail_unless(mock_icmp_code(mock, buffer, len) == 0);
fail_unless(pico_checksum(buffer + 20, (uint32_t)(len - 20)) == 0);
/* cobble up a reply */
buffer[20] = 0; /* type 0 : reply */
memcpy(temp_buf, buffer + 12, 4);
memcpy(buffer + 12, buffer + 16, 4);
memcpy(buffer + 16, temp_buf, 4);
buffer[26] = (uint8_t)~buffer[26]; /* flip some bits in the sequence number, to see if the packet gets ignored properly */
/* using the mock-device because otherwise I have to put everything in a pico_frame correctly myself. */
pico_mock_network_write(mock, buffer, len);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(ping_test_var == 2);
}
END_TEST
START_TEST (test_icmp4_incoming_ping)
{
int bufferlen = 76;
uint8_t buffer[76] = {
0x45, 0x00, 0x00, 0x4c,
0x91, 0xc3, 0x40, 0x00,
0x40, 0x01, 0x24, 0xd0,
0xc0, 0xa8, 0x01, 0x66,
0xc0, 0xa8, 0x01, 0x64,
0x08, 0x00, 0x66, 0x3c,
0x91, 0xc2, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int buffer2len = 76;
int len;
int cntr = 0;
uint8_t buffer2[bufferlen];
struct pico_ip4 local = {
.addr = long_be(0xc0a80164)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
printf("*********************** starting %s * \n", __func__);
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
hdr->crc = 0;
hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
pico_mock_network_write(mock, buffer, bufferlen);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, buffer2len);
/* inspect it */
while(cntr < len) {
printf("0x%02x ", buffer2[cntr]);
cntr++;
if(cntr % 4 == 0)
printf("\n");
}
fail_unless(len == buffer2len, "ping reply lenght does not match, expected len: %d, got: %d", buffer2len, len);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 0);
fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
}
END_TEST
START_TEST (test_icmp4_unreachable_send)
{
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
int len = 0;
int bufferlen = 80;
uint8_t buffer2[bufferlen];
uint8_t buffer[32] = {
0x45, 0x00, 0x00, 0x20, 0x91, 0xc0, 0x40, 0x00,
0x40, 0x11, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05,
0x0a, 0x28, 0x00, 0x04, 0x15, 0xb3, 0x15, 0xb3,
0x00, 0x0c, 0x00, 0x00, 'e', 'l', 'l', 'o'
};
/* fake packet with bad upper-layer-protocol */
uint8_t buffer3[20] = {
0x45, 0x00, 0x00, 0x14, 0x91, 0xc0, 0x40, 0x00,
0x40, 0xff, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05,
0x0a, 0x28, 0x00, 0x04
};
struct pico_frame*f = PICO_ZALLOC(sizeof(struct pico_frame));
printf("*********************** starting %s * \n", __func__);
f->net_hdr = buffer;
f->buffer = buffer;
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
fail_if(pico_icmp4_dest_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56, "len is indeed %d\n", len);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 1); /* host unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_port_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 3); /* port unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_proto_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_ttl_expired(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 11); /* ttl expired */
fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
f->net_hdr = buffer3;
f->buffer = buffer3;
fail_if(pico_icmp4_proto_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 48); /* Buffer 3 is shorter, reply is shorter too... */
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
}
END_TEST
int icmp4_socket_unreach_status = 0;
void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s)
{
IGNORE_PARAMETER(s);
if (ev == PICO_SOCK_EV_ERR) {
icmp4_socket_unreach_status = 1;
}
}
START_TEST (test_icmp4_unreachable_recv)
{
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 remote = {
.addr = long_be(0x0a280065)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
struct pico_socket*sock;
uint16_t port = short_be(7777);
/* put a host unreachable in the queue, run a few stack ticks */
uint8_t buffer[] = {
0x45, 0x00, 0x00, 0x20,
0x91, 0xc0, 0x40, 0x00,
0x40, 0x01, 0x94, 0xb4,
0x0a, 0x28, 0x00, 0x65,
0x0a, 0x28, 0x00, 0x64,
0x03, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
printf("*********************** starting %s * \n", __func__);
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
/* open a socket */
sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &icmp4_unreach_socket_cb);
fail_if(sock == NULL);
fail_if(pico_socket_bind(sock, &local, &port));
pico_socket_connect(sock, &remote, port);
pico_socket_write(sock, "fooo", 4);
/* see if my callback was called with the proper code */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* filling in the IP header and first 8 bytes */
hdr->crc = 0;
hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
printf("read %d bytes\n", pico_mock_network_read(mock, buffer + 28, 28));
printf("wrote %d bytes\n", pico_mock_network_write(mock, buffer, 56));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(icmp4_socket_unreach_status == 1);
}
END_TEST

View File

@@ -0,0 +1,852 @@
START_TEST (test_ipv4)
{
#define IP_TST_SIZ 256
uint32_t i;
struct pico_device *dev[IP_TST_SIZ];
char devname[8];
struct pico_ip4 a[IP_TST_SIZ], d[IP_TST_SIZ], *source[IP_TST_SIZ], nm16, nm32, gw[IP_TST_SIZ], r[IP_TST_SIZ], ret;
struct pico_ipv4_link *l[IP_TST_SIZ];
char ipstr[] = "192.168.1.1";
struct pico_ip4 ipaddr;
struct pico_frame *f_NULL = NULL;
struct pico_ip4 *dst_NULL = NULL;
pico_stack_init();
nm16.addr = long_be(0xFFFF0000);
nm32.addr = long_be(0xFFFFFFFF);
/*link_add*/
for (i = 0; i < IP_TST_SIZ; i++) {
snprintf(devname, 8, "nul%d", i);
dev[i] = pico_null_create(devname);
a[i].addr = long_be(0x0a000001u + (i << 16));
d[i].addr = long_be(0x0a000002u + (i << 16));
fail_if(pico_ipv4_link_add(dev[i], a[i], nm16) != 0, "Error adding link");
}
/*link_find + link_get + route_add*/
for (i = 0; i < IP_TST_SIZ; i++) {
gw[i].addr = long_be(0x0a0000f0u + (i << 16));
r[i].addr = long_be(0x0c00001u + (i << 16));
fail_unless(pico_ipv4_link_find(&a[i]) == dev[i], "Error finding link");
l[i] = pico_ipv4_link_get(&a[i]);
fail_if(l[i] == NULL, "Error getting link");
fail_if(pico_ipv4_route_add(r[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
fail_if(pico_ipv4_route_add(d[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
}
/*get_gateway + source_find*/
for (i = 0; i < IP_TST_SIZ; i++) {
ret = pico_ipv4_route_get_gateway(&r[i]);
fail_if(ret.addr != gw[i].addr, "Error get gateway: returned wrong route");
source[i] = pico_ipv4_source_find(&d[i]);
fail_if(source[i]->addr != a[i].addr, "Error find source: returned wrong route");
}
/*route_del + link_del*/
for (i = 0; i < IP_TST_SIZ; i++) {
fail_if(pico_ipv4_route_del(r[i], nm32, 1) != 0, "Error deleting route");
fail_if(pico_ipv4_link_del(dev[i], a[i]) != 0, "Error deleting link");
}
/*string_to_ipv4 + ipv4_to_string*/
pico_string_to_ipv4(ipstr, &(ipaddr.addr));
fail_if(ipaddr.addr != long_be(0xc0a80101), "Error string to ipv4");
memset(ipstr, 0, 12);
pico_ipv4_to_string(ipstr, ipaddr.addr);
fail_if(strncmp(ipstr, "192.168.1.1", 11) != 0, "Error ipv4 to string");
/*valid_netmask*/
fail_if(pico_ipv4_valid_netmask(long_be(nm32.addr)) != 32, "Error checking netmask");
/*is_unicast*/
fail_if((pico_ipv4_is_unicast(long_be(0xc0a80101))) != 1, "Error checking unicast");
fail_if((pico_ipv4_is_unicast(long_be(0xe0000001))) != 0, "Error checking unicast");
/*rebound*/
fail_if(pico_ipv4_rebound(f_NULL) != -1, "Error rebound frame");
/*frame_push*/
fail_if(pico_ipv4_frame_push(f_NULL, dst_NULL, PICO_PROTO_TCP) != -1, "Error push frame");
}
END_TEST
START_TEST (test_nat_enable_disable)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
const char *raw_data = "ello";
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src.addr = long_be(0x0a280008); /* 10.40.0.8 */
net->dst.addr = long_be(0x0a320001); /* 10.50.0.1 */
udp->trans.sport = short_be(5555);
udp->trans.dport = short_be(6667);
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT ENABLE/DISABLE TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
fail_unless(nat_link->address.addr == link.address.addr);
fail_unless(pico_ipv4_nat_is_enabled(&link.address));
fail_if(pico_ipv4_nat_outbound(f, &net->dst));
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
fail_if(pico_ipv4_nat_disable());
fail_if(pico_ipv4_nat_is_enabled(&link.address));
}
END_TEST
START_TEST (test_nat_translation)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
struct pico_ip4 src_ori = {
.addr = long_be(0x0a280008)
}; /* 10.40.0.8 */
struct pico_ip4 dst_ori = {
.addr = long_be(0x0a320009)
}; /* 10.50.0.9 */
struct pico_ip4 nat = {
.addr = long_be(0x0a320001)
}; /* 10.50.0.9 */
const char *raw_data = "ello";
uint16_t sport_ori = short_be(5555);
uint16_t dport_ori = short_be(6667);
uint16_t nat_port = 0;
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src = src_ori;
net->dst = dst_ori;
udp->trans.sport = sport_ori;
udp->trans.dport = dport_ori;
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT TRANSLATION TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
/* perform outbound translation, check if source IP got translated */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
/* perform outbound translation of same packet, check if source IP and PORT got translated the same as previous packet */
nat_port = udp->trans.sport;
net->src = src_ori; /* restore original src */
udp->trans.sport = sport_ori; /* restore original sport */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
fail_if(udp->trans.sport != nat_port, "frames with the same source IP, source PORT and PROTO did not get translated the same");
/* perform outbound translation of packet with changed source PORT, check if source PORT got translated differently as previous packet */
nat_port = udp->trans.sport;
net->src = src_ori; /* restore original src */
udp->trans.sport = short_be(5556); /* change sport */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
fail_if(udp->trans.sport == short_be(sport_ori), "two frames with different sport get translated the same");
/* perform inbound translation of previous packet, check if destination IP and PORT got translated to the original source IP and PORT */
nat_port = udp->trans.sport;
net->src = dst_ori;
net->dst = nat;
udp->trans.sport = sport_ori;
udp->trans.dport = nat_port;
fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
fail_if(net->dst.addr != src_ori.addr, "destination address not translated correctly");
fail_if(udp->trans.dport != short_be(5556), "ports not translated correctly");
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
fail_if(pico_ipv4_nat_disable());
}
END_TEST
START_TEST (test_nat_port_forwarding)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
struct pico_ip4 src_addr = {
.addr = long_be(0x0a280008)
}; /* 10.40.0.8 */
struct pico_ip4 dst_addr = {
.addr = long_be(0x0a320009)
}; /* 10.50.0.9 */
struct pico_ip4 nat_addr = {
.addr = long_be(0x0a320001)
}; /* 10.50.0.9 */
const char *raw_data = "ello";
uint16_t sport_ori = short_be(5555);
uint16_t fport_pub = short_be(80);
uint16_t fport_priv = short_be(8080);
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src = dst_addr;
net->dst = nat_addr;
udp->trans.sport = sport_ori;
udp->trans.dport = fport_pub;
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT PORT FORWARD TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_ADD));
fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
fail_if(net->dst.addr != src_addr.addr, "destination address not translated correctly");
fail_if(udp->trans.dport != fport_priv, "destination port not translated correctly");
fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_DEL));
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
}
END_TEST
START_TEST (test_ipfilter)
{
struct pico_device *dev = NULL;
uint8_t proto = 0, tos = 0;
uint16_t sport = 0, dport = 0;
int8_t priority = 0;
int ret = 0;
struct pico_ip4 src_addr = {
0
};
struct pico_ip4 saddr_netmask = {
0
};
struct pico_ip4 dst_addr = {
0
};
struct pico_ip4 daddr_netmask = {
0
};
enum filter_action action = 1;
uint32_t filter_id1;
/* 192.168.1.2:16415 -> 192.168.1.109:1222 [sending a TCP syn] */
uint8_t ipv4_buf[] = {
0x00, 0x02, 0xf7, 0xf1, 0x79, 0x33, 0xe0, 0xdb, 0x55,
0xd4, 0xb6, 0x27, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28,
0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf7, 0x0f, 0xc0,
0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x6d, 0x40, 0x1f,
0x04, 0xc6, 0x00, 0xb1, 0x56, 0x5a, 0x00, 0x00, 0x00,
0x00, 0x50, 0x02, 0x20, 0x00, 0x70, 0x32, 0x00, 0x00
};
struct pico_frame *f;
printf("IP Filter> Adding a new filter...\n");
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
fail_if(filter_id1 <= 0, "Error adding filter\n");
printf("filter_id1 = %d\n", filter_id1);
printf("IP Filter> Trying to add the same filter...\n");
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
fail_if(ret > 0, "Error adding filter\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Trying to delete the same filter\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != -1, "Deleting non existing filter failed\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
/* adding exact filter */
pico_string_to_ipv4("192.168.1.109", &src_addr.addr);
pico_string_to_ipv4("255.255.255.255", &saddr_netmask.addr);
sport = 1222u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_REJECT);
fail_if(filter_id1 <= 0, "Error adding exact filter\n");
printf("Filter is added\n");
sync();
sleep(1);
ret = ipfilter(f);
fail_if(ret != 1, "Frame wasn't filtered\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Adding masked filter...\n");
pico_string_to_ipv4("192.168.1.7", &src_addr.addr);
pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
sport = 1222u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
fail_if(filter_id1 <= 0, "Error adding masked filter\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
ret = ipfilter(f);
fail_if(ret != 1, "Mask filter failed to filter\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Adding bad filter..\n");
pico_string_to_ipv4("191.1.1.7", &src_addr.addr);
pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
sport = 1991u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
fail_if(filter_id1 <= 0, "Error adding bad filter\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
ret = ipfilter(f);
fail_if(ret != 0, "Filter shouldn't have filtered this frame\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
}
END_TEST
#ifdef PICO_SUPPORT_MCAST
START_TEST (test_igmp_sockopts)
{
int i = 0, j = 0, k = 0, ret = 0;
struct pico_socket *s, *s1 = NULL;
struct pico_device *dev = NULL;
union pico_address *source = NULL;
union pico_address inaddr_dst = {
0
}, inaddr_incorrect = {
0
}, inaddr_uni = {
0
}, inaddr_null = {
0
}, netmask = {
0
};
union pico_address inaddr_link[2] = {0};
union pico_address inaddr_mcast[8] = {0};
union pico_address inaddr_source[8] = {0};
struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
struct pico_ip_mreq_source mreq_source[128] = {0};
struct pico_tree_node *index = NULL;
int ttl = 64;
int getttl = 0;
int loop = 9;
int getloop = 0;
union pico_address mcast_def_link = {
0
};
pico_stack_init();
printf("START IGMP SOCKOPTS TEST\n");
pico_string_to_ipv4("224.7.7.7", &inaddr_dst.ip4.addr);
pico_string_to_ipv4("10.40.0.2", &inaddr_uni.ip4.addr);
pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.ip4.addr);
pico_string_to_ipv4("0.0.0.0", &inaddr_null.ip4.addr);
pico_string_to_ipv4("10.40.0.1", &inaddr_link[0].ip4.addr); /* 0 */
pico_string_to_ipv4("10.50.0.1", &inaddr_link[1].ip4.addr); /* 1 */
pico_string_to_ipv4("232.1.1.0", &inaddr_mcast[0].ip4.addr); /* 0 */
pico_string_to_ipv4("232.2.2.1", &inaddr_mcast[1].ip4.addr); /* 1 */
pico_string_to_ipv4("232.3.3.2", &inaddr_mcast[2].ip4.addr); /* 2 */
pico_string_to_ipv4("232.4.4.3", &inaddr_mcast[3].ip4.addr); /* 3 */
pico_string_to_ipv4("232.5.5.4", &inaddr_mcast[4].ip4.addr); /* 4 */
pico_string_to_ipv4("232.6.6.5", &inaddr_mcast[5].ip4.addr); /* 5 */
pico_string_to_ipv4("232.7.7.6", &inaddr_mcast[6].ip4.addr); /* 6 */
pico_string_to_ipv4("232.8.8.7", &inaddr_mcast[7].ip4.addr); /* 7 */
pico_string_to_ipv4("10.40.1.0", &inaddr_source[0].ip4.addr); /* 0 */
pico_string_to_ipv4("10.40.1.1", &inaddr_source[1].ip4.addr); /* 1 */
pico_string_to_ipv4("10.40.1.2", &inaddr_source[2].ip4.addr); /* 2 */
pico_string_to_ipv4("10.40.1.3", &inaddr_source[3].ip4.addr); /* 3 */
pico_string_to_ipv4("10.40.1.4", &inaddr_source[4].ip4.addr); /* 4 */
pico_string_to_ipv4("10.40.1.5", &inaddr_source[5].ip4.addr); /* 5 */
pico_string_to_ipv4("10.40.1.6", &inaddr_source[6].ip4.addr); /* 6 */
pico_string_to_ipv4("10.40.1.7", &inaddr_source[7].ip4.addr); /* 7 */
/* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
for (i = 0; i < 16; i++) {
mreq[i].mcast_link_addr = inaddr_link[i / 8];
mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
}
/* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017 */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
/* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
}
}
dev = pico_null_create("dummy0");
netmask.ip4.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link[0].ip4, netmask.ip4);
fail_if(ret < 0, "link add failed");
dev = pico_null_create("dummy1");
netmask.ip4.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link[1].ip4, netmask.ip4);
fail_if(ret < 0, "link add failed");
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(s == NULL, "UDP socket open failed");
s1 = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(s1 == NULL, "UDP socket open failed");
/* argument validation tests */
printf("IGMP SETOPTION ARGUMENT VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
loop = 0;
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
fail_if(getloop != loop, "setoption loop != getoption loop\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_null;
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
_mreq.mcast_group_addr = inaddr_uni;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
_mreq.mcast_group_addr = inaddr_null;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_uni;
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
_mreq.mcast_group_addr = inaddr_incorrect;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
_mreq.mcast_group_addr = inaddr_uni;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
_mreq.mcast_group_addr = inaddr_null;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_uni;
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
/* flow validation tests */
printf("IGMP SETOPTION FLOW VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* stress tests */
printf("IGMP SETOPTION STRESS TEST\n");
for (k = 0; k < 2; k++) {
/* ADD for even combinations of group and link, ADD_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
}
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* everything should be cleanup up, next iteration will fail if not */
}
/* filter validation tests */
printf("IGMP SETOPTION FILTER VALIDATION TEST\n");
/* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* INCLUDE + EXCLUDE expected filter: source of 2 */
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 1)
fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[2].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[3].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[4].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_close(s);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(s1);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#endif
START_TEST (test_slaacv4)
{
uint32_t tmp;
struct pico_device *dev;
struct mock_device *mock;
char ip_addr[20];
uint8_t macaddr1[6] = {
0xc3, 0, 0, 0xa, 0xc, 0xf
};
/* verify min boundary*/
tmp = SLAACV4_CREATE_IPV4(0);
pico_ipv4_to_string(ip_addr, tmp);
printf("IP address generated by slaac: %s\n", ip_addr);
fail_if(long_be(tmp) < (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
/* verify max boundary*/
tmp = SLAACV4_CREATE_IPV4(0x00FD);
fail_if(long_be(tmp) > (long_be(SLAACV4_NETWORK) | 0x0000FEFF));
/* verify case where dev->eth is NULL */
dev = pico_null_create("dummy");
tmp = pico_slaacv4_getip(dev, 0);
fail_if(long_be(tmp) != (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
/* verify nominal case; two runs of slaacv4_get_ip need to return same value */
mock = pico_mock_create(macaddr1);
tmp = pico_slaacv4_getip(mock->dev, 0);
fail_if(tmp != pico_slaacv4_getip(mock->dev, 0));
}
END_TEST

View File

@@ -0,0 +1,760 @@
#ifdef PICO_SUPPORT_IPV6
START_TEST (test_ipv6)
{
char ipstr[40] = {
0
};
char ipstr0[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr0_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr1[] = "2001:db8:130f:0000:0000:09c0:876a:130b";
char ipstr1_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr2[] = "2001:b8:130f:0000:0000:09c0:876a:130b";
char ipstr2_t[] = "2001:00b8:130f:0000:0000:09c0:876a:130b";
char ipstr3[] = "2001:8:130f:0000:0000:09c0:876a:130b";
char ipstr3_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
char ipstr4[] = "2001:8:130f:0:0:09c0:876a:130b";
char ipstr4_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
char ipstr5[] = "2001::8:130f:09c0:876a:130b";
char ipstr5_t[] = "2001:0000:0000:0008:130f:09c0:876a:130b";
char ipstr6[] = "2001::8:09c0:876a:130b";
char ipstr6_t[] = "2001:0000:0000:0000:0008:09c0:876a:130b";
char ipstr7[] = "2001::8:876a:130b";
char ipstr7_t[] = "2001:0000:0000:0000:0000:0008:876a:130b";
char ipstr8[] = "2001::876a:130b";
char ipstr8_t[] = "2001:0000:0000:0000:0000:0000:876a:130b";
char ipstr9[] = "ff01::1";
char ipstr9_t[] = "ff01:0000:0000:0000:0000:0000:0000:0001";
char ipstr10[] = "::1";
char ipstr10_t[] = "0000:0000:0000:0000:0000:0000:0000:0001";
char ipstr11[] = "fe80::";
char ipstr11_t[] = "fe80:0000:0000:0000:0000:0000:0000:0000";
char ipstr12[] = "::";
char ipstr12_t[] = "0000:0000:0000:0000:0000:0000:0000:0000";
char ipstr13[] = "2001:8:130f::09c0::130b"; /* invalid */
char ipstr14[] = "2001:8:xxxx::09c0:130b"; /* invalid */
char ipstr15[] = "2001:8:$$$$::09c0:130b"; /* invalid */
char ipstr16[] = "2001:8:!@#$::%^&*:()0b"; /* invalid */
char ipstr17[] = "2001:1"; /* invalid */
char ipstr18[] = "20010db8:130f:0000:0000:09c0:876a:130b"; /* invalid */
char ipstr19[] = "20010db8130f0000000009c0876a130b"; /* invalid */
char ipstr20[] = "2001;0db8;130f;0000;0000;09c0;876a;130b"; /* invalid */
uint8_t iphex0[PICO_SIZE_IP6] = {
0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex1[PICO_SIZE_IP6] = {
0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex2[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex3[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex4[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex5[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x0f, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex6[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex7[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex8[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex9[PICO_SIZE_IP6] = {
0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
uint8_t iphex10[PICO_SIZE_IP6] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
uint8_t iphex11[PICO_SIZE_IP6] = {
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t iphex12[PICO_SIZE_IP6] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
struct pico_ip6 iphex_a = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }};
struct pico_ip6 iphex_r = {{ 0x40, 0x02, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }};
struct pico_ip6 iphex_gw = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f }};
struct pico_ip6 nm64 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
struct pico_ip6 nm128 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
struct pico_ip6 ipaddr = {{0}};
struct pico_ip6 _gw, r[IP_TST_SIZ], a[IP_TST_SIZ], gw[IP_TST_SIZ], *source[IP_TST_SIZ];
struct pico_device *dev[IP_TST_SIZ];
struct pico_ipv6_link *l[IP_TST_SIZ];
struct pico_ipv6_link *_link = NULL;
struct pico_ipv6_route *_route = NULL;
char devname[8];
int ret = 0;
int i = 0;
pico_stack_init();
/* pico_string_to_ipv6 and pico_ipv6_to_string */
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr0);
pico_string_to_ipv6(ipstr0, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex0, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr0_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr1);
pico_string_to_ipv6(ipstr1, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex1, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr1_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr2);
pico_string_to_ipv6(ipstr2, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex2, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr2_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr3);
pico_string_to_ipv6(ipstr3, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex3, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr3_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr4);
pico_string_to_ipv6(ipstr4, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex4, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr4_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr5);
pico_string_to_ipv6(ipstr5, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex5, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr5_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr6);
pico_string_to_ipv6(ipstr6, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex6, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr6_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr7);
pico_string_to_ipv6(ipstr7, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex7, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr7_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr8);
pico_string_to_ipv6(ipstr8, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex8, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr8_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr9);
pico_string_to_ipv6(ipstr9, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex9, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr9_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr10);
pico_string_to_ipv6(ipstr10, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex10, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr10_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr11);
pico_string_to_ipv6(ipstr11, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex11, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr11_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr12);
pico_string_to_ipv6(ipstr12, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex12, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr12_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr13);
ret = pico_string_to_ipv6(ipstr13, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr14);
ret = pico_string_to_ipv6(ipstr14, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr15);
ret = pico_string_to_ipv6(ipstr15, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr16);
ret = pico_string_to_ipv6(ipstr16, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr17);
ret = pico_string_to_ipv6(ipstr17, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr18);
ret = pico_string_to_ipv6(ipstr18, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr19);
ret = pico_string_to_ipv6(ipstr19, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr20);
ret = pico_string_to_ipv6(ipstr20, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
/*link_add*/
for (i = 0; i < 10; ++i) {
snprintf(devname, 8, "nul%d", i);
dev[i] = pico_null_create(devname);
a[i] = iphex_a;
a[i].addr[4] = (uint8_t)(a[i].addr[4] + i);
fail_if(pico_ipv6_link_add(dev[i], a[i], nm64) == NULL, "Error adding link");
}
/*link_find + link_get + route_add*/
for (i = 0; i < 10; ++i) {
gw[i] = iphex_gw;
gw[i].addr[4] = (uint8_t)(gw[i].addr[4] + i);
fail_unless(pico_ipv6_link_find(&a[i]) == dev[i], "Error finding link");
l[i] = pico_ipv6_link_get(&a[i]);
fail_if(l[i] == NULL, "Error getting link");
r[i] = iphex_r;
r[i].addr[4] = (uint8_t)(r[i].addr[4] + i);
fail_if(pico_ipv6_route_add(r[i], nm128, a[i], 1, l[i]) != 0, "Error adding route");
}
/*get_gateway*/
for (i = 0; i < 10; i++) {
_gw = pico_ipv6_route_get_gateway(&r[i]);
fail_if(memcmp(_gw.addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error get gateway: returned wrong route");
source[i] = pico_ipv6_source_find(&r[i]);
fail_if(memcmp(source[i]->addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error find source: returned wrong route");
}
/*route_del + link_del*/
for (i = 0; i < 10; i++) {
fail_if(pico_ipv6_route_del(r[i], nm128, a[i], 1, l[i]) != 0, "Error deleting route");
fail_if(pico_ipv6_link_del(dev[i], a[i]) != 0, "Error deleting link");
}
/* add 2 links to dev[0] */
_link = pico_ipv6_link_add(dev[0], a[0], nm64);
fail_if (!_link, "Error adding link");
_link = pico_ipv6_link_add(dev[0], a[1], nm64);
fail_if (!_link, "Error adding link");
/* add 2 routes to each of the links */
ret = pico_ipv6_route_add(r[0], nm128, a[0], 1, l[0]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[1], nm128, a[0], 1, l[0]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[2], nm128, a[1], 1, l[1]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[3], nm128, a[1], 1, l[1]);
fail_if(ret != 0, "Error adding route");
/* add 2 links to dev[1] */
_link = pico_ipv6_link_add(dev[1], a[8], nm64);
fail_if (!_link, "Error adding link");
_link = pico_ipv6_link_add(dev[1], a[9], nm64);
fail_if (!_link, "Error adding link");
/* add 2 routes to each of the links */
ret = pico_ipv6_route_add(r[6], nm128, a[8], 1, l[8]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[7], nm128, a[8], 1, l[8]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[8], nm128, a[9], 1, l[9]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[9], nm128, a[9], 1, l[9]);
fail_if(ret != 0, "Error adding route");
/* destroy device, should clean up all links and routes */
pico_device_destroy(dev[0]);
_link = pico_ipv6_link_get(&a[0]);
fail_if(_link != NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[1]);
fail_if(_link != NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[8]);
fail_if(_link == NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[9]);
fail_if(_link == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[0]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[1]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[2]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[3]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[6]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[7]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[8]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[9]);
fail_if(_route == NULL, "Error destroying device");
}
END_TEST
#ifdef PICO_SUPPORT_MCAST
START_TEST (test_mld_sockopts)
{
int i = 0, j = 0, k = 0, ret = 0;
struct pico_socket *s, *s1 = NULL;
struct pico_device *dev = NULL;
union pico_address *source = NULL;
union pico_address inaddr_dst = {
0
}, inaddr_incorrect = {
0
}, inaddr_uni = {
0
}, inaddr_null = {
0
};
struct pico_ip6 netmask = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
union pico_address inaddr_link[2] = {0};
union pico_address inaddr_mcast[8] = {0};
union pico_address inaddr_source[8] = {0};
struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
struct pico_ip_mreq_source mreq_source[128] = {0};
struct pico_tree_node *index = NULL;
struct pico_ipv6_link *ret_link = NULL;
int ttl = 64;
int getttl = 0;
int loop = 9;
int getloop = 0;
struct pico_ip6 mcast_def_link = {
0
};
pico_stack_init();
printf("START MLD SOCKOPTS TEST\n");
pico_string_to_ipv6("ff00:0:0:0:0:0:e007:707", inaddr_dst.ip6.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:2", inaddr_uni.ip6.addr);
pico_string_to_ipv6("ff00:0:0:0:0:0:e008:808", inaddr_incorrect.ip6.addr);
pico_string_to_ipv6("::", inaddr_null.ip6.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:0001", inaddr_link[0].ip6.addr); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a32:0001", inaddr_link[1].ip6.addr); /* 1 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", inaddr_mcast[0].ip6.addr); /* 0 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e802:201", inaddr_mcast[1].ip6.addr); /* 1 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:302", inaddr_mcast[2].ip6.addr); /* 2 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:403", inaddr_mcast[3].ip6.addr); /* 3 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:504", inaddr_mcast[4].ip6.addr); /* 4 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:605", inaddr_mcast[5].ip6.addr); /* 5 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:706", inaddr_mcast[6].ip6.addr); /* 6 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:807", inaddr_mcast[7].ip6.addr); /* 7 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", inaddr_source[0].ip6.addr); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:101", inaddr_source[1].ip6.addr); /* 1 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:102", inaddr_source[2].ip6.addr); /* 2 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:103", inaddr_source[3].ip6.addr); /* 3 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:104", inaddr_source[4].ip6.addr); /* 4 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:105", inaddr_source[5].ip6.addr); /* 5 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:106", inaddr_source[6].ip6.addr); /* 6 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:107", inaddr_source[7].ip6.addr); /* 7 */
/* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
for (i = 0; i < 16; i++) {
mreq[i].mcast_link_addr = inaddr_link[i / 8];
mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
}
/* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017 */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
/* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
}
}
dev = pico_null_create("dummy0");
ret_link = pico_ipv6_link_add(dev, inaddr_link[0].ip6, netmask);
fail_if(ret_link == NULL, "link add failed");
dev = pico_null_create("dummy1");
ret_link = pico_ipv6_link_add(dev, inaddr_link[1].ip6, netmask);
fail_if(ret_link == NULL, "link add failed");
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
fail_if(s == NULL, "UDP socket open failed");
s1 = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
fail_if(s1 == NULL, "UDP socket open failed");
/* argument validation tests */
printf("MLD SETOPTION ARGUMENT VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
loop = 0;
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
fail_if(getloop != loop, "setoption loop != getoption loop\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_incorrect.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
/* flow validation tests */
printf("MLD SETOPTION FLOW VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* stress tests */
printf("MLD SETOPTION STRESS TEST\n");
for (k = 0; k < 2; k++) {
/* ADD for even combinations of group and link, ADD_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
}
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* everything should be cleanup up, next iteration will fail if not */
}
/* filter validation tests */
printf("MLD SETOPTION FILTER VALIDATION TEST\n");
/* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* INCLUDE + EXCLUDE expected filter: source of 2 */
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 1)
fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[2].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[3].mcast_source_addr, sizeof(struct pico_ip6) == 0)) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[4].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_close(s);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(s1);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
#define BUFLEN (576 + 14 + 20 + 8)
int mock_print_protocol(uint8_t *buf);
int printbuf(uint8_t *buf, uint32_t len, const char *str, uint8_t printbufactive);
int tick_it(uint32_t nticks);
int mock_print_protocol(uint8_t *buf)
{
uint8_t pnr = buf[0x17]; /* protocol number */
printf("transport protocol: %s\n",
(pnr == PICO_PROTO_ICMP4 ? "icmp4" :
(pnr == PICO_PROTO_IGMP ? "igmp" :
(pnr == PICO_PROTO_TCP ? "tcp" :
(pnr == PICO_PROTO_UDP ? "udp" :
(pnr == PICO_PROTO_ICMP6 ? "icmp6" :
"unknown proto"))))));
return 0;
}
int printbuf(uint8_t *buf, uint32_t len, const char *str, uint8_t printbufactive)
{
uint8_t printMethod = 0;
uint32_t cntr = 0;
uint32_t cntr2 = 0;
if((printbufactive) && (printMethod == 0)) {
printf("\n%s:\n", str);
for(cntr = 0; cntr < len; cntr++) {
if((cntr % 8) == 0 && cntr != 0)
printf(" ");
if((cntr % 16) == 0 && cntr != 0)
printf("\n");
if((cntr % 16) == 0)
printf("%03x0 ", cntr2++);
printf("%02x ", buf[cntr]);
}
printf("\n");
}else if((printbufactive) && (printMethod == 1)) {
printf("\n%s:\n", str);
printf("Buf = {");
for(cntr = 0; cntr < len; cntr++) {
if(cntr != 0)
printf(",");
if((cntr % 16 == 0) && (cntr != 0))
printf("\n");
printf("0x%02x", buf[cntr]);
}
printf("}\n");
}
return 0;
}
#define BUFLEN (576 + 14 + 20 + 8)
#define DHCP_MSG_TYPE_DISCOVER (1)
#define DHCP_MSG_TYPE_OFFER (2)
#define DHCP_MSG_TYPE_REQUEST (3)
#define DHCP_MSG_TYPE_ACK (4)
int tick_it(uint32_t nticks)
{
uint32_t i = 0;
for (i = 0; i < nticks; i++) {
pico_stack_tick();
}
return 0;
}

View File

@@ -0,0 +1,93 @@
/* RB tree unit test */
typedef struct
{
int value;
}elem;
int compare(void *a, void *b);
int compare(void *a, void *b)
{
return ((elem *)a)->value - ((elem *)b)->value;
}
static PICO_TREE_DECLARE(test_tree, compare);
static PICO_TREE_DECLARE(test_tree2, compare);
#define RBTEST_SIZE 20000
START_TEST (test_rbtree2)
{
struct pico_tree_node *s;
elem *e;
int i, last;
struct timeval start, end;
gettimeofday(&start, 0);
srand48(RBTEST_SIZE); /* use test-size as salt */
for (i = 0; i < (RBTEST_SIZE >> 1); i++)
{
e = malloc(sizeof(elem));
e->value = (int)lrand48() % RBTEST_SIZE;
if (pico_tree_findKey(&test_tree2, e)) {
free(e);
} else {
pico_tree_insert(&test_tree2, e);
}
}
gettimeofday(&end, 0);
printf("Rbtree test 2 inserted %d entries in %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
last = 0;
pico_tree_foreach(s, &test_tree2){
fail_if (last > ((elem *)(s->keyValue))->value, "error");
last = ((elem *)(s->keyValue))->value;
}
gettimeofday(&end, 0);
printf("Rbtree test 2 duration with %d entries: %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
printf("Test finished.\n");
}
END_TEST
START_TEST (test_rbtree)
{
struct pico_tree_node *s, *tmp;
elem t, *e;
int i;
struct timeval start, end;
printf("Started test...\n");
gettimeofday(&start, 0);
for (i = 0; i < (RBTEST_SIZE >> 1); i++) {
e = malloc(sizeof(elem));
e->value = i;
pico_tree_insert(&test_tree, e);
/* RB_INSERT(rbtree, &RBTREE, e); */
e = malloc(sizeof(elem));
e->value = (RBTEST_SIZE - 1) - i;
pico_tree_insert(&test_tree, e);
}
i = 0;
pico_tree_foreach(s, &test_tree){
fail_if (i++ != ((elem *)(s->keyValue))->value, "error");
}
t.value = RBTEST_SIZE >> 2;
e = pico_tree_findKey(&test_tree, &t);
fail_if(!e, "Search failed...");
fail_if(e->value != t.value, "Wrong element returned...");
pico_tree_foreach_reverse_safe(s, &test_tree, tmp){
fail_if(!s, "Reverse safe returned null");
e = (elem *)pico_tree_delete(&test_tree, s->keyValue);
free(e);
}
fail_if(!pico_tree_empty(&test_tree), "Not empty");
gettimeofday(&end, 0);
printf("Rbtree test duration with %d entries: %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
printf("Test finished...\n");
}
END_TEST

View File

@@ -0,0 +1,521 @@
int pico_aodv_init(void)
{
return 0;
}
START_TEST (test_socket)
{
int ret = 0;
uint16_t port_be = 0, porta, proto, port_got;
char buf[] = "test";
struct pico_socket *sk_tcp, *sk_udp, *s, *sl, *sa;
struct pico_device *dev;
struct pico_ip4 inaddr_dst, inaddr_link, inaddr_incorrect, inaddr_uni, inaddr_null, netmask, orig, inaddr_got;
int getnodelay = -1;
int nodelay = -1;
int count = 0;
uint32_t getsocket_buffer = 0;
uint32_t socket_buffer = 0;
pico_stack_init();
printf("START SOCKET TEST\n");
pico_string_to_ipv4("224.7.7.7", &inaddr_dst.addr);
pico_string_to_ipv4("10.40.0.2", &inaddr_link.addr);
pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.addr);
pico_string_to_ipv4("0.0.0.0", &inaddr_null.addr);
pico_string_to_ipv4("10.40.0.3", &inaddr_uni.addr);
dev = pico_null_create("dummy");
netmask.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link, netmask);
fail_if(ret < 0, "socket> error adding link");
/* socket_open passing wrong parameters */
s = pico_socket_open(PICO_PROTO_IPV4, 99, NULL);
fail_if(s != NULL, "Error got socket wrong parameters");
s = pico_socket_open(PICO_PROTO_IPV4, 0xFFFF, NULL);
fail_if(s != NULL, "Error got socket");
s = pico_socket_open(99, PICO_PROTO_UDP, NULL);
fail_if(s != NULL, "Error got socket");
s = pico_socket_open(0xFFFF, PICO_PROTO_UDP, NULL);
fail_if(s != NULL, "Error got socket");
sk_tcp = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, NULL);
fail_if(sk_tcp == NULL, "socket> tcp socket open failed");
port_be = short_be(5555);
/* socket_bind passing wrong parameters */
ret = pico_socket_bind(NULL, &inaddr_link, &port_be);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
ret = pico_socket_bind(sk_tcp, NULL, &port_be);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
ret = pico_socket_bind(sk_tcp, &inaddr_link, NULL);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
/* socket_getname passing wrong parameters */
ret = pico_socket_getname(NULL, &inaddr_link, &port_be, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, NULL, &port_be, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, &inaddr_link, NULL, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, &inaddr_link, &port_be, NULL);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
/* socket_bind passing correct parameters */
ret = pico_socket_bind(sk_tcp, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> tcp socket bind failed");
count = pico_count_sockets(PICO_PROTO_TCP);
printf("Count: %d\n", count);
fail_unless(count == 1);
count = pico_count_sockets(0);
printf("Count: %d\n", count);
fail_unless(count == 1);
sk_udp = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(sk_udp == NULL, "socket> udp socket open failed");
port_be = short_be(5555);
ret = pico_socket_bind(sk_udp, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> udp socket bind failed");
fail_if (pico_count_sockets(PICO_PROTO_UDP) != 1);
fail_if (pico_count_sockets(0) != 2);
ret = pico_socket_getname(sk_udp, &inaddr_got, &port_got, &proto);
fail_if(ret < 0, "socket> udp socket getname failed");
fail_if(inaddr_got.addr != inaddr_link.addr, "Getname: Address is different");
fail_if(port_be != port_got, "Getname: Port is different");
fail_if(proto != PICO_PROTO_IPV4, "Getname: proto is wrong");
/* socket_close passing wrong parameter */
ret = pico_socket_close(NULL);
fail_if(ret == 0, "Error socket close with wrong parameters");
/* socket_connect passing wrong parameters */
ret = pico_socket_connect(sk_udp, NULL, port_be);
fail_if(ret == 0, "Error socket connect with wrong parameters");
ret = pico_socket_connect(NULL, &inaddr_dst, port_be);
fail_if(ret == 0, "Error socket connect with wrong parameters");
/* socket_connect passing correct parameters */
ret = pico_socket_connect(sk_udp, &inaddr_dst, port_be);
fail_if(ret < 0, "Error socket connect");
ret = pico_socket_connect(sk_tcp, &inaddr_dst, port_be);
fail_if(ret < 0, "Error socket connect");
/* testing listening socket */
sl = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, NULL);
fail_if(sl == NULL, "socket> tcp socket open failed");
port_be = short_be(6666);
ret = pico_socket_bind(sl, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> tcp socket bind failed");
/* socket_listen passing wrong parameters */
ret = pico_socket_listen(sl, 0);
fail_if(ret == 0, "Error socket tcp socket listen done, wrong parameter");
ret = pico_socket_listen(NULL, 10);
fail_if(ret == 0, "Error socket tcp socket listen done, wrong parameter");
/* socket_listen passing correct parameters */
ret = pico_socket_listen(sl, 10);
fail_if(ret < 0, "socket> tcp socket listen failed: %s", strerror(pico_err));
/* socket_accept passing wrong parameters */
sa = pico_socket_accept(sl, &orig, NULL);
fail_if(sa != NULL, "Error socket tcp socket accept wrong argument");
sa = pico_socket_accept(sl, NULL, &porta);
fail_if(sa != NULL, "Error socket tcp socket accept wrong argument");
/* socket_accept passing correct parameters */
sa = pico_socket_accept(sl, &orig, &porta);
fail_if(sa == NULL && pico_err != PICO_ERR_EAGAIN, "socket> tcp socket accept failed: %s", strerror(pico_err));
ret = pico_socket_close(sl);
fail_if(ret < 0, "socket> tcp socket close failed: %s\n", strerror(pico_err));
/* testing socket read/write */
/* socket_write passing wrong parameters */
ret = pico_socket_write(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket write succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_write(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket write failed: %s\n", strerror(pico_err));
/* socket_read passing wrong parameters */
ret = pico_socket_read(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket read succeeded, wrong argument\n");
/* socket_read passing correct parameters */
ret = pico_socket_read(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket read failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns 0 when no frame !? */
/* send/recv */
/* socket_send passing wrong parameters */
ret = pico_socket_send(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket send succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_send(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret <= 0, "socket> tcp socket send failed: %s\n", strerror(pico_err));
/* socket_recv passing wrong parameters */
ret = pico_socket_recv(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket recv succeeded, wrong argument\n");
/* socket_recv passing correct parameters */
ret = pico_socket_recv(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket recv failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns 0 when no frame !? */
/* sendto/recvfrom */
/* socket_sendto passing wrong parameters */
ret = pico_socket_sendto(NULL, (void *)buf, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, NULL, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, 0, &inaddr_dst, port_be);
fail_if(ret > 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), NULL, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), &inaddr_dst, 0xFFFF);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), &inaddr_dst, short_be(5555));
fail_if(ret <= 0, "socket> udp socket sendto failed, ret = %d: %s\n", ret, strerror(pico_err));
/* socket_recvfrom passing wrong parameters */
ret = pico_socket_recvfrom(NULL, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, NULL, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, 0, &orig, &porta);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), NULL, &porta);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), &orig, NULL);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
/* socket_recvfrom passing correct parameters */
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret != 0, "socket> tcp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns -1 when no frame !? */
/* testing socket read/write */
/* socket_write passing wrong parameters */
ret = pico_socket_write(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket write succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_write(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket write failed: %s\n", strerror(pico_err));
/* socket_read passing wrong parameters */
ret = pico_socket_read(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, (void *)buf, 0xFFFF + 1);
fail_if(ret >= 0, "Error socket read succeeded while len was > 0xFFFF");
/* socket_read passing correct parameters */
ret = pico_socket_read(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret != 0, "socket> udp socket read failed, ret = %d: %s\n", ret, strerror(pico_err));
/* send/recv */
/* socket_send passing wrong parameters */
ret = pico_socket_send(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket send succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_send(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret <= 0, "socket> tcp socket send failed: %s\n", strerror(pico_err));
/* socket_recv passing wrong parameters */
ret = pico_socket_recv(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, (void *)buf, 0xFFFF + 1);
fail_if(ret >= 0, "Error socket recv succeeded while len was > 0xFFFF");
/* socket_recv passing correct parameters */
ret = pico_socket_recv(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret != 0, "socket> udp socket recv failed, ret = %d: %s\n", ret, strerror(pico_err));
/* sendto/recvfrom */
/* socket_sendto passing wrong parameters */
ret = pico_socket_sendto(NULL, (void *)buf, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, NULL, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, 0, &inaddr_dst, port_be);
fail_if(ret > 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), NULL, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), &inaddr_dst, 0xFFFF);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), &inaddr_dst, short_be(5555));
fail_if(ret <= 0, "socket> udp socket sendto failed, ret = %d: %s\n", ret, strerror(pico_err));
/* socket_recvfrom passing wrong parameters */
ret = pico_socket_recvfrom(NULL, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_udp, NULL, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_udp, (void *)buf, 0xFFFF + 1, &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded while len was > 0xFFFF");
/* socket_recvfrom passing correct parameters */
ret = pico_socket_recvfrom(sk_udp, (void *)buf, 0, &orig, &porta);
fail_if(ret != 0, "socket> udp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err));
ret = pico_socket_recvfrom(sk_udp, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret != 0, "socket> udp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err));
/* temporary fix, until Nagle problems are analyzed and fixed */
{
nodelay = 0;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
}
/* setoption/getoption */
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed (err = %s)\n", strerror(pico_err));
fail_if(getnodelay != 0, "socket> socket_setoption: default PICO_TCP_NODELAY != 0 (nagle disabled by default)\n");
nodelay = 1;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_TCP_NODELAY failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed\n");
fail_if(getnodelay == 0, "socket> socket_setoption: PICO_TCP_NODELAY is off (expected: on!)\n");
nodelay = 0;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_TCP_NODELAY failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed\n");
fail_if(getnodelay != 0, "socket> socket_setoption: PICO_TCP_NODELAY is on (expected: off!)\n");
/* Set/get recv buffer (TCP) */
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
/* Set/get send buffer (TCP) */
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT got: %d exp: %d\n", getsocket_buffer, PICO_DEFAULT_SOCKETQ);
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
/* Set/get recv buffer (UDP) */
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
/* Set/get send buffer (UDP) */
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
/* Close sockets, eventually. */
ret = pico_socket_close(sk_tcp);
fail_if(ret < 0, "socket> tcp socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(sk_udp);
fail_if(ret < 0, "socket> udp socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#ifdef PICO_SUPPORT_CRC_FAULTY_UNIT_TEST
START_TEST (test_crc_check)
{
uint8_t buffer[64] = {
0x45, 0x00, 0x00, 0x40, /* start of IP hdr */
0x91, 0xc3, 0x40, 0x00,
0x40, 0x11, 0x24, 0xcf, /* last 2 bytes are CRC */
0xc0, 0xa8, 0x01, 0x66,
0xc0, 0xa8, 0x01, 0x64, /* end of IP hdr */
0x15, 0xb3, 0x1F, 0x90, /* start of UDP/TCP hdr */
0x00, 0x2c, 0x27, 0x22, /* end of UDP hdr */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* end of TCP hdr */
0x01, 0x23, 0x45, 0x67, /* start of data */
0x89, 0xab, 0xcd, 0xef,
0xc0, 0xca, 0xc0, 0x1a
};
struct pico_frame *f = NULL;
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
struct pico_udp_hdr *udp_hdr = NULL;
struct pico_tcp_hdr *tcp_hdr = NULL;
uint32_t *f_usage_count = NULL;
uint8_t *f_buffer = NULL;
int ret = -1;
printf("START CRC TEST\n");
pico_stack_init();
/* IPv4 CRC unit tests */
/* Allocated memory will not be freed when pico_ipv4_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->net_len = PICO_SIZE_IP4HDR;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 512;
hdr->crc = 0;
printf(">>>>>>>>>>>>>>>>>>>>> CRC VALUE = %X\n", pico_checksum(hdr, PICO_SIZE_IP4HDR));
hdr->crc = short_be(0x24CF); /* Make check pass */
ret = pico_ipv4_crc_check(f);
fail_if(ret == 0, "correct IPv4 checksum got rejected\n");
hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_ipv4_crc_check(f);
fail_if(ret == 1, "incorrect IPv4 checksum got accepted\n");
/* UDP CRC unit tests */
/* Allocated memory will be freed when pico_transport_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 1;
hdr->proto = 0x11; /* UDP */
hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
/* udp_hdr->crc = 0; */
/* printf(">>>>>>>>>>>>>>>>>>>>> UDP CRC VALUE = %X\n", pico_udp_checksum_ipv4(f)); */
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "correct UDP checksum got rejected\n");
udp_hdr->crc = 0;
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "UDP checksum of 0 did not get ignored\n");
udp_hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_transport_crc_check(f);
fail_if(ret == 1, "incorrect UDP checksum got accepted\n");
/* TCP CRC unit tests */
/* Allocated memory will be freed when pico_transport_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 1;
hdr->proto = 0x06; /* TCP */
hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tcp_hdr->seq = long_be(0x002c2722); /* Set sequence number correct */
/* tcp_hdr = 0; */
/* printf(">>>>>>>>>>>>>>>>>>>>> TCP CRC VALUE = %X\n", pico_tcp_checksum_ipv4(f)); */
tcp_hdr->crc = short_be(0x0016); /* Set correct TCP CRC */
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "correct TCP checksum got rejected\n");
tcp_hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_transport_crc_check(f);
fail_if(ret == 1, "incorrect TCP checksum got accepted\n");
}
END_TEST
#endif

View File

@@ -0,0 +1,40 @@
#define EXISTING_TIMERS 7
START_TEST (test_timers)
{
uint32_t T[128];
int i;
struct pico_timer_ref *tref;
pico_stack_init();
for (i = 0; i < 128; i++) {
pico_time expire = (pico_time)(999999 + i);
void (*timer)(pico_time, void *) =(void (*)(pico_time, void *))0xff00 + i;
void *arg = ((void*)0xaa00 + i);
T[i] = pico_timer_add(expire, timer, arg);
printf("New timer %u\n", T[i]);
}
for (i = 0; i < 128; i++) {
void (*timer)(pico_time, void *) =(void (*)(pico_time, void *))0xff00 + i;
void *arg = ((void*)0xaa00 + i);
fail_if((uint32_t)(i + 1) > Timers->n);
tref = heap_get_element(Timers, (uint32_t)i + EXISTING_TIMERS);
fail_unless(tref->id == T[i]);
fail_unless(tref->tmr->timer == timer);
fail_unless(tref->tmr->arg == arg);
}
for (i = 127; i >= 0; i--) {
printf("Deleting timer %d \n", i );
pico_timer_cancel(T[i]);
printf("Deleted timer %d \n", i );
tref = heap_get_element(Timers, (uint32_t)i + EXISTING_TIMERS);
fail_unless(tref->tmr == NULL);
}
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
}
END_TEST

Some files were not shown because too many files have changed in this diff Show More