Skip to content

Examples

Toon Peters edited this page Jan 28, 2016 · 11 revisions

picoTCP comes with a handful of examples that run with the help of the picoapp executable and which are used for smoke testing (hence they can be found in the test dir). In this section we explore these applications and explain how they work. Since they require picoapp, the code of these examples can not be run standalone and so are solely to give you some insight in featureset of picoTCP.

The different steps are currently under construction

  1. Build picoapp.elf (and the IPv6 equivalent picoapp6.elf), which you'll then find in ./build/test/. These 2 are compiled versions of code you can find in ./test/examples/

    term1$ make test
    
  2. From here on, you can use picoapp.elf in many different ways. The first step is to run it without any specific functionality. This will allow you to ping the picoTCP instance. For this we'll use a TAP device.

    term1$ sudo ./build/test/picoapp.elf --tap myTAP:192.168.13.37:255.255.255.0 --app noop
    term2$ sudo ifconfig myTAP 192.168.13.38/24
    term2$ ping 192.168.13.37
    

In this case, the picoTCP instance has the .37 ip, while the host has .38. You can easily use wireshark to look at the myTAP interface. 3. Next, we'll use picoapp as a udp echo server

```
term1$ sudo ./build/test/picoapp.elf --tap myTAP:192.168.13.37:255.255.255.0 --app udpecho:192.168.13.37:6667:6667:1400
term2$ sudo ifconfig myTAP 192.168.13.38/24
term2$ nc -vu 192.168.13.37 6667
send "end" through netcat
```

The first instruction starts pico as a udp echo server, receiving and transmitting on port 6667 and it allocates a 1400 byte buffer for bytes to be transferred. You can then netcat to your instance and start chatting with yourself. 4. The same we can do for tcp echo, which has a slightly different syntax, as it listens to all addresses

```
term1$ sudo ./build/test/picoapp.elf --tap myTAP:192.168.13.37:255.255.255.0 --app tcpecho:6667
term2$ sudo ifconfig myTAP 192.168.13.38/24
term2$ nc 192.168.13.37 6667
```

The first instruction starts pico as a tcp echo server, receiving and transmitting on port 6667. You can then netcat to your instance (.37) and start chatting with yourself. 5. Next, we can also use the udp example with a tun device (a layer 3 network device)

```
term1$ sudo ./build/test/picoapp.elf --tun myTUN:192.168.13.37:255.255.255.0 --app udpecho:192.168.13.37:6667:6667:1400
term2$ sudo ifconfig myTUN 192.168.13.38/24
term2$ nc -vu 192.168.13.37 6667
send "end" through netcat
```
  1. You can use VDE (Virtual Distributed Ethernet) as well, try the udp echo example with

    term1$ sudo ./test/vde_sock_start.sh
    term1$ sudo ./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
    term2$ sudo ifconfig pic0 10.40.0.4/24
    term2$ nc -vu 10.40.0.3 6667
    
    

To work with VDE devices on linux, you'll need a switch first (created in the shell script)

When looking at the source code of the examples bear in mind they support on picoapp.c for basic functionality. To see how the stack is initialized and how the loop is maintained take a closer look at picoapp.c as well!

Ping example analysis

This ping example is entirely stand-alone, where the picoTCP instance pings itself. Run the example with

$ sudo ./build/test/picoapp.elf --tun myTUN:192.168.13.37:255.255.255.0 --app ping:192.168.13.37

Let’s take a look at what’s happening behind the scenes in a (simplified version) of ping.c (find this file in test/examples/

Step 1:

Since ping uses the ICMPv4 protocol, we need to add the proper header file. While we’re at it, we define the amount of times we’d like to ping a given IPv4 address.

#include "utils.h"
#include <pico_icmp4.h>
 
#define NUM_PING 5

Step 2:

We define a destination IP address and a timeout. All we have to do then is call pico_icmp4_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping); to initiate the pinging. We pass the function an IPv4 destination address, a number of pings, the interval between them, the timeout, a payload size and a callback function.

For the timeout to take effect, we need to create a timer with pico_timer_add(timeout * 1000, ping_abort_timer, &id); to be able to handle the situation where a ping times out.

All of this can be done as follows:

void app_ping(char *arg)
{
    static int id;
    char *dest = "192.168.1.5";
    int timeout = 20;
 
    id = pico_icmp4_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping);
 
    if (timeout > 0) {
        printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
        pico_timer_add(timeout * 1000, ping_abort_timer, &id);
    }
}

Step 3:

We still need to handle both callbacks! Let’s take a look at the ping callback function

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, 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);
    }
}

What happens here? The library will call this function and pass it a struct with some statistics. To print the IPv4 address we need to convert it to a readable format with pico_ipv4_to_string(host, s->dst.addr); Once we’ve got the amount of pings we requested, we exit the application.

Step 4:

The last thing to do is write the timeout callback. This function is called when it takes too long for a ping reply to be received.

void ping_abort_timer(pico_time now, void *_id)
{
    int *id = (int *) _id;
    printf("Ping: aborting...\n");
    pico_icmp4_ping_abort(*id);
}

When a timeout happens, we want to stop pinging. An abort can be done with pico_icmp4_ping_abort(*id); This will tell the library to stop pinging the address we’ve supplied.

Where to go from here?

You can now run picoTCP instances on your linux machine, and learned some more about applications. Use the other examples, the API documentation and most importantly, this wiki.

Clone this wiki locally