diff --git a/sys/net/sixlowpan/Jamfile b/sys/net/sixlowpan/Jamfile index 5f29608ce9..1570d45b92 100644 --- a/sys/net/sixlowpan/Jamfile +++ b/sys/net/sixlowpan/Jamfile @@ -2,7 +2,7 @@ SubDir TOP sys net sixlowpan ; # HDRS += $(TOP)/sys/net/sixlowpan/ ; -Module 6lowpan : sixlowpan.c sixlowip.c sixlowmac.c sixlownd.c ieee802154_frame.c serialnumber.c ; +Module 6lowpan : sixlowpan.c sixlowip.c sixlowmac.c sixlownd.c sixlowedge.c ieee802154_frame.c serialnumber.c ; UseModule vtimer ; UseModule transceiver ; diff --git a/sys/net/sixlowpan/sixlowedge.c b/sys/net/sixlowpan/sixlowedge.c new file mode 100644 index 0000000000..fa819a12d8 --- /dev/null +++ b/sys/net/sixlowpan/sixlowedge.c @@ -0,0 +1,136 @@ +#include +#include +#include "ieee802154_frame.h" +#include "sixlowedge.h" +#include "sixlowip.h" +#include "serialnumber.h" +#include "sixlowerror.h" + +abr_cache_t *abr_info; +uint16_t abro_version; + +uint16_t get_next_abro_version(); +void init_edge_router_info(ipv6_addr_t *abr_addr); +uint8_t abr_info_add_context(lowpan_context_t *context); +uint8_t abr_info_add_prefix(plist_t *prefix); + +uint16_t get_next_abro_version() { + abro_version = serial_add16(abro_version, 1); + return abro_version; +} + +uint8_t edge_initialize(transceiver_type_t trans,ipv6_addr_t *edge_router_addr) { + /* only allow addresses generated accoding to + * RFC 4944 (Section 6) & RFC 2464 (Section 4) from short address + * -- for now + */ + if ( edge_router_addr->uint16[4] != HTONS(IEEE_802154_PAN_ID ^ 0x0200) || + edge_router_addr->uint16[5] != HTONS(0x00FF) || + edge_router_addr->uint16[6] != HTONS(0xFE00) + ) { + return SIXLOWERROR_ADDRESS; + } + + // radio-address is 8-bit so this must be tested extra + if (edge_router_addr->uint8[14] != 0) { + return SIXLOWERROR_ADDRESS; + } + + sixlowpan_init(trans,edge_router_addr->uint8[15]); + + init_edge_router_info(edge_router_addr); + + ipv6_init_iface_as_router(); + + return SUCCESS; +} + +lowpan_context_t *edge_define_context(uint8_t cid, ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t lifetime) { + lowpan_context_t *context; + + context = lowpan_context_update(cid, prefix, prefix_len, OPT_6CO_FLAG_C_VALUE_SET, lifetime); + abr_info_add_context(context); + return context; +} + +lowpan_context_t *edge_alloc_context(ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t lifetime) { + lowpan_context_t *context = lowpan_context_lookup(prefix); + + if (context != NULL && context->length == prefix_len) { + context = edge_define_context(context->num, prefix, prefix_len, lifetime); + } + + context = NULL; + for (int i = 0; i < LOWPAN_CONTEXT_MAX; i++) { + if (lowpan_context_num_lookup(i) != NULL) { + context = edge_define_context(i, prefix, prefix_len, lifetime); + } + } + return context; +} + +uint8_t abr_info_add_context(lowpan_context_t *context) { + if (context == NULL) return SIXLOWERROR_NULLPTR; + uint16_t abro_version = get_next_abro_version(); + int i; + for (i = 0; i < abr_info->contexts_num; i++) { + if (abr_info->contexts[i]->num == context->num) { + abr_info->contexts[i] = context; + abr_info->version = abro_version; + return SUCCESS; + } + } + + if (abr_info->contexts_num == LOWPAN_CONTEXT_MAX) { + return SIXLOWERROR_ARRAYFULL; + } + + abr_info->contexts[abr_info->contexts_num++] = context; + abr_info->version = abro_version; + return SUCCESS; +} + +uint8_t abr_info_add_prefix(plist_t *prefix) { + if (prefix == NULL) return SIXLOWERROR_NULLPTR; + if (abr_info->prefixes_num == OPT_PI_LIST_LEN) { + return SIXLOWERROR_ARRAYFULL; + } + + uint16_t abro_version = get_next_abro_version(); + + abr_info->prefixes[abr_info->prefixes_num++] = prefix; + abr_info->version = abro_version; + + return SUCCESS; +} + +void init_edge_router_info(ipv6_addr_t *abr_addr) { + uint16_t abro_version = get_next_abro_version(); + ipv6_addr_t prefix; + plist_t *prefix_info; + lowpan_context_t *context; + + if (abr_info == NULL) + abr_info = abr_update_cache(abro_version,abr_addr,NULL,0,NULL,0); + else + abr_info = abr_update_cache( + abro_version, + abr_addr, + abr_info->contexts, + abr_info->contexts_num, + abr_info->prefixes, + abr_info->prefixes_num + ); + + ipv6_iface_add_addr(abr_addr,ADDR_STATE_PREFERRED,0,0,ADDR_TYPE_UNICAST); + ipv6_set_prefix(abr_addr, &prefix); + prefix_info = plist_add(&prefix, 64, OPT_PI_VLIFETIME_INFINITE,0,1,OPT_PI_FLAG_A); + abr_info_add_prefix(prefix_info); + + context = edge_define_context(0, &prefix, 64, 5); // has to be reset some time later + abr_info_add_context(context); +} + +abr_cache_t *get_edge_router_info() { + return abr_info; +} diff --git a/sys/net/sixlowpan/sixlowedge.h b/sys/net/sixlowpan/sixlowedge.h new file mode 100644 index 0000000000..ef8b8433ee --- /dev/null +++ b/sys/net/sixlowpan/sixlowedge.h @@ -0,0 +1,48 @@ +/* 6LoWPAN Edge Router header file */ + +#ifndef SIXLOWEDGE_H +#define SIXLOWEDGE_H + +#include +#include "sixlowip.h" +#include "sixlowpan.h" +#include "sixlownd.h" + +/* constants for conjestion control [rfc2581 section 1] */ +#define EDGE_CC_SMSS 1500 +#define EDGE_CC_RMSS 1500 +#define EDGE_CC_IW 3000 // 2*SMSS +#define EDGE_CC_LW 1500 // 1*SMSS + +/* packet types of tty-packets */ +#define EDGE_PACKET_TYPE_CONF 0 +#define EDGE_PACKET_TYPE_L3 3 + +/* ethertypes for L3 packets */ +#define EDGE_ETHERTYPE_IPV6 0x86DD + +extern uint16_t abro_version; + +typedef struct edge_packet_t { + uint8_t type; + uint8_t seq_num; +} edge_packet_t; + +typedef struct edge_l3_header_t { + uint8_t type; + uint8_t seq_num; + uint16_t ethertype; +} edge_l3_header_t; + +uint8_t edge_initialize(transceiver_type_t trans,ipv6_addr_t *edge_router_addr); +void edge_send_ipv6_over_tty(uint8_t *packet); +void edge_process_tty(void); +void edge_send_ipv6_over_lowpan(uint8_t *packet); +void edge_process_lowpan(void); + +abr_cache_t *get_edge_router_info(); + +lowpan_context_t *edge_define_context(uint8_t cid, ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t lifetime); +lowpan_context_t *edge_alloc_context(ipv6_addr_t *prefix, uint8_t prefix_len, uint16_t lifetime); + +#endif /* SIXLOWEDGE_H*/