Skip to content

Commit

Permalink
Merge branch 'dev' - Release 1.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniele Lacamera committed Oct 14, 2015
2 parents 72848bd + 2c3adc0 commit e1ecb06
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 11 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ units: mod core lib $(UNITS_OBJ) $(MOD_OBJ)
@$(CC) -o $(PREFIX)/test/modunit_dev_ppp.elf $(CFLAGS) -I. test/unit/modunit_pico_dev_ppp.c -lcheck -lm -pthread -lrt $(UNITS_OBJ) $(PREFIX)/lib/libpicotcp.a
@$(CC) -o $(PREFIX)/test/modunit_mld.elf $(CFLAGS) -I. test/unit/modunit_pico_mld.c -lcheck -lm -pthread -lrt $(UNITS_OBJ) $(PREFIX)/lib/libpicotcp.a
@$(CC) -o $(PREFIX)/test/modunit_igmp.elf $(CFLAGS) -I. test/unit/modunit_pico_igmp.c -lcheck -lm -pthread -lrt $(UNITS_OBJ) $(PREFIX)/lib/libpicotcp.a
@$(CC) -o $(PREFIX)/test/modunit_hotplug_detection.elf $(CFLAGS) -I. test/unit/modunit_pico_hotplug_detection.c -lcheck -lm -pthread -lrt $(UNITS_OBJ) $(PREFIX)/lib/libpicotcp.a

