1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

[sys/net/sixlowpan/sixlowborder.c]

* flow control outsourced to flowcontrol.*
This commit is contained in:
mlenders 2011-07-25 16:33:24 +02:00
parent 9322071520
commit b918924fc1
5 changed files with 219 additions and 192 deletions

View File

@ -2,7 +2,7 @@ SubDir TOP sys net sixlowpan ;
# HDRS += $(TOP)/sys/net/sixlowpan/ ;
Module 6lowpan : sixlowpan.c sixlowip.c sixlowmac.c sixlownd.c sixlowborder.c ieee802154_frame.c serialnumber.c semaphore.c ;
Module 6lowpan : sixlowpan.c sixlowip.c sixlowmac.c sixlownd.c sixlowborder.c ieee802154_frame.c serialnumber.c semaphore.c flowcontrol.c ;
UseModule vtimer ;
UseModule transceiver ;

View File

@ -0,0 +1,157 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vtimer.h>
#include "semaphore.h"
#include "bordermultiplex.h"
flowcontrol_stat_t slwin_stat;
sem_t connection_established;
int16_t synack_seqnum = -1;
ipv6_addr_t init_threeway_handshake() {
border_syn_packet_t *syn;
msg_t m;
m.content.ptr = NULL;
msg_send(&m,border_get_serial_reader(),1);
while(1) {
msg_receive(&m);
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;
memcpy(&addr, &(syn->addr), sizeof (ipv6_addr_t));
slwin_stat.next_exp = syn->next_seq_num;
slwin_stat.last_frame = syn->next_exp - 1;
slwin_stat.last_ack = slwin_stat.last_frame;
synack->reserved = 0;
synack->type = BORDER_PACKET_CONF_TYPE;
synack->conftype = BORDER_CONF_SYNACK;
flowcontrol_send_over_uart((border_packet_t *)synack,sizeof (border_conf_header_t));
synack_seqnum = synack->seq_num;
return addr;
}
}
ipv6_addr_t flowcontrol_init() {
int i;
slwin_stat.send_win_not_full = sem_init(BORDER_SWS);
for(i = 0; i < BORDER_SWS; i++) {
slwin_stat.send_win[i].frame_len = 0;
}
memset(&slwin_stat.send_win,0, sizeof(struct send_slot) * BORDER_SWS);
for(i = 0; i < BORDER_RWS; i++) {
slwin_stat.recv_win[i].received = 0;
slwin_stat.recv_win[i].frame_len = 0;
}
memset(&slwin_stat.recv_win,0, sizeof(struct recv_slot) * BORDER_RWS);
return init_threeway_handshake();
}
int set_timeout(vtimer_t *timeout, long useconds, void *args);
void timeout_callback (void *args) {
uint8_t seq_num = *((uint8_t *)args);
struct send_slot *slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
if (seq_num == ((border_packet_t *)(slot->frame))->seq_num) {
writepacket(slot->frame,slot->frame_len);
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, args) != 0) {
printf("ERROR: Error invoking timeout timer\n");
return;
}
} else {
return;
}
}
int set_timeout(vtimer_t *timeout, long useconds, void *args) {
timex_t interval;
interval.seconds = useconds / 1000000;
interval.nanoseconds = (useconds % 1000000) * 1000;
return vtimer_set_cb(timeout, interval, timeout_callback, args);
}
static int in_window(uint8_t seq_num, uint8_t min, uint8_t max) {
uint8_t pos = seq_num - min;
uint8_t maxpos = max - min + 1;
return pos < maxpos;
}
void flowcontrol_send_over_uart(border_packet_t *packet, int len) {
struct send_slot *slot;
uint8_t args[] = {packet->seq_num};
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;
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)args) != 0) {
printf("ERROR: Error invoking timeout timer\n");
return;
}
writepacket((uint8_t *)packet, len);
}
void send_ack(uint8_t seq_num) {
border_packet_t *packet = (border_packet_t *)get_serial_out_buffer(0);
packet->reserved = 0;
packet->type = BORDER_PACKET_ACK_TYPE;
packet->seq_num = seq_num;
writepacket((uint8_t *)packet, sizeof (border_packet_t));
}
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len) {
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) {
synack_seqnum = -1;
sem_signal(&connection_established);
}
do {
struct send_slot *slot;
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
vtimer_remove(&slot->timeout);
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
sem_signal(&slwin_stat.send_win_not_full);
} while (slwin_stat.last_ack != packet->seq_num);
}
} else {
struct recv_slot *slot;
slot = &(slwin_stat.recv_win[packet->seq_num % BORDER_RWS]);
if ( !in_window(packet->seq_num,
slwin_stat.next_exp,
slwin_stat.next_exp + BORDER_RWS - 1)) {
return;
}
memcpy(slot->frame, (uint8_t *)packet, len);
slot->received = 1;
if (packet->seq_num == slwin_stat.next_exp) {
while (slot->received) {
demultiplex((border_packet_t *)slot->frame, slot->frame_len);
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
slot->received = 0;
slot = &slwin_stat.recv_win[++(slwin_stat.next_exp) % BORDER_RWS];
}
}
send_ack(slwin_stat.next_exp - 1);
}
}

