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:
parent
9322071520
commit
b918924fc1
@ -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 ;
|
||||
|
157
sys/net/sixlowpan/flowcontrol.c
Normal file
157
sys/net/sixlowpan/flowcontrol.c
Normal 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);
|
||||
}
|
||||
}
|
55
sys/net/sixlowpan/flowcontrol.h
Normal file
55
sys/net/sixlowpan/flowcontrol.h
Normal 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*/
|
@ -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;
|
||||
|
||||
|
@ -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*/
|
||||
|
Loading…
Reference in New Issue
Block a user