2013-06-22 05:11:53 +02:00
|
|
|
/**
|
2013-08-08 13:39:00 +02:00
|
|
|
* 6lowpan border router flow control
|
2013-06-22 05:11:53 +02:00
|
|
|
*
|
|
|
|
* Copyright (C) 2013 INRIA.
|
|
|
|
*
|
|
|
|
* This file subject to the terms and conditions of the GNU Lesser General
|
|
|
|
* Public License. See the file LICENSE in the top level directory for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* @ingroup sixlowpan
|
|
|
|
* @{
|
|
|
|
* @file flowcontrol.c
|
2013-08-08 13:39:00 +02:00
|
|
|
* @brief flowcontrol for constraint node border router implementation
|
2013-06-22 05:11:53 +02:00
|
|
|
* @author Martin Lenders <mlenders@inf.fu-berlin.de>
|
|
|
|
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
#include "vtimer.h"
|
|
|
|
#include "thread.h"
|
2011-07-25 16:33:24 +02:00
|
|
|
#include "semaphore.h"
|
|
|
|
#include "bordermultiplex.h"
|
2011-07-25 17:00:18 +02:00
|
|
|
#include "flowcontrol.h"
|
2011-07-25 16:33:24 +02:00
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
|
|
|
|
static int set_timeout(vtimer_t *timeout, long useconds, void *args);
|
|
|
|
static void sending_slot(void);
|
|
|
|
|
|
|
|
char sending_slot_stack[SENDING_SLOT_STACK_SIZE];
|
|
|
|
unsigned int sending_slot_pid;
|
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
flowcontrol_stat_t slwin_stat;
|
|
|
|
sem_t connection_established;
|
|
|
|
int16_t synack_seqnum = -1;
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
ipv6_addr_t init_threeway_handshake(void)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
border_syn_packet_t *syn;
|
|
|
|
msg_t m;
|
|
|
|
m.content.ptr = NULL;
|
2013-06-22 05:11:53 +02:00
|
|
|
msg_send(&m, border_get_serial_reader(), 1);
|
2012-01-11 17:02:43 +01:00
|
|
|
msg_receive(&m);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
syn = (border_syn_packet_t *)m.content.ptr;
|
|
|
|
border_conf_header_t *synack = (border_conf_header_t *)get_serial_out_buffer(0);
|
|
|
|
ipv6_addr_t addr;
|
2013-06-22 05:11:53 +02:00
|
|
|
memcpy(&addr, &(syn->addr), sizeof(ipv6_addr_t));
|
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
slwin_stat.next_exp = syn->next_seq_num;
|
|
|
|
slwin_stat.last_frame = syn->next_exp - 1;
|
|
|
|
slwin_stat.last_ack = slwin_stat.last_frame;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
synack->empty = 0;
|
|
|
|
synack->type = BORDER_PACKET_CONF_TYPE;
|
|
|
|
synack->conftype = BORDER_CONF_SYNACK;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
sending_slot_pid = thread_create(sending_slot_stack, SENDING_SLOT_STACK_SIZE, PRIORITY_MAIN - 1, CREATE_SLEEPING, sending_slot, "sending slot");
|
|
|
|
flowcontrol_send_over_uart((border_packet_t *)synack, sizeof(border_conf_header_t));
|
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
synack_seqnum = synack->seq_num;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
return addr;
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
ipv6_addr_t flowcontrol_init(void)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
int i;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-10-03 17:51:27 +02:00
|
|
|
sem_init(&slwin_stat.send_win_not_full, 0, BORDER_SWS);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
for (i = 0; i < BORDER_SWS; i++) {
|
2011-07-25 16:33:24 +02:00
|
|
|
slwin_stat.send_win[i].frame_len = 0;
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
memset(&slwin_stat.send_win, 0, sizeof(struct send_slot) * BORDER_SWS);
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
for (i = 0; i < BORDER_RWS; i++) {
|
2011-07-25 16:33:24 +02:00
|
|
|
slwin_stat.recv_win[i].received = 0;
|
|
|
|
slwin_stat.recv_win[i].frame_len = 0;
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
|
|
|
memset(&slwin_stat.recv_win, 0, sizeof(struct recv_slot) * BORDER_RWS);
|
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
return init_threeway_handshake();
|
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
static void sending_slot(void)
|
|
|
|
{
|
2012-01-11 17:02:43 +01:00
|
|
|
msg_t m;
|
|
|
|
uint8_t seq_num;
|
|
|
|
struct send_slot *slot;
|
|
|
|
border_packet_t *tmp;
|
2011-07-25 16:33:24 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
while (1) {
|
2012-01-11 17:02:43 +01:00
|
|
|
msg_receive(&m);
|
|
|
|
seq_num = *((uint8_t *)m.content.ptr);
|
|
|
|
slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
|
2013-06-22 05:11:53 +02:00
|
|
|
tmp = (border_packet_t *)slot->frame;
|
2012-01-11 17:02:43 +01:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (seq_num == tmp->seq_num) {
|
2013-06-22 05:11:53 +02:00
|
|
|
writepacket(slot->frame, slot->frame_len);
|
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)m.content.ptr) != 0) {
|
2012-01-11 17:02:43 +01:00
|
|
|
printf("ERROR: Error invoking timeout timer\n");
|
|
|
|
}
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
static int set_timeout(vtimer_t *timeout, long useconds, void *args)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
timex_t interval;
|
|
|
|
interval.seconds = useconds / 1000000;
|
2012-01-11 17:02:43 +01:00
|
|
|
interval.microseconds = (useconds % 1000000) * 1000;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2012-01-11 17:02:43 +01:00
|
|
|
return vtimer_set_msg(timeout, interval, sending_slot_pid, args);
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
static int in_window(uint8_t seq_num, uint8_t min, uint8_t max)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
uint8_t pos = seq_num - min;
|
|
|
|
uint8_t maxpos = max - min + 1;
|
2013-08-14 17:45:14 +02:00
|
|
|
return (pos < maxpos);
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void flowcontrol_send_over_uart(border_packet_t *packet, int len)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
struct send_slot *slot;
|
|
|
|
uint8_t args[] = {packet->seq_num};
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
sem_wait(&(slwin_stat.send_win_not_full));
|
|
|
|
packet->seq_num = ++slwin_stat.last_frame;
|
|
|
|
slot = &(slwin_stat.send_win[packet->seq_num % BORDER_SWS]);
|
|
|
|
memcpy(slot->frame, (uint8_t *)packet, len);
|
|
|
|
slot->frame_len = len;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)args) != 0) {
|
2011-07-25 16:33:24 +02:00
|
|
|
printf("ERROR: Error invoking timeout timer\n");
|
|
|
|
return;
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
writepacket((uint8_t *)packet, len);
|
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void send_ack(uint8_t seq_num)
|
|
|
|
{
|
2011-07-25 16:33:24 +02:00
|
|
|
border_packet_t *packet = (border_packet_t *)get_serial_out_buffer(0);
|
2011-08-05 15:45:38 +02:00
|
|
|
packet->empty = 0;
|
2011-07-25 16:33:24 +02:00
|
|
|
packet->type = BORDER_PACKET_ACK_TYPE;
|
|
|
|
packet->seq_num = seq_num;
|
2013-06-22 05:11:53 +02:00
|
|
|
writepacket((uint8_t *)packet, sizeof(border_packet_t));
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
|
|
|
|
2013-06-22 05:11:53 +02:00
|
|
|
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len)
|
|
|
|
{
|
2013-06-24 22:37:35 +02:00
|
|
|
if (packet->type == BORDER_PACKET_ACK_TYPE) {
|
|
|
|
if (in_window(packet->seq_num, slwin_stat.last_ack + 1, slwin_stat.last_frame)) {
|
|
|
|
if (synack_seqnum == packet->seq_num) {
|
2011-07-25 16:33:24 +02:00
|
|
|
synack_seqnum = -1;
|
2013-10-03 17:51:27 +02:00
|
|
|
sem_post(&connection_established);
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
do {
|
|
|
|
struct send_slot *slot;
|
|
|
|
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
|
|
|
|
vtimer_remove(&slot->timeout);
|
2013-06-22 05:11:53 +02:00
|
|
|
memset(&slot->frame, 0, BORDER_BUFFER_SIZE);
|
2013-10-03 17:51:27 +02:00
|
|
|
sem_post(&slwin_stat.send_win_not_full);
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
2013-06-24 22:37:35 +02:00
|
|
|
while (slwin_stat.last_ack != packet->seq_num);
|
2011-07-25 16:33:24 +02:00
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
}
|
|
|
|
else {
|
2011-07-25 16:33:24 +02:00
|
|
|
struct recv_slot *slot;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
slot = &(slwin_stat.recv_win[packet->seq_num % BORDER_RWS]);
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (!in_window(packet->seq_num,
|
2013-08-08 13:39:00 +02:00
|
|
|
slwin_stat.next_exp,
|
|
|
|
slwin_stat.next_exp + BORDER_RWS - 1)) {
|
2011-07-25 16:33:24 +02:00
|
|
|
return;
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
memcpy(slot->frame, (uint8_t *)packet, len);
|
|
|
|
slot->received = 1;
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2013-06-24 22:37:35 +02:00
|
|
|
if (packet->seq_num == slwin_stat.next_exp) {
|
|
|
|
while (slot->received) {
|
2011-07-25 16:33:24 +02:00
|
|
|
demultiplex((border_packet_t *)slot->frame, slot->frame_len);
|
2013-06-22 05:11:53 +02:00
|
|
|
memset(&slot->frame, 0, BORDER_BUFFER_SIZE);
|
2011-07-25 16:33:24 +02:00
|
|
|
slot->received = 0;
|
|
|
|
slot = &slwin_stat.recv_win[++(slwin_stat.next_exp) % BORDER_RWS];
|
|
|
|
}
|
|
|
|
}
|
2013-06-22 05:11:53 +02:00
|
|
|
|
2011-07-25 16:33:24 +02:00
|
|
|
send_ack(slwin_stat.next_exp - 1);
|
|
|
|
}
|
|
|
|
}
|