View File

@ -0,0 +1,55 @@
#ifndef FLOWCONTROL_H
#define FLOWCONTROL_H
#include <stdint.h>
#include <vtimer.h>
#include "semaphore.h"
#include "sixlowip.h"
#include "bordermultiplex.h"
/* packet types for flowcontrol */
#define BORDER_PACKET_ACK_TYPE 1
/* configuration types for flowcontrol */
#define BORDER_CONF_SYN 0
#define BORDER_CONF_SYNACK 1
#define BORDER_SWS 8
#define BORDER_RWS 8
#define BORDER_SL_TIMEOUT 500 // microseconds, maybe smaller
typedef struct flowcontrol_stat_t {
/* Sender state */
uint8_t last_ack;
uint8_t last_frame;
sem_t send_win_not_full;
struct send_slot {
vtimer_t timeout;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} send_win[BORDER_SWS];
/* Receiver state */
uint8_t next_exp;
struct recv_slot {
int8_t received;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} recv_win[BORDER_RWS];
} flowcontrol_stat_t;
typedef struct __attribute__ ((packed)) border_syn_packet_t {
uint8_t reserved;
uint8_t type;
uint8_t next_seq_num;
uint8_t conftype;
uint8_t next_exp;
ipv6_addr_t addr;
} border_syn_packet_t;
ipv6_addr_t flowcontrol_init();
void flowcontrol_send_over_uart(border_packet_t *packet, int len);
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len);
#endif /* FLOWCONTROL_H*/

View File