devunits: mod core lib
@echo -e "\n\t[UNIT TESTS SUITE: device drivers]"
Expand Down
30 changes: 30 additions & 0 deletions modules/pico_dev_tap.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <signal.h>
#include "pico_device.h"
#include "pico_dev_tap.h"
#include "pico_stack.h"
Expand All @@ -26,6 +27,26 @@ struct pico_device_tap {

#define TUN_MTU 2048

// We only support one global link state - we only have two USR signals, we
// can't spread these out over an arbitrary amount of devices. When you unplug
// one tap, you unplug all of them.

static int link_state = 0;

static void sig_handler(int signo)
{
if (signo == SIGUSR1)
link_state = 0;
if (signo == SIGUSR2)
link_state = 1;
}

static int tap_link_state(struct pico_device *self)
{
return link_state;
}


static int pico_tap_send(struct pico_device *dev, void *buf, int len)
{
struct pico_device_tap *tap = (struct pico_device_tap *) dev;
Expand Down Expand Up @@ -155,10 +176,19 @@ struct pico_device *pico_tap_create(char *name)
{
struct pico_device_tap *tap = PICO_ZALLOC(sizeof(struct pico_device_tap));
uint8_t mac[6] = {};
struct sigaction sa;

if (!tap)
return NULL;

sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sig_handler;

if ((sigaction(SIGUSR1, &sa, NULL) == 0) &&
(sigaction(SIGUSR2, &sa, NULL) == 0))
tap->dev.link_state = &tap_link_state;

tap->dev.overhead = 0;
tap->fd = tap_open(name);
if (tap->fd < 0) {
Expand Down
134 changes: 134 additions & 0 deletions modules/pico_hotplug_detection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*********************************************************************
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
See LICENSE and COPYING for usage.
Authors: Frederik Van Slycken
*********************************************************************/
#include "pico_protocol.h"
#include "pico_hotplug_detection.h"
#include "pico_tree.h"
#include "pico_device.h"

struct pico_hotplug_device{
struct pico_device *dev;
int prev_state;
struct pico_tree callbacks;
};

uint32_t timer_id = 0;

static int pico_hotplug_dev_cmp(void *ka, void *kb)
{
struct pico_hotplug_device *a = ka, *b = kb;
if (a->dev->hash < b->dev->hash)
return -1;

if (a->dev->hash > b->dev->hash)
return 1;

return 0;
}

static int callback_compare(void *ka, void *kb)
{
if (ka < kb)
return -1;
if (ka > kb)
return 1;
return 0;
}

PICO_TREE_DECLARE(Hotplug_device_tree, pico_hotplug_dev_cmp);

static void timer_cb(__attribute__((unused)) pico_time t, __attribute__((unused)) void* v)
{
struct pico_tree_node *node = NULL, *safe = NULL, *cb_node = NULL, *cb_safe = NULL;
int new_state, event;
struct pico_hotplug_device *hpdev = NULL;
void (*cb)(struct pico_device *dev, int event);

//we don't know if one of the callbacks might deregister, so be safe
pico_tree_foreach_safe(node, &Hotplug_device_tree, safe)
{
hpdev = node->keyValue;
new_state = hpdev->dev->link_state(hpdev->dev);
if (new_state != hpdev->prev_state)
{
if (new_state == 1){
event = PICO_HOTPLUG_EVENT_UP;
} else {
event = PICO_HOTPLUG_EVENT_DOWN;
}
//we don't know if one of the callbacks might deregister, so be safe
pico_tree_foreach_safe(cb_node, &(hpdev->callbacks), cb_safe)
{
cb = cb_node->keyValue;
cb(hpdev->dev, event);
}
hpdev->prev_state = new_state;
}
}

timer_id = pico_timer_add(PICO_HOTPLUG_INTERVAL, &timer_cb, NULL);
}


int pico_hotplug_register(struct pico_device *dev, void (*cb)(struct pico_device *dev, int event))
{
struct pico_hotplug_device *hotplug_dev;
struct pico_hotplug_device search = {.dev = dev};

if (dev->link_state == NULL){
pico_err = PICO_ERR_EPROTONOSUPPORT;
return -1;
}

hotplug_dev = (struct pico_hotplug_device*)pico_tree_findKey(&Hotplug_device_tree, &search);
if (! hotplug_dev )
{
hotplug_dev = PICO_ZALLOC(sizeof(struct pico_hotplug_device));
if (!hotplug_dev)
{
pico_err = PICO_ERR_ENOMEM;
return -1;
}
hotplug_dev->dev = dev;
hotplug_dev->prev_state = dev->link_state(hotplug_dev->dev);
hotplug_dev->callbacks.root = &LEAF;
hotplug_dev->callbacks.compare = &callback_compare;
pico_tree_insert(&Hotplug_device_tree, hotplug_dev);
}
pico_tree_insert(&(hotplug_dev->callbacks), cb);

if (timer_id == 0)
{
timer_id = pico_timer_add(PICO_HOTPLUG_INTERVAL, &timer_cb, NULL);
}

return 0;
}

int pico_hotplug_deregister(struct pico_device *dev, void (*cb)(struct pico_device *dev, int event))
{
struct pico_hotplug_device* hotplug_dev;
struct pico_hotplug_device search = {.dev = dev};

hotplug_dev = (struct pico_hotplug_device*)pico_tree_findKey(&Hotplug_device_tree, &search);
if (!hotplug_dev)
//wasn't registered
return 0;
pico_tree_delete(&hotplug_dev->callbacks, cb);
if (pico_tree_empty(&hotplug_dev->callbacks))
{
pico_tree_delete(&Hotplug_device_tree, hotplug_dev);
PICO_FREE(hotplug_dev);
}

if (pico_tree_empty(&Hotplug_device_tree) && timer_id != 0)
{
pico_timer_cancel(timer_id);
timer_id = 0;
}
return 0;
}

20 changes: 20 additions & 0 deletions modules/pico_hotplug_detection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*********************************************************************
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
See LICENSE and COPYING for usage.
Authors: Frederik Van Slycken
*********************************************************************/
#ifndef INCLUDE_PICO_SUPPORT_HOTPLUG
#define INCLUDE_PICO_SUPPORT_HOTPLUG
#include "pico_stack.h"

#define PICO_HOTPLUG_EVENT_UP 1 /* link went up */
#define PICO_HOTPLUG_EVENT_DOWN 2 /* link went down */

#define PICO_HOTPLUG_INTERVAL 100

int pico_hotplug_register(struct pico_device *dev, void (*cb)(struct pico_device *dev, int event));
int pico_hotplug_deregister(struct pico_device *dev, void (*cb)(struct pico_device *dev, int event));

#endif /* _INCLUDE_PICO_SUPPORT_HOTPLUG */

1 change: 1 addition & 0 deletions modules/pico_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,7 @@ int pico_ipv4_link_del(struct pico_device *dev, struct pico_ip4 address)
PICO_FREE(g);
}
} while(0);
pico_free(found->MCASTGroups);
#endif

pico_ipv4_cleanup_routes(found);
Expand Down
79 changes: 69 additions & 10 deletions modules/pico_slaacv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "pico_arp.h"
#include "pico_constants.h"
#include "pico_stack.h"
#include "pico_hotplug_detection.h"

#ifdef PICO_SUPPORT_SLAACV4

Expand All @@ -26,6 +27,7 @@
#define ANNOUNCE_NB 2 /* number of announcement packets */
#define ANNOUNCE_INTERVAL 2 /* time between announcement packets */
#define MAX_CONFLICTS 10 /* max conflicts before rate limiting */
#define MAX_CONFLICTS_FAIL 20 /* max conflicts before declaring failure */
#define RATE_LIMIT_INTERVAL 60 /* time between successive attempts */
#define DEFEND_INTERVAL 10 /* minimum interval between defensive ARP */

Expand All @@ -48,6 +50,8 @@ struct slaacv4_cookie {
void (*cb)(struct pico_ip4 *ip, uint8_t code);
};

static void pico_slaacv4_hotplug_cb(struct pico_device *dev, int event);

static struct slaacv4_cookie slaacv4_local;

static uint32_t pico_slaacv4_getip(struct pico_device *dev, uint8_t rand)
Expand Down Expand Up @@ -125,8 +129,6 @@ static void pico_slaacv4_send_probe_timer(pico_time now, void *arg)
}
}



static void pico_slaacv4_receive_ipconflict(int reason)
{
struct slaacv4_cookie *tmp = &slaacv4_local;
Expand All @@ -153,10 +155,20 @@ static void pico_slaacv4_receive_ipconflict(int reason)
tmp->probe_try_nb++;
tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp);
}
else if (tmp->conflict_nb < MAX_CONFLICTS_FAIL)
{
tmp->state = SLAACV4_CLAIMING;
tmp->probe_try_nb = 0;
tmp->announce_nb = 0;
tmp->ip.addr = pico_slaacv4_getip(tmp->device, (uint8_t)1);
pico_arp_register_ipconflict(&tmp->ip, &tmp->device->eth->mac, pico_slaacv4_receive_ipconflict);
tmp->timer = pico_timer_add(RATE_LIMIT_INTERVAL * 1000, pico_slaacv4_send_probe_timer, tmp);
}
else
{
if (tmp->cb != NULL)
{
pico_hotplug_deregister(tmp->device, &pico_slaacv4_hotplug_cb);
tmp->cb(&tmp->ip, PICO_SLAACV4_ERROR);
}

Expand All @@ -165,6 +177,30 @@ static void pico_slaacv4_receive_ipconflict(int reason)

}

static void pico_slaacv4_hotplug_cb(struct pico_device *dev, int event)
{
struct slaacv4_cookie *tmp = &slaacv4_local;

if (event == PICO_HOTPLUG_EVENT_UP )
{
slaacv4_local.state = SLAACV4_CLAIMING;
tmp->probe_try_nb = 0;
tmp->announce_nb = 0;

pico_arp_register_ipconflict(&tmp->ip, &tmp->device->eth->mac, pico_slaacv4_receive_ipconflict);
pico_arp_request(tmp->device, &tmp->ip, PICO_ARP_PROBE);
tmp->probe_try_nb++;
tmp->timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, tmp);

}
else
{
if (tmp->state == SLAACV4_CLAIMED )
pico_ipv4_link_del(tmp->device, tmp->ip);
pico_slaacv4_cancel_timers(tmp);
}
}

int pico_slaacv4_claimip(struct pico_device *dev, void (*cb)(struct pico_ip4 *ip, uint8_t code))
{
struct pico_ip4 ip;
Expand All @@ -174,14 +210,37 @@ int pico_slaacv4_claimip(struct pico_device *dev, void (*cb)(struct pico_ip4 *ip
return -1;
}

ip.addr = pico_slaacv4_getip(dev, 0);
if( dev->link_state != NULL )
{
//hotplug detect will work

pico_slaacv4_init_cookie(&ip, dev, &slaacv4_local, cb);
pico_arp_register_ipconflict(&ip, &dev->eth->mac, pico_slaacv4_receive_ipconflict);
pico_arp_request(dev, &ip, PICO_ARP_PROBE);
slaacv4_local.state = SLAACV4_CLAIMING;
slaacv4_local.probe_try_nb++;
slaacv4_local.timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, &slaacv4_local);
ip.addr = pico_slaacv4_getip(dev, 0);
pico_slaacv4_init_cookie(&ip, dev, &slaacv4_local, cb);

if (pico_hotplug_register(dev, &pico_slaacv4_hotplug_cb))
{
return -1;
}
if (dev->link_state(dev) == 1)
{
pico_arp_register_ipconflict(&ip, &dev->eth->mac, pico_slaacv4_receive_ipconflict);
pico_arp_request(dev, &ip, PICO_ARP_PROBE);
slaacv4_local.state = SLAACV4_CLAIMING;
slaacv4_local.probe_try_nb++;
slaacv4_local.timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, &slaacv4_local);
}
}
else
{
ip.addr = pico_slaacv4_getip(dev, 0);

pico_slaacv4_init_cookie(&ip, dev, &slaacv4_local, cb);
pico_arp_register_ipconflict(&ip, &dev->eth->mac, pico_slaacv4_receive_ipconflict);
pico_arp_request(dev, &ip, PICO_ARP_PROBE);
slaacv4_local.state = SLAACV4_CLAIMING;
slaacv4_local.probe_try_nb++;
slaacv4_local.timer = pico_timer_add(PROBE_WAIT * 1000, pico_slaacv4_send_probe_timer, &slaacv4_local);
}

return 0;
}
Expand All @@ -201,7 +260,7 @@ void pico_slaacv4_unregisterip(void)
pico_slaacv4_cancel_timers(tmp);
pico_slaacv4_init_cookie(&empty, NULL, tmp, NULL);
pico_arp_register_ipconflict(&tmp->ip, NULL, NULL);

pico_hotplug_deregister(tmp->device, &pico_slaacv4_hotplug_cb);
}

#endif
2 changes: 1 addition & 1 deletion rules/slaacv4.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
OPTIONS+=-DPICO_SUPPORT_SLAACV4
MOD_OBJ+=$(LIBBASE)modules/pico_slaacv4.o
MOD_OBJ+=$(LIBBASE)modules/pico_slaacv4.o $(LIBBASE)modules/pico_hotplug_detection.o
Loading

0 comments on commit e1ecb06

Please sign in to comment.