@ -1,7 +1,6 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <mutex.h>
#include <thread.h>
#include <msg.h>
@ -9,6 +8,7 @@
#include <posix_io.h>
#include <board_uart0.h>
#include "ieee802154_frame.h"
#include "flowcontrol.h"
#include "sixlowborder.h"
#include "sixlowip.h"
#include "sixlownd.h"
@ -30,64 +30,11 @@ uint16_t serial_reader_pid;
uint8_t serial_out_buf[BORDER_BUFFER_SIZE];
uint8_t serial_in_buf[BORDER_BUFFER_SIZE];
flowcontrol_stat_t slwin_stat;
sem_t connection_established;
int16_t synack_seqnum = -1;
int readpacket(uint8_t *packet_buf, int size);
void serial_reader_f(void);
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len);
void slwin_init() {
int i;
slwin_stat.send_win_not_full = sem_init(BORDER_SWS);
for(i = 0; i < BORDER_SWS; i++) {
slwin_stat.send_win[i].frame_len = 0;
}
memset(&slwin_stat.send_win,0, sizeof(struct send_slot) * BORDER_SWS);
for(i = 0; i < BORDER_RWS; i++) {
slwin_stat.recv_win[i].received = 0;
slwin_stat.recv_win[i].frame_len = 0;
}
memset(&slwin_stat.recv_win,0, sizeof(struct recv_slot) * BORDER_RWS);
}
ipv6_addr_t init_threeway_handshake() {
border_syn_packet_t *syn;
msg_t m;
m.content.ptr = NULL;
msg_send(&m,serial_reader_pid,1);
while(1) {
msg_receive(&m);
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;
memcpy(&addr, &(syn->addr), sizeof (ipv6_addr_t));
slwin_stat.next_exp = syn->next_seq_num;
slwin_stat.last_frame = syn->next_exp - 1;
slwin_stat.last_ack = slwin_stat.last_frame;
synack->reserved = 0;
synack->type = BORDER_PACKET_CONF_TYPE;
synack->conftype = BORDER_CONF_SYNACK;
flowcontrol_send_over_uart((border_packet_t *)synack,sizeof (border_conf_header_t));
synack_seqnum = synack->seq_num;
return addr;
}
}
uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_addr) {
ipv6_addr_t addr;
slwin_init();
serial_reader_pid = thread_create(
serial_reader_stack, READER_STACK_SIZE,
PRIORITY_MAIN-1, CREATE_STACKTEST,
@ -96,7 +43,7 @@ uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_ad
if (border_router_addr == NULL) {
border_router_addr = &addr;
addr = init_threeway_handshake();
addr = flowcontrol_init();
}
/* only allow addresses generated accoding to
@ -270,38 +217,6 @@ void serial_reader_f(void) {
}
}
int set_timeout(vtimer_t *timeout, long useconds, void *args);
void timeout_callback (void *args) {
uint8_t seq_num = *((uint8_t *)args);
struct send_slot *slot = &(slwin_stat.send_win[seq_num % BORDER_SWS]);
if (seq_num == ((border_packet_t *)(slot->frame))->seq_num) {
writepacket(slot->frame,slot->frame_len);
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, args) != 0) {
printf("ERROR: Error invoking timeout timer\n");
return;
}
} else {
return;
}
}
int set_timeout(vtimer_t *timeout, long useconds, void *args) {
timex_t interval;
interval.seconds = useconds / 1000000;
interval.nanoseconds = (useconds % 1000000) * 1000;
return vtimer_set_cb(timeout, interval, timeout_callback, args);
}
static int in_window(uint8_t seq_num, uint8_t min, uint8_t max) {
uint8_t pos = seq_num - min;
uint8_t maxpos = max - min + 1;
return pos < maxpos;
}
void demultiplex(border_packet_t *packet, int len) {
switch (packet->type) {
case (BORDER_PACKET_RAW_TYPE):{
@ -359,71 +274,6 @@ void demultiplex(border_packet_t *packet, int len) {
}
}
void border_send_ack(uint8_t seq_num) {
border_packet_t *packet = (border_packet_t *)get_serial_out_buffer(0);
packet->reserved = 0;
packet->type = BORDER_PACKET_ACK_TYPE;
packet->seq_num = seq_num;
writepacket((uint8_t *)packet, sizeof (border_packet_t));
}
void flowcontrol_deliver_from_uart(border_packet_t *packet, int len) {
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) {
synack_seqnum = -1;
sem_signal(&connection_established);
}
do {
struct send_slot *slot;
slot = &(slwin_stat.send_win[++slwin_stat.last_ack % BORDER_SWS]);
vtimer_remove(&slot->timeout);
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
sem_signal(&slwin_stat.send_win_not_full);
} while (slwin_stat.last_ack != packet->seq_num);
}
} else {
struct recv_slot *slot;
slot = &(slwin_stat.recv_win[packet->seq_num % BORDER_RWS]);
if ( !in_window(packet->seq_num,
slwin_stat.next_exp,
slwin_stat.next_exp + BORDER_RWS - 1)) {
return;
}
memcpy(slot->frame, (uint8_t *)packet, len);
slot->received = 1;
if (packet->seq_num == slwin_stat.next_exp) {
while (slot->received) {
demultiplex((border_packet_t *)slot->frame, slot->frame_len);
memset(&slot->frame,0,BORDER_BUFFER_SIZE);
slot->received = 0;
slot = &slwin_stat.recv_win[++(slwin_stat.next_exp) % BORDER_RWS];
}
}
border_send_ack(slwin_stat.next_exp - 1);
}
}
void flowcontrol_send_over_uart(border_packet_t *packet, int len) {
struct send_slot *slot;
uint8_t args[] = {packet->seq_num};
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;
if (set_timeout(&slot->timeout, BORDER_SL_TIMEOUT, (void *)args) != 0) {
printf("ERROR: Error invoking timeout timer\n");
return;
}
writepacket((uint8_t *)packet, len);
}
void multiplex_send_ipv6_over_uart(struct ipv6_hdr_t *packet) {
border_l3_header_t *serial_buf;

View File

@ -5,27 +5,17 @@
#include <stdint.h>
#include <mutex.h>
#include <vtimer.h>
#include "sixlowip.h"
#include "sixlowpan.h"
#include "sixlownd.h"
#include "semaphore.h"
#define BORDER_SWS 8
#define BORDER_RWS 8
#define BORDER_SL_TIMEOUT 500 // microseconds, maybe smaller
#define BORDER_HEADER_LENGTH 2
/* packet types of uart-packets */
#define BORDER_PACKET_RAW_TYPE 0
#define BORDER_PACKET_ACK_TYPE 1
#define BORDER_PACKET_CONF_TYPE 2
#define BORDER_PACKET_L3_TYPE 3
/* configuration types */
#define BORDER_CONF_SYN 0
#define BORDER_CONF_SYNACK 1
#define BORDER_CONF_CONTEXT 2
#define BORDER_CONF_IPADDR 3
@ -52,15 +42,6 @@ typedef struct __attribute__ ((packed)) border_conf_header_t {
uint8_t conftype;
} border_conf_header_t;
typedef struct __attribute__ ((packed)) border_syn_packet_t {
uint8_t reserved;
uint8_t type;
uint8_t next_seq_num;
uint8_t conftype;
uint8_t next_exp;
ipv6_addr_t addr;
} border_syn_packet_t;
typedef struct __attribute__ ((packed)) border_addr_packet_t {
uint8_t reserved;
uint8_t type;
@ -85,34 +66,18 @@ typedef struct __attribute__ ((packed)) border_context_packet_t {
#define BORDER_BUFFER_SIZE (sizeof (border_l3_header_t) + MTU)
typedef struct flowcontrol_stat_t {
/* Sender state */
uint8_t last_ack;
uint8_t last_frame;
sem_t send_win_not_full;
struct send_slot {
vtimer_t timeout;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} send_win[BORDER_SWS];
/* Receiver state */
uint8_t next_exp;
struct recv_slot {
int8_t received;
uint8_t frame[BORDER_BUFFER_SIZE];
size_t frame_len;
} recv_win[BORDER_RWS];
} flowcontrol_stat_t;
uint16_t border_get_serial_reader();
uint8_t *get_serial_out_buffer(int offset);
uint8_t *get_serial_in_buffer(int offset);
uint8_t border_initialize(transceiver_type_t trans,ipv6_addr_t *border_router_addr);
void demultiplex(border_packet_t *packet, int len);
void multiplex_send_ipv6_over_uart(struct ipv6_hdr_t *packet);
void multiplex_send_addr_over_uart(ipv6_addr_t *addr);
void flowcontrol_send_over_uart(border_packet_t *packet, int len);
void border_send_ipv6_over_lowpan(struct ipv6_hdr_t *packet, uint8_t aro_flag, uint8_t sixco_flag);
void border_process_lowpan(void);
int readpacket(uint8_t *packet_buf, int size);
int writepacket(uint8_t *packet_buf, size_t size);
#endif /* SIXLOWBORDER_H*/