From 1e4badf85aad8fdcd5c2784e20f7f3242d7a8f48 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Fri, 31 Jan 2014 14:36:09 +0100 Subject: [PATCH 01/19] Fix coding conventions in sys/transceiver/transceiver.c --- sys/transceiver/transceiver.c | 166 +++++++++++++++++++++++++--------- 1 file changed, 121 insertions(+), 45 deletions(-) diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index c975a7ec2d6e..b03f677077b7 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -86,10 +86,10 @@ static volatile uint8_t rx_buffer_pos = 0; static volatile uint8_t transceiver_buffer_pos = 0; #ifdef MODULE_CC110X - void *cc1100_payload; - int cc1100_payload_size; - packet_info_t *cc1100_packet_info; - uint8_t cc1100_pkt[CC1100_MAX_DATA_LENGTH]; +void *cc1100_payload; +int cc1100_payload_size; +packet_info_t *cc1100_packet_info; +uint8_t cc1100_pkt[CC1100_MAX_DATA_LENGTH]; #endif @@ -158,6 +158,7 @@ void transceiver_init(transceiver_type_t t) reg[i].transceivers = TRANSCEIVER_NONE; reg[i].pid = 0; } + /* check if a non defined bit is set */ if (t & ~(TRANSCEIVER_CC1100 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X | TRANSCEIVER_NATIVE | TRANSCEIVER_AT86RF231)) { puts("Invalid transceiver type"); @@ -175,11 +176,13 @@ int transceiver_start(void) if (transceiver_pid < 0) { puts("Error creating transceiver thread"); } + #ifdef MODULE_CC110X_NG else if (transceivers & TRANSCEIVER_CC1100) { DEBUG("transceiver: Transceiver started for CC1100\n"); cc110x_init(transceiver_pid); } + #endif #ifdef MODULE_CC110X else if (transceivers & TRANSCEIVER_CC1100) { @@ -187,28 +190,33 @@ int transceiver_start(void) cc1100_init(); cc1100_set_packet_monitor(cc1100_packet_monitor); } + #endif #ifdef MODULE_CC2420 - else if(transceivers & TRANSCEIVER_CC2420) { + else if (transceivers & TRANSCEIVER_CC2420) { DEBUG("transceiver: Transceiver started for CC2420\n"); cc2420_init(transceiver_pid); } + #endif #ifdef MODULE_AT86RF231 - else if(transceivers & TRANSCEIVER_AT86RF231) { + else if (transceivers & TRANSCEIVER_AT86RF231) { DEBUG("transceiver: Transceiver started for AT86RF231\n"); at86rf231_init(transceiver_pid); } + #endif #ifdef MODULE_MC1322X else if (transceivers & TRANSCEIVER_MC1322X) { maca_init(); } + #endif #ifdef MODULE_NATIVENET else if (transceivers & TRANSCEIVER_NATIVE) { nativenet_init(transceiver_pid); } + #endif return transceiver_pid; } @@ -220,8 +228,8 @@ uint8_t transceiver_register(transceiver_type_t t, int pid) /* find pid in registered threads or first unused space */ for (i = 0; ((i < TRANSCEIVER_MAX_REGISTERED) && - (reg[i].pid != pid) && - (reg[i].transceivers != TRANSCEIVER_NONE)); i++); + (reg[i].pid != pid) && + (reg[i].transceivers != TRANSCEIVER_NONE)); i++); if (i >= TRANSCEIVER_MAX_REGISTERED) { return ENOMEM; @@ -256,7 +264,7 @@ void run(void) cmd = (transceiver_command_t *) m.content.ptr; DEBUG("transceiver: Transceiver: Message received, type: %02X\n", m.type); - switch(m.type) { + switch (m.type) { case RCV_PKT_CC1020: case RCV_PKT_CC1100: case RCV_PKT_CC2420: @@ -265,6 +273,7 @@ void run(void) case RCV_PKT_AT86RF231: receive_packet(m.type, m.content.value); break; + case SND_PKT: response = send_packet(cmd->transceivers, cmd->data); m.content.value = response; @@ -302,17 +311,20 @@ void run(void) case SWITCH_RX: switch_to_rx(cmd->transceivers); break; + case GET_PAN: *((int32_t *) cmd->data) = get_pan(cmd->transceivers); msg_reply(&m, &m); break; + case SET_PAN: *((int32_t *) cmd->data) = set_pan(cmd->transceivers, cmd->data); msg_reply(&m, &m); break; #ifdef DBG_IGNORE + case DBG_IGN: - *((int16_t*) cmd->data) = ignore_add(cmd->transceivers, cmd->data); + *((int16_t *) cmd->data) = ignore_add(cmd->transceivers, cmd->data); msg_reply(&m, &m); break; #endif @@ -341,7 +353,7 @@ static void receive_packet(uint16_t type, uint8_t pos) DEBUG("Packet received\n"); - switch(type) { + switch (type) { case RCV_PKT_CC1020: t = TRANSCEIVER_CC1020; break; @@ -349,18 +361,23 @@ static void receive_packet(uint16_t type, uint8_t pos) case RCV_PKT_CC1100: t = TRANSCEIVER_CC1100; break; + case RCV_PKT_CC2420: t = TRANSCEIVER_CC2420; break; + case RCV_PKT_MC1322X: t = TRANSCEIVER_MC1322X; break; - case RCV_PKT_NATIVE: - t = TRANSCEIVER_NATIVE; - break; + + case RCV_PKT_NATIVE: + t = TRANSCEIVER_NATIVE; + break; + case RCV_PKT_AT86RF231: t = TRANSCEIVER_AT86RF231; break; + default: t = TRANSCEIVER_NONE; break; @@ -427,14 +444,18 @@ static void receive_packet(uint16_t type, uint8_t pos) puts("Invalid transceiver type"); return; } + #ifdef DBG_IGNORE + for (uint8_t i = 0; (i < MAX_IGNORED_ADDR) && (ignored_addr[i]); i++) { DEBUG("check if source (%u) is ignored -> %u\n", trans_p->src, ignored_addr[i]); + if (trans_p->src == ignored_addr[i]) { DEBUG("ignored packet from %" PRIu16 "\n", trans_p->src); return; } } + #endif } @@ -444,7 +465,7 @@ static void receive_packet(uint16_t type, uint8_t pos) while (reg[i].transceivers != TRANSCEIVER_NONE) { if (reg[i].transceivers & t) { - m.content.ptr = (char *) & (transceiver_buffer[transceiver_buffer_pos]); + m.content.ptr = (char *) &(transceiver_buffer[transceiver_buffer_pos]); DEBUG("transceiver: Notify thread %i\n", reg[i].pid); if (msg_send(&m, reg[i].pid, false) && (m.type != ENOBUFFER)) { @@ -474,10 +495,10 @@ static void receive_cc110x_packet(radio_packet_t *trans_p) trans_p->rssi = cc110x_rx_buffer[rx_buffer_pos].rssi; trans_p->lqi = cc110x_rx_buffer[rx_buffer_pos].lqi; trans_p->length = p.length - CC1100_HEADER_LENGTH; - memcpy((void *)&(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.data, CC1100_MAX_DATA_LENGTH); + memcpy((void *) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.data, CC1100_MAX_DATA_LENGTH); eINT(); - trans_p->data = (uint8_t *)&(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]); + trans_p->data = (uint8_t *) &(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]); DEBUG("transceiver: Packet %p (%p) was from %hu to %hu, size: %u\n", trans_p, trans_p->data, trans_p->src, trans_p->dst, trans_p->length); } #endif @@ -491,16 +512,17 @@ void receive_cc1100_packet(radio_packet_t *trans_p) trans_p->rssi = cc1100_packet_info->rssi; trans_p->lqi = cc1100_packet_info->lqi; trans_p->length = cc1100_payload_size; - memcpy((void *)&(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), cc1100_payload, CC1100_MAX_DATA_LENGTH); + memcpy((void *) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), cc1100_payload, CC1100_MAX_DATA_LENGTH); eINT(); - trans_p->data = (uint8_t *)&(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]); + trans_p->data = (uint8_t *) &(data_buffer[transceiver_buffer_pos * CC1100_MAX_DATA_LENGTH]); } #endif #ifdef MODULE_CC2420 -void receive_cc2420_packet(radio_packet_t *trans_p) { +void receive_cc2420_packet(radio_packet_t *trans_p) +{ DEBUG("transceiver: Handling CC2420 packet\n"); dINT(); cc2420_packet_t p = cc2420_rx_buffer[rx_buffer_pos]; @@ -519,23 +541,25 @@ void receive_cc2420_packet(radio_packet_t *trans_p) { #endif #ifdef MODULE_MC1322X -void receive_mc1322x_packet(radio_packet_t *trans_p) { - maca_packet_t* maca_pkt; +void receive_mc1322x_packet(radio_packet_t *trans_p) +{ + maca_packet_t *maca_pkt; dINT(); - maca_pkt = maca_get_rx_packet (); + maca_pkt = maca_get_rx_packet(); trans_p->lqi = maca_pkt->lqi; trans_p->length = maca_pkt->length; - memcpy((void*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), maca_pkt->data, MACA_MAX_PAYLOAD_SIZE); - maca_free_packet( maca_pkt ); + memcpy((void *) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), maca_pkt->data, MACA_MAX_PAYLOAD_SIZE); + maca_free_packet(maca_pkt); eINT(); - trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * MACA_MAX_PAYLOAD_SIZE]); + trans_p->data = (uint8_t *) &(data_buffer[transceiver_buffer_pos * MACA_MAX_PAYLOAD_SIZE]); } #endif #ifdef MODULE_NATIVENET -void receive_nativenet_packet(radio_packet_t *trans_p) { +void receive_nativenet_packet(radio_packet_t *trans_p) +{ unsigned state; radio_packet_t *p = &_nativenet_rx_buffer[rx_buffer_pos].packet; @@ -546,7 +570,7 @@ void receive_nativenet_packet(radio_packet_t *trans_p) { memcpy(trans_p, p, sizeof(radio_packet_t)); memcpy(&(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p->data, p->length); - trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]); + trans_p->data = (uint8_t *) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]); DEBUG("Packet %p was from %" PRIu16 " to %" PRIu16 ", size: %" PRIu8 "\n", trans_p, trans_p->src, trans_p->dst, trans_p->length); @@ -556,7 +580,8 @@ void receive_nativenet_packet(radio_packet_t *trans_p) { #endif #ifdef MODULE_AT86RF231 -void receive_at86rf231_packet(radio_packet_t *trans_p) { +void receive_at86rf231_packet(radio_packet_t *trans_p) +{ DEBUG("Handling AT86RF231 packet\n"); dINT(); at86rf231_packet_t p = at86rf231_rx_buffer[rx_buffer_pos]; @@ -591,7 +616,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) cc110x_packet_t cc110x_pkt; #endif #ifdef MODULE_MC1322X - maca_packet_t* maca_pkt = maca_get_free_packet(); + maca_packet_t *maca_pkt = maca_get_free_packet(); #endif #ifdef MODULE_CC2420 @@ -603,6 +628,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) #endif DEBUG("transceiver: Send packet to %" PRIu16 "\n", p.dst); + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG @@ -621,6 +647,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) #endif break; #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: cc2420_pkt.frame.payload_len = p.length; cc2420_pkt.frame.dest_addr[1] = (uint8_t)(p.dst >> 8); @@ -640,7 +667,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) case TRANSCEIVER_MC1322X: maca_pkt->length = p.length; memcpy(maca_pkt->data, p.data, p.length); - maca_set_tx_packet( maca_pkt ); + maca_set_tx_packet(maca_pkt); res = 1; break; #endif @@ -665,6 +692,7 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) res = at86rf231_send(&at86rf231_pkt); break; #endif + default: puts("Unknown transceiver"); break; @@ -686,7 +714,7 @@ static int32_t set_channel(transceiver_type_t t, void *channel) { uint8_t c = *((uint8_t *)channel); - switch(t) { + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_set_channel(c); @@ -696,22 +724,27 @@ static int32_t set_channel(transceiver_type_t t, void *channel) return -1; #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_set_channel(c); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: maca_set_channel(c); - return c; ///< TODO: should be changed! implement get channel + return c; ///< TODO: should be changed!implement get channel #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_set_channel(c); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_set_channel(c); #endif + default: return -1; } @@ -726,7 +759,7 @@ static int32_t set_channel(transceiver_type_t t, void *channel) */ static int32_t get_channel(transceiver_type_t t) { - switch(t) { + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_get_channel(); @@ -736,22 +769,27 @@ static int32_t get_channel(transceiver_type_t t) return -1; #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_get_channel(); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: ///< TODO:implement return maca_get_channel(); return -1; #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_get_channel(); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_get_channel(); #endif + default: return -1; } @@ -766,25 +804,32 @@ static int32_t get_channel(transceiver_type_t t) * * @return The pan AFTER calling the set command, -1 on error */ -static int32_t set_pan(transceiver_type_t t, void *pan) { - uint16_t c = *((uint16_t*) pan); +static int32_t set_pan(transceiver_type_t t, void *pan) +{ + uint16_t c = *((uint16_t *) pan); + switch (t) { #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_set_pan(c); #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_set_pan(c); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_set_pan(c); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: return maca_set_pan(c); #endif + default: /* get rid of compiler warning about unused variable */ (void) c; @@ -799,24 +844,30 @@ static int32_t set_pan(transceiver_type_t t, void *pan) { * * @return The current pan of the transceiver, -1 on error */ -static int32_t get_pan(transceiver_type_t t) { +static int32_t get_pan(transceiver_type_t t) +{ switch (t) { #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_get_pan(); #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_get_pan(); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_get_pan(); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: return maca_get_pan(); #endif + default: return -1; } @@ -833,7 +884,7 @@ static int32_t get_pan(transceiver_type_t t) { */ static radio_address_t get_address(transceiver_type_t t) { - switch(t) { + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_get_address(); @@ -843,21 +894,26 @@ static radio_address_t get_address(transceiver_type_t t) return 0; /* XXX see TODO above */ #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_get_address(); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: return maca_get_address(); #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_get_address(); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_get_address(); #endif + default: return 0; /* XXX see TODO above */ } @@ -877,7 +933,7 @@ static radio_address_t set_address(transceiver_type_t t, void *address) { radio_address_t addr = *((radio_address_t *)address); - switch(t) { + switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG return cc110x_set_address(addr); @@ -887,21 +943,26 @@ static radio_address_t set_address(transceiver_type_t t, void *address) return 0; /* XXX see TODO above */ #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: return cc2420_set_address(addr); #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: return maca_set_address(addr); #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: return nativenet_set_address(addr); #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: return at86rf231_set_address(addr); #endif + default: return 0; /* XXX see TODO above */ } @@ -917,26 +978,31 @@ static void set_monitor(transceiver_type_t t, void *mode) { (void) mode; - switch(t) { + switch (t) { #ifdef MODULE_CC110X_NG + case TRANSCEIVER_CC1100: cc110x_set_monitor(*((uint8_t *)mode)); break; #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: - cc2420_set_monitor(*((uint8_t*) mode)); + cc2420_set_monitor(*((uint8_t *) mode)); break; #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: - nativenet_set_monitor(*((uint8_t*) mode)); + nativenet_set_monitor(*((uint8_t *) mode)); break; #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: - at86rf231_set_monitor(*((uint8_t*) mode)); + at86rf231_set_monitor(*((uint8_t *) mode)); #endif + default: break; } @@ -957,22 +1023,26 @@ void cc1100_packet_monitor(void *payload, int payload_size, protocol_t protocol, /*------------------------------------------------------------------------------------*/ static void powerdown(transceiver_type_t t) { - switch(t) { + switch (t) { #ifdef MODULE_CC110X_NG + case TRANSCEIVER_CC1100: cc110x_switch_to_pwd(); break; #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: maca_off(); break; #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: nativenet_powerdown(); break; #endif + default: break; } @@ -981,27 +1051,32 @@ static void powerdown(transceiver_type_t t) /*------------------------------------------------------------------------------------*/ static void switch_to_rx(transceiver_type_t t) { - switch(t) { + switch (t) { #ifdef MODULE_CC110X_NG + case TRANSCEIVER_CC1100: cc110x_switch_to_rx(); break; #endif #ifdef MODULE_CC2420 + case TRANSCEIVER_CC2420: cc2420_switch_to_rx(); break; #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: nativenet_switch_to_rx(); break; #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: at86rf231_switch_to_rx(); #endif + default: break; } @@ -1020,6 +1095,7 @@ static int16_t ignore_add(transceiver_type_t transceiver, void *address) return i; } } + return -1; } #endif From fa11d8244385f1710f4a9443e934c4e8557a9329 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Fri, 24 Jan 2014 16:59:06 +0100 Subject: [PATCH 02/19] Allow IEEE 802.15.4 addressing types for transceiver IEEE 802.15.4 has two addressing modes: 16-bit short and the device's EUI-64. Currently RIOT supports only sending of packets with 16-bit short addresses via the transceiver interface. This patch allows at least for the radio chips that support IEEE 802.15.4 to let the application/upper layer decide which addressing mode to use. Upper layer implementation will be implemented in follow-up PR to #460 --- sys/net/include/ieee802154_frame.h | 14 ++ sys/transceiver/Makefile | 12 ++ sys/transceiver/transceiver.c | 198 +++++++++++++++++++---------- 3 files changed, 154 insertions(+), 70 deletions(-) diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 5e2088d4fc7f..132cc052f2bf 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -62,6 +62,20 @@ typedef struct __attribute__((packed)) { uint8_t payload_len; } ieee802154_frame_t; +/** + * Structure to represent an IEEE 802.15.4 packet for the transceiver. + */ +typedef struct __attribute__(( packed )) { + /* @{ */ + uint8_t processing; /** < internal processing state */ + uint8_t length; /** < the length of the frame of the frame including fcs*/ + ieee802154_frame_t frame; /** < the ieee802154 frame */ + int8_t rssi; /** < the rssi value */ + uint8_t crc; /** < 1 if crc was successfull, 0 otherwise */ + uint8_t lqi; /** < the link quality indicator */ + /* @} */ +} ieee802154_packet_t; + uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf); uint8_t ieee802154_frame_get_hdr_len(ieee802154_frame_t *frame); uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len); diff --git a/sys/transceiver/Makefile b/sys/transceiver/Makefile index 3c18dcb47842..2828e7bb28cd 100644 --- a/sys/transceiver/Makefile +++ b/sys/transceiver/Makefile @@ -1,3 +1,15 @@ MODULE =transceiver +ifneq (,$(filter cc2420,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include +endif + +ifneq (,$(filter at86rf231,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include +endif + +ifneq (,$(filter mc1322x,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include +endif + include $(MAKEBASE)/Makefile.base diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index b03f677077b7..34886005ed63 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -40,12 +40,14 @@ #ifdef MODULE_CC2420 #include "cc2420.h" +#include "ieee802154_frame.h" #endif #ifdef MODULE_MC1322X #include "mc1322x.h" #include "maca.h" #include "maca_packet.h" +#include "ieee802154_frame.h" #endif #ifdef MODULE_NATIVENET @@ -55,10 +57,12 @@ #ifdef MODULE_AT86RF231 #include "at86rf231.h" +#include "ieee802154_frame.h" #endif #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED #undef TRANSCEIVER_STACK_SIZE #define TRANSCEIVER_STACK_SIZE (KERNEL_CONF_STACKSIZE_PRINTF) #endif @@ -72,7 +76,11 @@ transceiver_type_t transceivers = TRANSCEIVER_NONE; registered_t reg[TRANSCEIVER_MAX_REGISTERED]; /* packet buffers */ +#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X +ieee802154_packet_t transceiver_buffer[TRANSCEIVER_BUFFER_SIZE]; +#else radio_packet_t transceiver_buffer[TRANSCEIVER_BUFFER_SIZE]; +#endif uint8_t data_buffer[TRANSCEIVER_BUFFER_SIZE * PAYLOAD_SIZE]; /* message buffer */ @@ -108,13 +116,13 @@ void cc1100_packet_monitor(void *payload, int payload_size, protocol_t protocol, void receive_cc1100_packet(radio_packet_t *trans_p); #endif #ifdef MODULE_CC2420 -static void receive_cc2420_packet(radio_packet_t *trans_p); +static void receive_cc2420_packet(ieee802154_packet_t *trans_p); #endif #ifdef MODULE_NATIVENET static void receive_nativenet_packet(radio_packet_t *trans_p); #endif #ifdef MODULE_AT86RF231 -void receive_at86rf231_packet(radio_packet_t *trans_p); +void receive_at86rf231_packet(ieee802154_packet_t *trans_p); #endif static int8_t send_packet(transceiver_type_t t, void *pkt); static int32_t get_channel(transceiver_type_t t); @@ -148,7 +156,7 @@ void transceiver_init(transceiver_type_t t) } /* Initializing transceiver buffer and data buffer */ - memset(transceiver_buffer, 0, TRANSCEIVER_BUFFER_SIZE * sizeof(radio_packet_t)); + memset(transceiver_buffer, 0, sizeof(transceiver_buffer)); memset(data_buffer, 0, TRANSCEIVER_BUFFER_SIZE * PAYLOAD_SIZE); #ifdef DBG_IGNORE memset(ignored_addr, 0, MAX_IGNORED_ADDR * sizeof(radio_address_t)); @@ -398,46 +406,41 @@ static void receive_packet(uint16_t type, uint8_t pos) } /* copy packet and handle it */ else { - radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); m.type = PKT_PENDING; /* pass a null pointer if a packet from a undefined transceiver is * received */ if (type == RCV_PKT_CC1100) { #ifdef MODULE_CC110X_NG + radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_cc110x_packet(trans_p); #elif MODULE_CC110X + radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_cc1100_packet(trans_p); -#else - trans_p = NULL; #endif } else if (type == RCV_PKT_MC1322X) { #ifdef MODULE_MC1322X + ieee802154_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_mc1322x_packet(trans_p); -#else - trans_p = NULL; #endif } else if (type == RCV_PKT_CC2420) { #ifdef MODULE_CC2420 + ieee802154_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_cc2420_packet(trans_p); -#else - trans_p = NULL; #endif } else if (type == RCV_PKT_AT86RF231) { #ifdef MODULE_AT86RF231 + ieee802154_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_at86rf231_packet(trans_p); -#else - trans_p = NULL; #endif } else if (type == RCV_PKT_NATIVE) { #ifdef MODULE_NATIVENET + radio_packet_t *trans_p = &(transceiver_buffer[transceiver_buffer_pos]); receive_nativenet_packet(trans_p); -#else - trans_p = NULL; #endif } else { @@ -521,21 +524,56 @@ void receive_cc1100_packet(radio_packet_t *trans_p) #ifdef MODULE_CC2420 -void receive_cc2420_packet(radio_packet_t *trans_p) +void receive_cc2420_packet(ieee802154_packet_t *trans_p) { DEBUG("transceiver: Handling CC2420 packet\n"); dINT(); - cc2420_packet_t p = cc2420_rx_buffer[rx_buffer_pos]; - trans_p->src = (uint16_t)((p.frame.src_addr[1] << 8) | p.frame.src_addr[0]); - trans_p->dst = (uint16_t)((p.frame.dest_addr[1] << 8)| p.frame.dest_addr[0]); - trans_p->rssi = p.rssi; - trans_p->lqi = p.lqi; - trans_p->length = p.frame.payload_len; - memcpy((void*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.frame.payload, CC2420_MAX_DATA_LENGTH); + cc2420_packet_t *p = &cc2420_rx_buffer[rx_buffer_pos]; + trans_p->length = p->length; + memcpy(&trans_p->frame, &p->frame, p->length); + trans_p->rssi = p->rssi; + trans_p->crc = p->crc; + trans_p->lqi = p->lqi; + memcpy(&data_buffer[transceiver_buffer_pos * CC2420_MAX_DATA_LENGTH], + p->frame.payload, p->frame.payload_len); + trans_p->frame.payload = (uint8_t *) & (data_buffer[transceiver_buffer_pos * CC2420_MAX_DATA_LENGTH]); eINT(); - DEBUG("transceiver: Packet %p was from %u to %u, size: %u\n", trans_p, trans_p->src, trans_p->dst, trans_p->length); - trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * CC2420_MAX_DATA_LENGTH]); +#ifdef DEBUG_ENABLED + + if (trans_p->frame.fcf.dest_addr_m == IEEE_802154_SHORT_ADDR_M) { + if (trans_p->frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + DEBUG("Packet %p was from %" PRIu16 " to %" PRIu16 ", size: %u\n", trans_p, *((uint16_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + } + else if (trans_p->frame.fcf.src_addr_m == IEEE_802154_LONG_ADDR_M) { + DEBUG("Packet %p was from %016" PRIx64 " to %" PRIu16 ", size: %u\n", trans_p, *((uint64_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + + } + else { + DEBUG("Illegal source address mode: %d\n", trans_p->frame.fcf.src_addr_m); + return; + } + } + else if (trans_p->frame.fcf.dest_addr_m == IEEE_802154_LONG_ADDR_M) { + if (trans_p->frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + DEBUG("Packet %p was from %" PRIu16 " to %016" PRIx64 ", size: %u\n", trans_p, *((uint16_t *) &trans_p->frame.src_addr[0]), *((uint64_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + } + else if (trans_p->frame.fcf.src_addr_m == IEEE_802154_LONG_ADDR_M) { + DEBUG("Packet %p was from %016" PRIx64 " to %016" PRIx64 ", size: %u\n", trans_p, *((uint64_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + + } + else { + DEBUG("Illegal source address mode: %d\n", trans_p->frame.fcf.src_addr_m); + return; + } + } + else { + DEBUG("Illegal destination address mode: %d\n", trans_p->frame.fcf.src_addr_m); + return; + } +#endif + trans_p->frame.payload = (uint8_t *) &(data_buffer[transceiver_buffer_pos * CC2420_MAX_DATA_LENGTH]); + trans_p->frame.payload_len = p->frame.payload_len; DEBUG("transceiver: Content: %s\n", trans_p->data); } #endif @@ -580,22 +618,44 @@ void receive_nativenet_packet(radio_packet_t *trans_p) #endif #ifdef MODULE_AT86RF231 -void receive_at86rf231_packet(radio_packet_t *trans_p) +void receive_at86rf231_packet(ieee802154_packet_t *trans_p) { DEBUG("Handling AT86RF231 packet\n"); dINT(); - at86rf231_packet_t p = at86rf231_rx_buffer[rx_buffer_pos]; - trans_p->src = (uint16_t)((p.frame.src_addr[1] << 8) | p.frame.src_addr[0]); - trans_p->dst = (uint16_t)((p.frame.dest_addr[1] << 8)| p.frame.dest_addr[0]); - trans_p->rssi = p.rssi; - trans_p->lqi = p.lqi; - trans_p->length = p.frame.payload_len; - memcpy((void*) &(data_buffer[transceiver_buffer_pos * PAYLOAD_SIZE]), p.frame.payload, AT86RF231_MAX_DATA_LENGTH); + at86rf231_packet_t *p = &at86rf231_rx_buffer[rx_buffer_pos]; + trans_p->length = p->length; + trans_p->rssi = p->rssi; + trans_p->crc = p->crc; + trans_p->lqi = p->lqi; + memcpy(&trans_p->frame, &p->frame, p->length); + memcpy(&data_buffer[transceiver_buffer_pos * AT86RF231_MAX_DATA_LENGTH], p->frame.payload, + p->frame.payload_len); + trans_p->frame.payload = (uint8_t *) & (data_buffer[transceiver_buffer_pos * AT86RF231_MAX_DATA_LENGTH]); eINT(); - DEBUG("Packet %p was from %u to %u, size: %u\n", trans_p, trans_p->src, trans_p->dst, trans_p->length); - trans_p->data = (uint8_t*) &(data_buffer[transceiver_buffer_pos * AT86RF231_MAX_DATA_LENGTH]); - DEBUG("Content: %s\n", trans_p->data); +#ifdef DEBUG_ENABLED + + if (trans_p->frame.fcf.dest_addr_m == IEEE_802154_SHORT_ADDR_M) { + if (trans_p->frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + DEBUG("Packet %p was from %" PRIu16 " to %" PRIu16 ", size: %u\n", trans_p, *((uint16_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + } + else { + DEBUG("Packet %p was from %016" PRIx64 " to %" PRIu16 ", size: %u\n", trans_p, *((uint64_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + + } + } + else { + if (trans_p->frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + DEBUG("Packet %p was from %" PRIu16 " to %016" PRIx64 ", size: %u\n", trans_p, *((uint16_t *) &trans_p->frame.src_addr[0]), *((uint64_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + } + else { + DEBUG("Packet %p was from %016" PRIx64 " to %016" PRIx64 ", size: %u\n", trans_p, *((uint64_t *) &trans_p->frame.src_addr[0]), *((uint16_t *) &trans_p->frame.dest_addr), trans_p->frame.payload_len); + + } + } + +#endif + DEBUG("Content: %s\n", trans_p->frame.payload); } #endif /*------------------------------------------------------------------------------------*/ @@ -603,14 +663,29 @@ void receive_at86rf231_packet(radio_packet_t *trans_p) * @brief Sends a radio packet to the receiver * * @param t The transceiver device - * @param pkt Generic pointer to the packet + * @param pkt Generic pointer to the packet (use ieee802154_packet_t for + * AT86RF231, CC2420, and MC1322X) * * @return A negative value if operation failed, 0 or the number of bytes sent otherwise. */ static int8_t send_packet(transceiver_type_t t, void *pkt) { int8_t res = -1; - radio_packet_t p = *((radio_packet_t *)pkt); +#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X + ieee802154_packet_t *p = (ieee802154_packet_t *)pkt; + DEBUG("transceiver: Send packet to "); +#ifdef DEBUG_ENABLED + + for (size_t i = 0; i < 8; i++) { + printf("%02x ", p->frame.dest_addr[i]); + } + + printf("\n"); +#endif +#else + radio_packet_t *p = (radio_packet_t *)pkt; + DEBUG("transceiver: Send packet to %" PRIu16 "\n", p->dst); +#endif #ifdef MODULE_CC110X_NG cc110x_packet_t cc110x_pkt; @@ -627,21 +702,19 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) at86rf231_packet_t at86rf231_pkt; #endif - DEBUG("transceiver: Send packet to %" PRIu16 "\n", p.dst); - switch (t) { case TRANSCEIVER_CC1100: #ifdef MODULE_CC110X_NG - cc110x_pkt.length = p.length + CC1100_HEADER_LENGTH; - cc110x_pkt.address = p.dst; + cc110x_pkt.length = p->length + CC1100_HEADER_LENGTH; + cc110x_pkt.address = p->dst; cc110x_pkt.flags = 0; - memcpy(cc110x_pkt.data, p.data, p.length); + memcpy(cc110x_pkt.data, p->data, p->length); res = cc110x_send(&cc110x_pkt); #elif MODULE_CC110X - memcpy(cc1100_pkt, p.data, p.length); + memcpy(cc1100_pkt, p->data, p->length); - res = cc1100_send_csmaca(p.dst, 4, 0, (char *) cc1100_pkt, p.length); - DEBUG("transceiver: snd_ret (%u) = %i\n", p.length, snd_ret); + res = cc1100_send_csmaca(p->dst, 4, 0, (char *) cc1100_pkt, p->length); + DEBUG("transceiver: snd_ret (%u) = %i\n", p->length, snd_ret); #else puts("Unknown transceiver"); #endif @@ -649,46 +722,31 @@ static int8_t send_packet(transceiver_type_t t, void *pkt) #ifdef MODULE_CC2420 case TRANSCEIVER_CC2420: - cc2420_pkt.frame.payload_len = p.length; - cc2420_pkt.frame.dest_addr[1] = (uint8_t)(p.dst >> 8); - cc2420_pkt.frame.dest_addr[0] = (uint8_t)(p.dst & 0xFF); - cc2420_pkt.frame.dest_pan_id = cc2420_get_pan(); - cc2420_pkt.frame.fcf.dest_addr_m = 2; - cc2420_pkt.frame.fcf.src_addr_m = 2; - cc2420_pkt.frame.fcf.ack_req = 0; - cc2420_pkt.frame.fcf.sec_enb = 0; - cc2420_pkt.frame.fcf.frame_type = 1; - cc2420_pkt.frame.fcf.frame_pend = 0; - cc2420_pkt.frame.payload = p.data; + memcpy(&cc2420_pkt.frame, &p->frame, sizeof(ieee802154_frame_t)); + cc2420_pkt.length = p->frame.payload_len + IEEE_802154_FCS_LEN; res = cc2420_send(&cc2420_pkt); break; #endif #ifdef MODULE_MC1322X + case TRANSCEIVER_MC1322X: - maca_pkt->length = p.length; - memcpy(maca_pkt->data, p.data, p.length); + maca_pkt->length = p->length; + memcpy(maca_pkt->data, p->data, p->length); maca_set_tx_packet(maca_pkt); res = 1; break; #endif #ifdef MODULE_NATIVENET + case TRANSCEIVER_NATIVE: - res = nativenet_send(&p); + res = nativenet_send(p); break; #endif #ifdef MODULE_AT86RF231 + case TRANSCEIVER_AT86RF231: - at86rf231_pkt.frame.payload_len = p.length; - at86rf231_pkt.frame.dest_addr[1] = (uint8_t)(p.dst >> 8); - at86rf231_pkt.frame.dest_addr[0] = (uint8_t)(p.dst & 0xFF); - at86rf231_pkt.frame.dest_pan_id = at86rf231_get_pan(); - at86rf231_pkt.frame.fcf.dest_addr_m = 2; - at86rf231_pkt.frame.fcf.src_addr_m = 2; - at86rf231_pkt.frame.fcf.ack_req = 0; - at86rf231_pkt.frame.fcf.sec_enb = 0; - at86rf231_pkt.frame.fcf.frame_type = 1; - at86rf231_pkt.frame.fcf.frame_pend = 0; - at86rf231_pkt.frame.payload = p.data; + memcpy(&at86rf231_pkt.frame, &p->frame, sizeof(ieee802154_frame_t)); + at86rf231_pkt.length = p->frame.payload_len + IEEE_802154_FCS_LEN; res = at86rf231_send(&at86rf231_pkt); break; #endif From 7f8e2c2991b0a1f12d037001277a1ba65cd62edc Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Tue, 21 Jan 2014 17:08:27 +0100 Subject: [PATCH 03/19] Add getter and setter of long addresses to transceiver --- sys/include/transceiver.h | 7 +++ sys/shell/commands/sc_transceiver.c | 30 +++++++++++++ sys/shell/commands/shell_commands.c | 9 +++- sys/transceiver/transceiver.c | 69 +++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 1 deletion(-) diff --git a/sys/include/transceiver.h b/sys/include/transceiver.h index cafad10bd4e8..79553216fd81 100644 --- a/sys/include/transceiver.h +++ b/sys/include/transceiver.h @@ -107,6 +107,11 @@ */ typedef uint16_t transceiver_type_t; +/** + * @brief Data type to represent the transceiver's EUI-64. + */ +typedef uint64_t transceiver_eui64_t; + /** * @brief Message types for transceiver interface */ @@ -129,6 +134,8 @@ enum transceiver_msg_type_t { SET_CHANNEL, ///< Set a new channel GET_ADDRESS, ///< Get the radio address SET_ADDRESS, ///< Set the radio address + GET_LONG_ADDR, ///< Get the long radio address, if existing + SET_LONG_ADDR, ///< Set the long radio address, if supported by hardware SET_MONITOR, ///< Set transceiver to monitor mode (disable address checking) GET_PAN, ///< Get current pan SET_PAN, ///< Set a new pan diff --git a/sys/shell/commands/sc_transceiver.c b/sys/shell/commands/sc_transceiver.c index 6d5ec8c5e676..f4029504faa4 100644 --- a/sys/shell/commands/sc_transceiver.c +++ b/sys/shell/commands/sc_transceiver.c @@ -80,6 +80,36 @@ void _transceiver_get_set_address_handler(int argc, char **argv) printf("[transceiver] got address: %" PRIu16 "\n", a); } +/* checked for type safety */ +void _transceiver_get_set_long_addr_handler(int argc, char **argv) +{ + msg_t mesg; + transceiver_command_t tcmd; + transceiver_eui64_t a; + + if (transceiver_pid < 0) { + puts("Transceiver not initialized"); + return; + } + + tcmd.transceivers = _TC_TYPE; + tcmd.data = &a; + mesg.content.ptr = (char *) &tcmd; + + if (argc > 1) { + a = atoll(argv[1]); + printf("[transceiver] trying to set EUI-64 %016"PRIx64"\n", a); + mesg.type = SET_LONG_ADDR; + } + else { + mesg.type = GET_LONG_ADDR; + } + + msg_send_receive(&mesg, &mesg, transceiver_pid); + printf("[transceiver] got EUI-64: %016"PRIx64"\n", a); +} + + /* checked for type safety */ void _transceiver_get_set_channel_handler(int argc, char **argv) { diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 8149785a79f3..da236fa7e858 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -65,7 +65,8 @@ extern void _reset_current_handler(int argc, char **argv); #define _TC_MON #define _TC_SEND #endif -#if (defined(MODULE_CC2420) || defined(MODULE_NATIVENET)) +#if (defined(MODULE_CC2420) || defined(MODULE_AT86RF231) || defined(MODULE_NATIVENET)) +#define _TC_LONG_ADDR #define _TC_PAN #endif #else /* WITHOUT MODULE_TRANSCEIVER */ @@ -79,6 +80,9 @@ extern void _cc110x_get_set_channel_handler(int argc, char **argv); #ifdef _TC_ADDR extern void _transceiver_get_set_address_handler(int argc, char **argv); #endif +#ifdef _TC_LONG_ADDR +extern void _transceiver_get_set_long_addr_handler(int argc, char **argv); +#endif #ifdef _TC_CHAN extern void _transceiver_get_set_channel_handler(int argc, char **argv); #endif @@ -138,6 +142,9 @@ const shell_command_t _shell_command_list[] = { #ifdef _TC_ADDR {"addr", "Gets or sets the address for the transceiver", _transceiver_get_set_address_handler}, #endif +#ifdef _TC_LONG_ADDR + {"eui64", "Gets or sets the EUI-64 for the transceiver", _transceiver_get_set_long_addr_handler}, +#endif #ifdef _TC_CHAN {"chan", "Gets or sets the channel for the transceiver", _transceiver_get_set_channel_handler}, #endif diff --git a/sys/transceiver/transceiver.c b/sys/transceiver/transceiver.c index 34886005ed63..f047274ff202 100644 --- a/sys/transceiver/transceiver.c +++ b/sys/transceiver/transceiver.c @@ -129,6 +129,9 @@ static int32_t get_channel(transceiver_type_t t); static int32_t set_channel(transceiver_type_t t, void *channel); static radio_address_t get_address(transceiver_type_t t); static radio_address_t set_address(transceiver_type_t t, void *address); +static transceiver_eui64_t get_long_addr(transceiver_type_t t); +static transceiver_eui64_t set_long_addr(transceiver_type_t t, + void *address); static int32_t get_pan(transceiver_type_t t); static int32_t set_pan(transceiver_type_t t, void *pan); @@ -308,6 +311,16 @@ void run(void) msg_reply(&m, &m); break; + case GET_LONG_ADDR: + *((transceiver_eui64_t *) cmd->data) = get_long_addr(cmd->transceivers); + msg_reply(&m, &m); + break; + + case SET_LONG_ADDR: + *((transceiver_eui64_t *) cmd->data) = set_long_addr(cmd->transceivers, cmd->data); + msg_reply(&m, &m); + break; + case SET_MONITOR: set_monitor(cmd->transceivers, cmd->data); break; @@ -1026,6 +1039,62 @@ static radio_address_t set_address(transceiver_type_t t, void *address) } } +/* + * @brief Get the current long address of transceiver device + * + * @param t The transceiver device + * + * @return The configured long address of the device, 0 on error + */ +static transceiver_eui64_t get_long_addr(transceiver_type_t t) +{ + switch (t) { +#ifdef MODULE_CC2420 + + case TRANSCEIVER_CC2420: + return cc2420_get_address_long(); +#endif +#ifdef MODULE_AT86RF231 + + case TRANSCEIVER_AT86RF231: + return at86rf231_get_address_long(); +#endif + + default: + return 0; + } +} + +/* + * @brief Set the long address of the transceiver device + * + * @param t The transceiver device + * @param address Generic pointer to the long address to set + * + * @return The new long radio address of the device, 0 on error + */ +static transceiver_eui64_t set_long_addr(transceiver_type_t t, void *address) +{ + uint64_t addr = *((uint64_t *)address); + + switch (t) { +#ifdef MODULE_CC2420 + + case TRANSCEIVER_CC2420: + return cc2420_set_address_long(addr); +#endif +#ifdef MODULE_AT86RF231 + + case TRANSCEIVER_AT86RF231: + return at86rf231_set_address_long(addr); +#endif + + default: + (void) addr; + return 0; + } +} + /* * @brief Set the transceiver device into monitor mode (disabling address check) * From 848ac70f900b944ce765d0eb4711c90d5d824204 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Fri, 20 Dec 2013 15:23:09 +0100 Subject: [PATCH 04/19] Implement net_if module --- Makefile.dep | 6 + sys/Makefile | 3 + sys/auto_init/Makefile | 4 + sys/auto_init/auto_init.c | 39 ++ sys/net/include/ieee802154_frame.h | 4 + sys/net/include/net_help.h | 9 + sys/net/include/net_if.h | 504 +++++++++++++++++++++++++ sys/net/link_layer/net_if/Makefile | 5 + sys/net/link_layer/net_if/net_if.c | 552 ++++++++++++++++++++++++++++ sys/shell/commands/sc_transceiver.c | 61 ++- 10 files changed, 1186 insertions(+), 1 deletion(-) create mode 100644 sys/net/include/net_if.h create mode 100644 sys/net/link_layer/net_if/Makefile create mode 100644 sys/net/link_layer/net_if/net_if.c diff --git a/Makefile.dep b/Makefile.dep index 578f190882f5..9d86d5abad67 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -102,3 +102,9 @@ ifneq (,$(filter vtimer,$(USEMODULE))) USEMODULE += timex endif endif + +ifneq (,$(filter net_if,$(USEMODULE))) + ifeq (,$(filter transceiver,$(USEMODULE))) + USEMODULE += transceiver + endif +endif diff --git a/sys/Makefile b/sys/Makefile index e6c9cfef0728..0614547c705b 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -42,6 +42,9 @@ endif ifneq (,$(filter vtimer,$(USEMODULE))) DIRS += vtimer endif +ifneq (,$(filter net_if,$(USEMODULE))) + DIRS += net/link_layer/net_if +endif ifneq (,$(filter destiny,$(USEMODULE))) DIRS += net/transport_layer/destiny endif diff --git a/sys/auto_init/Makefile b/sys/auto_init/Makefile index dc73b225e9b7..f5b62c8ad7ab 100644 --- a/sys/auto_init/Makefile +++ b/sys/auto_init/Makefile @@ -1,3 +1,7 @@ MODULE = auto_init +ifneq (,$(filter net_if,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include/ +endif + include $(RIOTBASE)/Makefile.base diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 8cf58b8dff59..5652f3ce7ac4 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -55,6 +55,11 @@ #include "destiny.h" #endif +#ifdef MODULE_NET_IF +#include "net_if.h" +#include "transceiver.h" +#endif + #define ENABLE_DEBUG (0) #include "debug.h" @@ -97,6 +102,40 @@ void auto_init(void) DEBUG("Auto init mci module.\n"); MCI_initialize(); #endif +#ifdef MODULE_NET_IF + DEBUG("Auto init net_if module.\n"); + transceiver_type_t transceivers = 0; +#ifdef MODULE_AT86RF231 + transceivers |= TRANSCEIVER_AT86RF231; +#endif +#ifdef MODULE_CC1020 + transceivers |= TRANSCEIVER_CC1020; +#endif +#if MODULE_CC110X || MODULE_CC110X_NG + transceivers |= TRANSCEIVER_CC1100; +#endif +#ifdef MODULE_CC2420 + transceivers |= TRANSCEIVER_CC2420; +#endif +#ifdef MODULE_MC1322X + transceivers |= TRANSCEIVER_MC1322X; +#endif +#ifdef MODULE_NATIVENET + transceivers |= TRANSCEIVER_NATIVE; +#endif + net_if_init(); + + if (transceivers != 0) { + transceiver_init(transceivers); + transceiver_start(); + int iface = net_if_init_interface(0, transceivers); + + if (iface >= 0) { + DEBUG("Interface %d initialized\n", iface); + } + } + +#endif #ifdef MODULE_PROFILING extern void profiling_init(void); profiling_init(); diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 132cc052f2bf..42af6b5dfaff 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -38,6 +38,10 @@ #define IEEE_802154_SHORT_ADDR_M 2 #define IEEE_802154_LONG_ADDR_M 3 +#define IEEE_802154_SHORT_MCAST_ADDR (0xffff) +#define IEEE_802154_LONG_MCAST_ADDR {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ + 0xff, 0xff}} + #define IEEE_802154_PAN_ID 0x1234 typedef struct __attribute__((packed)) { diff --git a/sys/net/include/net_help.h b/sys/net/include/net_help.h index 6dd566efa141..03d890b711b3 100644 --- a/sys/net/include/net_help.h +++ b/sys/net/include/net_help.h @@ -21,8 +21,17 @@ (((uint32_t) (a) & 0x00ff0000) >> 8) | \ (((uint32_t) (a) & 0x0000ff00) << 8) | \ (((uint32_t) (a) & 0x000000ff) << 24)) +#define HTONLL(a) ((((uint64_t) (a) & 0xff00000000000000) >> 56) | \ + (((uint64_t) (a) & 0x00ff000000000000) >> 40) | \ + (((uint64_t) (a) & 0x0000ff0000000000) >> 24) | \ + (((uint64_t) (a) & 0x000000ff00000000) >> 8) | \ + (((uint64_t) (a) & 0x00000000ff000000) << 8) | \ + (((uint64_t) (a) & 0x0000000000ff0000) << 24) | \ + (((uint64_t) (a) & 0x000000000000ff00) << 40) | \ + (((uint64_t) (a) & 0x00000000000000ff) << 56)) #define NTOHS HTONS #define NTOHL HTONL +#define NTOHLL HTONLL #define CMP_IPV6_ADDR(a, b) (memcmp(a, b, 16)) diff --git a/sys/net/include/net_if.h b/sys/net/include/net_if.h new file mode 100644 index 000000000000..561788f0625e --- /dev/null +++ b/sys/net/include/net_if.h @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin. + * + * This file is 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. + */ + +/** + * @defgroup net_if Network interfaces + * @brief Abstraction layer between transceiver module and L3 protocol + * implementations. + * @ingroup net + * + * @{ + * + * @file net_if.h + * @brief Types and functions for network interfaces + * @author Freie Universität Berlin + * @author Martin Lenders + */ +#ifndef _NET_IF_H +#define _NET_IF_H + +#include +#include + +#include "mutex.h" +#include "transceiver.h" + +/** + * @brief type to specify types of upper layer addresses + */ +typedef uint8_t net_if_l3p_t; + +/** + * @brief Interface protocols (for net_if_t.protocols): Use raw packets with + * static addresses in upper layer. + */ +#define NET_IF_L3P_RAW (0x00) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use unicast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_UNICAST (0x01) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use multicast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_MULTICAST (0x02) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use anycast IPv6 + * address in upper layer, addr_len must be 128. + */ +#define NET_IF_L3P_IPV6_ANYCAST (0x04) + +/** + * @brief Interface protocols (for net_if_t.protocols): Use IPv6 prefix in + * upper layer, addr_len <= 128 becomes prefix length. + */ +#define NET_IF_L3P_IPV6_PREFIX (0x08) + +/** + * @brief Interface protocols (for net_if_t.protocols): Convenience macro + * combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST, and + * NET_IF_L3P_IPV6_MULTICAST for comparisons + */ +#define NET_IF_L3P_IPV6_ADDR (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \ + | NET_IF_L3P_IPV6_MULTICAST) + +/** + * @brief Interface protocols (for net_if_t.protocols): Convenience macro + * combining NET_IF_L3P_IPV6_UNICAST, NET_IF_L3P_IPV6_ANYCAST, + * NET_IF_L3P_IPV6_MULTICAST, and NET_IF_L3P_IPV6_PREFIX for + * comparisons + */ +#define NET_IF_L3P_IPV6 (NET_IF_L3P_IPV6_UNICAST | NET_IF_L3P_IPV6_ANYCAST \ + | NET_IF_L3P_IPV6_MULTICAST | NET_IF_L3P_IPV6_PREFIX) + +/** + * @brief Interface protocols: Return value of net_if_get_l3p_types() on + * error. + */ +#define NET_IF_L3P_FAILURE (0x80) + +#ifndef NET_IF_MAX +/** + * @brief Maximum number of interfaces. Redefinable via compiler flag. + */ +#define NET_IF_MAX (1) +#endif + +/** + * @brief Data type to represent an EUI-64. + */ +typedef union __attribute__((packed)) { + uint8_t uint8[8]; ///< split into 8 8-bit words. + uint16_t uint16[4]; ///< split into 4 16-bit words. + uint32_t uint32[2]; ///< split into 2 32-bit words. + uint64_t uint64; ///< as one 64-bit word. +} net_if_eui64_t; + +/** + * @brief list type for upper layer address of an interface. + * + * @details The interpretation of the address data is left to the upper layer + * implementations. + */ +typedef struct __attribute__((packed)) net_if_addr_t { + /** + * @brief The next address on the interface. Initialise with NULL + */ + struct net_if_addr_t *addr_next; + + /** + * @brief The next address on the interface. Initialise with NULL + */ + struct net_if_addr_t *addr_prev; + + /** + * @brief Flags to define upper layer protocols this address applies to + */ + net_if_l3p_t addr_protocol; + void *addr_data; ///< The actual upper layer address + uint8_t addr_len; ///< Length of the upper layer address in bit. +} net_if_addr_t; + +typedef uint8_t net_if_trans_addr_m_t; + +/** + * @brief Interface type. + */ +typedef struct __attribute__((packed)) { + uint8_t initialized; ///< Detemines if interface is initialized + uint8_t protocols; ///< Interface L3 protocols + transceiver_type_t transceivers; ///< Transceivers to use with this interface + net_if_trans_addr_m_t trans_src_addr_m; ///< Transceiver address mode + mutex_t address_buffer_mutex; ///< Mutex for address buffer operations + net_if_addr_t *addresses; ///< Adresses + uint8_t l3p_data[9]; ///< generic L3 data +} net_if_t; + +#define NET_IF_TRANS_ADDR_M_SHORT 2 ///< Transceiver address mode for short addresses +#define NET_IF_TRANS_ADDR_M_LONG 3 ///< Transceiver address mode for long addresses + +/** + * All registered interfaces. + */ +extern net_if_t interfaces[NET_IF_MAX]; + +/** + * @brief Initializes the module. + */ +void net_if_init(void); + +/** + * @brief Inititializes a new interface + * + * @pre *transceivers* may not be zero. + * + * @param[in] protocols The upper layer protocols to use on this interface. + * @param[in] transceivers The transceivers this interface uses. + * + * @return The new interface's ID on success, -1 on failure. + */ +int net_if_init_interface(net_if_l3p_t protocols, + transceiver_type_t transceivers); + +/** + * @brief Get interface. + * + * @param[in] if_id The interface's ID + * + * @return The interface identified by *if_id* or NULL on failure. + */ +static inline net_if_t *net_if_get_interface(int if_id) +{ + if (if_id < NET_IF_MAX && interfaces[if_id].initialized) { + return &interfaces[if_id]; + } + else { + return NULL; + } +} + + +/** + * @brief Iterates over all intitialized interfaces + * + * @param[in] start Return value of last iteration step. -1 to start iteration. + * + * @return ID of an initialized interface. -1 if end of interface list is + * reached. + */ +int net_if_iter_interfaces(int start); + +/** + * @brief Sets the source address mode for the interface + * + * @param[in] if_id Interface to set source address mode for. + * @param[in] mode The mode to set to. + * + * @return 1 on success, 0 on error + */ +static inline int net_if_set_src_address_mode(int if_id, + net_if_trans_addr_m_t mode) +{ + if (!interfaces[if_id].initialized) { + return 0; + } + + interfaces[if_id].trans_src_addr_m = mode; + return 1; +} + +/** + * @brief Gets the source address mode for the interface + * + * @param[in] if_id Interface to get source address mode from. + * + * @return The interfaces address mode, 0 on error + */ +static inline net_if_trans_addr_m_t net_if_get_src_address_mode(int if_id) +{ + if (!interfaces[if_id].initialized) { + return 0; + } + + return interfaces[if_id].trans_src_addr_m; +} + +/** + * @brief Adds new address to interface + * + * @pre *addr* is not NULL, *addr->addr_data* is not NULL + * + * @param[in] if_id The interface's ID + * @param[in] addr The address to add + * + * @return 1 on success, 0 on failure. + */ +int net_if_add_address(int if_id, net_if_addr_t *addr); + +/** + * @brief Removes first occurance of address from interface + * + * @pre *addr* is not NULL, *addr->addr_data* is not NULL + * + * @param[in] if_id The interface's ID + * @param[in] addr The address to remove + * + * @return 1 on success (and if given address is not registered to this + * interface), 0 on failure + */ +int net_if_del_address(int if_id, net_if_addr_t *addr); + +/** + * @brief Iterates over registered addresses of an interface. + * + * @param[in] if_id The interface's ID + * @param[in,out] addr The previous address as in or the next address as out. + * If *addr* points to NULL it will be set to the + * first address assigned to *if_id*, if *addr* points to + * NULL as out, the last address assigned to *if_id* was + * given as *addr* previously (and the address list was + * completely iterated). + * + * @return The pointer *addr* refers to after call of this function or NULL on + * error + */ +net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr); + +/** + * @brief Get the upper layer protocol types assigned to the interface *if_id* + * + * @param[in] if_id The interface's ID + * @return The upper layer protocol types assigned to the interface *if_id* on + * success, NET_IF_L3P_FAILURE on failure. + */ +net_if_l3p_t net_if_get_l3p_types(int if_id); + +/** + * @brief Add an upper layer protocol types to the interface *if_id* + * + * @param[in] if_id The interface's ID + * @param[in] protocols The upper layer protocol types to assign to the + * interface *if_id* + * @return 1 on success, 0 on failure. + */ +int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols); + +/** + * @brief Remove upper layer protocol types and all addresses of this scope + * from the interface *if_id* + * + * @param[in] if_id The interface's ID + * @param[in] protocols The upper layer protocol types to be removed from the + * interface *if_id* + * @return 1 on success, 0 on failure. + */ +int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols); + +/** + * @brief Sends a packet to a short address over the interface. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The interface's ID. + * @param[in] target The target's short transceiver address. + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, negative + * number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet(int if_id, uint16_t target, const void *packet_data, + size_t packet_len); + +/** + * @brief Sends a packet to a long address over the interface. If transceiver + * only supports smaller addresses the least significant bit of the + * address will be taken. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The interface's ID. + * @param[in] target The target's long transceiver address. + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, negative + * number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet_long(int if_id, net_if_eui64_t *target, + const void *packet_data, size_t packet_len); + +/** + * @brief Sends a packet over all initialized interfaces. + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] preferred_dest_mode The preferred transceiver address mode for + * the destination broadcast address. Choose + * NET_IF_TRANS_ADDR_M_SHORT if you are not + * sure + * @param[in] packet_data The packet to send + * @param[in] packet_len The length of the packet's data in byte, + * negative number on error. + * + * @return The number of bytes send on success, negative value on failure + */ +int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode, + const void *payload, size_t payload_len); + +/** + * @brief register a thread for events an interface's transceiver + * @details This function just wraps transceiver_register(). + * + * @pre Transceivers has to be initialized and transceiver thread has + * to be started. + * + * @param[in] if_id The transceiver's interface to register for + * @param[in] pid The pid of the thread to register + * + * @return 1 on success, 0 otherwise + */ +int net_if_register(int if_id, int pid); + +/** + * Returns the EUI-64 of the transeivers attached to this interface. This can + * be get by the actual EUI-64 if the transceiver has one or a generated one + * based of the hardware address + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @see + * RFC 4944, section 5 + * + * @see + * RFC 6282, section 3.2.2 + * + * + * @param[out] eui64 The EUI-64 to fill + * @param[in] if_id The interface's ID + * @param[in] force_generation Force generation from a short address if the + * hardware supports it, even if the hardware + * supplies an EUI-64 + * + * @return 1 on success, 0 on failure + */ +int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation); + +/** + * @brief Parses a string to an EUI-64. + * @detail The parsing will be back to front, every non-hexadecimal character + * and every hexadecimal character beyond the count of 8 will be + * ignored + * + * @param[out] eui64 The generated binary EUI-64. + * @param[in] eui64_str A hexadecimal number in string representation. + */ +void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str); + +/** + * Returns the address of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's hardware address on success, 0 on failure + */ +uint16_t net_if_get_hardware_address(int if_id); + +/** + * Returns the EUI-64 of the transeivers attached to this interface. This can + * be get by the actual EUI-64 if the transceiver has one or a generated one + * based of the hardware address + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] eui64 The new EUI-64 + * + * @return 1 on success, 0 on failure + */ +int net_if_set_eui64(int if_id, net_if_eui64_t *eui64); + +/** + * Sets the address of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] addr The new hardware address + * + * @return the new hardware address on success, 0 on failure. + */ +uint16_t net_if_set_hardware_address(int if_id, uint16_t addr); + +/** + * Returns the channel of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's frequency channel on success, -1 on failure. + */ +int32_t net_if_get_channel(int if_id); + +/** + * Sets the channel of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] channel The new frequency channel + * + * @return the new channel on success, -1 on failure. + */ +int32_t net_if_set_channel(int if_id, uint16_t channel); + +/** + * Returns the PAN ID of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * + * @return The transceiver's PAN ID on success, -1 on failure + */ +int32_t net_if_get_pan_id(int if_id); + +/** + * Sets the PAN ID of the transceiver associated with the given interface. + * + * @pre Transceivers of this interface has to be initialized and + * transceiver thread has to be started. + * + * @param[in] if_id The interface's ID + * @param[in] pan_id The new frequency channel + * + * @return the PAN ID on success, -1 on failure. + */ +int32_t net_if_set_pan_id(int if_id, uint16_t pan_id); + +/** + * @} + */ +#endif /* _NET_IF_H */ diff --git a/sys/net/link_layer/net_if/Makefile b/sys/net/link_layer/net_if/Makefile new file mode 100644 index 000000000000..81bfe881437e --- /dev/null +++ b/sys/net/link_layer/net_if/Makefile @@ -0,0 +1,5 @@ +MODULE:=$(shell basename $(CURDIR)) +INCLUDES += -I$(RIOTBASE)/drivers/include \ + -I$(RIOTBASE)/drivers/cc110x_ng/include \ + -I$(RIOTBASE)/sys/net/include +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/net_if/net_if.c b/sys/net/link_layer/net_if/net_if.c new file mode 100644 index 000000000000..4ded2494a5e9 --- /dev/null +++ b/sys/net/link_layer/net_if/net_if.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin. + * + * This file is 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 net_if + * @{ + * @file net_if.c + * @author Martin Lenders + */ +#include + +#include "clist.h" +#include "ieee802154_frame.h" +#include "msg.h" +#include "mutex.h" +#include "net_help.h" +#include "transceiver.h" + +#include "net_if.h" + +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif +#include "debug.h" + +net_if_t interfaces[NET_IF_MAX]; + +#ifdef DEBUG_ENABLED +void print_addr_hex(net_if_addr_t *addr) +{ + int i; + DEBUG("0x"); + + for (i = 0; i < addr->addr_len; i++) { + DEBUG("%02x", ((char *)addr->addr_data)[i]); + } + + DEBUG("\n"); +} +#endif + +uint8_t net_if_hex_to_dec(char c) +{ + if (c >= '0' && c <= '9') { + return (uint8_t)(c - '0'); + } + else if (c >= 'A' && c <= 'F') { + return (uint8_t)(c - 55); + } + else if (c >= 'a' && c <= 'f') { + return (uint8_t)(c - 87); + } + else { + return 0xff; + } +} + +void net_if_hex_to_eui64(net_if_eui64_t *eui64, const char *eui64_str) +{ + int i; + const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1]; + eui64->uint64 = 0; + + for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) { + uint8_t digit; + + while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return; + } + } + + eui64->uint8[i] = digit; + eui64_rev--; + + while ((digit = net_if_hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return; + } + } + + eui64->uint8[i] |= digit << 4; + eui64_rev--; + } +} + +void net_if_init(void) +{ + memset(&interfaces, 0, sizeof(net_if_t) * NET_IF_MAX); +} + +int net_if_init_interface(uint8_t protocols, transceiver_type_t transceivers) +{ + int i; + + if (transceivers == 0) { + DEBUG("Interface initialization: Precondition not met.\n"); + return -1; + } + + for (i = 0; i < NET_IF_MAX; i++) { + if (!interfaces[i].initialized) { + interfaces[i].initialized = 1; + interfaces[i].protocols = protocols; + mutex_init(&interfaces[i].address_buffer_mutex); + interfaces[i].transceivers = transceivers; + DEBUG("Initialized interface %d for protocols %d on transceivers 0x%x\n", + i, protocols, transceivers); + return i; + } + } + + DEBUG("Interface buffer full.\n"); + return -1; +} + +int net_if_iter_interfaces(int start) +{ + if (start == NET_IF_MAX - 1) { + return -1; + } + + start++; + + while (start < NET_IF_MAX && !interfaces[start].initialized) { + start++; + } + + return start; +} + +int net_if_add_address(int if_id, net_if_addr_t *addr) +{ + if (!addr || !addr->addr_data) { + DEBUG("Address addition: Precondition not met.\n"); + return 0; + } + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address addition: No interface initialized with ID %d.\n", if_id); + return 0; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + interfaces[if_id].protocols |= addr->addr_protocol; + + clist_add((clist_node_t **)&interfaces[if_id].addresses, + (clist_node_t *)addr); + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return 1; +} + +int net_if_del_address(int if_id, net_if_addr_t *addr) +{ + if (!addr || !addr->addr_data) { + DEBUG("Address deletion: Precondition not met.\n"); + return 0; + } + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address deletion: No interface initialized with ID %d.\n", if_id); + return 0; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + clist_remove((clist_node_t **)&interfaces[if_id].addresses, + (clist_node_t *)addr); + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return 1; +} + +net_if_addr_t *net_if_iter_addresses(int if_id, net_if_addr_t **addr) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Address iteration: No interface initialized with ID %d.\n", if_id); + return NULL; + } + + if (*addr == NULL) { + *addr = interfaces[if_id].addresses; + return *addr; + } + + clist_advance((clist_node_t **)addr); + + if (*addr == interfaces[if_id].addresses) { + *addr = NULL; + } + + return *addr; +} + +net_if_l3p_t net_if_get_l3p_types(int if_id) +{ + net_if_l3p_t protocols; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get L3 protocols: No interface initialized with ID %d.\n", if_id); + return NET_IF_L3P_FAILURE; + } + + mutex_lock(&interfaces[if_id].address_buffer_mutex); + + protocols = interfaces[if_id].protocols; + + mutex_unlock(&interfaces[if_id].address_buffer_mutex); + + return protocols; +} + +int net_if_add_l3p_types(int if_id, net_if_l3p_t protocols) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Add L3 protocols: No interface initialized with ID %d.\n", if_id); + return 0; + } + + interfaces[if_id].protocols |= protocols; + + return 1; +} + +int net_if_del_l3p_types(int if_id, net_if_l3p_t protocols) +{ + net_if_addr_t *addr_ptr = NULL; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Remove L3 protocols: No interface initialized with ID %d.\n", if_id); + return 0; + } + + while (net_if_iter_addresses(if_id, &addr_ptr)) { + if (addr_ptr->addr_protocol & protocols) { + net_if_del_address(if_id, addr_ptr); + addr_ptr = NULL; + } + } + + interfaces[if_id].protocols &= ~protocols; + + return 1; +} + +uint32_t net_if_transceiver_get_set_handler(int if_id, uint16_t op_type, + void *data) +{ + DEBUG("net_if_transceiver_get_set_handler: if_id = %d, op_type = %d, data = %p\n", + if_id, op_type, data); + msg_t msg; + transceiver_command_t tcmd; + + tcmd.transceivers = interfaces[if_id].transceivers; + tcmd.data = (char *)data; + msg.content.ptr = (char *)&tcmd; + msg.type = op_type; + msg_send_receive(&msg, &msg, transceiver_pid); + + return msg.content.value; +} + +int net_if_send_packet_broadcast(net_if_trans_addr_m_t preferred_dest_mode, + const void *payload, size_t payload_len) +{ + int if_id = -1; + int res = 0, res_prev = 0; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC1100 | TRANSCEIVER_NATIVE)) { + res = net_if_send_packet(if_id, 0, + payload, payload_len); + } + else if (preferred_dest_mode == NET_IF_TRANS_ADDR_M_SHORT) { + res = net_if_send_packet(if_id, IEEE_802154_SHORT_MCAST_ADDR, + payload, payload_len); + } + else { + net_if_eui64_t mcast_addr = IEEE_802154_LONG_MCAST_ADDR; + res = net_if_send_packet_long(if_id, &mcast_addr, payload, + payload_len); + } + + if (res_prev != 0) { + if (res != res_prev) { + return -1; + } + } + else { + if (res == 0) { + break; + } + } + + res_prev = res; + } + + return res; +} + +int net_if_send_packet(int if_id, uint16_t target, const void *payload, + size_t payload_len) +{ + DEBUG("net_if_send_packet: if_id = %d, target = %d, payload = %p, " + "payload_len = %d\n", if_id, target, payload, payload_len); + uint32_t response; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Send packet: No interface initialized with ID %d.\n", if_id); + return -1; + } + + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 | TRANSCEIVER_AT86RF231 | TRANSCEIVER_MC1322X)) { + ieee802154_packet_t p; + + memset(&p, 0, sizeof(ieee802154_packet_t)); + + p.frame.payload = (uint8_t *)payload; + p.frame.payload_len = (uint8_t)payload_len; + p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m; + p.frame.fcf.dest_addr_m = IEEE_802154_SHORT_ADDR_M; + p.frame.fcf.ack_req = 0; + p.frame.fcf.sec_enb = 0; + p.frame.fcf.frame_type = 1; + p.frame.fcf.frame_pend = 0; + + p.frame.dest_pan_id = net_if_get_pan_id(if_id); + memcpy(p.frame.dest_addr, &target, 2); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + else { + radio_packet_t p; + memset(&p, 0, sizeof(radio_packet_t)); + p.data = (uint8_t *) payload; + p.length = payload_len; + p.dst = target; + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + + + return (response > payload_len) ? (int)payload_len : (int)response; +} + +int net_if_send_packet_long(int if_id, net_if_eui64_t *target, + const void *payload, size_t payload_len) +{ + DEBUG("net_if_send_packet: if_id = %d, target = %016" PRIx64 ", " + "payload = %p, payload_len = %d\n", if_id, NTOHLL(target->uint64), payload, + payload_len); + uint32_t response; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Send packet: No interface initialized with ID %d.\n", if_id); + return -1; + } + + if (interfaces[if_id].transceivers & (TRANSCEIVER_CC2420 | + TRANSCEIVER_AT86RF231 | + TRANSCEIVER_MC1322X)) { + ieee802154_packet_t p; + memset(&p, 0, sizeof(ieee802154_packet_t)); + p.frame.payload = (uint8_t *)payload; + p.frame.payload_len = (uint8_t)payload_len; + p.frame.fcf.src_addr_m = (uint8_t)interfaces[if_id].trans_src_addr_m; + p.frame.fcf.dest_addr_m = IEEE_802154_LONG_ADDR_M; + p.frame.fcf.ack_req = 0; + p.frame.fcf.sec_enb = 0; + p.frame.fcf.frame_type = 1; + p.frame.fcf.frame_pend = 0; + p.frame.dest_pan_id = net_if_get_pan_id(if_id); + memcpy(p.frame.dest_addr, target, 8); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + else { + radio_packet_t p; + memset(&p, 0, sizeof(radio_packet_t)); + p.data = (uint8_t *) payload; + p.length = payload_len; + p.dst = NTOHS(target->uint16[3]); + response = net_if_transceiver_get_set_handler(if_id, SND_PKT, (void *)&p); + } + + + return (response > payload_len) ? (int)payload_len : (int)response; +} + +int net_if_register(int if_id, int pid) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Register thread: No interface initialized with ID %d.\n", if_id); + return 0; + } + + return (int)transceiver_register(interfaces[if_id].transceivers, pid); +} + +int net_if_get_eui64(net_if_eui64_t *eui64, int if_id, int force_generation) +{ + uint64_t tmp; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get EUI-64: No interface initialized with ID %d.\n", if_id); + return 0; + } + + if (eui64 == NULL) { + DEBUG("Get EUI-64: parameter eui64 is a NULL pointer.\n"); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, GET_LONG_ADDR, &tmp); + + eui64->uint64 = HTONLL(tmp); + + if (eui64->uint64 == 0 || force_generation) { + uint16_t hwaddr = net_if_get_hardware_address(if_id); + + if (hwaddr == 0) { + return 0; + } + + /* RFC 6282 Section 3.2.2 / RFC 2464 Section 4 */ + eui64->uint32[0] = HTONL(0x000000ff); + eui64->uint16[2] = HTONS(0xfe00); + + if (sizeof(hwaddr) == 2) { + eui64->uint16[3] = HTONS(hwaddr); + } + else if (sizeof(hwaddr) == 1) { + eui64->uint8[6] = 0; + eui64->uint8[7] = (uint8_t)hwaddr; + } + else { + DEBUG("Error on EUI-64 generation: do not know what to do with " + "hardware address of length %d\n", sizeof(hwaddr)); + return 0; + } + + } + + return 1; +} + +int net_if_set_eui64(int if_id, net_if_eui64_t *eui64) +{ + if (eui64 == NULL) { + return 0; + } + + uint64_t tmp = NTOHLL(eui64->uint64); + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set EUI-64: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, SET_LONG_ADDR, (void *) &tmp); + + return eui64->uint64 != 0; +} + +uint16_t net_if_get_hardware_address(int if_id) +{ + uint16_t addr; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get hardware address: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, GET_ADDRESS, &addr); + return addr; +} + +uint16_t net_if_set_hardware_address(int if_id, uint16_t addr) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set hardware address: No interface initialized with ID %d.\n", if_id); + return 0; + } + + net_if_transceiver_get_set_handler(if_id, SET_ADDRESS, &addr); + return addr; +} + +int32_t net_if_get_channel(int if_id) +{ + int32_t channel; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get channel: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, GET_CHANNEL, &channel); + return channel; +} + +int32_t net_if_set_channel(int if_id, uint16_t channel) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set channel: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, SET_CHANNEL, &channel); + return channel; +} + +int32_t net_if_get_pan_id(int if_id) +{ + int32_t pan_id; + + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Get PAN ID: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, GET_PAN, &pan_id); + if (pan_id < 0) { + return 0; + } + else { + return pan_id; + } + +} + +int32_t net_if_set_pan_id(int if_id, uint16_t pan_id) +{ + if (if_id < 0 || if_id > NET_IF_MAX || !interfaces[if_id].initialized) { + DEBUG("Set PAN ID: No interface initialized with ID %d.\n", if_id); + return -1; + } + + net_if_transceiver_get_set_handler(if_id, SET_PAN, &pan_id); + return pan_id; +} + +/** + * @} + */ diff --git a/sys/shell/commands/sc_transceiver.c b/sys/shell/commands/sc_transceiver.c index f4029504faa4..b5caa0a2682b 100644 --- a/sys/shell/commands/sc_transceiver.c +++ b/sys/shell/commands/sc_transceiver.c @@ -21,6 +21,9 @@ #include #include +#ifdef MODULE_NET_IF +#include "net_if.h" +#endif #include "transceiver.h" #include "msg.h" @@ -80,6 +83,56 @@ void _transceiver_get_set_address_handler(int argc, char **argv) printf("[transceiver] got address: %" PRIu16 "\n", a); } +#ifndef MODULE_NET_IF +uint8_t hex_to_dec(char c) +{ + if (c >= '0' && c <= '9') { + return (uint8_t)(c - '0'); + } + else if (c >= 'A' && c <= 'F') { + return (uint8_t)(c - 55); + } + else if (c >= 'a' && c <= 'f') { + return (uint8_t)(c - 87); + } + else { + return 0xff; + } +} + +uint64_t _str_to_eui64(const char *eui64_str) +{ + int i; + const char *eui64_rev = &eui64_str[strlen(eui64_str) - 1]; + uint64_t eui64 = 0; + + for (i = 7; i >= 0 || eui64_rev >= eui64_str; i--) { + uint8_t digit; + eui64 <<= 8; + + while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return eui64; + } + } + + eui64 = digit; + eui64_rev--; + + while ((digit = hex_to_dec(*eui64_rev)) == 0xFF) { + if (--eui64_rev < eui64_str) { + return eui64; + } + } + + eui64 |= digit << 4; + eui64_rev--; + } + + return eui64; +} +#endif + /* checked for type safety */ void _transceiver_get_set_long_addr_handler(int argc, char **argv) { @@ -97,7 +150,13 @@ void _transceiver_get_set_long_addr_handler(int argc, char **argv) mesg.content.ptr = (char *) &tcmd; if (argc > 1) { - a = atoll(argv[1]); +#ifdef MODULE_NET_IF + net_if_eui64_t eui64; + net_if_hex_to_eui64(&eui64, argv[1]); + a = eui64.uint64; +#else + a = _str_to_eui64(argv[1]); +#endif printf("[transceiver] trying to set EUI-64 %016"PRIx64"\n", a); mesg.type = SET_LONG_ADDR; } From 4a6495987eb907e8fff4f36cabefcdaed866bbd5 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Wed, 25 Dec 2013 18:28:11 +0100 Subject: [PATCH 05/19] Add shell commands for interface configuration --- Makefile.dep | 6 + sys/shell/commands/Makefile | 4 + sys/shell/commands/sc_net_if.c | 613 ++++++++++++++++++++++++++++ sys/shell/commands/shell_commands.c | 10 +- 4 files changed, 630 insertions(+), 3 deletions(-) create mode 100644 sys/shell/commands/sc_net_if.c diff --git a/Makefile.dep b/Makefile.dep index 9d86d5abad67..afa5b34ae124 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -108,3 +108,9 @@ ifneq (,$(filter net_if,$(USEMODULE))) USEMODULE += transceiver endif endif + +ifneq (,$(filter shell_commands,$(USEMODULE))) + ifneq (,$(filter net_if,$(USEMODULE))) + USEMODULE += net_help + endif +endif diff --git a/sys/shell/commands/Makefile b/sys/shell/commands/Makefile index fbb5c12005f8..f4d7dc8f69a5 100644 --- a/sys/shell/commands/Makefile +++ b/sys/shell/commands/Makefile @@ -11,6 +11,10 @@ ifneq (,$(filter cc110x,$(USEMODULE))) SRC += sc_cc1100.c endif endif +ifneq (,$(filter net_if,$(USEMODULE))) + INCLUDES += -I$(RIOTBASE)/sys/net/include + SRC += sc_net_if.c +endif ifneq (,$(filter mci,$(USEMODULE))) SRC += sc_disk.c endif diff --git a/sys/shell/commands/sc_net_if.c b/sys/shell/commands/sc_net_if.c new file mode 100644 index 000000000000..790173abe24b --- /dev/null +++ b/sys/shell/commands/sc_net_if.c @@ -0,0 +1,613 @@ +/* + * Shell commands for network interfaces + * + * Copyright (C) 2013 Martin Lenders + * + * This file is 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 shell_commands + * @{ + * @file sc_net_if.c + * @brief provides shell commands to configure network interfaces + * @author Martin Lenders + * @} + */ + +#include +#include +#include +#include +#include + +#include "destiny/socket.h" /* for AF_INET6 */ +#include "inet_pton.h" +#include "inet_ntop.h" +#include "net_help.h" +#include "net_if.h" +#include "transceiver.h" + +#define ADDR_REGISTERED_MAX (6) +#define ADDRS_LEN_MAX (16) + +static uint8_t addr_registered = 0; +static uint8_t addrs[ADDR_REGISTERED_MAX][ADDRS_LEN_MAX]; + +void _net_if_ifconfig_add(int if_id, int argc, char **argv); +void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv); +void _net_if_ifconfig_set(int if_id, char *key, char *value); +void _net_if_ifconfig_set_srcaddrmode(int if_id, char *mode); +void _net_if_ifconfig_set_eui64(int if_id, char *addr); +void _net_if_ifconfig_set_hwaddr(int if_id, char *addr); +void _net_if_ifconfig_set_pan_id(int if_id, char *pan_id); +void _net_if_ifconfig_set_channel(int if_id, char *channel); +void _net_if_ifconfig_create(char *transceivers_str); +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, + char *addr_data_str, char *addr_data_len); +void _net_if_ifconfig_list(int if_id); + +int isnumber(char *str) +{ + for (; *str; str++) { + if (!isdigit((int)*str)) { + return 0; + } + } + + return 1; +} + +static inline void _eui64_to_str(char *eui64_str, net_if_eui64_t *eui64) +{ + sprintf(eui64_str, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", + eui64->uint8[0], eui64->uint8[1], eui64->uint8[2], eui64->uint8[3], + eui64->uint8[4], eui64->uint8[5], eui64->uint8[6], eui64->uint8[7]); +} + +char *addr_data_to_str(char *addr_str, const uint8_t *addr, uint8_t addr_len) +{ + int i; + + for (i = 0; i < addr_len / 8; i++) { + sprintf(addr_str, "%02x", addr[i]); + } + + uint8_t r = addr_len % 8; + + if (r) { + uint8_t mask = 0x00; + + while (r) { + mask |= 0x1 << (8 - (r--)); + } + + sprintf(addr_str, "%02x", addr[addr_len / 8] & mask); + } + + return addr_str; +} + +void add_usage(void) +{ + puts("Usage: ifconfig add ipv6 [multicast|anycast] "); +} + +void set_usage(void) +{ + printf("Usage: ifconfig set \n" + " Sets an transceiver specific value\n" + " may be one of the following\n" + " * \"srcaddrmode\" - sets the source address mode for IEEE\n" + " 802.15.4 transeivers (valid values: \"short\" or \"long\"),\n" + " * \"sam\" - alias for \"srcaddrmode\"\n" + " * \"eui64\" - sets the EUI-64 if supported by transceivers,\n" + " * \"hwaddr\" - sets the 16-bit address (or just the address\n" + " for e.g cc1100) of the transceivers\n" + " * \"pan_id\" - sets the PAN ID of the transceiver\n" + " * \"pan\" - alias for \"pan_id\"\n" + " * \"channel\" - sets the frequency channel of the transceiver\n" + " * \"chan\" - alias for \"channel\"\n"); +} + +void create_usage(void) +{ + puts("Usage: ifconfig create [,,...]\n" + " may be one of the following values:\n" +#ifdef MODULE_AT86RF231 + " * at86rv231\n" +#endif +#ifdef MODULE_CC1020 + " * cc1020\n" +#endif +#if MODULE_CC110X || MODULE_CC110X_NG + " * cc1100\n" +#endif +#ifdef MODULE_CC2420 + " * cc2420\n" +#endif +#ifdef MODULE_MC1322X + " * mc1322x\n" +#endif +#ifdef MODULE_NATIVENET + " * native\n" +#endif + ); +} + +void _net_if_ifconfig(int argc, char **argv) +{ + if (argc < 2) { + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + _net_if_ifconfig_list(if_id); + } + + return; + } + else if (strcmp(argv[1], "create") == 0) { + _net_if_ifconfig_create(argv[2]); + return; + } + else if (isnumber(argv[1])) { + int if_id = atoi(argv[1]); + + if (argc < 3) { + _net_if_ifconfig_list(if_id); + return; + } + else if (strcmp(argv[2], "add") == 0) { + if (argc < 5) { + add_usage(); + return; + } + + _net_if_ifconfig_add(if_id, argc, argv); + return; + } + else if (strcmp(argv[2], "set") == 0) { + if (argc < 5) { + set_usage(); + return; + } + + _net_if_ifconfig_set(if_id, argv[3], argv[4]); + return; + } + } + + create_usage(); + printf("or: ifconfig [ [add |set ]]\n"); +} + +void _net_if_ifconfig_set_srcaddrmode(int if_id, char *mode) +{ + if (mode == NULL) { + set_usage(); + return; + } + else if (strcmp(mode, "short") == 0) { + net_if_set_src_address_mode(if_id, NET_IF_TRANS_ADDR_M_SHORT); + } + else if (strcmp(mode, "long") == 0) { + net_if_set_src_address_mode(if_id, NET_IF_TRANS_ADDR_M_LONG); + } + else { + set_usage(); + return; + } +} + +void _net_if_ifconfig_set_eui64(int if_id, char *eui64_str) +{ + net_if_eui64_t eui64; + + if (eui64_str == NULL) { + set_usage(); + return; + } + + net_if_hex_to_eui64(&eui64, eui64_str); + net_if_set_eui64(if_id, &eui64); +} + +void _net_if_ifconfig_set_hwaddr(int if_id, char *addr_str) +{ + int addr; + + if (addr_str == NULL) { + set_usage(); + return; + } + + if (isnumber(addr_str)) { + if ((addr = atoi(addr_str)) > 0xffff) { + set_usage(); + return; + } + } + else { + if ((addr = strtoul(addr_str, NULL, 16)) > 0xffff) { + set_usage(); + return; + } + } + + net_if_set_hardware_address(if_id, (uint16_t)addr); +} + +void _net_if_ifconfig_set_pan_id(int if_id, char *pan_str) +{ + int pan_id; + + if (pan_str == NULL) { + set_usage(); + return; + } + + if (isnumber(pan_str)) { + if ((pan_id = atoi(pan_str)) > 0xffff) { + set_usage(); + return; + } + } + else { + if ((pan_id = strtoul(pan_str, NULL, 16)) > 0xffff) { + set_usage(); + return; + } + } + + net_if_set_pan_id(if_id, (uint16_t) pan_id); +} + +void _net_if_ifconfig_set_channel(int if_id, char *chan_str) +{ + int channel; + + if (chan_str == NULL) { + set_usage(); + return; + } + + if (isnumber(chan_str)) { + if ((channel = atoi(chan_str)) > 0xffff) { + set_usage(); + return; + } + } + else { + if ((channel = strtoul(chan_str, NULL, 16)) > 0xffff) { + set_usage(); + return; + } + } + + net_if_set_channel(if_id, (uint16_t) channel); +} + +void _net_if_ifconfig_set(int if_id, char *key, char *value) +{ + if (strcmp(key, "sam") == 0 || strcmp(key, "srcaddrmode") == 0) { + _net_if_ifconfig_set_srcaddrmode(if_id, value); + } + else if (strcmp(key, "eui64") == 0) { + _net_if_ifconfig_set_eui64(if_id, value); + } + else if (strcmp(key, "hwaddr") == 0) { + _net_if_ifconfig_set_hwaddr(if_id, value); + } + else if (strcmp(key, "pan") == 0 || strcmp(key, "pan_id") == 0) { + _net_if_ifconfig_set_pan_id(if_id, value); + } + else if (strcmp(key, "chan") == 0 || strcmp(key, "channel") == 0) { + _net_if_ifconfig_set_channel(if_id, value); + } + else { + set_usage(); + return; + } +} + +void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv) +{ + char *type; + char *addr_str; + char *addr_data_str; + char *addr_data_len; + net_if_addr_t addr; + + if (argc > 5) { + if (strcmp(argv[4], "multicast") == 0 || strcmp(argv[4], "anycast") == 0 || strcmp(argv[4], "unicast") == 0) { + type = argv[4]; + addr_str = argv[5]; + } + else { + add_usage(); + return; + } + } + else { + addr_str = argv[4]; + type = NULL; + } + + addr_data_str = strtok(addr_str, "/"); + addr_data_len = strtok(NULL, "/"); + + if (!_net_if_ifconfig_ipv6_addr_convert(&addr, type, addr_data_str, addr_data_len)) { + add_usage(); + return; + } + + if (net_if_add_address(if_id, &addr) < 0) { + add_usage(); + return; + } + + addr_registered++; +} + +void _net_if_ifconfig_add(int if_id, int argc, char **argv) +{ + if (strcmp(argv[3], "ipv6") == 0) { + _net_if_ifconfig_add_ipv6(if_id, argc, argv); + } + else { + add_usage(); + } +} + +void _net_if_ifconfig_create(char *transceivers_str) +{ + char *transceiver_str; + transceiver_type_t transceivers = TRANSCEIVER_NONE; + int iface; + + transceiver_str = strtok(transceivers_str, ","); + + while (transceiver_str) { + if (strcasecmp(transceiver_str, "at86rv231") == 0) { + transceivers |= TRANSCEIVER_AT86RF231; + } + else if (strcasecmp(transceiver_str, "cc1020") == 0) { + transceivers |= TRANSCEIVER_CC1020; + } + else if (strcasecmp(transceiver_str, "cc1100") == 0) { + transceivers |= TRANSCEIVER_CC1100; + } + else if (strcasecmp(transceiver_str, "cc2420") == 0) { + transceivers |= TRANSCEIVER_CC2420; + } + else if (strcasecmp(transceiver_str, "mc1322x") == 0) { + transceivers |= TRANSCEIVER_MC1322X; + } + else if (strcasecmp(transceiver_str, "native") == 0) { + transceivers |= TRANSCEIVER_NATIVE; + } + else { + create_usage(); + return; + } + + transceiver_str = strtok(NULL, ","); + } + + if (!transceivers) { + create_usage(); + return; + } + + iface = net_if_init_interface(NET_IF_L3P_RAW, transceivers); + + if (iface < 0) { + puts("Maximum number of allowed interfaces reached.\n"); + } + else { + printf("Initialized interface %d\n", iface); + } +} + +static inline int _is_multicast(uint8_t *addr) +{ + return *addr == 0xff; +} + +static inline int _is_link_local(uint8_t *addr) +{ + return (addr[0] == 0xfe && addr[1] == 0x80) || + (_is_multicast(addr) && (addr[1] & 0x0f) == 2); +} + +int _set_protocol_from_type(char *type, net_if_addr_t *addr) +{ + if (type != NULL) { + if ((strcmp(type, "multicast") == 0) && + _is_multicast((uint8_t *)addr->addr_data)) { + addr->addr_protocol |= NET_IF_L3P_IPV6_MULTICAST; + return 1; + } + else if ((strcmp(type, "anycast") == 0) && + addr->addr_protocol & NET_IF_L3P_IPV6_PREFIX) { + addr->addr_protocol |= NET_IF_L3P_IPV6_ANYCAST; + return 1; + } + + return 0; + } + else if (_is_multicast((uint8_t *)addr->addr_data)) { + addr->addr_protocol |= NET_IF_L3P_IPV6_MULTICAST; + return 1; + } + else { + addr->addr_protocol |= NET_IF_L3P_IPV6_UNICAST; + return 1; + } +} + +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, + char *addr_data_str, char *addr_data_len) +{ + if (addr_data_len && !isnumber(addr_data_len)) { + return 0; + } + + addr->addr_data = (void *)&addrs[addr_registered][0]; + + if (!inet_pton(AF_INET6, addr_data_str, addr->addr_data)) { + return 0; + } + + else if (addr_data_len == NULL) { + addr->addr_len = 128; + addr->addr_protocol = 0; + + if (!_set_protocol_from_type(type, addr)) { + return 0; + } + } + else { + addr->addr_len = atoi(addr_data_len); + addr->addr_protocol = NET_IF_L3P_IPV6_PREFIX; + + if (addr->addr_len > 128 || !_set_protocol_from_type(type, addr)) { + return 0; + } + } + + return 1; +} + +void _net_if_ifconfig_list(int if_id) +{ + net_if_t *iface = net_if_get_interface(if_id); + transceiver_type_t transceivers; + uint16_t hw_address; + int32_t channel; + int32_t pan_id; + net_if_eui64_t eui64; + char eui64_str[24]; + net_if_addr_t *addr_ptr = NULL; + + if (!iface) { + return; + } + + transceivers = iface->transceivers; + hw_address = net_if_get_hardware_address(if_id); + channel = net_if_get_channel(if_id); + pan_id = net_if_get_pan_id(if_id); + net_if_get_eui64(&eui64, if_id, 0); + _eui64_to_str(eui64_str, &eui64); + + printf("Iface %3d HWaddr: 0x%04x", if_id, + hw_address); + + if (channel < 0) { + printf(" Channel: not set"); + } + else { + printf(" Channel: %d", (uint16_t) channel); + } + + if (pan_id < 0) { + printf(" PAN ID: not set"); + } + else { + printf(" PAN ID: 0x%04x", (uint16_t)pan_id); + } + + printf("\n"); + + printf(" EUI-64: %s\n", eui64_str); + + switch (net_if_get_src_address_mode(if_id)) { + case NET_IF_TRANS_ADDR_M_SHORT: + puts(" Source address mode: short"); + break; + + case NET_IF_TRANS_ADDR_M_LONG: + puts(" Source address mode: long"); + break; + + default: + puts(" Source address mode: unknown"); + break; + } + + puts(" Transceivers:"); + + if (transceivers & TRANSCEIVER_AT86RF231) { + puts(" * at86rf231"); + } + + if (transceivers & TRANSCEIVER_CC1020) { + puts(" * cc1020"); + } + + if (transceivers & TRANSCEIVER_CC1100) { + puts(" * cc1100"); + } + + if (transceivers & TRANSCEIVER_CC2420) { + puts(" * cc2420"); + } + + if (transceivers & TRANSCEIVER_MC1322X) { + puts(" * mc1322x"); + } + + if (transceivers & TRANSCEIVER_NATIVE) { + puts(" * native"); + } + + while (net_if_iter_addresses(if_id, &addr_ptr)) { + if (addr_ptr->addr_protocol == NET_IF_L3P_RAW) { + char addr_str[addr_ptr->addr_len / 4 + 3]; + + printf(" Raw L3 addr: 0x"); + printf("%s", addr_data_to_str(addr_str, addr_ptr->addr_data, + addr_ptr->addr_len)); + puts("\n"); + } + + if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6) { + char addr_str[50]; + printf(" inet6 addr: "); + + if (inet_ntop(AF_INET6, addr_ptr->addr_data, addr_str, + addr_ptr->addr_len / 8 + 1)) { + printf("%s/%d", addr_str, addr_ptr->addr_len); + printf(" scope: "); + + if (addr_ptr->addr_len > 2 && _is_link_local((uint8_t *)addr_ptr->addr_data)) { + printf("local"); + } + else { + printf("local"); + } + + if (!(addr_ptr->addr_protocol & NET_IF_L3P_IPV6_UNICAST)) { + printf(" "); + + if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6_MULTICAST) { + printf("[multicast]"); + } + else if (addr_ptr->addr_protocol & NET_IF_L3P_IPV6_ANYCAST) { + printf("[anycast]"); + } + } + + printf("\n"); + } + else { + printf("error in conversion\n"); + } + } + } + + puts(""); +} diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index da236fa7e858..f1740511daf7 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -100,6 +100,10 @@ extern void _transceiver_set_ignore_handler(int argc, char **argv); #endif #endif +#ifdef MODULE_NET_IF +extern void _net_if_ifconfig(int argc, char **argv); +#endif + #ifdef MODULE_MCI extern void _get_sectorsize(int argc, char **argv); extern void _get_blocksize(int argc, char **argv); @@ -137,7 +141,6 @@ const shell_command_t _shell_command_list[] = { {"cur", "Prints current and average power consumption.", _get_current_handler}, {"rstcur", "Resets coulomb counter.", _reset_current_handler}, #endif - #ifdef MODULE_TRANSCEIVER #ifdef _TC_ADDR {"addr", "Gets or sets the address for the transceiver", _transceiver_get_set_address_handler}, @@ -166,7 +169,9 @@ const shell_command_t _shell_command_list[] = { {"chan", "Gets or sets the channel for the CC1100 transceiver", _cc110x_get_set_channel_handler}, #endif #endif - +#ifdef MODULE_NET_IF + {"ifconfig", "Configures a network interface", _net_if_ifconfig}, +#endif #ifdef MODULE_MCI {DISK_READ_SECTOR_CMD, "Reads the specified sector of inserted memory card", _read_sector}, {DISK_READ_BYTES_CMD, "Reads the specified bytes from inserted memory card", _read_bytes}, @@ -178,6 +183,5 @@ const shell_command_t _shell_command_list[] = { { "mersenne_init", "initializes the PRNG", _mersenne_init }, { "mersenne_get", "returns 32 bit of pseudo randomness", _mersenne_get }, #endif - {NULL, NULL, NULL} }; From a5e0e92bb38946a1cd28fc41947815f221aad0bb Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sat, 18 Jan 2014 21:07:07 +0100 Subject: [PATCH 06/19] Add test cases for net_if module --- tests/test_net_if/Makefile | 32 +++ tests/test_net_if/main.c | 470 +++++++++++++++++++++++++++++++++++++ 2 files changed, 502 insertions(+) create mode 100644 tests/test_net_if/Makefile create mode 100644 tests/test_net_if/main.c diff --git a/tests/test_net_if/Makefile b/tests/test_net_if/Makefile new file mode 100644 index 000000000000..51fb1828647f --- /dev/null +++ b/tests/test_net_if/Makefile @@ -0,0 +1,32 @@ +export PROJECT = test_net_if + +BOARD_WHITELIST = native msba2 telosb + +include ../Makefile.tests_common + +ifeq ($(BOARD),stm32f4discovery) + include Makefile.$(BOARD) +endif + +USEMODULE += auto_init +USEMODULE += net_if +ifeq ($(BOARD),native) + USEMODULE += nativenet +else ifeq ($(BOARD),msba2) + USEMODULE += cc110x_ng +else ifeq ($(BOARD),telosb) + USEMODULE += cc2420 +else ifeq ($(BOARD),wsn430-v1_4) + USEMODULE += cc2420 +else ifeq ($(BOARD),iot-lab_M3) + USEMODULE += at86rf231 +endif + +export INCLUDES += -I$(RIOTBASE)/sys/net/include + +ifeq ($(BOARD),msba2) + export INCLUDES += -I$(RIOTBASE)/drivers/cc110x_ng/include \ + -I$(RIOTBASE)/boards/msba2-common/include +endif + +include $(RIOTBASE)/Makefile.include diff --git a/tests/test_net_if/main.c b/tests/test_net_if/main.c new file mode 100644 index 000000000000..3f4a58a9808b --- /dev/null +++ b/tests/test_net_if/main.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2013 Martin Lenders + * + * 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. + */ + +#include +#include +#include + +#include "net_if.h" +#include "net_help.h" +#include "transceiver.h" + +#ifndef TRANSCEIVER +#ifdef MODULE_AT86RF231 +#define TRANSCEIVER (TRANSCEIVER_AT86RF231) +#elif MODULE_CC110X_NG +#define TRANSCEIVER (TRANSCEIVER_CC1100) +#elif MODULE_NATIVENET +#define TRANSCEIVER (TRANSCEIVER_NATIVE) +#elif MODULE_CC2420 +#define TRANSCEIVER (TRANSCEIVER_CC2420) +#endif +#endif + +int initialize_tests(void); +int test_net_if_initialization(int iface); +int test_net_if_get_add_l3p_types(int iface); +int test_net_if_add_address(int iface, net_if_addr_t *addr1, + net_if_addr_t *addr2); +int test_net_if_del_address(int iface, net_if_addr_t *addr1, + net_if_addr_t *addr2); +int test_net_if_get_set_hardware_address(int iface, uint16_t addr); +int test_net_if_get_set_pan_id(int iface); +int test_net_if_get_set_eui64(int iface, net_if_eui64_t *eui64, + uint16_t addr); + +int main(void) +{ + int iface; + char *addr1_data = "abcdefgh", *addr2_data = "12345678"; + net_if_addr_t addr1 = { + .addr_next = NULL, + .addr_prev = NULL, + .addr_protocol = NET_IF_L3P_IPV6_MULTICAST, + .addr_data = (void *)addr1_data, + .addr_len = (strlen(addr1_data) + 1) * 8 + }; + net_if_addr_t addr2 = { + .addr_next = NULL, + .addr_prev = NULL, + .addr_protocol = NET_IF_L3P_IPV6_PREFIX, + .addr_data = (void *)addr2_data, + .addr_len = (strlen(addr2_data) + 1) * 8 + }; + uint16_t own = 1, target = 2; + net_if_eui64_t eui64; + + iface = initialize_tests(); + + if (!test_net_if_initialization(iface)) { + printf("FAILED: test_net_if_initialization()\n"); + return -1; + } + + if (!test_net_if_get_add_l3p_types(iface)) { + printf("FAILED: test_net_if_get_add_l3p_types()\n"); + return -1; + } + + if (!test_net_if_add_address(iface, &addr1, &addr2)) { + printf("FAILED: test_net_if_add_address()\n"); + return -1; + } + + if (!test_net_if_del_address(iface, &addr1, &addr2)) { + printf("FAILED: test_net_if_del_address()\n"); + return -1; + } + + if (!test_net_if_get_set_hardware_address(iface, own)) { + printf("FAILED: test_net_if_get_set_hardware_address()\n"); + return -1; + } + + if (!test_net_if_get_set_pan_id(iface)) { + printf("FAILED: test_net_if_get_set_pan_id()\n"); + return -1; + } + + if (!test_net_if_get_set_eui64(iface, &eui64, own)) { + printf("FAILED: test_net_if_get_set_eui64()\n"); + return -1; + } + + int count = net_if_send_packet(iface, target, "Test", 4); + + printf("Count was %i after net_if_send_packet()\n", count); + + printf("All test ran successfully.\n"); + + return 0; +} + +int initialize_tests(void) +{ + int iface; + +#ifndef MODULE_AUTO_INIT + transceiver_init(TRANSCEIVER); + transceiver_start(); + net_if_init(); + iface = net_if_init_interface(0, TRANSCEIVER); + return iface; +#else + iface = -1; + + while ((iface = net_if_iter_interfaces(iface)) >= 0) { + return iface; + } + + return iface; +#endif +} + +int test_net_if_initialization(int iface) +{ + net_if_addr_t *addr_ptr = NULL; + + if (net_if_get_l3p_types(iface)) { + printf("FAILED: No L3 type expected on interface %d.\n", iface); + return 0; + } + + if (net_if_iter_addresses(iface + 1, &addr_ptr)) { + printf("FAILED: Expected error on interface '%d'\n", iface + 1); + return 0; + } + + if (net_if_iter_addresses(iface, &addr_ptr)) { + printf("FAILED: Expected error on interface '%d'\n", iface); + return 0; + } + + return 1; +} + +int test_net_if_get_add_l3p_types(int iface) +{ + if (net_if_add_l3p_types(iface + 1, NET_IF_L3P_IPV6_UNICAST)) { + printf("FAILED: expected net_if_add_l3p_types to fail for iface %d.\n", + iface + 1); + return 0; + } + + if (!net_if_add_l3p_types(iface, 0)) { + printf("FAILED: expected net_if_add_l3p_types to succeed for iface %d and no type\n", + iface); + return 0; + } + + + if (!net_if_add_l3p_types(iface, NET_IF_L3P_IPV6_UNICAST)) { + printf("FAILED: expected net_if_add_l3p_types to succeed for iface %d and no type\n", + iface); + return 0; + } + + if (!(net_if_get_l3p_types(iface) & NET_IF_L3P_IPV6_UNICAST)) { + printf("FAILED: L3 type IPv6 unicast expected on interface %d.\n", iface); + return 0; + } + + if (net_if_get_l3p_types(iface) & ~NET_IF_L3P_IPV6_UNICAST) { + printf("FAILED: L3 type other than IPv6 unicast not expected on interface %d.\n", + iface); + return 0; + } + + if (net_if_del_l3p_types(iface + 1, NET_IF_L3P_IPV6_UNICAST)) { + printf("FAILED: expected net_if_del_l3p_types to fail for iface %d.\n", + iface + 1); + return 0; + } + + if (!net_if_del_l3p_types(iface, 0)) { + printf("FAILED: expected net_if_del_l3p_types to succeed for iface %d and no type\n", + iface); + return 0; + } + + if (!net_if_del_l3p_types(iface, NET_IF_L3P_IPV6_UNICAST)) { + printf("FAILED: expected net_if_del_l3p_types to succeed for iface %d and no type\n", + iface); + return 0; + } + + if (net_if_get_l3p_types(iface)) { + printf("FAILED: No L3 type expected on interface %d.\n", iface); + return 0; + } + + return 1; +} + +int test_net_if_add_address(int iface, net_if_addr_t *addr1, + net_if_addr_t *addr2) +{ + int count = 0; + net_if_addr_t *addr_ptr = NULL; + + if (net_if_add_address(iface + 1, addr1)) { + printf("FAILED: expected net_if_add_address(%d, %p) to fail.\n", + iface + 1, (void *)addr1); + return 0; + } + + if (net_if_add_address(iface, NULL)) { + printf("FAILED: expected net_if_add_address(%d, NULL) to fail.\n", + iface); + return 0; + } + + if (!net_if_add_address(iface, addr1)) { + printf("FAILED: Address addition failed\n"); + return 0; + } + + if (!(net_if_get_l3p_types(iface) & NET_IF_L3P_IPV6_MULTICAST)) { + printf("FAILED: L3 type IPv6 multicast expected on interface %d.\n", iface); + return 0; + } + + if (net_if_get_l3p_types(iface) & ~NET_IF_L3P_IPV6_MULTICAST) { + printf("FAILED: L3 type other than IPv6 multicast not expected on interface %d.\n", + iface); + return 0; + } + + if (!net_if_add_address(iface, addr2)) { + printf("FAILED: Address addition failed\n"); + return 0; + } + + if (!(net_if_get_l3p_types(iface) & NET_IF_L3P_IPV6_MULTICAST)) { + printf("FAILED: L3 type IPv6 multcast expected on interface %d.\n", iface); + return 0; + } + + if (!(net_if_get_l3p_types(iface) & NET_IF_L3P_IPV6_PREFIX)) { + printf("FAILED: L3 type IPv6 prefix expected on interface %d.\n", iface); + return 0; + } + + if (net_if_get_l3p_types(iface) & ~(NET_IF_L3P_IPV6_MULTICAST | NET_IF_L3P_IPV6_PREFIX)) { + printf("FAILED: L3 type other than IPv6 multicast and IPv6 prefix not expected on interface %d.\n", + iface); + return 0; + } + + while (net_if_iter_addresses(iface, &addr_ptr)) { + if (addr_ptr == addr1 || addr_ptr == addr2) { + count++; + } + } + + if (count != 2) { + printf("FAILED: expected 2 addresses in iface's address list once respectively\n"); + printf(" missing '%d'\n", 2 - count); + return 0; + } + + return 1; +} + +int test_net_if_del_address(int iface, net_if_addr_t *addr1, + net_if_addr_t *addr2) +{ + int count = 0; + net_if_addr_t *addr_ptr = NULL; + + if (net_if_del_address(iface + 1, addr1)) { + printf("FAILED: expected net_if_del_address(%d, %p) to fail.\n", + iface + 1, (void *)addr1); + return 0; + } + + if (net_if_del_address(iface, NULL)) { + printf("FAILED: expected net_if_del_address(%d, NULL) to fail.\n", + iface); + return 0; + } + + if (!net_if_del_address(iface, addr1)) { + printf("FAILED: Address deletion failed\n"); + return 0; + } + + while (net_if_iter_addresses(iface, &addr_ptr)) { + if (addr_ptr == addr1 || addr_ptr == addr2) { + count++; + } + } + + if (count != 1) { + printf("FAILED: expected 1 address in iface's address list\n"); + printf(" missing '%d'\n", 1 - count); + return 0; + } + + return 1; +} + +int test_net_if_get_set_hardware_address(int iface, uint16_t addr) +{ + uint16_t tmp; + + if (net_if_set_hardware_address(iface + 1, addr)) { + printf("FAILED: expected net_if_set_hardware_address(%d, %d) to fail.\n", + iface + 1, addr); + return 0; + } + + if (net_if_set_hardware_address(iface, 0)) { + printf("FAILED: expected net_if_set_hardware_address(%d, 0) to fail.\n", + iface); + return 0; + } + + tmp = net_if_set_hardware_address(iface, addr); + + if (addr != tmp) { + printf("FAILED: Expected '%d' as result of net_if_set_hardware_addr() " + "(was '%d')\n", addr, tmp); + return 0; + } + + tmp = net_if_get_hardware_address(iface); + + if (addr != tmp) { + printf("FAILED: Expected '%d' as result of net_if_get_hardware_addr() " + "(was '%d')\n", addr, tmp); + return 0; + } + + return 1; +} + +int test_net_if_get_set_pan_id(int iface) +{ + int32_t res; + uint16_t pan_id = 0xabcd; + + if ((res = net_if_get_pan_id(iface + 1)) >= 0) { + printf("FAILED: net_if_get_pan_id(%d) not failed\n", iface); + return 0; + } + + if ((res = net_if_set_pan_id(iface, pan_id)) < 0) { + printf("FAILED: net_if_set_pan_id(%d, 0x%04x) failed\n", iface, pan_id); + return 0; + } + +#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X + + if ((res = net_if_get_pan_id(iface)) < 0) { + printf("FAILED: net_if_get_pan_id(%d) failed\n", iface); + return 0; + } + + pan_id = (uint16_t)res; +#else + pan_id = 0; +#endif + + return 1; +} + +int test_net_if_get_set_eui64(int iface, net_if_eui64_t *eui64, + uint16_t addr) +{ + uint16_t pan_id; + +#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X + int32_t res; + + if ((res = net_if_get_pan_id(iface)) < 0) { + printf("FAILED: net_if_get_pan_id(%d) failed\n", iface); + return 0; + } + + pan_id = (uint16_t)res; +#else + pan_id = 0; +#endif + + if (net_if_get_eui64(NULL, iface, 1)) { + printf("FAILED: expected net_if_get_eui64(NULL, %d, 1) to fail\n", + iface); + return 0; + } + + if (!net_if_get_eui64(eui64, iface, 1)) { + printf("FAILED: Error getting EUI-64 on interface %d\n", iface); + return 0; + } + + if (eui64->uint16[0] != HTONS(pan_id) || eui64->uint8[2] != 0 || + eui64->uint8[3] != 0xff || eui64->uint8[4] != 0xfe || + eui64->uint8[5] != 0 || (uint16_t)eui64->uint16[3] != HTONS(addr)) { + printf("FAILED: Expected last 16 bit of EUI-64 to be 0x%04x (is 0x%04x)\n", + addr, NTOHS(eui64->uint16[3])); + return 0; + } + + eui64->uint64 = 0; + + if (net_if_set_eui64(iface, NULL)) { + printf("FAILED: expected error on net_if_set_eui64(%d, NULL)\n", iface); + return 0; + } + + if (net_if_set_eui64(iface, eui64)) { + printf("FAILED: expected error trying to set EUI-64 to broadcast\n"); + return 0; + } + +#if MODULE_AT86RF231 || MODULE_CC2420 || MODULE_MC1322X + eui64->uint8[0] = 0x11; + eui64->uint8[1] = 0x22; + eui64->uint8[2] = 0x33; + eui64->uint8[3] = 0x44; + eui64->uint8[4] = 0x55; + eui64->uint8[5] = 0x66; + eui64->uint8[6] = 0x77; + eui64->uint8[7] = 0x88; + + if (!net_if_set_eui64(iface, eui64)) { + printf("FAILED: Error setting EUI-64 on interface %d\n", iface); + return 0; + } + + eui64->uint64 = 0; + + if (!net_if_get_eui64(eui64, iface, 0)) { + printf("FAILED: Error getting EUI-64 on interface %d\n", iface); + return 0; + } + + /* transceivers that do not support EUI-64 addresses convert automatically + * so we have to test both cases */ + if (eui64->uint8[0] != 0x11 || eui64->uint8[1] != 0x22 || + eui64->uint8[2] != 0x33 || eui64->uint8[3] != 0x44 || + eui64->uint8[4] != 0x55 || eui64->uint8[5] != 0x66 || + eui64->uint8[6] != 0x77 || eui64->uint8[7] != 0x88) { + printf("FAILED: EUI-64 to be 11-22-33-44-55-66-77-88 but is " + "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + eui64->uint8[0], eui64->uint8[1], eui64->uint8[2], + eui64->uint8[3], eui64->uint8[4], eui64->uint8[5], + eui64->uint8[6], eui64->uint8[7]); + return 0; + } + +#endif + + return 1; +} From bc4befb4e9c4c8ff933acf4b26b1d52ffe0cc15a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Wed, 5 Feb 2014 00:12:01 +0100 Subject: [PATCH 07/19] Fix coding conventions for sixlowpan and rpl module --- sys/net/include/sixlowpan/ip.h | 4 +-- sys/net/network_layer/sixlowpan/icmp.c | 2 +- sys/net/network_layer/sixlowpan/icmp.h | 2 +- sys/net/network_layer/sixlowpan/ip.c | 22 +++++++++------ sys/net/network_layer/sixlowpan/lowpan.c | 11 +++++--- sys/net/network_layer/sixlowpan/mac.c | 17 +++++------ sys/net/routing/rpl/etx_beaconing.c | 4 +-- sys/net/routing/rpl/rpl.c | 36 ++++++++++++++++-------- sys/net/routing/rpl/rpl_dodag.c | 1 + sys/net/routing/rpl/trickle.c | 2 ++ 10 files changed, 63 insertions(+), 38 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 6f231a0c93ea..9b84c401bb08 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -92,7 +92,7 @@ ipv6_hdr_t *ipv6_get_buf(void); * is going to try to find a route */ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, - const uint8_t *payload, uint16_t payload_length); + const uint8_t *payload, uint16_t payload_length); /** * @brief Determines if node is a router. @@ -375,7 +375,7 @@ void ipv6_iface_print_addrs(void); * * @param next_hop function that returns the next hop to reach dest */ -void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t* dest)); +void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t *dest)); /** * @brief Calculates the IPv6 upper-layer checksum. diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 0125430ea2fe..ffb2ed425ae2 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -1570,7 +1570,7 @@ void def_rtr_lst_rem(ndp_default_router_list_t *entry) /* prefix list functions */ int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) + uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) { if (prefix_count == OPT_PI_LIST_LEN) { return SIXLOWERROR_ARRAYFULL; diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index 297b18e06015..6cb502d3fec2 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -54,7 +54,7 @@ void recv_nbr_sol(void); void nbr_cache_auto_rem(void); int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); + uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 65553676fb1a..e6071d341e1b 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -54,7 +54,7 @@ uint8_t iface_addr_list_count = 0; int udp_packet_handler_pid = 0; int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; -ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t*) = 0; +ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; @@ -100,7 +100,7 @@ uint8_t *get_payload_buf(uint8_t ext_len) } int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, - const uint8_t *payload, uint16_t payload_length) + const uint8_t *payload, uint16_t payload_length) { uint8_t *p_ptr; uint16_t packet_length; @@ -296,7 +296,8 @@ void ipv6_process(void) (ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) { packet_length = IPV6_HDR_LEN + ipv6_buf->length; - ipv6_addr_t* dest; + ipv6_addr_t *dest; + if (ip_get_next_hop == NULL) { dest = &ipv6_buf->destaddr; } @@ -320,10 +321,12 @@ void ipv6_process(void) switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); + /* checksum test*/ - if (ipv6_csum(ipv6_buf, (uint8_t*) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { printf("ERROR: wrong checksum\n"); } + icmpv6_demultiplex(icmp_buf); break; } @@ -695,9 +698,11 @@ void ipv6_register_next_header_handler(uint8_t next_header, int pid) case (IPV6_PROTO_NUM_TCP): set_tcp_packet_handler_pid(pid); break; + case (IPV6_PROTO_NUM_UDP): set_udp_packet_handler_pid(pid); break; + default: /* TODO */ break; @@ -705,7 +710,8 @@ void ipv6_register_next_header_handler(uint8_t next_header, int pid) } /* register routing function */ -void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t* dest)) { +void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t *dest)) +{ ip_get_next_hop = next_hop; } @@ -718,9 +724,9 @@ uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t { uint16_t sum = 0; DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), - len, buf, proto); + ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + len, buf, proto); sum = len + proto; sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); sum = csum(sum, buf, len); diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 08cd65844076..1af050f7097b 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -180,8 +180,9 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, } /* check if packet needs to be fragmented */ - DEBUG("sixlowpan_lowpan_sendto(%s, data, %" PRIu16 "): send_packet_length: %" PRIu16 ", header_size: %" PRIu16 "\n", - sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + DEBUG("sixlowpan_lowpan_sendto(%s, data, %"PRIu16"): send_packet_length: %"PRIu16", header_size: %"PRIu16"\n", + sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + if (send_packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { uint8_t fragbuf[send_packet_length + header_size]; uint8_t remaining; @@ -642,7 +643,7 @@ void check_timeout(void) while (temp_buf != NULL) { if ((timex_uint64(now) - timex_uint64(temp_buf->timestamp)) >= LOWPAN_REAS_BUF_TIMEOUT) { printf("TIMEOUT!cur_time: %" PRIu64 ", temp_buf: %" PRIu64 "\n", timex_uint64(now), - timex_uint64(temp_buf->timestamp)); + timex_uint64(temp_buf->timestamp)); temp_buf = collect_garbage(temp_buf); } else { @@ -786,6 +787,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, else { lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_laddr, d_laddr); + if (current_buf && current_buf->packet) { /* Copy packet bytes into corresponding packet space area */ memcpy(current_buf->packet, data, length); @@ -795,6 +797,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, else { DEBUG("ERROR: no memory left in packet buffer!\n"); } + if (thread_getstatus(transfer_pid) == STATUS_SLEEPING) { thread_wakeup(transfer_pid); } @@ -1676,7 +1679,7 @@ void lowpan_init(transceiver_type_t trans, uint8_t r_addr, ipv6_addr_set_by_eui64(&tmp, prefix); DEBUG("%s, %d: set unique address to %s, according to prefix %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp), ipv6_addr_to_str(addr_str, prefix)); ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); + NDP_ADDR_STATE_PREFERRED, 0, 0); } DEBUG("%s, %d: set link local prefix to %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index dd7969b1ae31..34c71cba6b58 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -138,12 +138,13 @@ void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr) laddr->uint8[7] = sixlowpan_mac_get_radio_address(); } -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) { - sprintf(addr_str, - "%02x:%02x:%02x:%02x", - laddr->uint16[0], laddr->uint16[1], - laddr->uint16[2], laddr->uint16[3]); - return addr_str; +char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) +{ + sprintf(addr_str, + "%02x:%02x:%02x:%02x", + laddr->uint16[0], laddr->uint16[1], + laddr->uint16[2], laddr->uint16[3]); + return addr_str; } void recv_ieee802154_frame(void) @@ -238,9 +239,9 @@ void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, memcpy(&buf[hdrlen], frame.payload, frame.payload_len); /* set FCS */ /* RSSI = 0 */ - buf[frame.payload_len+hdrlen] = 0; + buf[frame.payload_len + hdrlen] = 0; /* FCS Valid = 1 / LQI Correlation Value = 0 */ - buf[frame.payload_len+hdrlen+1] = 0x80; + buf[frame.payload_len + hdrlen + 1] = 0x80; DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame.dest_pan_id, frame.src_pan_id, frame.seq_nr); p.length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; diff --git a/sys/net/routing/rpl/etx_beaconing.c b/sys/net/routing/rpl/etx_beaconing.c index 991413873a73..cc16ddfb5d8d 100644 --- a/sys/net/routing/rpl/etx_beaconing.c +++ b/sys/net/routing/rpl/etx_beaconing.c @@ -195,7 +195,7 @@ void etx_beacon(void) packet->length = p_length; sixlowpan_mac_send_ieee802154_frame(&empty_addr, &etx_send_buf[0], - ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); + ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); etx_set_packets_received(); cur_round++; @@ -457,7 +457,7 @@ void etx_update(etx_neighbor_t *candidate) /* * Calculate the current ETX value for my link to this candidate. */ - if (d_f *d_r != 0) { + if (d_f * d_r != 0) { candidate->cur_etx = 1 / (d_f * d_r); } else { diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 24b42d5fb64c..ae7bc1313136 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -88,23 +88,28 @@ static uint8_t *get_rpl_send_payload_buf(uint8_t ext_len) return &(rpl_send_buffer[IPV6_HDR_LEN + ext_len]); } -static icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len) { +static icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len) +{ return ((icmpv6_hdr_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ext_len])); } -static struct rpl_dio_t *get_rpl_send_dio_buf(void) { +static struct rpl_dio_t *get_rpl_send_dio_buf(void) +{ return ((struct rpl_dio_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_t *get_rpl_send_dao_buf(void) { +static struct rpl_dao_t *get_rpl_send_dao_buf(void) +{ return ((struct rpl_dao_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void) { +static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void) +{ return ((struct rpl_dao_ack_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dis_t *get_rpl_send_dis_buf(void) { +static struct rpl_dis_t *get_rpl_send_dis_buf(void) +{ return ((struct rpl_dis_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } @@ -129,20 +134,24 @@ static ipv6_hdr_t *get_rpl_ipv6_buf(void) return ((ipv6_hdr_t *) &(rpl_buffer[0])); } -static struct rpl_dio_t *get_rpl_dio_buf(void) { +static struct rpl_dio_t *get_rpl_dio_buf(void) +{ return ((struct rpl_dio_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_t *get_rpl_dao_buf(void) { +static struct rpl_dao_t *get_rpl_dao_buf(void) +{ return ((struct rpl_dao_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void) { +static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void) +{ return ((struct rpl_dao_ack_t *) &(buffer[(LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN)])); } -static struct rpl_dis_t *get_rpl_dis_buf(void) { - return ((struct rpl_dis_t *) & (rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); +static struct rpl_dis_t *get_rpl_dis_buf(void) +{ + return ((struct rpl_dis_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } static rpl_opt_t *get_rpl_opt_buf(uint8_t rpl_msg_len) @@ -345,6 +354,7 @@ void send_DIS(ipv6_addr_t *destination) void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index) { DEBUG("Send DAO\n"); + if (i_am_root) { return; } @@ -364,6 +374,7 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, mutex_unlock(&rpl_send_mutex); return; } + destination = &my_dodag->my_preferred_parent->addr; } @@ -664,6 +675,7 @@ void recv_rpl_dio(void) else { DEBUG("Cannot access DODAG because of DIO with infinite rank\n"); } + return; } @@ -694,7 +706,7 @@ void recv_rpl_dio(void) reset_trickletimer(); } - /* We are root, all done! */ + /* We are root, all done!*/ if (my_dodag->my_rank == ROOT_RANK) { if (rpl_dio_buf->rank != INFINITE_RANK) { trickle_increment_counter(); @@ -924,7 +936,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = 0; - icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t*) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); + icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t *) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); /* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the diff --git a/sys/net/routing/rpl/rpl_dodag.c b/sys/net/routing/rpl/rpl_dodag.c index cad23b33caca..5c356f7d3c58 100644 --- a/sys/net/routing/rpl/rpl_dodag.c +++ b/sys/net/routing/rpl/rpl_dodag.c @@ -222,6 +222,7 @@ void rpl_delete_worst_parent(void) void rpl_delete_all_parents(void) { rpl_dodag_t *my_dodag = rpl_get_my_dodag(); + if (my_dodag != NULL) { my_dodag->my_preferred_parent = NULL; } diff --git a/sys/net/routing/rpl/trickle.c b/sys/net/routing/rpl/trickle.c index be0b88d1677c..eb98dcc4afd4 100644 --- a/sys/net/routing/rpl/trickle.c +++ b/sys/net/routing/rpl/trickle.c @@ -166,11 +166,13 @@ void trickle_interval_over(void) timex_normalize(&I_time); vtimer_remove(&trickle_t_timer); + if (vtimer_set_wakeup(&trickle_t_timer, t_time, timer_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } vtimer_remove(&trickle_I_timer); + if (vtimer_set_wakeup(&trickle_I_timer, I_time, interval_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } From 90e946eb49016834cbb0b5b8dd87be7f8eecee09 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 07:59:02 +0100 Subject: [PATCH 08/19] Fix ieee802154_frame module --- sys/net/include/ieee802154_frame.h | 40 +++-- .../link_layer/ieee802154/ieee802154_frame.c | 145 ++++++++++++------ 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 42af6b5dfaff..e983b1682bfa 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -26,23 +26,44 @@ #include /* maximum 802.15.4 header length */ -#define IEEE_802154_MAX_HDR_LEN 23 +#define IEEE_802154_MAX_HDR_LEN (23) /* ...and FCS*/ -#define IEEE_802154_FCS_LEN 2 +#define IEEE_802154_FCS_LEN (2) -#define IEEE_802154_BEACON_FRAME 0 -#define IEEE_802154_DATA_FRAME 1 -#define IEEE_802154_ACK_FRAME 2 -#define IEEE_802154_MAC_CMD_FRAME 3 +#define IEEE_802154_BEACON_FRAME (0) +#define IEEE_802154_DATA_FRAME (1) +#define IEEE_802154_ACK_FRAME (2) +#define IEEE_802154_MAC_CMD_FRAME (3) -#define IEEE_802154_SHORT_ADDR_M 2 -#define IEEE_802154_LONG_ADDR_M 3 +#define IEEE_802154_SHORT_ADDR_M (2) +#define IEEE_802154_LONG_ADDR_M (3) #define IEEE_802154_SHORT_MCAST_ADDR (0xffff) #define IEEE_802154_LONG_MCAST_ADDR {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff}} +/** + * @brief Transform 16-bit number from network order (big-endian) to + * little-endian byte order (as used by IEEE 802.15.4). + */ +#define NTOLES(a) (((a) >> 8) | (((a) & 0x00ff) << 8)) + +/** + * @brief Transform 16-bit number from little-endian byte order to network + * order (big-endian). + */ +#define LETONS(a) NTOLES(a) -#define IEEE_802154_PAN_ID 0x1234 +/** + * @brief Transform 16-bit number from host byte order to little-endian byte + * order (as used by IEEE 802.15.4). + */ +#define HTOLES(a) a + +/** + * @brief Transform 16-bit number from little-endian byte order to host byte + * order. + */ +#define LETOHS(a) HTOLES(a) typedef struct __attribute__((packed)) { uint8_t frame_type; @@ -84,6 +105,7 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf); uint8_t ieee802154_frame_get_hdr_len(ieee802154_frame_t *frame); uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len); void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame); +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len); /** @} */ #endif /* IEEE802154_IEEE802154_FRAME */ diff --git a/sys/net/link_layer/ieee802154/ieee802154_frame.c b/sys/net/link_layer/ieee802154/ieee802154_frame.c index 866cb457da1b..7a9e412a7578 100644 --- a/sys/net/link_layer/ieee802154/ieee802154_frame.c +++ b/sys/net/link_layer/ieee802154/ieee802154_frame.c @@ -18,6 +18,13 @@ #include "ieee802154_frame.h" +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif +#include "debug.h" + +#define IEEE_802154_FCS_POLY (0x8408) /* x^16 + x^12 + x^5 + 1 for LSB first */ uint8_t ieee802154_hdr_ptr; uint8_t ieee802154_payload_ptr; @@ -28,16 +35,16 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Frame Control Field - 802.15.4 - 2006 - 7.2.1.1 */ uint8_t index = 0; - buf[index] = ((frame->fcf.frame_type) | - (frame->fcf.sec_enb << 3) | - (frame->fcf.frame_pend << 4) | - (frame->fcf.ack_req << 5) | - (frame->fcf.panid_comp << 6)); + buf[index] = (((frame->fcf.frame_type) & 0x07) | + ((frame->fcf.sec_enb << 3) & 0x08) | + ((frame->fcf.frame_pend << 4) & 0x10) | + ((frame->fcf.ack_req << 5) & 0x20) | + ((frame->fcf.panid_comp << 6) & 0x40)); index++; - buf[index] = ((frame->fcf.dest_addr_m << 2) | - (frame->fcf.frame_ver << 4) | - (frame->fcf.src_addr_m << 6)); + buf[index] = (((frame->fcf.dest_addr_m << 2) & 0x0c) | + ((frame->fcf.frame_ver << 4) & 0x30) | + ((frame->fcf.src_addr_m << 6) & 0xc0)); index++; @@ -55,49 +62,62 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Destination Address - 802.15.4 - 2006 - 7.2.1.4 */ if (frame->fcf.dest_addr_m == 0x02) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; + buf[index] = frame->dest_addr[1]; + buf[index + 1] = frame->dest_addr[0]; index += 2; } else if (frame->fcf.dest_addr_m == 0x03) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; - buf[index + 2] = frame->dest_addr[2]; - buf[index + 3] = frame->dest_addr[3]; - buf[index + 4] = frame->dest_addr[4]; - buf[index + 5] = frame->dest_addr[5]; - buf[index + 6] = frame->dest_addr[6]; - buf[index + 7] = frame->dest_addr[7]; + buf[index] = frame->dest_addr[7]; + buf[index + 1] = frame->dest_addr[6]; + buf[index + 2] = frame->dest_addr[5]; + buf[index + 3] = frame->dest_addr[4]; + buf[index + 4] = frame->dest_addr[3]; + buf[index + 5] = frame->dest_addr[2]; + buf[index + 6] = frame->dest_addr[1]; + buf[index + 7] = frame->dest_addr[0]; index += 8; } /* Source PAN Identifier - 802.15.4 - 2006 - 7.2.1.5 */ if (!(frame->fcf.panid_comp & 0x01)) { if (frame->fcf.src_addr_m == 0x02 || frame->fcf.src_addr_m == 0x03) { - buf[index] = ((frame->src_pan_id >> 8) & 0xff); - buf[index + 1] = (frame->src_pan_id & 0xff); + buf[index + 1] = ((frame->src_pan_id >> 8) & 0xff); + buf[index] = (frame->src_pan_id & 0xff); index += 2; } } /* Source Address field - 802.15.4 - 2006 - 7.2.1.6 */ if (frame->fcf.src_addr_m == 0x02) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; + buf[index] = frame->src_addr[1]; + buf[index + 1] = frame->src_addr[0]; index += 2; } else if (frame->fcf.src_addr_m == 0x03) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; - buf[index + 2] = frame->src_addr[2]; - buf[index + 3] = frame->src_addr[3]; - buf[index + 4] = frame->src_addr[4]; - buf[index + 5] = frame->src_addr[5]; - buf[index + 6] = frame->src_addr[6]; - buf[index + 7] = frame->src_addr[7]; + buf[index] = frame->src_addr[7]; + buf[index + 1] = frame->src_addr[6]; + buf[index + 2] = frame->src_addr[5]; + buf[index + 3] = frame->src_addr[4]; + buf[index + 4] = frame->src_addr[3]; + buf[index + 5] = frame->src_addr[2]; + buf[index + 6] = frame->src_addr[1]; + buf[index + 7] = frame->src_addr[0]; index += 8; } +#ifdef DEBUG_ENABLED + DEBUG("INFO: IEEE 802.15.4 header initialized:\n"); + + for (size_t i = 0; i < index; i++) { + printf("%02x ", buf[i]); + + if (!((i + 1) % 16) || i == index - 1) { + printf("\n"); + } + } + +#endif + return index; } @@ -170,13 +190,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; - switch(frame->fcf.dest_addr_m) { + switch (frame->fcf.dest_addr_m) { case (0): { - printf("fcf.dest_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.dest_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->dest_addr[0] = buf[index]; frame->dest_addr[1] = buf[index + 1]; index += 2; @@ -184,14 +205,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->dest_addr[0] = buf[index]; - frame->dest_addr[1] = buf[index + 1]; - frame->dest_addr[2] = buf[index + 2]; - frame->dest_addr[3] = buf[index + 3]; - frame->dest_addr[4] = buf[index + 4]; - frame->dest_addr[5] = buf[index + 5]; - frame->dest_addr[6] = buf[index + 6]; - frame->dest_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->dest_addr[7] = buf[index]; + frame->dest_addr[6] = buf[index + 1]; + frame->dest_addr[5] = buf[index + 2]; + frame->dest_addr[4] = buf[index + 3]; + frame->dest_addr[3] = buf[index + 4]; + frame->dest_addr[2] = buf[index + 5]; + frame->dest_addr[1] = buf[index + 6]; + frame->dest_addr[0] = buf[index + 7]; index += 8; break; } @@ -202,13 +224,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; } - switch(frame->fcf.src_addr_m) { + switch (frame->fcf.src_addr_m) { case (0): { - printf("fcf.src_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.src_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->src_addr[0] = buf[index]; frame->src_addr[1] = buf[index + 1]; index += 2; @@ -216,14 +239,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->src_addr[0] = buf[index]; - frame->src_addr[1] = buf[index + 1]; - frame->src_addr[2] = buf[index + 2]; - frame->src_addr[3] = buf[index + 3]; - frame->src_addr[4] = buf[index + 4]; - frame->src_addr[5] = buf[index + 5]; - frame->src_addr[6] = buf[index + 6]; - frame->src_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->src_addr[7] = buf[index]; + frame->src_addr[6] = buf[index + 1]; + frame->src_addr[5] = buf[index + 2]; + frame->src_addr[4] = buf[index + 3]; + frame->src_addr[3] = buf[index + 4]; + frame->src_addr[2] = buf[index + 5]; + frame->src_addr[1] = buf[index + 6]; + frame->src_addr[0] = buf[index + 7]; index += 8; break; } @@ -236,6 +260,27 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, return hdrlen; } +/* crc with lsb first */ +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len) +{ + uint16_t r = 0; + + for (uint8_t byte = 0; byte < frame_len; ++byte) { + r ^= frame[byte]; + + for (uint8_t bit = 8; bit > 0; --bit) { + if (r & 0x0001) { + r = (r >> 1) ^ IEEE_802154_FCS_POLY; + } + else { + r = (r >> 1); + } + } + } + + return r; +} + void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame) { printf("frame type: %02x\n" From 4e39cbdd54b9ba25ed63230e9e2666f1f275703f Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sun, 16 Feb 2014 16:08:48 +0100 Subject: [PATCH 09/19] Put 6LoWPAN border router in its own module --- Makefile.dep | 6 ++++++ sys/Makefile | 3 +++ sys/net/network_layer/sixlowpan/{ => border}/border.c | 0 sys/net/network_layer/sixlowpan/{ => border}/border.h | 0 .../network_layer/sixlowpan/{ => border}/bordermultiplex.c | 0 .../network_layer/sixlowpan/{ => border}/bordermultiplex.h | 0 sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.c | 0 sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.h | 0 sys/net/network_layer/sixlowpan/lowpan.c | 4 +++- 9 files changed, 12 insertions(+), 1 deletion(-) rename sys/net/network_layer/sixlowpan/{ => border}/border.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/border.h (100%) rename sys/net/network_layer/sixlowpan/{ => border}/bordermultiplex.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/bordermultiplex.h (100%) rename sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.h (100%) diff --git a/Makefile.dep b/Makefile.dep index afa5b34ae124..eff649d8a441 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -79,6 +79,12 @@ ifneq (,$(filter destiny,$(USEMODULE))) endif endif +ifneq (,$(filter sixlowborder,$(USEMODULE))) + ifeq (,$(filter sixlowpan,$(USEMODULE))) + USEMODULE += sixlowpan + endif +endif + ifneq (,$(filter sixlowpan,$(USEMODULE))) ifeq (,$(filter ieee802154,$(USEMODULE))) USEMODULE += ieee802154 diff --git a/sys/Makefile b/sys/Makefile index 0614547c705b..69bc1a233a03 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -57,6 +57,9 @@ endif ifneq (,$(filter sixlowpan,$(USEMODULE))) DIRS += net/network_layer/sixlowpan endif +ifneq (,$(filter sixlowborder,$(USEMODULE))) + DIRS += net/network_layer/sixlowpan/border +endif ifneq (,$(filter rpl,$(USEMODULE))) DIRS += net/routing/rpl endif diff --git a/sys/net/network_layer/sixlowpan/border.c b/sys/net/network_layer/sixlowpan/border/border.c similarity index 100% rename from sys/net/network_layer/sixlowpan/border.c rename to sys/net/network_layer/sixlowpan/border/border.c diff --git a/sys/net/network_layer/sixlowpan/border.h b/sys/net/network_layer/sixlowpan/border/border.h similarity index 100% rename from sys/net/network_layer/sixlowpan/border.h rename to sys/net/network_layer/sixlowpan/border/border.h diff --git a/sys/net/network_layer/sixlowpan/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c similarity index 100% rename from sys/net/network_layer/sixlowpan/bordermultiplex.c rename to sys/net/network_layer/sixlowpan/border/bordermultiplex.c diff --git a/sys/net/network_layer/sixlowpan/bordermultiplex.h b/sys/net/network_layer/sixlowpan/border/bordermultiplex.h similarity index 100% rename from sys/net/network_layer/sixlowpan/bordermultiplex.h rename to sys/net/network_layer/sixlowpan/border/bordermultiplex.h diff --git a/sys/net/network_layer/sixlowpan/flowcontrol.c b/sys/net/network_layer/sixlowpan/border/flowcontrol.c similarity index 100% rename from sys/net/network_layer/sixlowpan/flowcontrol.c rename to sys/net/network_layer/sixlowpan/border/flowcontrol.c diff --git a/sys/net/network_layer/sixlowpan/flowcontrol.h b/sys/net/network_layer/sixlowpan/border/flowcontrol.h similarity index 100% rename from sys/net/network_layer/sixlowpan/flowcontrol.h rename to sys/net/network_layer/sixlowpan/border/flowcontrol.h diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 1af050f7097b..e0b6b95b59a3 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -36,7 +36,9 @@ #include "sixlowpan/ndp.h" #include "lowpan.h" -#include "border.h" +#ifdef MODULE_SIXLOWBORDER +#include "border/border.h" +#endif #include "ip.h" #include "icmp.h" From 78b5f2ae5d9af4aa43928d782ea8e4f458b95219 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 13:37:23 +0100 Subject: [PATCH 10/19] Decouple ICMPv6 from 6LoWPAN --- sys/net/include/sixlowpan/ip.h | 15 +++++++ .../sixlowpan/border/bordermultiplex.c | 2 +- sys/net/network_layer/sixlowpan/icmp.c | 45 ++++++++----------- sys/net/network_layer/sixlowpan/ip.c | 2 +- sys/net/routing/rpl/rpl.c | 10 ++--- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 9b84c401bb08..63c0cda1ebd5 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -94,6 +94,21 @@ ipv6_hdr_t *ipv6_get_buf(void); int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, const uint8_t *payload, uint16_t payload_length); +/** + * @brief Send an IPv6 packet defined by its header. + * + * @param[in] packet Pointer to an prepared IPv6 packet header. + * The payload is expected directly after the + * packet. + * + * @return length of payload : on success + * -1 : if no route to the given dest could be obtained + * Packet is dropped + * In case of reactive routing: routing is going + * to try to find a route + */ +int ipv6_send_packet(ipv6_hdr_t *packet); + /** * @brief Determines if node is a router. * diff --git a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c index 34e76c1b5774..3cd0ed2b3890 100644 --- a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c +++ b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c @@ -48,7 +48,7 @@ void demultiplex(border_packet_t *packet) switch (l3_header_buf->ethertype) { case (BORDER_ETHERTYPE_IPV6): { ipv6_hdr_t *ipv6_buf = (ipv6_hdr_t *)(((unsigned char *)packet) + sizeof(border_l3_header_t)); - ipv6_send_bytes(ipv6_buf); + ipv6_send_packet(ipv6_buf); break; } diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index ffb2ed425ae2..0e3fd4316b9d 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -35,6 +35,9 @@ #include "net_help.h" #define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif #include "debug.h" #define LLHDR_ICMPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN) @@ -269,12 +272,12 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send echo request to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], (uint8_t *)ipv6_buf, packet_length); + ipv6_send_packet(ipv6_buf); } void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) @@ -308,14 +311,12 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send echo request to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } /* send router solicitation message - RFC4861 section 4.1 */ @@ -357,14 +358,12 @@ void icmpv6_send_router_sol(uint8_t sllao) icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router solicitation to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } void recv_echo_req(void) @@ -374,7 +373,7 @@ void recv_echo_req(void) char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REQ_LEN); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo request from: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); @@ -396,13 +395,13 @@ void recv_echo_req(void) void recv_echo_repl(void) { +#ifdef DEBUG_ENABLED ipv6_buf = ipv6_get_buf(); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + - ipv6_ext_hdr_len + ECHO_REPL_LEN); -#ifdef ENABLE_DEBUG + size_t data_len = ipv6_buf->length - ICMPV6_HDR_LEN - ECHO_REPL_LEN; char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: received echo reply from: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); printf("\n"); @@ -416,6 +415,8 @@ void recv_echo_repl(void) } } +#else + return; #endif } @@ -462,15 +463,11 @@ void recv_rtr_sol(void) icmpv6_send_router_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router advertisment to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - IPV6_HDR_LEN + NTOHS(ipv6_buf->length)); - } uint8_t set_opt_6co_flags(uint8_t compression_flag, uint8_t cid) @@ -848,14 +845,11 @@ void recv_rtr_adv(void) * * if new address was configured, set src to newaddr(gp16) */ icmpv6_send_neighbor_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send neighbor solicitation to: %s\n", ipv6_addr_to_str(addr_str, &(ipv6_buf->destaddr))); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); } } @@ -1109,14 +1103,11 @@ void recv_nbr_sol(void) uint8_t flags = (ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE | ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED); icmpv6_send_neighbor_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), &(alist_targ->addr), flags, 0, OPT_ARO); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send neighbor advertisment to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); } } diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index e6071d341e1b..38fc83130671 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -59,7 +59,7 @@ ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; -void ipv6_send_bytes(ipv6_hdr_t *bytes) +int ipv6_send_packet(ipv6_hdr_t *bytes) { uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index ae7bc1313136..013c7258a5a0 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -929,7 +929,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_send_buf->flowlabel = 0; ipv6_send_buf->nextheader = next_header; ipv6_send_buf->hoplimit = MULTIHOP_HOPLIMIT; - ipv6_send_buf->length = p_len; + ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); @@ -949,9 +949,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ packet_length = IPV6_HDR_LEN + p_len; if (ipv6_addr_is_multicast(&ipv6_send_buf->destaddr)) { - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_send_buf->destaddr.uint16[4]), - (uint8_t *)ipv6_send_buf, - packet_length); + ipv6_send_packet(ipv6_send_buf); } else { /* find appropriate next hop before sending */ @@ -972,9 +970,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ } } - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(next_hop->uint16[4]), - (uint8_t *)ipv6_send_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } } From 470d8745e95783b90d854958555cbf797e4718c0 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Mon, 17 Feb 2014 19:37:31 +0100 Subject: [PATCH 11/19] Add capability to set and get variable default hop limit --- sys/net/include/sixlowpan/ip.h | 14 ++++++++++++++ sys/net/network_layer/sixlowpan/icmp.c | 4 ++-- sys/net/network_layer/sixlowpan/ip.c | 14 +++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 63c0cda1ebd5..d365a65c3312 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -116,6 +116,20 @@ int ipv6_send_packet(ipv6_hdr_t *packet); */ uint8_t ipv6_is_router(void); +/** + * @brief Sets the default hop limit to use with IPv6 packets. + * + * @param[in] hop_limit The hop limit to set the default hop limit to. + */ +void ipv6_set_default_hop_limit(uint8_t hop_limit); + +/** + * @brief Gets the default hop limit that is used for IPv6 packets. + * + * @return The current default hop limit for IPv6 packets. + */ +uint8_t ipv6_get_default_hop_limit(void); + /** * @brief Registers a handler thread for incoming IP packets. * diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 0e3fd4316b9d..af3881bf9f98 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -256,7 +256,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = IPV6_PROTO_NUM_ICMPV6; - ipv6_buf->hoplimit = 0xff; + ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); @@ -295,7 +295,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = IPV6_PROTO_NUM_ICMPV6; - ipv6_buf->hoplimit = 0xff; + ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 38fc83130671..73a7566d1860 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -56,6 +56,8 @@ int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; +static uint8_t default_hop_limit = MULTIHOP_HOPLIMIT; + /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; @@ -118,7 +120,7 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = next_header; - ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT; + ipv6_buf->hoplimit = default_hop_limit; ipv6_buf->length = payload_length; memcpy(&(ipv6_buf->destaddr), dest, 16); @@ -146,6 +148,16 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, return payload_length; } +void ipv6_set_default_hop_limit(uint8_t hop_limit) +{ + default_hop_limit = hop_limit; +} + +uint8_t ipv6_get_default_hop_limit(void) +{ + return default_hop_limit; +} + /* Register an upper layer thread */ uint8_t ipv6_register_packet_handler(int pid) { From 108989b65d047eeff71ed5575512e8042f6fb633 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 15:18:16 +0100 Subject: [PATCH 12/19] Use net_if in 6LoWPAN MAC layer --- sys/net/include/sixlowpan/mac.h | 81 ++---- sys/net/network_layer/sixlowpan/icmp.c | 24 +- sys/net/network_layer/sixlowpan/ip.c | 1 + sys/net/network_layer/sixlowpan/lowpan.c | 32 ++- sys/net/network_layer/sixlowpan/mac.c | 352 +++++++++++++---------- sys/net/routing/rpl/etx_beaconing.c | 15 +- 6 files changed, 263 insertions(+), 242 deletions(-) diff --git a/sys/net/include/sixlowpan/mac.h b/sys/net/include/sixlowpan/mac.h index a09960d788f0..84dbaef90e17 100644 --- a/sys/net/include/sixlowpan/mac.h +++ b/sys/net/include/sixlowpan/mac.h @@ -34,78 +34,29 @@ #define IEEE_802154_MAX_ADDR_STR_LEN (12) /** - * @brief Gets current radio transmitter address. + * @brief Send an IEEE 802.15.4 frame to a long address. * - * @return Current radio address as 8-bit value. - */ -uint8_t sixlowpan_mac_get_radio_address(void); - -/** - * @brief Sets radio transmitter address. - * - * @param[in] addr 8-bit radio address. - */ -void sixlowpan_mac_set_radio_address(uint8_t addr); - -/** - * @brief Generates EUI-64 from IEEE 802.15.4 PAN ID and - * radio transceiver address. + * @param[in] if_id The interface to send over (will be ignored if + * *mcast* is 1). + * @param[in] dest The destination address of the frame (will be + * ignored if *mcast* is 1). + * @param[in] dest_len The lengts of the destination address in byte. + * @param[in] payload The payload of the frame. + * @param[in] length The length of the payload. + * @param[in] mcast send frame as multicast frame (*addr* and *if_id* + * will be ignored). * - * @param[out] laddr The EUI-64 address of this node. + * @return Length of transmitted data in byte */ -void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr); +int sixlowpan_mac_send_ieee802154_frame(int if_id, const void *dest, + uint8_t dest_len, const void *payload, uint8_t length, uint8_t mcast); /** - * @brief Generates IEEE 802.15.4 16-bit short address from radio - * transceiver address. - * - * @param[out] saddr The IEEE 802.15.4 16-bit short address of this - * node. - */ -void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr); - -/** - * @brief Get pointer to potential EUI-64 bit of the IPv6 address. - * - * @param[in] ipaddr An IPv6 address of this node. - * - * @return The EUI-64 address of this node. - */ -ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr); - -/** - * @brief Send an IEEE 802.15.4 frame. - * - * @param[in] addr The destination address of the frame. - * @param[in] payload The payload of the frame. - * @param[in] length The length of the payload. - * @param[in] mcast send frame as multicast frame (identical to - * give a destination address of 0). - */ -void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, - const uint8_t *payload, - uint8_t length, uint8_t mcast); - -/** - * @brief Initialise 6LoWPAN MAC interface - * - * @param[in] type Type of transceiver. - */ -void sixlowpan_mac_init(transceiver_type_t type); - -/** - * @brief Converts IEEE 802.15.4 long address into string. - * Note that addr_str must allocate at least - * IEEE_802154_MAX_ADDR_STR_LEN byte (12 byte). - * - * @param[out] addr_str The IEEE 802.15.4 long address as string. Must - * allocate at least IEEE_802154_ADDR_STR_LEN byte (12 - * byte). - * @param[in] laddr IEEE 802.15.4 address to be converted. + * @brief Initialise 6LoWPAN MAC layer and register it to interface layer * - * @return Pointer to addr_str. + * @return PID of the MAC receiver thread. */ -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr); +int sixlowpan_mac_init(void); /** @} */ #endif /* SIXLOWPAN_MAC_H */ diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index af3881bf9f98..5d93f56bbd21 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -22,15 +22,13 @@ #include #include -#include "malloc.h" #include "vtimer.h" #include "mutex.h" +#include "net_if.h" #include "sixlowpan/error.h" -#include "sixlowpan/mac.h" #include "ip.h" #include "icmp.h" -#include "lowpan.h" #include "serialnumber.h" #include "net_help.h" @@ -857,6 +855,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * uint8_t sllao, uint8_t aro) { uint16_t packet_length; + int if_id = 0; // TODO: get this somehow ipv6_buf = ipv6_get_buf(); ipv6_buf->version_trafficclass = IPV6_VER; @@ -910,7 +909,14 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * opt_aro_buf->status = 0; opt_aro_buf->reserved1 = 0; opt_aro_buf->reserved2 = 0; - memcpy(&(opt_aro_buf->eui64), sixlowpan_mac_get_eui64(src), 8); + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 1); + } + else if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 0); + } + icmpv6_opt_hdr_len += OPT_ARO_HDR_LEN; packet_length += OPT_ARO_HDR_LEN; @@ -1114,6 +1120,7 @@ void recv_nbr_sol(void) void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt, uint8_t rso, uint8_t sllao, uint8_t aro) { + int if_id = 0; // TODO: get this somehow uint16_t packet_length; ipv6_buf = ipv6_get_buf(); @@ -1156,7 +1163,14 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t opt_aro_buf->status = 0; /* TODO */ opt_aro_buf->reserved1 = 0; opt_aro_buf->reserved2 = 0; - memcpy(&(opt_aro_buf->eui64), sixlowpan_mac_get_eui64(dst), 8); + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 1); + } + else if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 0); + } + icmpv6_opt_hdr_len += OPT_ARO_HDR_LEN; packet_length += OPT_ARO_HDR_LEN; diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 73a7566d1860..7616e697870c 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -25,6 +25,7 @@ #include "vtimer.h" #include "mutex.h" #include "msg.h" +#include "net_if.h" #include "sixlowpan/mac.h" #include "ip.h" diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index e0b6b95b59a3..00a20fff9408 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -159,6 +159,7 @@ void lowpan_ipv6_set_dispatch(uint8_t *data); void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, uint8_t *data, uint16_t data_len) { + int if_id = 0; uint8_t mcast = 0; ipv6_buf = (ipv6_hdr_t *) data; @@ -200,10 +201,11 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[2] = tag >> 8; fragbuf[3] = tag; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, + sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, max_frag_initial + header_size + 4, mcast); + /* subsequent fragments */ position = max_frag_initial; max_frag = ((max_frame - 5) / 8) * 8; @@ -220,9 +222,9 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[3] = tag; fragbuf[4] = position / 8; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, - max_frag + 5, mcast); + sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, + max_frame + 5, mcast); data += max_frag; position += max_frag; @@ -240,13 +242,15 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[3] = tag; fragbuf[4] = position / 8; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, - remaining + 5, mcast); + if (sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, remaining + 5, mcast) < 0) { + return -1; + } } else { - sixlowpan_mac_send_ieee802154_frame(&laddr, data, - send_packet_length, mcast); + return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + data, send_packet_length, + mcast); } tag++; @@ -1649,17 +1653,13 @@ void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, void lowpan_init(transceiver_type_t trans, uint8_t r_addr, const ipv6_addr_t *prefix, int as_border) { + int if_id = 0; ipv6_addr_t tmp; short i; - /* init mac-layer and radio transceiver */ - sixlowpan_mac_init(trans); /* init interface addresses */ memset(&iface, 0, sizeof(iface_t)); - sixlowpan_mac_set_radio_address(r_addr); - sixlowpan_mac_init_802154_short_addr(&(iface.saddr)); - sixlowpan_mac_init_802154_long_addr(&(iface.laddr)); /* init lowpan context mutex */ mutex_init(&lowpan_context_mutex); @@ -1705,6 +1705,8 @@ void lowpan_init(transceiver_type_t trans, uint8_t r_addr, ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, NDP_ADDR_STATE_PREFERRED, 0, 0); + /* init mac-layer and radio transceiver */ + sixlowpan_mac_init(); if (as_border) { ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index 34c71cba6b58..ab27207b31a4 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -24,13 +24,10 @@ #include #include -#include "ltc4150.h" -#include "hwtimer.h" #include "thread.h" #include "msg.h" #include "radio/radio.h" -#include "transceiver.h" -#include "vtimer.h" +#include "net_if.h" #include "sixlowpan/mac.h" #include "ip.h" @@ -49,110 +46,37 @@ #define RADIO_RCV_BUF_SIZE (64) #define RADIO_SENDING_DELAY (1000) +#define DEFAULT_IEEE_802154_PAN_ID (0x1234) +#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) + char radio_stack_buffer[RADIO_STACK_SIZE]; msg_t msg_q[RADIO_RCV_BUF_SIZE]; -static uint8_t r_src_addr; -uint8_t buf[PAYLOAD_SIZE]; +uint8_t lowpan_mac_buf[PAYLOAD_SIZE]; static uint8_t macdsn; -static radio_packet_t p; -static msg_t mesg; -int transceiver_type; -static transceiver_command_t tcmd; - -uint8_t sixlowpan_mac_get_radio_address(void) -{ - int16_t address; - DEBUG("sixlowpan_mac_get_radio_address()\n"); - - tcmd.transceivers = transceiver_type; - tcmd.data = &address; - mesg.content.ptr = (char *)&tcmd; - mesg.type = GET_ADDRESS; - msg_send_receive(&mesg, &mesg, transceiver_pid); - - return (uint8_t)address; -} - -void sixlowpan_mac_set_radio_address(uint8_t addr) -{ - int16_t address = (int16_t)addr; - - tcmd.transceivers = transceiver_type; - tcmd.data = &address; - mesg.content.ptr = (char *)&tcmd; - mesg.type = SET_ADDRESS; - msg_send_receive(&mesg, &mesg, transceiver_pid); -} - -void set_radio_channel(uint8_t channel) -{ - int16_t chan = (int16_t)channel; - - tcmd.transceivers = transceiver_type; - tcmd.data = &chan; - mesg.content.ptr = (char *)&tcmd; - mesg.type = SET_CHANNEL; - msg_send_receive(&mesg, &mesg, transceiver_pid); -} - -void switch_to_rx(void) -{ - mesg.type = SWITCH_RX; - mesg.content.ptr = (char *) &tcmd; - tcmd.transceivers = TRANSCEIVER_CC1100; - msg_send(&mesg, transceiver_pid, 1); -} - -void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr) -{ - DEBUG("sixlowpan_mac_init_802154_short_addr(saddr=%02X)\n", *saddr); - saddr->uint8[0] = 0; - saddr->uint8[1] = sixlowpan_mac_get_radio_address(); -} - -ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr) +static inline void mac_short_to_eui64(net_if_eui64_t *eui64, + uint16_t short_addr) { - return ((ieee_802154_long_t *) &ipaddr->uint8[8]); -} - -void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr) -{ -#ifdef DEBUG_ENABLED - char addr_str[IEEE_802154_MAX_ADDR_STR_LEN]; - sixlowpan_mac_802154_long_addr_to_str(addr_str, laddr); - DEBUG("sixlowpan_mac_init_802154_long_addr(laddr=%s)\n", addr_str); -#endif - - // 16bit Pan-ID:16-zero-bits:16-bit-short-addr = 48bit - laddr->uint16[0] = IEEE_802154_PAN_ID; - - /* RFC 4944 Section 6 / RFC 2464 Section 4 */ - laddr->uint8[0] ^= 0x02; - laddr->uint8[2] = 0; - laddr->uint8[3] = 0xFF; - laddr->uint8[4] = 0xFE; - laddr->uint8[5] = 0; - laddr->uint8[6] = 0; - laddr->uint8[7] = sixlowpan_mac_get_radio_address(); -} - -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) -{ - sprintf(addr_str, - "%02x:%02x:%02x:%02x", - laddr->uint16[0], laddr->uint16[1], - laddr->uint16[2], laddr->uint16[3]); - return addr_str; + eui64->uint32[0] = HTONL(0x000000ff); + eui64->uint16[2] = HTONS(0xfe00); + eui64->uint16[3] = LETONS(short_addr); } void recv_ieee802154_frame(void) { msg_t m; +#if (defined(MODULE_AT86RF231) | \ + defined(MODULE_CC2420) | \ + defined(MODULE_MC1322X)) + ieee802154_packet_t *p; +#else radio_packet_t *p; - uint8_t hdrlen, length; + uint8_t hdrlen; +#endif + uint8_t length; ieee802154_frame_t frame; + net_if_eui64_t src, dst; msg_init_queue(msg_q, RADIO_RCV_BUF_SIZE); @@ -160,22 +84,84 @@ void recv_ieee802154_frame(void) msg_receive(&m); if (m.type == PKT_PENDING) { - +#if (defined(MODULE_AT86RF231) | \ + defined(MODULE_CC2420) | \ + defined(MODULE_MC1322X)) + p = (ieee802154_packet_t *) m.content.ptr; + memcpy(&frame, &p->frame, sizeof(ieee802154_frame_t)); + length = p->frame.payload_len; +#else p = (radio_packet_t *) m.content.ptr; hdrlen = ieee802154_frame_read(p->data, &frame, p->length); length = p->length - hdrlen - IEEE_802154_FCS_LEN; +#endif + +#ifdef DEBUG_ENABLED + DEBUG("INFO: Received IEEE 802.15.4. packet (length = %d):\n", length); + DEBUG("INFO: FCF:\n"); + ieee802154_frame_print_fcf_frame(&frame); + + DEBUG("Sender:"); + + for (uint8_t i = 0; i < 8; i++) { + printf("%02x ", frame.src_addr[i]); + } + + DEBUG("\n"); + + DEBUG("Receiver:"); + + for (size_t i = 0; i < 8; i++) { + printf("%02x ", frame.dest_addr[i]); + } + + DEBUG("\n"); + + DEBUG("Payload:\n"); + + for (uint8_t i = 0; i < frame.payload_len; i++) { + printf("%02x ", frame.payload[i]); + + if (!((i + 1) % 16) || i == frame.payload_len - 1) { + printf("\n"); + } + } + +#endif + + if (frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + mac_short_to_eui64(&src, *((uint16_t *)frame.src_addr)); + } + else if (frame.fcf.src_addr_m == IEEE_802154_LONG_ADDR_M) { + memcpy(&src, frame.src_addr, 8); + } + else { + DEBUG("Unknown IEEE 802.15.4 source address mode.\n"); + continue; + } + + if (frame.fcf.dest_addr_m == IEEE_802154_SHORT_ADDR_M) { + mac_short_to_eui64(&dst, *((uint16_t *)frame.dest_addr)); + } + else if (frame.fcf.dest_addr_m == IEEE_802154_LONG_ADDR_M) { + memcpy(&dst, frame.dest_addr, 8); + } + else { + DEBUG("Unknown IEEE 802.15.4 destination address mode.\n"); + continue; + } /* deliver packet to network(6lowpan)-layer */ - lowpan_read(frame.payload, length, (ieee_802154_long_t *)&frame.src_addr, - (ieee_802154_long_t *)&frame.dest_addr); + lowpan_read(frame.payload, length, &src, &dst); + /* TODO: get interface ID somehow */ p->processing--; } else if (m.type == ENOBUFFER) { - puts("Transceiver buffer full"); + DEBUG("Transceiver buffer full"); } else { - puts("Unknown packet received"); + DEBUG("Unknown packet received"); } } } @@ -187,86 +173,158 @@ void set_ieee802154_fcf_values(ieee802154_frame_t *frame, uint8_t dest_mode, frame->fcf.sec_enb = 0; frame->fcf.frame_pend = 0; frame->fcf.ack_req = 0; - frame->fcf.panid_comp = 0; + frame->fcf.panid_comp = (frame->dest_pan_id == frame->src_pan_id); frame->fcf.frame_ver = 0; frame->fcf.src_addr_m = src_mode; frame->fcf.dest_addr_m = dest_mode; -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED ieee802154_frame_print_fcf_frame(frame); #endif } -void set_ieee802154_frame_values(ieee802154_frame_t *frame) +void set_ieee802154_frame_values(int if_id, uint16_t dest_pan, + ieee802154_frame_t *frame) { + int32_t pan_id = net_if_get_pan_id(if_id); // TODO: addresse aus ip paket auslesen und in frame einfuegen - frame->dest_pan_id = IEEE_802154_PAN_ID; - frame->src_pan_id = IEEE_802154_PAN_ID; + + if (pan_id < 0) { + frame->dest_pan_id = NTOLES(dest_pan); + frame->src_pan_id = HTOLES(DEFAULT_IEEE_802154_PAN_ID); + } + else { + frame->dest_pan_id = NTOLES(dest_pan); + frame->src_pan_id = HTOLES((uint16_t)pan_id); + } + frame->seq_nr = macdsn; macdsn++; } -void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, - const uint8_t *payload, - uint8_t length, uint8_t mcast) +int sixlowpan_mac_prepare_ieee802144_frame( + ieee802154_frame_t *frame, int if_id, uint16_t dest_pan, const void *dest, + uint8_t dest_len, const void *payload, uint8_t length, uint8_t mcast) { - uint16_t daddr; - /* TODO: check if dedicated response struct is necessary */ - msg_t transceiver_rsp; - r_src_addr = local_address; - mesg.type = SND_PKT; - mesg.content.ptr = (char *) &tcmd; + uint8_t src_mode = net_if_get_src_address_mode(if_id); + uint8_t dest_mode; + uint16_t *fcs; + set_ieee802154_frame_values(if_id, dest_pan, frame); - tcmd.transceivers = transceiver_type; - tcmd.data = &p; + if (dest_len == 8) { + dest_mode = IEEE_802154_LONG_ADDR_M; + } + else if (dest_len == 2) { + dest_mode = IEEE_802154_SHORT_ADDR_M; + } + else { + DEBUG("Illegal IEEE 802.15.4 address for address length %d\n", dest_len); + return -1; + } - ieee802154_frame_t frame; + set_ieee802154_fcf_values(frame, dest_mode, src_mode); - memset(&frame, 0, sizeof(frame)); - set_ieee802154_fcf_values(&frame, IEEE_802154_LONG_ADDR_M, - IEEE_802154_LONG_ADDR_M); - set_ieee802154_frame_values(&frame); - memcpy(&(frame.dest_addr[0]), &(addr->uint8[0]), 8); - memcpy(&(frame.src_addr[0]), &(iface.laddr.uint8[0]), 8); + if (src_mode == IEEE_802154_LONG_ADDR_M) { + net_if_get_eui64((net_if_eui64_t *)&frame->src_addr[0], if_id, 0); + } + else if (src_mode == IEEE_802154_SHORT_ADDR_M) { + uint16_t src = HTONS(net_if_get_hardware_address(if_id)); + memcpy(&frame->src_addr[0], &src, 2); + } + else { + DEBUG("Illegal IEEE 802.15.4 address mode: %d\n", src_mode); + return -1; + } + + if (mcast) { + memset(&frame->dest_addr[0], 0xff, dest_len); + } + else { + memcpy(&frame->dest_addr[0], dest, dest_len); + } - daddr = HTONS(addr->uint16[3]); - frame.payload = (uint8_t *)payload; // payload won't be changed so cast is legal. - frame.payload_len = length; - uint8_t hdrlen = ieee802154_frame_get_hdr_len(&frame); + frame->payload = (uint8_t *)payload; // payload won't be changed so cast is legal. + frame->payload_len = length; + uint8_t hdrlen = ieee802154_frame_get_hdr_len(frame); - memset(&buf, 0, PAYLOAD_SIZE); - ieee802154_frame_init(&frame, (uint8_t *)&buf); - memcpy(&buf[hdrlen], frame.payload, frame.payload_len); + memset(&lowpan_mac_buf, 0, PAYLOAD_SIZE); + ieee802154_frame_init(frame, (uint8_t *)&lowpan_mac_buf); + memcpy(&lowpan_mac_buf[hdrlen], frame->payload, frame->payload_len); /* set FCS */ - /* RSSI = 0 */ - buf[frame.payload_len + hdrlen] = 0; - /* FCS Valid = 1 / LQI Correlation Value = 0 */ - buf[frame.payload_len + hdrlen + 1] = 0x80; - DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame.dest_pan_id, frame.src_pan_id, frame.seq_nr); + fcs = (uint16_t *)&lowpan_mac_buf[frame->payload_len + hdrlen]; + *fcs = ieee802154_frame_get_fcs(lowpan_mac_buf, frame->payload_len + hdrlen); + DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", + lowpan_mac_buf[0], lowpan_mac_buf[1], frame->dest_pan_id, + frame->src_pan_id, frame->seq_nr); - p.length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; + return hdrlen; +} - if (mcast == 0) { - p.dst = daddr; +int sixlowpan_mac_send_data(int if_id, + const void *dest, uint8_t dest_len, + const void *payload, + uint8_t payload_len, uint8_t mcast) +{ + if (mcast) { + return net_if_send_packet_broadcast(IEEE_802154_SHORT_ADDR_M, + payload, + payload_len); } else { - p.dst = 0; + if (dest_len == 8) { + return net_if_send_packet_long(if_id, (net_if_eui64_t *) dest, + payload, (size_t)payload_len); + } + else if (dest_len == 2) { + return net_if_send_packet(if_id, NTOHS(*((uint16_t *)dest)), + payload, (size_t)payload_len); + } + } + + return -1; +} + +int sixlowpan_mac_send_ieee802154_frame(int if_id, + const void *dest, uint8_t dest_len, + const void *payload, + uint8_t payload_len, uint8_t mcast) +{ + if (net_if_get_interface(if_id) && + net_if_get_interface(if_id)->transceivers & IEEE802154_TRANSCEIVER) { + return sixlowpan_mac_send_data(if_id, dest, dest_len, payload, + payload_len, mcast); } + else { + ieee802154_frame_t frame; + uint16_t dest_pan = HTONS(0xabcd); + uint8_t length; + int hdrlen = sixlowpan_mac_prepare_ieee802144_frame(&frame, if_id, + dest_pan, dest, + dest_len, payload, + payload_len, mcast); + + if (hdrlen < 0) { + return -1; + } - p.data = buf; - msg_send_receive(&mesg, &transceiver_rsp, transceiver_pid); + length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; - hwtimer_wait(5000); + return sixlowpan_mac_send_data(if_id, dest, dest_len, lowpan_mac_buf, + length, mcast); + } } -void sixlowpan_mac_init(transceiver_type_t type) +int sixlowpan_mac_init(void) { int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE, PRIORITY_MAIN - 2, CREATE_STACKTEST, recv_ieee802154_frame , "radio"); - transceiver_type = type; - transceiver_init(transceiver_type); - transceiver_start(); - transceiver_register(type, recv_pid); + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + net_if_register(if_id, recv_pid); + } macdsn = rand() % 256; + + return recv_pid; } diff --git a/sys/net/routing/rpl/etx_beaconing.c b/sys/net/routing/rpl/etx_beaconing.c index cc16ddfb5d8d..e60f86a1daf1 100644 --- a/sys/net/routing/rpl/etx_beaconing.c +++ b/sys/net/routing/rpl/etx_beaconing.c @@ -169,14 +169,6 @@ void etx_beacon(void) etx_probe_t *packet = etx_get_send_buf(); uint8_t p_length = 0; - /* - * xxx If you get a -Wmissing-braces warning here: - * A -Wmissing-braces warning at this point is a gcc-bug! - * Please delete this information once it's fixed - * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 - */ - ieee_802154_long_t empty_addr = { {0} }; - while (true) { thread_sleep(); mutex_lock(&etx_mutex); @@ -194,7 +186,10 @@ void etx_beacon(void) } packet->length = p_length; - sixlowpan_mac_send_ieee802154_frame(&empty_addr, &etx_send_buf[0], + /* will be send broadcast, so if_id and destination address will be + * ignored (see documentation) + */ + sixlowpan_mac_send_ieee802154_frame(0, NULL, 8, &etx_send_buf[0], ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); etx_set_packets_received(); @@ -394,7 +389,7 @@ void etx_radio(void) ipv6_addr_t candidate_addr; ipv6_addr_set_link_local_prefix(&ll_address); - ipv6_iface_get_best_src_addr(&candidate_addr, &ll_address); + ipv6_net_if_get_best_src_addr(&candidate_addr, &ll_address); while (1) { msg_receive(&m); From c9e8adc41450a2c74debbf32228e2f4a1c1f579a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 15:54:42 +0100 Subject: [PATCH 13/19] Use net_if in 6LoWPAN layer --- sys/net/include/sixlowpan/lowpan.h | 75 +- .../network_layer/sixlowpan/border/border.c | 61 +- sys/net/network_layer/sixlowpan/ip.c | 12 +- sys/net/network_layer/sixlowpan/lowpan.c | 660 ++++++++++-------- sys/net/network_layer/sixlowpan/lowpan.h | 2 + sys/net/network_layer/sixlowpan/mac.c | 1 - 6 files changed, 473 insertions(+), 338 deletions(-) diff --git a/sys/net/include/sixlowpan/lowpan.h b/sys/net/include/sixlowpan/lowpan.h index bc0a1bdac124..67da952f7741 100644 --- a/sys/net/include/sixlowpan/lowpan.h +++ b/sys/net/include/sixlowpan/lowpan.h @@ -25,6 +25,8 @@ #include #include "transceiver.h" +#include "net_help.h" +#include "net_if.h" #include "sixlowpan/types.h" /** @@ -178,26 +180,44 @@ typedef struct __attribute__((packed)) { /** - * @brief Initializes 6LoWPAN. + * @brief Initializes all addresses on an interface needed for 6LoWPAN. * - * @param[in] trans Transceiver to use with 6LoWPAN. - * @param[in] r_addr PHY layer address. - * @param[in] as_border 1 if node should act as border router, - * 0 otherwise. + * @param[in] if_id The interface to use with 6LoWPAN. + * + * @return 1 on success, 0 on failure. */ -void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr, - int as_border); +int sixlowpan_lowpan_init_interface(int if_id); + +/** + * @brief Checks if an EUI-64 was set from a short address. If so + * it returns this address, else 0 + * + * @param[in] iid An EUI-64. + * + * @return The short address on success, 0 on failure. + */ +static inline uint16_t sixlowpan_lowpan_eui64_to_short_addr(const net_if_eui64_t *iid) +{ + if (iid->uint32[0] == HTONL(0x000000ff) && + iid->uint16[2] == HTONS(0xfe00)) { + return NTOHS(iid->uint16[3]); + } + + return 0; +} /** - * @brief Initializes a 6LoWPAN router with address prefix + * @brief Initializes all addresses and prefixes on an interface needed + * for 6LoWPAN. Calling this function together with + * sixlowpan_lowpan_init_interface() is not necessary. * - * @param[in] trans transceiver to use with 6LoWPAN. + * @param[in] if_id The interface to use with 6LoWPAN. * @param[in] prefix the address prefix to advertise. - * @param[in] r_addr PHY layer address. + * + * @return 1 on success, 0 on failure. */ -void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, - const ipv6_addr_t *prefix, - uint8_t r_addr); +int sixlowpan_lowpan_init_adhoc_interface(int if_id, + const ipv6_addr_t *prefix); /** * @brief Initializes a 6LoWPAN border router with an address @@ -205,26 +225,26 @@ void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, * @note Currently only working with addresses generated from * IEEE 802.15.4 16-bit short addresses. * - * @param[in] trans transceiver to use with 6LoWPAN. - * @param[in] border_router_addr Address of this border router. + * @param[in] if_id The interface to use with 6LoWPAN. * - * @return SIXLOWERROR_SUCCESS on success, otherwise SIXLOWERROR_ADDRESS if - * address was not generated from IEEE 802.15.4 16-bit short - * address. + * @return 1 on success, 0 on failure. */ -uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans, - const ipv6_addr_t *border_router_addr); +int sixlowpan_lowpan_border_init(int if_id); /** - * @brief Send data via 6LoWPAN to destination node dest. + * @brief Send data via 6LoWPAN to destination node or next hop dest. * - * @param[in] dest EUI-64 of destination node. + * @param[in] if_id The interface to send the data over. + * @param[in] dest Hardware address of the next hop or destination node. + * @param[in] dest_len Length of the destination address in byte. * @param[in] data Data to send to destination node (may be * manipulated). * @param[in] data_len Length of data. + * + * @return length of transmitted data on success, -1 on failure. */ -void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, - uint8_t *data, uint16_t data_len); +int sixlowpan_lowpan_sendto(int if_id, const void *dest, int dest_len, + uint8_t *data, uint16_t data_len); /** * @brief Set header compression status for 6LoWPAN. @@ -272,5 +292,12 @@ void sixlowpan_lowpan_print_fifo_buffers(void); void sixlowpan_lowpan_print_reassembly_buffers(void); #endif +/** + * @brief Initializes 6LoWPAN module. + * + * @return 1 on success, 0 on failure. + */ +int sixlowpan_lowpan_init(void); + /** @} */ #endif /* SIXLOWPAN_LOWPAN_H */ diff --git a/sys/net/network_layer/sixlowpan/border/border.c b/sys/net/network_layer/sixlowpan/border/border.c index fd84d585b572..f478a7505fc6 100644 --- a/sys/net/network_layer/sixlowpan/border/border.c +++ b/sys/net/network_layer/sixlowpan/border/border.c @@ -16,6 +16,7 @@ * @} */ +/* TODO: Put this in its own module */ #include #include #include @@ -37,9 +38,10 @@ #include "net_help.h" -#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define ENABLE_DEBUG (0) +#include "debug.h" -ipv6_addr_t abr_addr; +#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) char serial_reader_stack[READER_STACK_SIZE]; uint16_t serial_reader_pid; @@ -47,6 +49,8 @@ uint16_t serial_reader_pid; uint8_t serial_out_buf[BORDER_BUFFER_SIZE]; uint8_t serial_in_buf[BORDER_BUFFER_SIZE]; +ipv6_addr_t *abr_addr; + uint8_t *get_serial_out_buffer(int offset) { if (offset > BUFFER_SIZE) { @@ -120,45 +124,52 @@ void serial_reader_f(void) } } -uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans, - const ipv6_addr_t *border_router_addr) +int sixlowpan_lowpan_border_init(int if_id) { - ipv6_addr_t addr; + ipv6_net_if_addr_t *addr = NULL; + uint8_t abr_addr_initialized = 0; serial_reader_pid = thread_create( serial_reader_stack, READER_STACK_SIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, serial_reader_f, "serial_reader"); + ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + border_process_lowpan, + "border_process_lowpan"); - if (border_router_addr == NULL) { - border_router_addr = &addr; - - addr = flowcontrol_init(); + if (ip_process_pid < 0) { + return 0; } - /* only allow addresses generated accoding to - * RFC 4944 (Section 6) & RFC 2464 (Section 4) from short address - * -- for now - */ - if (border_router_addr->uint16[4] != HTONS(IEEE_802154_PAN_ID ^ 0x0200) || - border_router_addr->uint16[5] != HTONS(0x00FF) || - border_router_addr->uint16[6] != HTONS(0xFE00) - ) { - return SIXLOWERROR_ADDRESS; + if (!sixlowpan_lowpan_init()) { + return 0; } - /* radio-address is 8-bit so this must be tested extra */ - if (border_router_addr->uint8[14] != 0) { - return SIXLOWERROR_ADDRESS; + if (!sixlowpan_lowpan_init_interface(if_id)) { + return 0; } - memcpy(&(abr_addr.uint8[0]), &(border_router_addr->uint8[0]), 16); + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr)) { + if (!ipv6_addr_is_multicast(addr->addr_data) && + !ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_loopback(addr->addr_data) && + !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { + abr_addr_initialized = 1; + abr_addr = addr->addr_data; + break; + } + } - sixlowpan_lowpan_init(trans, border_router_addr->uint8[15], 1); + if (!abr_addr_initialized) { + DEBUG("sixlowpan_lowpan_border_init(): A prefix must be initialized to" + "interface %d first", if_id); + return 0; + } - ipv6_init_iface_as_router(); + ipv6_init_as_router(); - return SIXLOWERROR_SUCCESS; + return 1; } void border_process_lowpan(void) diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 7616e697870c..5b2e4538360f 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -64,6 +64,7 @@ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; int ipv6_send_packet(ipv6_hdr_t *bytes) { + int if_id = 0; uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); bytes->flowlabel = HTONS(bytes->flowlabel); @@ -72,9 +73,12 @@ int ipv6_send_packet(ipv6_hdr_t *bytes) memset(bytes, 0, BUFFER_SIZE); memcpy(bytes + LL_HDR_LEN, bytes, offset); - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &bytes->destaddr.uint16[4], - (uint8_t *)bytes, - offset); + if (sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, + (uint8_t *)packet, length) < 0) { + return -1; + } + + return length; } ipv6_hdr_t *ipv6_get_buf_send(void) @@ -143,7 +147,7 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, return -1; } - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &dest->uint16[4], + sixlowpan_lowpan_sendto(0, &dest->uint16[4], 8, (uint8_t *)ipv6_buf, packet_length); return payload_length; diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 00a20fff9408..4a5ca8e3215b 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -48,14 +48,14 @@ #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; #endif #include "debug.h" -#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN) -#define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) -#define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) -#define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) #define SIXLOWPAN_MAX_REGISTERED (4) @@ -72,33 +72,42 @@ typedef struct lowpan_interval_list_t { struct lowpan_interval_list_t *next; } lowpan_interval_list_t; +/** + * @brief 6LoWPAN reassembly buffer. + * + * @see + * RFC 4944, section 5.3 + * + */ typedef struct lowpan_reas_buf_t { - /* Source Address */ - ieee_802154_long_t s_laddr; - /* Destination Address */ - ieee_802154_long_t d_laddr; - /* Identification Number */ - uint16_t ident_no; - /* Timestamp of last packet fragment */ - timex_t timestamp; - /* Size of reassembled packet with possible IPHC header */ - uint16_t packet_size; - /* Additive size of currently already received fragments */ - uint16_t current_packet_size; - /* Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte */ - uint8_t *packet; - /* Pointer to list of intervals of received packet fragments (if any) */ - lowpan_interval_list_t *interval_list_head; - /* Pointer to next reassembly buffer (if any) */ + net_if_eui64_t s_addr; ///< Source address + net_if_eui64_t d_addr; ///< Destination address + uint16_t tag; ///< Fragment tag + timex_t timestamp; ///< Timestamp of last packet fragment + /** + * @brief Size of reassembled packet with possible IPHC header + */ + uint16_t packet_size; + /** + * @brief Additive size of currently already received fragments + */ + uint16_t current_packet_size; + /** + * @brief Pointer to allocated memory for reassembled packet + 6LoWPAN + * Dispatch Byte + */ + uint8_t *packet; + /** + * @brief Pointer to list of intervals of received packet fragments + * (if any) + */ + lowpan_interval_list_t *interval_list_head; struct lowpan_reas_buf_t *next; } lowpan_reas_buf_t; extern mutex_t lowpan_context_mutex; -uint16_t tag; -uint8_t header_size = 0; -uint8_t max_frame = 0; +uint16_t tag = 0; uint8_t max_frag_initial = 0; -uint8_t position; uint8_t max_frag; static uint16_t packet_length; @@ -112,22 +121,19 @@ uint16_t comp_len; uint8_t frag_size; uint8_t reas_buf[512]; uint8_t comp_buf[512]; -uint8_t byte_offset; uint8_t first_frag = 0; mutex_t fifo_mutex; -unsigned int ip_process_pid; -unsigned int nd_nbr_cache_rem_pid = 0; -unsigned int contexts_rem_pid = 0; -unsigned int transfer_pid = 0; +int ip_process_pid = 0; +int nd_nbr_cache_rem_pid = 0; +int contexts_rem_pid = 0; +int transfer_pid = 0; -iface_t iface; -ipv6_addr_t lladdr; -ieee_802154_long_t laddr; mutex_t lowpan_context_mutex; /* registered upper layer threads */ int sixlowpan_reg[SIXLOWPAN_MAX_REGISTERED]; +static sixlowpan_lowpan_frame_t current_frame; char ip_process_buf[IP_PROCESS_STACKSIZE]; char nc_buf[NC_STACKSIZE]; @@ -137,73 +143,107 @@ lowpan_context_t contexts[NDP_6LOWPAN_CONTEXT_MAX]; uint8_t context_len = 0; uint16_t local_address = 0; -void lowpan_init(transceiver_type_t trans, uint8_t r_addr, - const ipv6_addr_t *prefix, int as_border); +int lowpan_init(int as_border); void lowpan_context_auto_remove(void); -void lowpan_iphc_encoding(ieee_802154_long_t *dest, - ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr); -void lowpan_iphc_decoding(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr); +uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, + ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr); +void lowpan_iphc_decoding(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr); void add_fifo_packet(lowpan_reas_buf_t *current_packet); lowpan_reas_buf_t *collect_garbage_fifo(lowpan_reas_buf_t *current_buf); lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf); void init_reas_bufs(lowpan_reas_buf_t *buf); void check_timeout(void); +void print_long_local_addr(net_if_eui64_t *saddr); lowpan_context_t *lowpan_context_lookup(ipv6_addr_t *addr); -void lowpan_ipv6_set_dispatch(uint8_t *data); - /* deliver packet to mac*/ -void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, - uint8_t *data, uint16_t data_len) +int sixlowpan_lowpan_sendto(int if_id, const void *dest, int dest_len, + uint8_t *data, uint16_t data_len) { - int if_id = 0; uint8_t mcast = 0; ipv6_buf = (ipv6_hdr_t *) data; uint16_t send_packet_length = data_len; - memcpy(&laddr.uint8[0], &dest->uint8[0], 8); - if (ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { /* send broadcast */ mcast = 1; } + /* check if packet needs to be fragmented */ + DEBUG("sixlowpan_lowpan_sendto(%d, dest, %d, data, %"PRIu16")\n", + if_id, dest_len, data_len); +#ifdef DEBUG_ENABLED + DEBUG("dest: "); + + if (dest_len == 8) { + print_long_local_addr((net_if_eui64_t *)dest); + } + else { + printf("0x%04"PRIx16"\n", NTOHS(*((uint16_t *)dest))); + } + + DEBUG("data: \n"); + + for (int i = 0; i < data_len; i++) { + printf("%02x ", data[i]); + + if (!((i + 1) % 16) || i == data_len - 1) { + printf("\n"); + } + } + +#endif + + if (iphc_status == LOWPAN_IPHC_ENABLE) { - lowpan_iphc_encoding(&laddr, ipv6_buf, data); + if (!lowpan_iphc_encoding(if_id, dest, dest_len, ipv6_buf, data)) { + return -1; + } + data = &comp_buf[0]; send_packet_length = comp_len; } else { - ipv6_buf->length = HTONS(ipv6_buf->length); - lowpan_ipv6_set_dispatch(data); + memmove(data + 1, data, data_len); + data[0] = SIXLOWPAN_IPV6_DISPATCH; + send_packet_length++; } - /* check if packet needs to be fragmented */ - DEBUG("sixlowpan_lowpan_sendto(%s, data, %"PRIu16"): send_packet_length: %"PRIu16", header_size: %"PRIu16"\n", - sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + if (send_packet_length > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { + uint16_t remaining; + uint16_t position, datagram_size = send_packet_length; + uint8_t max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; + uint8_t fragbuf[max_frame + 5]; + + if (!(net_if_get_interface(if_id)->transceivers & (IEEE802154_TRANSCEIVER))) { + max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; + } + else { + max_frame = PAYLOAD_SIZE; + } - if (send_packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { - uint8_t fragbuf[send_packet_length + header_size]; - uint8_t remaining; - uint8_t i = 2; /* first fragment */ - max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; - max_frag_initial = ((max_frame - 4 - header_size) / 8) * 8; + max_frag_initial = ((max_frame - 4) / 8) * 8; + + if (data[0] == (char)SIXLOWPAN_IPV6_DISPATCH) { + /* XXX: weird, but only this way we get correct packet output */ + max_frag_initial++; + datagram_size--; + } - memcpy(fragbuf + 4, data, max_frag_initial); + memcpy(&fragbuf[4], data, max_frag_initial); - fragbuf[0] = ((SIXLOWPAN_FRAG1_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAG1_DISPATCH << 8) | send_packet_length; + fragbuf[0] = ((SIXLOWPAN_FRAG1_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAG1_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, &fragbuf, - max_frag_initial + header_size + 4, + max_frag_initial + 4, mcast); /* subsequent fragments */ @@ -213,11 +253,11 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, data += position; while (send_packet_length - position > max_frame - 5) { - memset(&fragbuf, 0, send_packet_length + header_size); - memcpy(fragbuf + 5, data, max_frag); + memset(&fragbuf[0], 0, sizeof(fragbuf)); + memcpy(&fragbuf[5], data, max_frag); - fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length; + fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; fragbuf[4] = position / 8; @@ -227,33 +267,32 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, max_frame + 5, mcast); data += max_frag; position += max_frag; - - i++; } remaining = send_packet_length - position; - memset(&fragbuf, 0, send_packet_length + header_size); - memcpy(fragbuf + 5, data, remaining); + memset(&fragbuf[0], 0, sizeof(fragbuf)); + memcpy(&fragbuf[5], data, remaining); - fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length; + fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; fragbuf[4] = position / 8; + tag++; + if (sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, &fragbuf, remaining + 5, mcast) < 0) { return -1; } } else { - return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, - data, send_packet_length, - mcast); + return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, data, + send_packet_length, mcast); } - tag++; + return data_len; } void sixlowpan_lowpan_set_iphc_status( @@ -262,8 +301,8 @@ void sixlowpan_lowpan_set_iphc_status( iphc_status = status; } -#if ENABLE_DEBUG -void print_long_local_addr(ieee_802154_long_t *saddr) +#ifdef DEBUG_ENABLED +void print_long_local_addr(net_if_eui64_t *saddr) { printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ((uint8_t *)saddr)[0], ((uint8_t *)saddr)[1], ((uint8_t *)saddr)[2], @@ -280,9 +319,9 @@ void sixlowpan_lowpan_print_reassembly_buffers(void) printf("\n\n--- Reassembly Buffers ---\n"); while (temp_buffer != NULL) { - print_long_local_addr(&temp_buffer->s_laddr); - printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %lu\n", - temp_buffer->ident_no, temp_buffer->current_packet_size, + print_long_local_addr(&temp_buffer->s_addr); + printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %"PRIu64"\n", + temp_buffer->tag, temp_buffer->current_packet_size, temp_buffer->packet_size, timex_uint64(temp_buffer->timestamp)); temp_interval = temp_buffer->interval_list_head; @@ -304,9 +343,9 @@ void sixlowpan_lowpan_print_fifo_buffers(void) printf("\n\n--- Reassembly Buffers ---\n"); while (temp_buffer != NULL) { - print_long_local_addr(&temp_buffer->s_laddr); - printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %lu\n", - temp_buffer->ident_no, temp_buffer->current_packet_size, + print_long_local_addr(&temp_buffer->s_addr); + printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %"PRIu64"\n", + temp_buffer->tag, temp_buffer->current_packet_size, temp_buffer->packet_size, timex_uint64(temp_buffer->timestamp)); temp_interval = temp_buffer->interval_list_head; @@ -336,25 +375,39 @@ void lowpan_transfer(void) if (current_buf != NULL) { mutex_unlock(&fifo_mutex); - if ((current_buf->packet)[0] == SIXLOWPAN_IPV6_DISPATCH) { + if (current_buf->packet[0] == SIXLOWPAN_IPV6_DISPATCH) { + DEBUG("INFO: Uncompressed IPv6 dispatch (0x%02x) received\n", + current_buf->packet[0]); ipv6_buf = ipv6_get_buf(); memcpy(ipv6_buf, (current_buf->packet) + 1, current_buf->packet_size - 1); m_send.content.ptr = (char *)ipv6_buf; packet_length = current_buf->packet_size - 1; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if (((current_buf->packet)[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH) { + else if ((current_buf->packet[0] & 0xf0) == IPV6_VER && + iphc_status == LOWPAN_IPHC_DISABLE) { + ipv6_buf = ipv6_get_buf(); + memcpy(ipv6_buf, (current_buf->packet), current_buf->packet_size); + m_send.content.ptr = (char *)ipv6_buf; + packet_length = current_buf->packet_size; + msg_send_receive(&m_send, &m_recv, ip_process_pid); + } + else if ((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH && + iphc_status == LOWPAN_IPHC_ENABLE) { + DEBUG("INFO: IPHC1 dispatch 0x%02x received, decompress\n", + current_buf->packet[0]); lowpan_iphc_decoding(current_buf->packet, current_buf->packet_size, - &(current_buf->s_laddr), - &(current_buf->d_laddr)); + ¤t_buf->s_addr, + ¤t_buf->d_addr); ipv6_buf = ipv6_get_buf(); m_send.content.ptr = (char *) ipv6_buf; msg_send_receive(&m_send, &m_recv, ip_process_pid); } else { - // printf("ERROR: packet with unknown dispatch received\n"); + DEBUG("ERROR: packet with unknown dispatch 0x%02x received\n", + current_buf->packet[0]); } collect_garbage_fifo(current_buf); @@ -369,11 +422,11 @@ void lowpan_transfer(void) } } -uint8_t ll_get_addr_match(ieee_802154_long_t *src, ieee_802154_long_t *dst) +uint8_t ll_get_addr_match(net_if_eui64_t *src, net_if_eui64_t *dst) { uint8_t val = 0, xor; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < sizeof(net_if_eui64_t); i++) { /* if bytes are equal add 8 */ if (src->uint8[i] == dst->uint8[i]) { val += 8; @@ -399,8 +452,8 @@ uint8_t ll_get_addr_match(ieee_802154_long_t *src, ieee_802154_long_t *dst) lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr, + net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr, lowpan_reas_buf_t *current_buf, lowpan_reas_buf_t *temp_buf) { @@ -415,10 +468,10 @@ lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, new_buf->packet = malloc(datagram_size); if (new_buf->packet != NULL) { - memcpy(&new_buf->s_laddr, s_laddr, IPV6_LL_ADDR_LEN); - memcpy(&new_buf->d_laddr, d_laddr, IPV6_LL_ADDR_LEN); + memcpy(&new_buf->s_addr, s_addr, 8); + memcpy(&new_buf->d_addr, d_addr, 8); - new_buf->ident_no = datagram_tag; + new_buf->tag = datagram_tag; new_buf->packet_size = datagram_size; vtimer_now(&new_buf->timestamp); @@ -443,17 +496,17 @@ lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) + net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { lowpan_reas_buf_t *current_buf = NULL, *temp_buf = NULL; current_buf = head; while (current_buf != NULL) { - if (((ll_get_addr_match(¤t_buf->s_laddr, s_laddr)) == 64) && - ((ll_get_addr_match(¤t_buf->d_laddr, d_laddr)) == 64) && + if (((ll_get_addr_match(¤t_buf->s_addr, s_addr)) == 64) && + ((ll_get_addr_match(¤t_buf->d_addr, d_addr)) == 64) && (current_buf->packet_size == datagram_size) && - (current_buf->ident_no == datagram_tag) && + (current_buf->tag == datagram_tag) && current_buf->interval_list_head != NULL) { /* Found buffer for current packet fragment */ vtimer_now(¤t_buf->timestamp); @@ -464,7 +517,7 @@ lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size, current_buf = current_buf->next; } - return new_packet_buffer(datagram_size, datagram_tag, s_laddr, d_laddr, + return new_packet_buffer(datagram_size, datagram_tag, s_addr, d_addr, current_buf, temp_buf); } @@ -603,13 +656,13 @@ lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf) void handle_packet_fragment(uint8_t *data, uint8_t datagram_offset, uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr, uint8_t hdr_length, - uint8_t frag_size) + net_if_eui64_t *s_addr, net_if_eui64_t *d_addr, + uint8_t hdr_length, uint8_t frag_size) { lowpan_reas_buf_t *current_buf; /* Is there already a reassembly buffer for this packet fragment? */ - current_buf = get_packet_frag_buf(datagram_size, datagram_tag, s_laddr, d_laddr); + current_buf = get_packet_frag_buf(datagram_size, datagram_tag, s_addr, + d_addr); if ((current_buf != NULL) && (handle_packet_frag_interval(current_buf, datagram_offset, @@ -727,8 +780,8 @@ uint8_t sixlowpan_lowpan_register(int pid) } } -void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) +void lowpan_read(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { /* check if packet is fragmented */ uint8_t hdr_length = 0; @@ -736,7 +789,6 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, uint16_t datagram_size = 0; uint16_t datagram_tag = 0; short i; - sixlowpan_lowpan_frame_t current_frame; check_timeout(); @@ -754,6 +806,9 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, /* Fragmented Packet */ if (((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAG1_DISPATCH) || ((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAGN_DISPATCH)) { + uint16_t byte_offset; + DEBUG("INFO: fragmentation dispatch 0x%02x received\n", + data[0] & SIXLOWPAN_FRAG_HDR_MASK); /* get 11-bit from first 2 byte*/ datagram_size = (((uint16_t)(data[0] << 8)) | data[1]) & 0x07ff; @@ -765,6 +820,11 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, case (SIXLOWPAN_FRAG1_DISPATCH): { datagram_offset = 0; hdr_length += 4; + + if (data[4] == (char)SIXLOWPAN_IPV6_DISPATCH) { + hdr_length++; + } + break; } @@ -787,12 +847,13 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, } handle_packet_fragment(data, byte_offset, datagram_size, datagram_tag, - s_laddr, d_laddr, hdr_length, frag_size); + s_addr, d_addr, hdr_length, frag_size); } /* Regular Packet */ else { - lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_laddr, - d_laddr); + DEBUG("INFO: unfragmentated packet with first byte 0x%02x received\n", + data[0]); + lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_addr, d_addr); if (current_buf && current_buf->packet) { /* Copy packet bytes into corresponding packet space area */ @@ -811,25 +872,32 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, } -void lowpan_ipv6_set_dispatch(uint8_t *data) -{ - memmove(data + 1, data, packet_length); - data[0] = SIXLOWPAN_IPV6_DISPATCH; - packet_length++; -} - /* draft-ietf-6lowpan-hc-13#section-3.1 */ -void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, - uint8_t *ptr) +uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, + ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr) { - ipv6_buf = ipv6_buf_extra; - - uint16_t payload_length = ipv6_buf->length; + uint16_t payload_length = NTOHS(ipv6_buf->length); uint8_t lowpan_iphc[2]; uint8_t *ipv6_hdr_fields = &comp_buf[2]; lowpan_context_t *con = NULL; uint16_t hdr_pos = 0; uint8_t tc; + net_if_eui64_t own_iid; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + if (!net_if_get_eui64(&own_iid, if_id, 0)) { + return 1; + } + } + else { + if (!net_if_get_eui64(&own_iid, if_id, 1)) { + return 1; + } + + own_iid.uint8[0] ^= 0x02; + } + + ipv6_buf = ipv6_buf_extra; memset(&lowpan_iphc, 0, 2); @@ -926,69 +994,47 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, /* SAC = 1 and SAM = 00 */ lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; } - else if ((con = lowpan_context_lookup(&ipv6_buf->srcaddr)) != NULL) { - /* 1: Source address compression uses stateful, context-based - * compression. */ - lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; - ipv6_hdr_fields[0] |= (con->num << 4); - - if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) { - /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ - lowpan_iphc[1] |= 0x30; - } - else if ((ipv6_buf->srcaddr.uint16[4] == 0) && - (ipv6_buf->srcaddr.uint16[5] == 0) && - (ipv6_buf->srcaddr.uint16[6] == 0) && - ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x20; + else { + if ((con = lowpan_context_lookup(&ipv6_buf->srcaddr)) != NULL) { + /* 1: Source address compression uses stateful, context-based + * compression. */ + lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; + ipv6_hdr_fields[0] |= (con->num << 4); } - else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x10; - } - } - else if (ipv6_addr_is_link_local(&ipv6_buf->srcaddr)) { - /* 0: Source address compression uses stateless compression.*/ - if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) { - /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ - lowpan_iphc[1] |= 0x30; - } - else if ((ipv6_buf->srcaddr.uint16[4] == 0) && - (ipv6_buf->srcaddr.uint16[5] == 0) && - (ipv6_buf->srcaddr.uint16[6] == 0) && - ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x20; + + if (con || ipv6_addr_is_link_local(&ipv6_buf->srcaddr)) { + /* 0: Source address compression uses stateless compression.*/ + if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &own_iid, 8) == 0) { + /* 0 bits. The address is derived using context information + * and possibly the link-layer addresses.*/ + lowpan_iphc[1] |= 0x30; + } + else if ((ipv6_buf->srcaddr.uint16[4] == 0) && + (ipv6_buf->srcaddr.uint16[5] == 0) && + (ipv6_buf->srcaddr.uint16[6] == 0) && + ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { + /* 49-bit of interface identifier are 0, so we can compress + * source address-iid to 16-bit */ + memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); + hdr_pos += 2; + /* 16 bits. The address is derived using context information + * and the 16 bits carried inline. */ + lowpan_iphc[1] |= 0x20; + } + else { + memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); + hdr_pos += 8; + /* 64 bits. The address is derived using context information + * and the 64 bits carried inline. */ + lowpan_iphc[1] |= 0x10; + } } else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x10; + /* full address carried inline */ + memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint8[0]), 16); + hdr_pos += 16; } } - else { - /* full address carried inline */ - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint8[0]), 16); - hdr_pos += 16; - } /* M: Multicast Compression */ if (ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { @@ -1049,35 +1095,22 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, lowpan_iphc[1] |= SIXLOWPAN_IPHC2_DAC; ipv6_hdr_fields[0] = con->num; - if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) { + } + + if (con || ipv6_addr_is_link_local(&ipv6_buf->destaddr)) { + if (dest_len == 8 && + ipv6_buf->destaddr.uint8[8] == (dest[0] ^ 0x02) && + memcmp(&ipv6_buf->destaddr.uint8[9], &dest[1], 7) == 0) { /* 0 bits. The address is derived using context information * and possibly the link-layer addresses.*/ lowpan_iphc[1] |= 0x03; } - else if ((ipv6_buf->destaddr.uint16[4] == 0) && - (ipv6_buf->destaddr.uint16[5] == 0) && - (ipv6_buf->destaddr.uint16[6] == 0) && - ((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->destaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x02; - } - else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->destaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x01; - } - } - else if (ipv6_addr_is_link_local(&ipv6_buf->destaddr)) { - if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) { + else if (dest_len == 2 && + ipv6_buf->destaddr.uint32[2] == HTONL(0x000000ff) && + ipv6_buf->destaddr.uint16[6] == HTONS(0xfe00) && + ipv6_buf->destaddr.uint16[7] == *((uint16_t *) dest)) { /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ + * and possibly the link-layer addresses.*/ lowpan_iphc[1] |= 0x03; } else if ((ipv6_buf->destaddr.uint16[4] == 0) && @@ -1096,7 +1129,7 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->destaddr.uint16[4]), 8); hdr_pos += 8; /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ + * and the 64 bits carried inline. */ lowpan_iphc[1] |= 0x01; } } @@ -1124,11 +1157,12 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], ipv6_buf->length); comp_len = 2 + hdr_pos + payload_length; + + return 1; } -void lowpan_iphc_decoding(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) +void lowpan_iphc_decoding(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { uint8_t hdr_pos = 0; uint8_t *ipv6_hdr_fields = data; @@ -1258,7 +1292,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x01): { /* 64-bits */ memcpy(&(ipv6_buf->srcaddr.uint8[8]), &ipv6_hdr_fields[hdr_pos], 8); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); hdr_pos += 8; @@ -1269,7 +1303,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, /* 16-bits */ memset(&(ipv6_buf->srcaddr.uint8[8]), 0, 6); memcpy(&(ipv6_buf->srcaddr.uint8[14]), &ipv6_hdr_fields[hdr_pos], 2); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); hdr_pos += 2; @@ -1278,9 +1312,8 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { /* 0-bits */ - memset(&(ipv6_buf->srcaddr.uint8[8]), 0, 8); - memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_laddr->uint8[0], 8); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_addr->uint8[0], 8); + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); break; @@ -1319,7 +1352,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, /* 0-bits */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &ll_prefix[0], 2); memset(&(ipv6_buf->srcaddr.uint8[2]), 0, 20); - memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_addr->uint8[0], 8); break; } @@ -1449,7 +1482,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { memset(&(ipv6_buf->destaddr.uint8[0]), 0, 8); - memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_addr->uint8[0], 8); /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); break; @@ -1484,7 +1517,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { memcpy(&(ipv6_buf->destaddr.uint8[0]), &ll_prefix, 2); memset(&(ipv6_buf->destaddr.uint8[2]), 0, 14); - memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_addr->uint8[0], 8); break; } @@ -1503,7 +1536,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, memcpy(ptr, &ipv6_hdr_fields[hdr_pos], length - hdr_pos); /* ipv6 length */ - ipv6_buf->length = length - hdr_pos; + ipv6_buf->length = HTONS(length - hdr_pos); packet_length = IPV6_HDR_LEN + ipv6_buf->length; } @@ -1626,113 +1659,172 @@ void lowpan_context_auto_remove(void) void init_reas_bufs(lowpan_reas_buf_t *buf) { - memset(&buf->s_laddr, 0, IPV6_LL_ADDR_LEN); - memset(&buf->d_laddr, 0, IPV6_LL_ADDR_LEN); - buf->ident_no = 0; + memset(&buf->s_addr, 0, sizeof(net_if_eui64_t)); + memset(&buf->d_addr, 0, sizeof(net_if_eui64_t)); + buf->tag = 0; memset(&buf->timestamp, 0, sizeof(timex_t)); - buf->packet_size = 0; - buf->current_packet_size = 0; - buf->packet = NULL; - buf->interval_list_head = NULL; - buf->next = NULL; + buf->packet_size = 0; + buf->current_packet_size = 0; + buf->packet = NULL; + buf->interval_list_head = NULL; + buf->next = NULL; } -void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr, - int as_border) +int sixlowpan_lowpan_init_adhoc_interface(int if_id, const ipv6_addr_t *prefix) { - lowpan_init(trans, r_addr, NULL, as_border); -} + ipv6_addr_t tmp; -void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, - const ipv6_addr_t *prefix, - uint8_t r_addr) -{ - lowpan_init(trans, r_addr, prefix, 0); + /* if prefix is set */ + if (prefix != NULL) { + /* init network prefix */ + ipv6_addr_t save_prefix; + + ipv6_addr_init_prefix(&save_prefix, prefix, 64); + ndp_add_prefix_info(if_id, &save_prefix, 64, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); + ipv6_init_as_router(); + + /* add global address */ + if (!ipv6_addr_set_by_eui64(&tmp, if_id, prefix)) { + return 0; + } + + DEBUG("%s, %d: set unique address for interface %d to %s, according " + "to prefix %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + return 0; + } + } + + return sixlowpan_lowpan_init_interface(if_id); } -void lowpan_init(transceiver_type_t trans, uint8_t r_addr, - const ipv6_addr_t *prefix, int as_border) +int sixlowpan_lowpan_init_interface(int if_id) { - int if_id = 0; ipv6_addr_t tmp; - short i; + /* init link-local prefix */ + ipv6_addr_set_link_local_prefix(&tmp); - /* init interface addresses */ - memset(&iface, 0, sizeof(iface_t)); + if (!ipv6_addr_set_by_eui64(&tmp, if_id, &tmp)) { + DEBUG("Can not set link-local by EUI-64 on interface %d\n", if_id); + return 0; + } - /* init lowpan context mutex */ - mutex_init(&lowpan_context_mutex); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add link local address to " + "interface %d: %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); - /* init packet_fifo mutex */ - mutex_init(&fifo_mutex); + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add link-local address to interface %d\n", if_id); + return 0; + } - local_address = r_addr; + /* add solicited nodes multicast address of link local address */ + ipv6_addr_set_solicited_node_addr(&tmp, &tmp); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add solicited nodes multicast address " + "to of link layer address interface %d: %s\n", __FILE__, __LINE__, + if_id, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); - /* if prefix is set */ - if (prefix != NULL) { - /* init network prefix */ - ipv6_addr_t save_prefix; - ipv6_addr_init_prefix(&save_prefix, prefix, 64); - plist_add(&save_prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1, - ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); - ipv6_init_iface_as_router(); - /* add global address */ - ipv6_addr_set_by_eui64(&tmp, prefix); - DEBUG("%s, %d: set unique address to %s, according to prefix %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp), ipv6_addr_to_str(addr_str, prefix)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; } - DEBUG("%s, %d: set link local prefix to %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); - /* init link-local address */ - ipv6_addr_set_link_local_prefix(&lladdr); - - /* add link local address */ - memcpy(&(lladdr.uint8[8]), &(iface.laddr.uint8[0]), 8); - DEBUG("%s, %d: sixlowpan_lowpan_init(): add link local address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); - ipv6_iface_add_addr(&lladdr, IPV6_ADDR_TYPE_LINK_LOCAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); + /* add all nodes multicast address */ + ipv6_addr_set_all_nodes_addr(&tmp); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add all nodes multicast address " + "to interface %d: %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; + } /* add loopback address */ ipv6_addr_set_loopback_addr(&tmp); - DEBUG("%s, %d: sixlowpan_lowpan_init(): add loopback address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, - NDP_ADDR_STATE_PREFERRED, 0, 0); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add loopback address to interface " + "0: %s\n", __FILE__, __LINE__, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(0, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; + } - /* add all nodes multicast address */ - DEBUG("%s, %d: sixlowpan_lowpan_init(): add all nodes multicast address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, - NDP_ADDR_STATE_PREFERRED, 0, 0); + icmpv6_send_router_sol(OPT_SLLAO); + + return 1; +} + +int sixlowpan_lowpan_init(void) +{ + short i; /* init mac-layer and radio transceiver */ sixlowpan_mac_init(); - if (as_border) { - ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, - PRIORITY_MAIN - 1, CREATE_STACKTEST, - border_process_lowpan, - "border_process_lowpan"); - } - else { + + /* init lowpan context mutex */ + mutex_init(&lowpan_context_mutex); + + /* init packet_fifo mutex */ + mutex_init(&fifo_mutex); + + if (!ip_process_pid) { ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, ipv6_process, "ip_process"); } + if (ip_process_pid < 0) { + return 0; + } + nd_nbr_cache_rem_pid = thread_create(nc_buf, NC_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, nbr_cache_auto_rem, "nbr_cache_rem"); + + if (nd_nbr_cache_rem_pid < 0) { + return 0; + } + contexts_rem_pid = thread_create(con_buf, CON_STACKSIZE, PRIORITY_MAIN + 1, CREATE_STACKTEST, lowpan_context_auto_remove, "lowpan_context_rem"); + + if (contexts_rem_pid < 0) { + return 0; + } + transfer_pid = thread_create(lowpan_transfer_buf, LOWPAN_TRANSFER_BUF_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, lowpan_transfer, "lowpan_transfer"); + if (transfer_pid < 0) { + return 0; + } + for (i = 0; i < SIXLOWIP_MAX_REGISTERED; i++) { sixlowip_reg[i] = 0; } + return 0; } diff --git a/sys/net/network_layer/sixlowpan/lowpan.h b/sys/net/network_layer/sixlowpan/lowpan.h index d4bd59e7d8b0..38830ae9b442 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.h +++ b/sys/net/network_layer/sixlowpan/lowpan.h @@ -29,6 +29,8 @@ #include "sixlowpan/lowpan.h" +#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) + typedef struct { uint8_t num; ipv6_addr_t prefix; diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index ab27207b31a4..723dac710e80 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -47,7 +47,6 @@ #define RADIO_SENDING_DELAY (1000) #define DEFAULT_IEEE_802154_PAN_ID (0x1234) -#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) char radio_stack_buffer[RADIO_STACK_SIZE]; msg_t msg_q[RADIO_RCV_BUF_SIZE]; From e2e62596bedab97cb1249a83df316d5761b2bc4c Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Thu, 27 Feb 2014 00:49:03 +0100 Subject: [PATCH 14/19] Byte order and rpl problems --- sys/net/network_layer/sixlowpan/icmp.c | 4 ++-- sys/net/network_layer/sixlowpan/lowpan.c | 2 +- sys/net/routing/rpl/rpl.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 5d93f56bbd21..69005329fe98 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -672,7 +672,7 @@ void recv_rtr_adv(void) ipv6_addr_t abro_addr; ipv6_buf = ipv6_get_buf(); - packet_length = IPV6_HDR_LEN + ipv6_buf->length; + packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); icmpv6_opt_hdr_len = RTR_ADV_LEN; rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len); ipv6_addr_t newaddr; @@ -937,7 +937,7 @@ void recv_nbr_sol(void) uint8_t send_na = 0; uint8_t sllao_set = 0; uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; - uint16_t packet_length = IPV6_HDR_LEN + ipv6_buf->length; + uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); /* check whick options are set, we need that because an aro * option condition is that a sllao option is set. thus that we don't diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 4a5ca8e3215b..a4f54979a6fe 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -1154,7 +1154,7 @@ uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, ptr = get_payload_buf(ipv6_ext_hdr_len); } */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], ipv6_buf->length); + memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], NTOHS(ipv6_buf->length)); comp_len = 2 + hdr_pos + payload_length; diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 013c7258a5a0..a9a7d6fa3c11 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -490,7 +490,7 @@ void rpl_process(void) code = ((uint8_t *)m_recv.content.ptr); /* differentiate packet types */ ipv6_buf = ipv6_get_buf(); - memcpy(&rpl_buffer, ipv6_buf, ipv6_buf->length + IPV6_HDR_LEN); + memcpy(&rpl_buffer, ipv6_buf, NTOHS(ipv6_buf->length) + IPV6_HDR_LEN); switch (*code) { case (ICMP_CODE_DIS): { @@ -583,7 +583,7 @@ void recv_rpl_dio(void) * ipv6_buf->length contains the packet length minus ipv6 and * icmpv6 header, so only ICMPV6_HDR_LEN remains to be * subtracted. */ - while (len < (ipv6_buf->length - ICMPV6_HDR_LEN)) { + while (len < (NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN)) { DEBUG("parsing DIO options\n"); rpl_opt_buf = get_rpl_opt_buf(len); @@ -970,7 +970,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ } } - ipv6_send_packet(ipv6_buf); + ipv6_send_packet(ipv6_send_buf); } } From 00acab920bacbf49dfbe5a68e939926053e54f60 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 13:57:59 +0100 Subject: [PATCH 15/19] Let IPv6 and ICMP use new 6LoWPAN layer (+fixes) --- Makefile.dep | 10 +- sys/net/include/sixlowpan/icmp.h | 4 +- sys/net/include/sixlowpan/ip.h | 207 ++++-- sys/net/include/sixlowpan/ndp.h | 126 +++- sys/net/include/sixlowpan/types.h | 21 +- .../network_layer/sixlowpan/border/border.h | 2 +- .../sixlowpan/border/bordermultiplex.c | 8 +- sys/net/network_layer/sixlowpan/icmp.c | 604 +++++++++++++----- sys/net/network_layer/sixlowpan/icmp.h | 5 +- sys/net/network_layer/sixlowpan/ip.c | 524 ++++++++------- sys/net/network_layer/sixlowpan/ip.h | 45 +- sys/net/network_layer/sixlowpan/lowpan.h | 6 +- sys/net/routing/rpl/rpl.c | 16 +- sys/net/routing/rpl/rpl.h | 2 +- sys/net/routing/rpl/rpl_dodag.c | 4 +- sys/net/transport_layer/destiny/socket.c | 32 +- sys/shell/commands/sc_net_if.c | 67 +- 17 files changed, 1127 insertions(+), 556 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index eff649d8a441..f7b80ef62bcb 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -92,13 +92,13 @@ ifneq (,$(filter sixlowpan,$(USEMODULE))) ifeq (,$(filter net_help,$(USEMODULE))) USEMODULE += net_help endif - ifeq (,$(filter semaphore,$(USEMODULE))) - USEMODULE += semaphore + ifeq (,$(filter net_if,$(USEMODULE))) + USEMODULE += net_if endif - ifeq (,$(filter transceiver,$(USEMODULE))) - USEMODULE += transceiver + ifeq (,$(filter semaphore, $(USEMODULE))) + USEMODULE += semaphore endif - ifeq (,$(filter vtimer,$(USEMODULE))) + ifeq (,$(filter vtimer, $(USEMODULE))) USEMODULE += vtimer endif endif diff --git a/sys/net/include/sixlowpan/icmp.h b/sys/net/include/sixlowpan/icmp.h index 6aa417c66c5e..97b08791aa67 100644 --- a/sys/net/include/sixlowpan/icmp.h +++ b/sys/net/include/sixlowpan/icmp.h @@ -150,7 +150,7 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, + uint16_t seq, uint8_t *data, size_t data_len); /** @@ -163,7 +163,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, size_t data_len); + uint16_t seq, uint8_t *data, size_t data_len); /** * @brief Send ICMPv6 router solicitation. diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index d365a65c3312..aaf41c44ac86 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -24,6 +24,9 @@ #include +#include "inet_ntop.h" +#include "net_help.h" +#include "net_if.h" #include "sixlowpan/types.h" /** @@ -32,7 +35,17 @@ #define IPV6_MTU (256) /** - * @brief Maximum length of a IPv6 address represented as string. + * @brief Length of an IPv6 address in byte. + */ +#define IPV6_ADDR_LEN (16) + +/** + * @brief Length of an IPv6 address in bit. + */ +#define IPV6_ADDR_BIT_LEN (128) + +/** + * @brief Maximum length of an IPv6 address represented as string. */ #define IPV6_MAX_ADDR_STR_LEN (40) @@ -160,7 +173,11 @@ void ipv6_register_rpl_handler(int pid); * * @param[in,out] ipv6_addr The address to set. */ -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xfe800000); + ipv6_addr->uint32[1] = 0; +} /** * @brief Sets IPv6 address *out* according to the remaining @@ -181,16 +198,20 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr5, uint16_t addr6, uint16_t addr7); /** - * @brief Sets IPv6 address *out* using the given *prefix* and this - * nodes EUI-64 (i. e. interface must be initialized). + * @brief Sets IPv6 address *out* using the given *prefix* and an interface's + * EUI-64. + * * * @param[out] out Address to be set. + * @param[in] if_id The interface to take the EUI-64 from. * @param[in] prefix 64-bit network prefix to be used for *out* * (only the first 64 bit of the ipv6_addr_t type * are copied to *out*) + * + * @return The Address to be set on success, NULL on error. */ -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, - const ipv6_addr_t *prefix); +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix); /** * @brief Sets IPv6 address *out* with the first *bits* bit taken @@ -213,7 +234,13 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, * * @param[out] ipv6_addr Is set to the loopback address. */ -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = 0; + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr* to a link-local all routers multicast @@ -226,7 +253,13 @@ void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all routers multicast * address. */ -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(2); +} /** * @brief Set *ipv6_addr* to a link-local all nodes multicast address @@ -239,7 +272,13 @@ void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all nodes multicast * address. */ -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr_out* to the solicited-node multicast address @@ -254,22 +293,34 @@ void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); * @param[in] ipv6_addr_in The IPv6 address the solicited-node * address. */ -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in); +static inline void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, + const ipv6_addr_t *ipv6_addr_in) +{ + /* copy only the last 24-bit of the ip-address that is beeing resolved */ + ipv6_addr_out->uint32[0] = HTONL(0xff020000); + ipv6_addr_out->uint32[1] = 0; + ipv6_addr_out->uint32[2] = HTONS(1); + ipv6_addr_out->uint8[12] = 0xff; + ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; + ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; +} /** - * @brief Converts IPv6 address into string (unabbrivated notation). - * Note that addr_str must allocate at least - * IPV6_MAX_ADDR_STR_LEN byte (40 byte). + * @brief Converts IPv6 address into string. * * @param[out] addr_str The IPv6 address as string. Must allocate * at least IPV6_MAX_ADDR_STR_LEN byte (40 * byte). + * @param[in] str_len The maximum length available to *addr_str*. * @param[in] ipv6_addr IPv6 address to be converted. * * @return Pointer to addr_str. */ -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); +static inline const char *ipv6_addr_to_str(char *addr_str, uint8_t str_len, + const ipv6_addr_t *ipv6_addr) +{ + return inet_ntop(AF_INET6, ipv6_addr, addr_str, (size_t)str_len); +} /** * @brief Checks if two IPv6 addresses are equal. @@ -279,7 +330,13 @@ char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); * * @return 1 if *a* and *b* are equal, 0 otherwise. */ -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); +static inline int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) +{ + return (a->uint32[0] == b->uint32[0]) && + (a->uint32[1] == b->uint32[1]) && + (a->uint32[2] == b->uint32[2]) && + (a->uint32[3] == b->uint32[3]); +} /** * @brief Checks if *ipv6_addr* is unspecified (all zero). @@ -292,10 +349,16 @@ int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); * * @return 1 if *ipv6_addr* is unspecified address, 0 otherwise. */ -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == 0) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == 0) && + (ipv6_addr->uint32[3] == 0); +} /** - * @brief Check if *ipv6_addr* is a link-local address. + * @brief Check if *ipv6_addr* is a multicast address. * * @see * RFC 4291 @@ -303,26 +366,34 @@ int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); * * @param[in] ipv6_addr An IPv6 address. * - * @return 1 if *ipv6_addr* is link-local address, 0 otherwise. + * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. */ -int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint8[0] == 0xff); +} /** - * @brief Check if *ipv6_addr* is unique local unicast address. + * @brief Checks if *ipv6_addr* is a loopback address. * - * @see - * RFC 4193 + * @see + * RFC 4291 * * - * @param[in] ipv6_addr An IPv6 address. + * @param[in] ipv6_addr An IPv6 address. * - * @return 1 if *ipv6_addr* is unique local unicast address, - * 0 otherwise. + * @return 1 if *ipv6_addr* is loopback address, 0 otherwise. */ -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr); +static inline int ipv6_addr_is_loopback(const ipv6_addr_t *ipv6_addr) +{ + return ipv6_addr->uint32[0] == 0 && + ipv6_addr->uint32[1] == 0 && + ipv6_addr->uint32[2] == 0 && + NTOHL(ipv6_addr->uint32[3]) == 1; +} /** - * @brief Check if *ipv6_addr* is a multicast address. + * @brief Check if *ipv6_addr* is a link-local address. * * @see * RFC 4291 @@ -330,9 +401,32 @@ int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr); * * @param[in] ipv6_addr An IPv6 address. * - * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. + * @return 1 if *ipv6_addr* is link-local address, 0 otherwise. */ -int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint32[0] == HTONL(0xfe800000)) && + (ipv6_addr->uint32[1] == 0)) || + (ipv6_addr_is_multicast(ipv6_addr) && + (ipv6_addr->uint8[1] & 0x0f) == 2); +} + +/** + * @brief Check if *ipv6_addr* is unique local unicast address. + * + * @see + * RFC 4193 + * + * + * @param[in] ipv6_addr An IPv6 address. + * + * @return 1 if *ipv6_addr* is unique local unicast address, + * 0 otherwise. + */ +static inline int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint8[0] == 0xfc) || (ipv6_addr->uint8[0] == 0xfd)); +} /** * @brief Check if *ipv6_addr* is solicited-node multicast address. @@ -346,7 +440,28 @@ int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); * @return 1 if *ipv6_addr* is solicited-node multicast address, * 0 otherwise. */ -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == HTONL(0xff020000)) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == HTONL(1)) && + (ipv6_addr->uint8[12] == 0xff); +} + +/** + * @brief Get pointer to potential EUI-64 bit of the IPv6 address. + * + * @param[in] ipv6_addr An IPv6 address of this node. + * @param[in] prefix_len Length of the prefix. Only multiples of 8 are + * possible. + * + * @return The IID (as EUI-64) of this node. + */ +static inline net_if_eui64_t *ipv6_addr_get_iid(const ipv6_addr_t *ipv6_addr, + uint8_t prefix_len) +{ + return ((net_if_eui64_t *) &ipv6_addr->uint8[prefix_len / 8]); +} /* * TODO to wrap sixlowpan initialisations @@ -354,26 +469,35 @@ int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); */ /** - * @brief Add an IPv6 address to this nodes interface. + * @brief Add an IPv6 address to one of this nodes interfaces. * * @see * RFC 4862 * * + * @param[in] if_id The interface's ID. * @param[in] addr Address to be added to the interface. * @param[in] type Type of this address. * @param[in] state Initial state of the address. - * @param[in] val_ltime Valid lifetime of this address in seconds. + * @param[in] val_ltime Valid lifetime of this address in seconds. Set 0 + * for unspecified. * @param[in] pref_ltime Preferred lifetime of this address in - * seconds. + * seconds. Set 0 for unspecified. + * @param[in] is_anycast Determines if an address is anycast. Anycast + * addresses are syntactically undistinguishable + * from unicast addresses and can only be identified + * with this flag. If *addr* is no unicast address + * and *is_anycast* is set, this function will fail. + * + * @return 1 on success, 0 on failure. */ -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime); + uint32_t pref_ltime, uint8_t is_anycast); /** * @brief Tries to determine best suitable source address attached to - * the interface of this node based on the given destination + * an interface of this node based on the given destination * address. The use-case for this function is to find a * suitable address for the source address field of an IPv6 * address upon sending. *src* may be empty (all zero) if there @@ -381,16 +505,11 @@ void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, * * @param[out] src The best source address for this node (may be * all zero if ther is none). + * @param[in] if_id The interface's ID. * @param[in] dest The destination address for a packet we search * the source address for. */ -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, - const ipv6_addr_t *dest); - -/** - * @brief Print all addresses attached to the interface to stdout. - */ -void ipv6_iface_print_addrs(void); +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest); /** * @brief Registers a function that decides how to route incomming diff --git a/sys/net/include/sixlowpan/ndp.h b/sys/net/include/sixlowpan/ndp.h index 939844fa53bd..9bf7b6956113 100644 --- a/sys/net/include/sixlowpan/ndp.h +++ b/sys/net/include/sixlowpan/ndp.h @@ -24,6 +24,7 @@ #include +#include "net_if.h" #include "timex.h" #include "sixlowpan/types.h" @@ -32,6 +33,7 @@ #define NDP_OPT_SLLAO_TYPE (1) #define NDP_OPT_TLLAO_TYPE (2) #define NDP_OPT_PI_VLIFETIME_INFINITE (0xffffffff) +#define NDP_OPT_PI_PLIFETIME_INFINITE (0xffffffff) #define NDP_OPT_ARO_STATE_SUCCESS (0) #define NDP_OPT_ARO_STATE_DUP_ADDR (1) #define NDP_OPT_ARO_STATE_NBR_CACHE_FULL (2) @@ -64,18 +66,37 @@ typedef enum __attribute__((packed)) { /** * @brief Prefix list type to store information spread by prefix - * information option. + * information option on the interface. + * + * @see net_if_addr_t */ -typedef struct __attribute__((packed)) { - uint8_t inuse; ///< Prefix is in in use. - uint8_t adv; - ipv6_addr_t addr; ///< The Prefix. - uint8_t length; ///< Length of the prefix. - uint8_t l_a_reserved1; ///< L and A flag of prefix information option - uint32_t val_ltime; ///< valid lifetime - uint32_t pref_ltime; ///< preferred lifetime - uint8_t infinite; ///< flag to set to infinite lifetime -} ndp_prefix_list_t; +typedef struct __attribute__((packed)) ndp_prefix_info_t { + /** + * @brief The next on the interface. Intialise with NULL + */ + struct ndp_prefix_info_t *addr_next; + /** + * @brief The prev address on the interface. Initialise with NULL + */ + struct ndp_prefix_info_t *addr_prev; + /** + * @brief Flags to define upper layer protocols this address applies to. + * For this layer NET_IF_L3P_IPV6_PREFIX must be set. + */ + net_if_l3p_t prefix_protocol; + ipv6_addr_t *prefix_data; ///< The Prefix. + uint8_t prefix_len; ///< Length of the prefix. + uint8_t inuse; ///< Prefix is in in use. + /** + * Use this information in Prefix Information Options of Router + * Advertisements. + */ + uint8_t advertisable; + uint8_t flags; ///< flags of the prefix information option + uint32_t valid_lifetime; ///< valid lifetime + uint32_t preferred_lifetime; ///< preferred lifetime + uint8_t infinite; ///< flag to set to infinite lifetime +} ndp_prefix_info_t; /** * @brief Default router list to store information spread by @@ -84,7 +105,7 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { ipv6_addr_t addr; ///< Address of router. timex_t inval_time; ///< remaining time until this entry is - ///< invalid. + ///< invalid. } ndp_default_router_list_t; /** @@ -94,14 +115,16 @@ typedef struct __attribute__((packed)) { * . */ typedef struct __attribute__((packed)) { + int if_id; ///< Interface the IPv6 address is reachable + ///< over ndp_nce_type_t type; ///< Type of neighbor cache entry. ndp_nce_state_t state; ///< State of neighbor cache entry. uint8_t isrouter; ///< Flag to signify that this neighbor - ///< is a router. + ///< is a router. ipv6_addr_t addr; ///< IPv6 address of the neighbor. - ieee_802154_long_t laddr; ///< EUI-64 of neighbor - ieee_802154_short_t saddr; ///< IEEE 802.15.4 16-bit short address - ///< of neighbor. + uint8_t lladdr[8]; ///< Link-layer address of the neighbor + uint8_t lladdr_len; ///< Length of link-layer address of the + ///< neighbor timex_t ltime; ///< lifetime of entry. } ndp_neighbor_cache_t; @@ -118,9 +141,76 @@ typedef struct __attribute__((packed)) { } ndp_a6br_cache_t; ndp_default_router_list_t *ndp_default_router_list_search(ipv6_addr_t *ipaddr); +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime); ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr); -/*TODO: to implement*/ -uint8_t ndp_prefix_list_search(ipv6_addr_t *addr); +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr); +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr); + +/** + * @brief Adds a prefix information to an interface. If it already exists, + * the values *valid_lifetime*, *preferred_lifetime*, *advertisable*, + * and flags will be updated accordingly and the prefix will be marked + * as *in_use*. + * + * @see + * RFC 4861, section 4.6.2 + * . + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix. + * @param[in] prefix_len The length of the prefix in bit. + * @param[in] valid_lifetime The time in seconds this prefix is valid + * for on-link determination. + * NDP_OPT_PI_VLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] preferred_lifetime The time in seconds addresses generated with + * this prefix remain preferred. + * NDP_OPT_PI_PLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] advertisable Set this to a value != 0 to advertise this + * prefix information with the Prefix + * Information Option, set it to 0 if not. + * @param[in] flags Flags for the Prefix Information Option. + * Valid values are + * ICMPV6_NDP_OPT_PI_FLAG_ON_LINK and + * ICMPV6_NDP_OPT_PI_FLAG_AUTONOM + */ +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags); + +/** + * @brief Searches the information for the longest prefix up to *up_to* bits + * on an interface fitting to an address *addr*. + * + * @param[in] if_id The interface's ID. + * @param[in] addr The address to search the prefix for. + * @param[in] up_to The number of bits up to which point the search should + * go. Set to IPV6_ADDR_BIT_LEN for the whole address. + * Values greater then IPV6_ADDR_BIT_LEN are set to + * IPV6_ADDR_BIT_LEN. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to); + +/** + * @brief Searches the information for the prefix that matches *prefix* with + * length *prefix_len*. + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix to search for. + * @param[in] prefix_len The length of the prefix in bit. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len); ndp_a6br_cache_t *ndp_a6br_cache_get_most_current(void); ndp_a6br_cache_t *ndp_a6br_cache_get_oldest(void); diff --git a/sys/net/include/sixlowpan/types.h b/sys/net/include/sixlowpan/types.h index 879d8e5d1d22..d8ebc0334e56 100644 --- a/sys/net/include/sixlowpan/types.h +++ b/sys/net/include/sixlowpan/types.h @@ -49,25 +49,6 @@ typedef union __attribute__((packed)) { uint32_t uint32[4]; ///< devided by 4 32-bit words. } ipv6_addr_t; -/** - * @brief Data type to represent IPv6 address types. - * - * @see - * RFC 4291 - * - */ -typedef enum __attribute__((packed)) { - IPV6_ADDR_TYPE_NONE, ///< address has no type/is invalid. - IPV6_ADDR_TYPE_UNICAST, ///< address is an unicast address. - IPV6_ADDR_TYPE_MULTICAST, ///< address is a multicast address. - IPV6_ADDR_TYPE_ANYCAST, ///< address is an anycast address. - IPV6_ADDR_TYPE_SOLICITED_NODE, ///< address is a solicitated node - ///< multicast address. - IPV6_ADDR_TYPE_LOOPBACK, ///< address is a loopback address. - IPV6_ADDR_TYPE_LINK_LOCAL, ///< address is a link-local address. - IPV6_ADDR_TYPE_GLOBAL ///< address is a global address. -} ipv6_addr_type_t; - /** * @brief Data type to represent an IPv6 packet header * @@ -78,7 +59,7 @@ typedef enum __attribute__((packed)) { typedef struct __attribute__((packed)) { uint8_t version_trafficclass; ///< Version field + first 4 bit of Traffic Class. uint8_t trafficclass_flowlabel; ///< last 4 bit of Traffic Class - ///< and first 4 bit of Flow Label. + ///< and first 4 bit of Flow Label. uint16_t flowlabel; ///< last 16 bit of Flow Label. uint16_t length; ///< payload length of this packet. uint8_t nextheader; ///< type of next header in this packet. diff --git a/sys/net/network_layer/sixlowpan/border/border.h b/sys/net/network_layer/sixlowpan/border/border.h index f9a7d0c9a5f7..fbdfe95be50d 100644 --- a/sys/net/network_layer/sixlowpan/border/border.h +++ b/sys/net/network_layer/sixlowpan/border/border.h @@ -29,7 +29,7 @@ #include "ip.h" #include "semaphore.h" -extern ipv6_addr_t abr_addr; +extern ipv6_addr_t *abr_addr; uint16_t border_get_serial_reader(void); diff --git a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c index 3cd0ed2b3890..1d113872eeea 100644 --- a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c +++ b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c @@ -77,7 +77,7 @@ void demultiplex(border_packet_t *packet) context->context.lifetime ); mutex_unlock(&lowpan_context_mutex); - abr_add_context(context->context.version, &abr_addr, context->context.cid); + abr_add_context(context->context.version, abr_addr, context->context.cid); /* Send router advertisement */ break; } @@ -141,7 +141,7 @@ int readpacket(uint8_t *packet_buf, size_t size) break; } - if ((size_t) (line_buf_ptr - packet_buf) >= size - 1) { + if ((size_t)(line_buf_ptr - packet_buf) >= size - 1) { return -SIXLOWERROR_ARRAYFULL; } @@ -179,8 +179,8 @@ int writepacket(uint8_t *packet_buf, size_t size) { uint8_t *byte_ptr = packet_buf; - while ((size_t) (byte_ptr - packet_buf) < size) { - if ((size_t) (byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { + while ((size_t)(byte_ptr - packet_buf) < size) { + if ((size_t)(byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { return -1; } diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 69005329fe98..31952db2c8e2 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -94,6 +94,8 @@ /* default router list size */ #define DEF_RTR_LST_SIZE (3) /* geeigneten wert finden */ +#define PREFIX_BUF_LEN (NET_IF_MAX * OPT_PI_LIST_LEN) + /* extern variables */ uint8_t ipv6_ext_hdr_len = 0; @@ -102,17 +104,18 @@ uint8_t abr_count = 0; uint8_t nbr_count = 0; uint8_t def_rtr_count = 0; uint8_t rtr_sol_count = 0; -uint8_t prefix_count = 0; +uint8_t prefix_info_count = 0; +uint8_t prefix_buf_count = 0; /* datastructures */ ndp_a6br_cache_t abr_cache[ABR_CACHE_SIZE]; ndp_neighbor_cache_t nbr_cache[NBR_CACHE_SIZE]; ndp_default_router_list_t def_rtr_lst[DEF_RTR_LST_SIZE]; -ndp_prefix_list_t plist[OPT_PI_LIST_LEN]; +ndp_prefix_info_t prefix_info_buf[PREFIX_BUF_LEN]; +uint8_t prefix_buf[sizeof(ipv6_addr_t) * PREFIX_BUF_LEN]; /* pointer */ static uint8_t *llao; -addr_list_t *addr_list_ptr; static ipv6_hdr_t *ipv6_buf; static icmpv6_hdr_t *icmp_buf; @@ -137,15 +140,11 @@ ndp_default_router_list_t *def_rtr_entry; uint8_t recvd_cids[NDP_6LOWPAN_CONTEXT_MAX]; uint8_t icmpv6_opt_hdr_len = 0; uint8_t recvd_cids_len = 0; -ndp_prefix_list_t *recvd_prefixes[OPT_PI_LIST_LEN]; +ndp_prefix_info_t *recvd_prefixes[PREFIX_BUF_LEN]; uint8_t recvd_pref_len = 0; void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime); void def_rtr_lst_rem(ndp_default_router_list_t *entry); -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr); void nbr_cache_rem(ipv6_addr_t *addr); /** @@ -153,11 +152,12 @@ void nbr_cache_rem(ipv6_addr_t *addr); * configuration. * * @param[out] sllao The SLLAO to set. + * @param[in] if_id The interface to get the link-layer address from. * @param[in] type The value for the type field of the SLLAO. * @param[in] length The value for the length field of the SLLAO */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, - uint8_t length); +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length); int min(int a, int b) { @@ -239,14 +239,14 @@ static icmpv6_ndp_opt_aro_t *get_opt_aro_buf(uint8_t ext_len, uint8_t opt_len) return ((icmpv6_ndp_opt_aro_t *) &buffer[LLHDR_ICMPV6HDR_LEN + ext_len + opt_len]); } -void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REQUEST; icmp_buf->code = 0; @@ -257,35 +257,36 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REQ_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo request (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } -void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REPLY; icmp_buf->code = 0; @@ -296,23 +297,24 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REPL_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo reply (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -321,6 +323,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch void icmpv6_send_router_sol(uint8_t sllao) { uint16_t packet_length; + int if_id = 0; // TODO get this somehow ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); @@ -337,29 +340,39 @@ void icmpv6_send_router_sol(uint8_t sllao) //iface_find_src_ipaddr(&ipv6_buf->srcaddr, NDP_ADDR_STATE_PREFERRED, /* IPV6_ADDR_TYPE_MULTICAST); */ - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmpv6_opt_hdr_len = RTR_SOL_LEN; - ipv6_buf->length = HTONS(ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN); if (sllao == OPT_SLLAO) { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + - RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MIN_LEN; + } } else { packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + RTR_SOL_LEN; } + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); + icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -368,15 +381,17 @@ void recv_echo_req(void) { ipv6_buf = ipv6_get_buf(); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + - ipv6_ext_hdr_len + ECHO_REQ_LEN); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REQ_LEN; + #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo request from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -387,8 +402,8 @@ void recv_echo_req(void) } #endif - icmpv6_send_echo_reply(&ipv6_buf->srcaddr, echo_buf->id, echo_buf->seq, - echo_data_buf, data_len); + icmpv6_send_echo_reply(&ipv6_buf->srcaddr, NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), echo_data_buf, data_len); } void recv_echo_repl(void) @@ -396,14 +411,16 @@ void recv_echo_repl(void) #ifdef DEBUG_ENABLED ipv6_buf = ipv6_get_buf(); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - ICMPV6_HDR_LEN - ECHO_REPL_LEN; + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REPL_LEN; char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo reply from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -420,6 +437,7 @@ void recv_echo_repl(void) void recv_rtr_sol(void) { + int if_id = 0; // TODO, get this somehow icmpv6_opt_hdr_len = RTR_SOL_LEN; ipv6_buf = ipv6_get_buf(); @@ -431,25 +449,39 @@ void recv_rtr_sol(void) } if (llao != NULL) { + uint8_t lladdr_len; nbr_entry = ndp_neighbor_cache_search(&ipv6_buf->srcaddr); + if (opt_stllao_buf->length == 2) { + lladdr_len = 8; + } + else if (opt_stllao_buf->length == 1) { + lladdr_len = 2; + } + else { + DEBUG("Unknown length for S/TLLAO: %d * 8 Bytes.\n", opt_stllao_buf->length); + return; + } + if (nbr_entry != NULL) { - /* found neighbor in cache, update values and check long addr */ - if (memcmp(&llao[2], &nbr_entry->laddr, 8) == 0) { + /* found neighbor in cache, update values and check addr */ + if (memcmp(&llao[2], &nbr_entry->lladdr, lladdr_len) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - /* new long addr found, update */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + /* new addr found, update */ + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], lladdr_len); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } } else { /* nothing found, add neigbor into cache*/ - nbr_cache_add(&ipv6_buf->srcaddr, (ieee_802154_long_t *)&llao[2], - 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, &llao[2], lladdr_len, + 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); } } @@ -460,12 +492,6 @@ void recv_rtr_sol(void) else { icmpv6_send_router_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } - -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send router advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif } uint8_t set_opt_6co_flags(uint8_t compression_flag, uint8_t cid) @@ -495,6 +521,7 @@ lowpan_context_t *abr_get_context(ndp_a6br_cache_t *abr, uint8_t cid); void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, uint8_t sixco, uint8_t abro) { + int if_id = 0; // TODO: get this somehow uint16_t packet_length; lowpan_context_t *contexts = NULL; @@ -516,7 +543,7 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 memcpy(&ipv6_buf->destaddr, addr, 16); } - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmp_buf->type = ICMPV6_TYPE_ROUTER_ADV; icmp_buf->code = 0; @@ -537,9 +564,17 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 if (sllao == OPT_SLLAO) { /* set link layer address option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; - packet_length += OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (mtu == OPT_MTU) { @@ -638,17 +673,21 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 } if (pi == OPT_PI) { + ndp_prefix_info_t *prefix = NULL; + /* set prefix option */ - for (int i = 0; i < OPT_PI_LIST_LEN; i++) { - if (plist[i].inuse && plist[i].adv) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX && + prefix->inuse && prefix->advertisable) { opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - memcpy(&(opt_pi_buf->addr.uint8[0]), &(plist[i].addr.uint8[0]), 16); + memset(&opt_pi_buf->addr, 0, sizeof(ipv6_addr_t)); + memcpy(&opt_pi_buf->addr, &prefix->prefix_data, prefix->prefix_len); opt_pi_buf->type = OPT_PI_TYPE; opt_pi_buf->length = OPT_PI_LEN; - opt_pi_buf->prefix_length = plist[i].length; - opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1; - opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime); - opt_pi_buf->pref_ltime = HTONL(plist[i].pref_ltime); + opt_pi_buf->prefix_length = prefix->prefix_len; + opt_pi_buf->l_a_reserved1 = prefix->flags; + opt_pi_buf->val_ltime = HTONL(prefix->valid_lifetime); + opt_pi_buf->pref_ltime = HTONL(prefix->preferred_lifetime); opt_pi_buf->reserved2 = 0; packet_length += OPT_PI_HDR_LEN; icmpv6_opt_hdr_len += OPT_PI_HDR_LEN; @@ -661,10 +700,19 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 /* calculate checksum */ icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send router advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_rtr_adv(void) { + int if_id = 0; // TODO: get this somehow int8_t trigger_ns = -1; int8_t abro_found = 0; int16_t abro_version = 0; /* later replaced, just to supress warnings */ @@ -680,11 +728,19 @@ void recv_rtr_adv(void) /* update interface reachable time and retrans timer */ if (rtr_adv_buf->reachable_time != 0) { - iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_reachable_time = NTOHL(rtr_adv_buf->reachable_time); + } } if (rtr_adv_buf->retrans_timer != 0) { - iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_retrans_timer = NTOHL(rtr_adv_buf->retrans_timer); + } } def_rtr_entry = ndp_default_router_list_search(&ipv6_buf->srcaddr); @@ -737,46 +793,51 @@ void recv_rtr_adv(void) } if (opt_pi_buf->l_a_reserved1 & ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) { - addr_list_ptr = ipv6_iface_addr_prefix_eq(&opt_pi_buf->addr); + ipv6_net_if_hit_t addr_hit; - if (addr_list_ptr == NULL) { + if (!ipv6_net_if_addr_prefix_eq(&addr_hit, &opt_pi_buf->addr)) { /* 5.5.3d */ if (opt_pi_buf->val_ltime != 0) { /* iid will also be added here */ - ipv6_addr_set_by_eui64(&newaddr, + ipv6_addr_set_by_eui64(&newaddr, if_id, &opt_pi_buf->addr); /* add into address list * TODO: duplicate address detection is not * implementet yet, so all new addresse will * be added with state PREFFERED */ - ipv6_iface_add_addr(&newaddr, - IPV6_ADDR_TYPE_UNICAST, - NDP_ADDR_STATE_PREFERRED, - opt_pi_buf->val_ltime, - opt_pi_buf->pref_ltime); + ipv6_net_if_add_addr(if_id, &newaddr, + NDP_ADDR_STATE_PREFERRED, + opt_pi_buf->val_ltime, + opt_pi_buf->pref_ltime, 0); DEBUG("INFO: added address to interface\n"); trigger_ns = 1; } } else { /* 5.5.3e */ - set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); + set_remaining_time(&addr_hit.addr->preferred_lifetime, + opt_pi_buf->pref_ltime); /* 7200 = 2hours in seconds */ if (HTONL(opt_pi_buf->val_ltime) > 7200 || HTONL(opt_pi_buf->val_ltime) > - get_remaining_time(&(addr_list_ptr->val_ltime))) { - set_remaining_time(&(addr_list_ptr->val_ltime), HTONL(opt_pi_buf->val_ltime)); + get_remaining_time(&addr_hit.addr->valid_lifetime)) { + set_remaining_time(&addr_hit.addr->valid_lifetime, + HTONL(opt_pi_buf->val_ltime)); } else { /* reset valid lifetime to 2 hours */ - set_remaining_time(&(addr_list_ptr->val_ltime), 7200); + set_remaining_time(&addr_hit.addr->valid_lifetime, + 7200); } } } } - /* TODO: save found prefixes */ + ndp_add_prefix_info(if_id, &opt_pi_buf->addr, opt_pi_buf->length, + opt_pi_buf->val_ltime, opt_pi_buf->pref_ltime, + 0, opt_pi_buf->l_a_reserved1); + break; } @@ -843,11 +904,6 @@ void recv_rtr_adv(void) * * if new address was configured, set src to newaddr(gp16) */ icmpv6_send_neighbor_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &(ipv6_buf->destaddr))); -#endif } } @@ -856,6 +912,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * { uint16_t packet_length; int if_id = 0; // TODO: get this somehow + ipv6_net_if_hit_t hit; ipv6_buf = ipv6_get_buf(); ipv6_buf->version_trafficclass = IPV6_VER; @@ -883,9 +940,9 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN; - if (ipv6_iface_addr_match(targ) == NULL) { + if (!ipv6_net_if_addr_match(&hit, targ)) { if (src == NULL) { - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); } else { memcpy(&(ipv6_buf->srcaddr), src, 16); @@ -894,10 +951,17 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } } @@ -926,17 +990,25 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor solicitation to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_sol(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); llao = NULL; icmpv6_opt_hdr_len = NBR_SOL_LEN; uint8_t send_na = 0; uint8_t sllao_set = 0; - uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); /* check whick options are set, we need that because an aro @@ -971,11 +1043,13 @@ void recv_nbr_sol(void) if (nbr_entry != NULL) { switch (opt_stllao_buf->length) { case (1): { - if (memcmp(&llao[2], &(nbr_entry->saddr), 2) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 2) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->saddr, &llao[2], 2); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 2); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -984,11 +1058,13 @@ void recv_nbr_sol(void) } case (2): { - if (memcmp(&llao[2], &(nbr_entry->laddr), 8) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 8) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->laddr, &llao[2], 8); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 8); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -1003,21 +1079,21 @@ void recv_nbr_sol(void) else { switch (opt_stllao_buf->length) { case (1): { - nbr_cache_add(&ipv6_buf->srcaddr, - NULL , 0, NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, - (ieee_802154_short_t *)&llao[2]); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 2, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } case (2): { - nbr_cache_add(&ipv6_buf->srcaddr, - (ieee_802154_long_t *)&llao[2], 0, - NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 8, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } @@ -1035,6 +1111,7 @@ void recv_nbr_sol(void) * isn't unspecified - draft-ietf-6lowpan-nd-15#section-6.5 */ if (!(ipv6_addr_is_unspecified(&ipv6_buf->srcaddr)) && sllao_set == 1) { + uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); @@ -1045,10 +1122,10 @@ void recv_nbr_sol(void) if (nbr_entry == NULL) { /* create neighbor cache */ - aro_state = nbr_cache_add(&ipv6_buf->srcaddr, - &(opt_aro_buf->eui64), 0, - NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - opt_aro_buf->reg_ltime, NULL); + aro_state = ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &(opt_aro_buf->eui64), 8, 0, + NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + opt_aro_buf->reg_ltime); } else { if (memcmp(&(nbr_entry->addr.uint16[4]), @@ -1086,20 +1163,19 @@ void recv_nbr_sol(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *alist_targ, *alist_dest; + ipv6_net_if_hit_t alist_targ, alist_dest; nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len); - alist_targ = ipv6_iface_addr_match(&(nbr_sol_buf->target_addr)); - if (alist_targ != NULL) { - alist_dest = ipv6_iface_addr_match(&(ipv6_buf->destaddr)); + if (ipv6_net_if_addr_match(&alist_targ, &nbr_sol_buf->target_addr) != NULL) { + ipv6_net_if_addr_match(&alist_dest, &ipv6_buf->destaddr); - if ((memcmp(&(alist_targ->addr), &(alist_dest->addr), 16) == 0) || + if ((memcmp(alist_targ.addr->addr_data, alist_dest.addr->addr_data, 16) == 0) || ipv6_addr_is_solicited_node(&ipv6_buf->destaddr)) { memcpy(&(ipv6_buf->destaddr.uint8[0]), - &(ipv6_buf->srcaddr.uint8[0]), 16); + &(ipv6_buf->srcaddr.uint8[0]), sizeof(ipv6_addr_t)); memcpy(&(ipv6_buf->srcaddr.uint8[0]), - &(nbr_sol_buf->target_addr.uint8[0]), 16); + &(nbr_sol_buf->target_addr.uint8[0]), sizeof(ipv6_addr_t)); send_na = 1; } } @@ -1108,12 +1184,7 @@ void recv_nbr_sol(void) /* solicited na */ uint8_t flags = (ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE | ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED); icmpv6_send_neighbor_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), - &(alist_targ->addr), flags, 0, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif + alist_targ.addr->addr_data, flags, 0, OPT_ARO); } } @@ -1135,8 +1206,13 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->type = ICMPV6_TYPE_NEIGHBOR_ADV; icmp_buf->code = 0; - memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); - memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + if (&ipv6_buf->destaddr != dst) { + memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); + } + + if (&ipv6_buf->srcaddr != src) { + memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + } nbr_adv_buf = get_nbr_adv_buf(ipv6_ext_hdr_len); nbr_adv_buf->rso = rso; @@ -1149,10 +1225,17 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (aro == OPT_ARO) { @@ -1180,12 +1263,21 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_adv(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); - uint16_t packet_length = IPV6_HDR_LEN + ipv6_buf->length; + uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); icmpv6_opt_hdr_len = NBR_ADV_LEN; llao = NULL; nbr_entry = NULL; @@ -1211,16 +1303,16 @@ void recv_nbr_adv(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *addr; - addr = ipv6_iface_addr_match(&nbr_adv_buf->target_addr); + ipv6_net_if_hit_t hit; - if (addr == NULL) { + if (ipv6_net_if_addr_match(&hit, &nbr_adv_buf->target_addr) == NULL) { nbr_entry = ndp_neighbor_cache_search(&nbr_adv_buf->target_addr); if (nbr_entry != NULL) { if (llao != 0) { - /* TODO: untersheiden zwischen short und long stllao option */ - new_ll = memcmp(&llao[2], &(nbr_entry->laddr), 8); + new_ll = memcmp(&llao[2], &(nbr_entry->lladdr), + nbr_entry->lladdr_len); + ((icmpv6_ndp_opt_stllao_t *)llao)->length = nbr_entry->lladdr_len / 8 + 1; } if (nbr_entry->state == NDP_NCE_STATUS_INCOMPLETE) { @@ -1228,8 +1320,19 @@ void recv_nbr_adv(void) return; } - /* TODO: untersheiden zwischen short und long stllao option */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else { + return; + } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { nbr_entry->state = NDP_NCE_STATUS_REACHABLE; @@ -1254,7 +1357,19 @@ void recv_nbr_adv(void) (!(nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE) && llao != 0 && !new_ll)) { if (llao != 0) { - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + } + else { + return; + } + + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { @@ -1274,7 +1389,8 @@ void recv_nbr_adv(void) } /* link-layer address option - RFC4861 section 4.6.1/ RFC4944 8. */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t length) +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length) { sllao->type = type; sllao->length = length; @@ -1284,17 +1400,34 @@ void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t /* get link layer address */ switch (length) { case (1): { - memcpy(&llao[2], &(iface.saddr), 2); - memset(&llao[4], 0, 4); - break; + uint16_t addr = net_if_get_hardware_address(if_id); + + if (addr != 0) { + addr = HTONS(addr); + memcpy(&llao[2], &addr, 2); + memset(&llao[4], 0, 4); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } case (2): { - memcpy(&llao[2], &(iface.laddr), 8); - memset(&llao[10], 0, 6); - break; + net_if_eui64_t addr; + + if (net_if_get_eui64(&addr, if_id, 0)) { + memcpy(&llao[2], &addr, 8); + memset(&llao[10], 0, 6); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } + SET_SLLAO_DEFAULT: + default: { printf("ERROR: llao not set\n"); break; @@ -1350,6 +1483,14 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send parameter problem to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } //------------------------------------------------------------------------------ @@ -1368,21 +1509,64 @@ ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr) return NULL; } -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr) +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr) +{ + ndp_neighbor_cache_t *nce = ndp_neighbor_cache_search(ipaddr); + + if (nce == NULL || nce->type == NDP_NCE_TYPE_GC || + nce->state == NDP_NCE_STATUS_INCOMPLETE) { + // TODO: send neighbor solicitation, wait, and recheck cache + return NULL; + } + + return nce; +} + +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr) +{ + ndp_prefix_info_t *pi; + ndp_neighbor_cache_t *nce; + int if_id = -1; + + if (ipv6_addr_is_link_local(dest_addr)) { + return 1; + } + + if ((nce = ndp_neighbor_cache_search(dest_addr))) { + return 1; + } + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if ((pi = ndp_prefix_info_search(if_id, dest_addr, 128))) { + return (pi->flags & ICMPV6_NDP_OPT_PI_FLAG_ON_LINK) != 0; + } + } + + /* TODO Other cases (http://tools.ietf.org/html/rfc4861#page-6): + * * neighboring router specifies address as target of + * redircect message + * * neighbor discovery message is received from address. + */ + + return 0; +} + +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime) { (void) ltime; - (void) saddr; if (nbr_count == NBR_CACHE_SIZE) { printf("ERROR: neighbor cache full\n"); return NDP_OPT_ARO_STATE_NBR_CACHE_FULL; } + nbr_cache[nbr_count].if_id = if_id; memcpy(&(nbr_cache[nbr_count].addr), ipaddr, 16); - memcpy(&(nbr_cache[nbr_count].laddr), laddr, 8); + memcpy(&(nbr_cache[nbr_count].lladdr), lladdr, lladdr_len); + nbr_cache[nbr_count].lladdr_len = lladdr_len; nbr_cache[nbr_count].isrouter = isrouter; nbr_cache[nbr_count].state = state; nbr_cache[nbr_count].type = type; @@ -1572,23 +1756,115 @@ void def_rtr_lst_rem(ndp_default_router_list_t *entry) } //------------------------------------------------------------------------------ -/* prefix list functions */ +/* prefix information functions */ -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags) { - if (prefix_count == OPT_PI_LIST_LEN) { + ndp_prefix_info_t *prefix_info = ndp_prefix_info_match(if_id, prefix, + prefix_len); + + if (prefix_info) { + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); + + return SIXLOWERROR_SUCCESS; + } + + if ((prefix_info_count >= PREFIX_BUF_LEN) || + (prefix_buf_count >= sizeof(prefix_buf))) { return SIXLOWERROR_ARRAYFULL; } - else { - plist[prefix_count].inuse = 1; - plist[prefix_count].length = size; - plist[prefix_count].adv = adv_opt; - plist[prefix_count].l_a_reserved1 = l_a_reserved1; - plist[prefix_count].val_ltime = HTONL(val_ltime); - plist[prefix_count].pref_ltime = HTONL(pref_ltime); - memcpy(&(plist[prefix_count].addr.uint8[0]), &(addr->uint8[0]), 16); - return SIXLOWERROR_SUCCESS; + if (prefix_len > 128) { + prefix_len = 128; + } + + prefix_info = &prefix_info_buf[prefix_info_count]; + + if (prefix_len > 0) { + memcpy(&prefix_buf[prefix_buf_count], prefix, (prefix_len / 8) + 1); + } + + prefix_info->prefix_data = (ipv6_addr_t *) &prefix_buf[prefix_buf_count]; + prefix_buf_count += prefix_len; + + prefix_info->prefix_len = prefix_len; + prefix_info->prefix_protocol = NET_IF_L3P_IPV6_PREFIX; + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); + + if (!net_if_add_address(if_id, (net_if_addr_t *) prefix_info)) { + return SIXLOWERROR_VALUE; + } + + prefix_info_count++; + + return SIXLOWERROR_SUCCESS; +} + +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to) +{ + uint8_t best_match = 0; + ndp_prefix_info_t *prefix = NULL, *tmp = NULL; + + if (up_to > 128) { + up_to = 128; + } + + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX) { + uint8_t match = 0, len = min(up_to, prefix->prefix_len); + uint8_t byte_len = (len / 8); + + for (int i = 0; i < byte_len; i++) { + if (addr->uint8[i] != prefix->prefix_data->uint8[i]) { + break; + } + + match += 8; + } + + if (byte_len < 16) { + for (int i = len % 8; i > 0; i--) { + if (addr->uint8[byte_len] >> i != + prefix->prefix_data->uint8[byte_len] >> i) { + break; + } + + match += 1; + } + } + + if (prefix->prefix_len == 0 && match > best_match) { + tmp = prefix; + best_match = match; + } + } + } + + return tmp; +} + +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len) +{ + ndp_prefix_info_t *res = ndp_prefix_info_search(if_id, prefix, + prefix_len); + + if (res != NULL && res->prefix_len == prefix_len) { + return res; + } + else { + return NULL; } } diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index 6cb502d3fec2..a8fcf12f1533 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -42,7 +42,7 @@ enum option_types_t { OPT_DAC, }; -extern unsigned int nd_nbr_cache_rem_pid; +extern int nd_nbr_cache_rem_pid; void recv_echo_req(void); @@ -53,9 +53,6 @@ void recv_nbr_adv(void); void recv_nbr_sol(void); void nbr_cache_auto_rem(void); -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); - ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); void abr_remove_context(uint8_t cid); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 5b2e4538360f..bf7f31ddbce9 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -25,6 +25,7 @@ #include "vtimer.h" #include "mutex.h" #include "msg.h" +#include "net_help.h" #include "net_if.h" #include "sixlowpan/mac.h" @@ -32,17 +33,18 @@ #include "icmp.h" #include "lowpan.h" -#include "destiny/socket.h" #include "net_help.h" #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; #endif #include "debug.h" #define IP_PKT_RECV_BUF_SIZE (64) #define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN) +#define IPV6_NET_IF_ADDR_BUFFER_LEN (NET_IF_MAX * IPV6_NET_IF_ADDR_LIST_LEN) uint8_t ip_send_buffer[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE]; @@ -51,34 +53,79 @@ ipv6_hdr_t *ipv6_buf; icmpv6_hdr_t *icmp_buf; uint8_t *nextheader; -uint8_t iface_addr_list_count = 0; int udp_packet_handler_pid = 0; int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; +static ipv6_net_if_ext_t ipv6_net_if_ext[NET_IF_MAX]; +static ipv6_net_if_addr_t ipv6_net_if_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static ipv6_addr_t ipv6_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static uint8_t ipv6_net_if_addr_buffer_count = 0; + static uint8_t default_hop_limit = MULTIHOP_HOPLIMIT; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; -int ipv6_send_packet(ipv6_hdr_t *bytes) +int ipv6_send_packet(ipv6_hdr_t *packet) { - int if_id = 0; - uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); + uint16_t length = IPV6_HDR_LEN + NTOHS(packet->length); + ndp_neighbor_cache_t *nce; + + ipv6_net_if_get_best_src_addr(&packet->srcaddr, &packet->destaddr); - bytes->flowlabel = HTONS(bytes->flowlabel); - bytes->length = HTONS(bytes->length); + if (!ipv6_addr_is_multicast(&packet->destaddr) && + ndp_addr_is_on_link(&packet->destaddr)) { + nce = ndp_get_ll_address(&packet->destaddr); - memset(bytes, 0, BUFFER_SIZE); - memcpy(bytes + LL_HDR_LEN, bytes, offset); - if (sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, - (uint8_t *)packet, length) < 0) { - return -1; + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, + length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; } + else { + /* see if dest should be routed to a different next hop */ + if (ipv6_addr_is_multicast(&packet->destaddr)) { + /* if_id will be ignored */ + uint16_t addr = 0xffff; + return sixlowpan_lowpan_sendto(0, &addr, 2, (uint8_t *)packet, + length); + } + + if (ip_get_next_hop == NULL) { + return -1; + } + + ipv6_addr_t *dest = ip_get_next_hop(&packet->destaddr); - return length; + if (dest == NULL) { + return -1; + } + + nce = ndp_get_ll_address(&packet->destaddr); + + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; + } } ipv6_hdr_t *ipv6_get_buf_send(void) @@ -110,7 +157,6 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, const uint8_t *payload, uint16_t payload_length) { uint8_t *p_ptr; - uint16_t packet_length; if (next_header == IPV6_PROTO_NUM_TCP) { p_ptr = get_payload_buf_send(ipv6_ext_hdr_len); @@ -125,32 +171,14 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = next_header; - ipv6_buf->hoplimit = default_hop_limit; - ipv6_buf->length = payload_length; + ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT; + ipv6_buf->length = HTONS(payload_length); memcpy(&(ipv6_buf->destaddr), dest, 16); - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); memcpy(p_ptr, payload, payload_length); - packet_length = IPV6_HDR_LEN + payload_length; - - /* see if dest should be routed to a different next hop */ - if (ip_get_next_hop == NULL || ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL) { - return -1; - } - - sixlowpan_lowpan_sendto(0, &dest->uint16[4], 8, - (uint8_t *)ipv6_buf, packet_length); - - return payload_length; + return ipv6_send_packet(ipv6_buf); } void ipv6_set_default_hop_limit(uint8_t hop_limit) @@ -278,19 +306,40 @@ uint8_t ipv6_get_addr_match(const ipv6_addr_t *src, return val; } +int is_our_address(ipv6_addr_t *addr) +{ + ipv6_net_if_ext_t *net_if_ext; + ipv6_net_if_addr_t *myaddr; + uint8_t prefix, suffix; + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + net_if_ext = ipv6_net_if_get_ext(if_id); + myaddr = NULL; + prefix = net_if_ext->prefix / 8; + suffix = IPV6_ADDR_LEN - prefix; + + while ((myaddr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **) &myaddr)) != NULL) { + if ((ipv6_get_addr_match(myaddr->addr_data, addr) >= net_if_ext->prefix) && + (memcmp(&addr->uint8[prefix], &myaddr->addr_data->uint8[prefix], suffix) == 0)) { + return 1; + } + } + } + + return 0; +} + void ipv6_process(void) { msg_t m_recv_lowpan, m_send_lowpan; msg_t m_recv, m_send; - ipv6_addr_t myaddr; uint8_t i; uint16_t packet_length; msg_init_queue(ip_msg_queue, IP_PKT_RECV_BUF_SIZE); - ipv6_addr_init(&myaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, - sixlowpan_mac_get_radio_address()); - while (1) { msg_receive(&m_recv_lowpan); @@ -308,40 +357,16 @@ void ipv6_process(void) } } - /* destination is foreign address */ - if ((ipv6_get_addr_match(&myaddr, &ipv6_buf->destaddr) >= 112) && - (ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) { - packet_length = IPV6_HDR_LEN + ipv6_buf->length; - - ipv6_addr_t *dest; - - if (ip_get_next_hop == NULL) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL || --ipv6_buf->hoplimit == 0) { - continue; - } - - /* copy received packet to send buffer */ - memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); - /* send packet to node ID derived from dest IP */ - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &dest->uint16[4], - (uint8_t *)ipv6_get_buf_send(), - packet_length); - } /* destination is our address */ - else { + if (is_our_address(&ipv6_buf->destaddr)) { switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); /* checksum test*/ - if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { - printf("ERROR: wrong checksum\n"); + if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, NTOHS(ipv6_buf->length), + IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + DEBUG("ERROR: wrong checksum\n"); } icmpv6_demultiplex(icmp_buf); @@ -354,7 +379,7 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid); } else { - printf("INFO: No TCP handler registered.\n"); + DEBUG("INFO: No TCP handler registered.\n"); } break; @@ -366,14 +391,14 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid); } else { - printf("INFO: No UDP handler registered.\n"); + DEBUG("INFO: No UDP handler registered.\n"); } break; } case (IPV6_PROTO_NUM_NONE): { - printf("INFO: Packet with no Header following the IPv6 Header received.\n"); + DEBUG("INFO: Packet with no Header following the IPv6 Header received.\n"); break; } @@ -381,97 +406,205 @@ void ipv6_process(void) break; } } + /* destination is foreign address */ + else { + packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); + ndp_neighbor_cache_t *nce; + + ipv6_addr_t *dest; + + if (ip_get_next_hop == NULL) { + dest = &ipv6_buf->destaddr; + } + else { + dest = ip_get_next_hop(&ipv6_buf->destaddr); + } + + if ((dest == NULL) || ((--ipv6_buf->hoplimit) == 0)) { + continue; + } + + nce = ndp_get_ll_address(dest); + + /* copy received packet to send buffer */ + memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); + + /* send packet to node ID derived from dest IP */ + if (nce != NULL) { + sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)ipv6_get_buf_send(), + packet_length); + } + } msg_reply(&m_recv_lowpan, &m_send_lowpan); } } -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id) +{ + if (net_if_get_interface(if_id)) { + return &ipv6_net_if_ext[if_id]; + } + else { + return NULL; + } +} + +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime) + uint32_t pref_ltime, uint8_t is_anycast) { + ipv6_net_if_addr_t *addr_entry; + ipv6_net_if_hit_t hit; + if (ipv6_addr_is_unspecified(addr) == 128) { - printf("ERROR: unspecified address (::) can't be assigned to interface.\n"); - return; + DEBUG("ERROR: unspecified address (::) can't be assigned to interface.\n"); + return 0; } - if (ipv6_iface_addr_match(addr) != 0) { - return; + if (ipv6_addr_is_multicast(addr) && is_anycast) { + DEBUG("ERROR: anycast addresses must not be multicast addresses " + "(i.e. start with ff::/2)\n"); + return 0; } - if (iface_addr_list_count < IFACE_ADDR_LIST_LEN) { - memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]), - &(addr->uint8[0]), 16); - iface.addr_list[iface_addr_list_count].state = state; + if (ipv6_net_if_addr_match(&hit, addr)) { + return 1; + } + + if (ipv6_net_if_addr_buffer_count < IPV6_NET_IF_ADDR_BUFFER_LEN) { timex_t valtime = {val_ltime, 0}; timex_t preftime = {pref_ltime, 0}; timex_t now; + vtimer_now(&now); - iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime); - iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime); - iface.addr_list[iface_addr_list_count].type = type; - iface_addr_list_count++; + + ipv6_addr_t *addr_data = &ipv6_addr_buffer[ipv6_net_if_addr_buffer_count]; + memcpy(addr_data, addr, sizeof(ipv6_addr_t)); + + addr_entry = &ipv6_net_if_addr_buffer[ipv6_net_if_addr_buffer_count]; + addr_entry->addr_data = addr_data; + addr_entry->addr_len = 128; + + if (is_anycast) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_ANYCAST; + } + else if (ipv6_addr_is_multicast(addr_data)) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_MULTICAST; + } + else { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_UNICAST; + } + + addr_entry->ndp_state = state; + addr_entry->valid_lifetime = timex_add(now, valtime); + addr_entry->preferred_lifetime = timex_add(now, preftime); + addr_entry->is_anycast = is_anycast; + + ipv6_net_if_addr_buffer_count++; + + net_if_add_address(if_id, (net_if_addr_t *)addr_entry); /* Register to Solicited-Node multicast address according to RFC 4291 */ - if (type == IPV6_ADDR_TYPE_ANYCAST || type == IPV6_ADDR_TYPE_LINK_LOCAL || - type == IPV6_ADDR_TYPE_GLOBAL || type == IPV6_ADDR_TYPE_UNICAST) { + if (is_anycast || !ipv6_addr_is_multicast(addr)) { ipv6_addr_t sol_node_mcast_addr; ipv6_addr_set_solicited_node_addr(&sol_node_mcast_addr, addr); - if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) { - ipv6_iface_add_addr(&sol_node_mcast_addr, - IPV6_ADDR_TYPE_SOLICITED_NODE, - state, val_ltime, pref_ltime); + if (ipv6_net_if_addr_match(&hit, &sol_node_mcast_addr) == NULL) { + ipv6_net_if_add_addr(if_id, &sol_node_mcast_addr, state, + val_ltime, pref_ltime, 0); } } + + return 1; } + + return 0; } -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr) +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, + const ipv6_addr_t *addr) { - int i; + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 16) == 0) { - return &(iface.addr_list[i]); + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + uint8_t byte_al = addr_entry->addr_len / 8; + uint8_t mask[] = {0x00, 0x80, 0xc0, 0xe0, + 0xf0, 0xf8, 0xfc, 0xfe + }; + + if (memcmp(addr_entry->addr_data, addr, byte_al) == 0 && + (addr_entry->addr_len % 8 == 0 || + ((addr_entry->addr_data->uint8[byte_al] - addr->uint8[byte_al]) & mask[addr_entry->addr_len - (byte_al * 8)]))) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } + } } } return NULL; } -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr) +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, + ipv6_addr_t *addr) { - int i; + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 8) == 0) { - return &(iface.addr_list[i]); + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + if (memcmp(addr_entry->addr_data, &addr, 8) == 0) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } + } } } return NULL; } -void ipv6_iface_print_addrs(void) -{ - for (int i = 0; i < iface_addr_list_count; i++) { - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("%s\n", ipv6_addr_to_str(addr_str, - &(iface.addr_list[i].addr))); - } -} +/* TODO ipv6_net_if_hit_t returning function similar wrapping + * ipv6_net_if_get_best_src_addr() to search on all interfaces */ -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, const ipv6_addr_t *prefix) +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix) { + uint8_t force_generation = 0; out->uint16[0] = prefix->uint16[0]; out->uint16[1] = prefix->uint16[1]; out->uint16[2] = prefix->uint16[2]; out->uint16[3] = prefix->uint16[3]; - memcpy(&(out->uint8[8]), &(iface.laddr.uint8[0]), 8); + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + force_generation = 1; + } + + if (net_if_get_eui64((net_if_eui64_t *) &out->uint8[8], if_id, + force_generation)) { +#ifdef MODULE_SIXLOWPAN + + if (!sixlowpan_lowpan_eui64_to_short_addr((net_if_eui64_t *)&out->uint8[8])) { + out->uint8[8] ^= 0x02; + } + +#else + out->uint8[8] ^= 0x02; +#endif + return out; + } + else { + return NULL; + } } void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, @@ -496,96 +629,51 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, out->uint8[bytes] = prefix->uint8[bytes] & mask; } -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0002); -} - -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = 0; - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) { /* try to find best match if dest is not mcast or link local */ - int8_t itmp = -1; + int if_id = 0; // TODO: get this somehow uint8_t tmp = 0; uint8_t bmatch = 0; + ipv6_net_if_addr_t *addr = NULL; + ipv6_net_if_addr_t *tmp_addr = NULL; if (!(ipv6_addr_is_link_local(dest)) && !(ipv6_addr_is_multicast(dest))) { - for (int i = 0; i < IFACE_ADDR_LIST_LEN; i++) { - if (iface.addr_list[i].state == NDP_ADDR_STATE_PREFERRED) { - if (!ipv6_addr_is_link_local(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_unique_local_unicast(&(iface.addr_list[i].addr))) { - tmp = ipv6_get_addr_match(dest, &(iface.addr_list[i].addr)); + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED) { + if (!ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data) && + !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { + tmp = ipv6_get_addr_match(dest, addr->addr_data); if (tmp >= bmatch) { bmatch = tmp; - itmp = i; + tmp_addr = addr; } } } } } else { - for (int j = 0; j < IFACE_ADDR_LIST_LEN; j++) { - if ((iface.addr_list[j].state == NDP_ADDR_STATE_PREFERRED) && - ipv6_addr_is_link_local(&(iface.addr_list[j].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[j].addr))) { - itmp = j; + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED && + ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data)) { + tmp_addr = addr; } } } - if (itmp == -1) { + if (tmp_addr == NULL) { memset(src, 0, 16); } else { - memcpy(src, &(iface.addr_list[itmp].addr), 16); + memcpy(src, tmp_addr->addr_data, 16); } } -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) -{ - return (ipv6_get_addr_match(a, b) == 128); -} - -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xfe80); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; -} - void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr2, uint16_t addr3, uint16_t addr4, uint16_t addr5, uint16_t addr6, uint16_t addr7) @@ -600,66 +688,6 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, out->uint16[7] = HTONS(addr7); } -int ipv6_addr_is_link_local(const ipv6_addr_t *addr) -{ - return (addr->uint16[0] == HTONS(0xfe80)); -} - -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xfc || addr->uint8[0] == 0xfd); -} - -int ipv6_addr_is_multicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xff); -} - -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint32[0] == 0) && (ipv6_addr->uint32[1] == 0) && - (ipv6_addr->uint32[2] == 0) && (ipv6_addr->uint32[3] == 0); -} - -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint8[0] == 0xFF) && - (ipv6_addr->uint8[1] == 0x02) && - (ipv6_addr->uint16[1] == 0x00) && - (ipv6_addr->uint16[2] == 0x00) && - (ipv6_addr->uint16[3] == 0x00) && - (ipv6_addr->uint16[4] == 0x00) && - (ipv6_addr->uint8[10] == 0x00) && - (ipv6_addr->uint8[11] == 0x01) && - (ipv6_addr->uint8[12] == 0xFF); -} - -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in) -{ - /* copy only the last 24-bit of the ip-address that is beeing resolved */ - ipv6_addr_out->uint16[0] = HTONS(0xff02); - ipv6_addr_out->uint16[1] = 0; - ipv6_addr_out->uint16[2] = 0; - ipv6_addr_out->uint16[3] = 0; - ipv6_addr_out->uint16[4] = 0; - ipv6_addr_out->uint16[5] = HTONS(0x0001); - ipv6_addr_out->uint8[12] = 0xff; - ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; - ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; -} - -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr) -{ - sprintf(addr_str, - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - NTOHS(ipv6_addr->uint16[0]), NTOHS(ipv6_addr->uint16[1]), - NTOHS(ipv6_addr->uint16[2]), NTOHS(ipv6_addr->uint16[3]), - NTOHS(ipv6_addr->uint16[4]), NTOHS(ipv6_addr->uint16[5]), - NTOHS(ipv6_addr->uint16[6]), NTOHS(ipv6_addr->uint16[7])); - return addr_str; -} - uint32_t get_remaining_time(timex_t *t) { timex_t now; @@ -677,22 +705,32 @@ void set_remaining_time(timex_t *t, uint32_t time) *t = timex_add(now, tmp); } -void ipv6_init_iface_as_router(void) +int ipv6_init_as_router(void) { ipv6_addr_t addr; + int if_id = -1; ipv6_addr_set_all_routers_addr(&addr); - ipv6_iface_add_addr(&addr, NDP_ADDR_STATE_PREFERRED, 0, 0, IPV6_ADDR_TYPE_MULTICAST); + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if (!ipv6_net_if_add_addr(if_id, &addr, NDP_ADDR_STATE_PREFERRED, 0, 0, + 0)) { + return 0; + } + } + + return 1; } uint8_t ipv6_is_router(void) { ipv6_addr_t addr; + ipv6_net_if_hit_t hit; ipv6_addr_set_all_routers_addr(&addr); - if (ipv6_iface_addr_match(&addr) != NULL) { + if (ipv6_net_if_addr_match(&hit, &addr) != NULL) { return 1; } @@ -741,8 +779,10 @@ uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t { uint16_t sum = 0; DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr), len, buf, proto); sum = len + proto; sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); diff --git a/sys/net/network_layer/sixlowpan/ip.h b/sys/net/network_layer/sixlowpan/ip.h index ec5ecf829140..740ef77b2238 100644 --- a/sys/net/network_layer/sixlowpan/ip.h +++ b/sys/net/network_layer/sixlowpan/ip.h @@ -25,8 +25,10 @@ #include +#include "kernel.h" #include "timex.h" #include "mutex.h" +#include "net_if.h" #include "sixlowpan/ip.h" #include "sixlowpan/types.h" @@ -39,52 +41,61 @@ #define MULTIHOP_HOPLIMIT (64) #define SIXLOWIP_MAX_REGISTERED (4) +#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN) /* extern variables */ extern uint8_t ipv6_ext_hdr_len; +extern int ip_process_pid; /* base header lengths */ #define LL_HDR_LEN (0x4) #define ICMPV6_HDR_LEN (0x4) #define IPV6_HDR_LEN (0x28) -#define IFACE_ADDR_LIST_LEN (10) // maybe to much +#define IPV6_NET_IF_ADDR_LIST_LEN (10) // maybe to much /* buffer */ extern uint8_t buffer[BUFFER_SIZE]; +extern char ip_process_buf[IP_PROCESS_STACKSIZE]; extern int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; typedef struct __attribute__((packed)) { - ipv6_addr_t addr; - ipv6_addr_type_t type; - ndp_addr_state_t state; - timex_t val_ltime; - timex_t pref_ltime; -} addr_list_t; + struct net_if_addr_t *addr_next; + struct net_if_addr_t *addr_prev; + net_if_l3p_t addr_protocol; + ipv6_addr_t *addr_data; + uint8_t addr_len; + ndp_addr_state_t ndp_state; + timex_t valid_lifetime; + timex_t preferred_lifetime; + uint8_t is_anycast; +} ipv6_net_if_addr_t; typedef struct __attribute__((packed)) { - ieee_802154_short_t saddr; - ieee_802154_long_t laddr; - addr_list_t addr_list[IFACE_ADDR_LIST_LEN]; + ipv6_net_if_addr_t *addr; + int if_id; +} ipv6_net_if_hit_t; + +typedef struct __attribute__((packed)) { + uint8_t prefix; ///< prefix length of the sub-net uint8_t adv_cur_hop_limit; uint32_t adv_reachable_time; uint32_t adv_retrans_timer; -} iface_t; - -extern iface_t iface; +} ipv6_net_if_ext_t; /* function prototypes */ -void ipv6_send_bytes(ipv6_hdr_t *bytes); +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id); + icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len); uint8_t *get_payload_buf(uint8_t ext_len); uint8_t *get_payload_buf_send(uint8_t ext_len); int icmpv6_demultiplex(const icmpv6_hdr_t *hdr); -void ipv6_init_iface_as_router(void); +int ipv6_init_as_router(void); void ipv6_process(void); -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr); -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, const ipv6_addr_t *addr); uint32_t get_remaining_time(timex_t *t); void set_remaining_time(timex_t *t, uint32_t time); diff --git a/sys/net/network_layer/sixlowpan/lowpan.h b/sys/net/network_layer/sixlowpan/lowpan.h index 38830ae9b442..e1c1af1a0029 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.h +++ b/sys/net/network_layer/sixlowpan/lowpan.h @@ -25,6 +25,7 @@ #define _SIXLOWPAN_LOWPAN_H #include "mutex.h" +#include "net_if.h" #include "vtimer.h" #include "sixlowpan/lowpan.h" @@ -42,9 +43,8 @@ typedef struct { extern uint16_t local_address; extern mutex_t lowpan_context_mutex; -void lowpan_read(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr); +void lowpan_read(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr); uint8_t lowpan_context_len(void); lowpan_context_t *lowpan_context_update(uint8_t num, const ipv6_addr_t *prefix, diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index a9a7d6fa3c11..eb1535ec8f45 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -191,15 +191,11 @@ rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp) return NULL; } -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) +uint8_t rpl_init(int if_id) { mutex_init(&rpl_send_mutex); mutex_init(&rpl_recv_mutex); - if (rpl_address == 0) { - return SIXLOWERROR_ADDRESS; - } - rpl_instances_init(); /* initialize routing table */ @@ -213,11 +209,15 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) objective_functions[0] = rpl_get_of0(); /* objective_functions[1] = rpl_get_of_ETX() */ - sixlowpan_lowpan_init(trans, rpl_address, 0); + if (!sixlowpan_lowpan_init()) { + return 0; + } + + sixlowpan_lowpan_init_interface(if_id); /* need link local prefix to query _our_ corresponding address */ ipv6_addr_t ll_address; ipv6_addr_set_link_local_prefix(&ll_address); - ipv6_iface_get_best_src_addr(&my_address, &ll_address); + ipv6_net_if_get_best_src_addr(&my_address, &ll_address); ipv6_register_rpl_handler(rpl_process_pid); /* initialize ETX-calculation if needed */ @@ -932,7 +932,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); - ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = 0; diff --git a/sys/net/routing/rpl/rpl.h b/sys/net/routing/rpl/rpl.h index 31497afc7dc1..7ab6ef1a9d5b 100644 --- a/sys/net/routing/rpl/rpl.h +++ b/sys/net/routing/rpl/rpl.h @@ -35,7 +35,7 @@ #define RPL_PKT_RECV_BUF_SIZE 16 #define RPL_PROCESS_STACKSIZE KERNEL_CONF_STACKSIZE_DEFAULT -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address); +uint8_t rpl_init(int if_id); void rpl_init_root(void); rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp); diff --git a/sys/net/routing/rpl/rpl_dodag.c b/sys/net/routing/rpl/rpl_dodag.c index 5c356f7d3c58..7689237307f0 100644 --- a/sys/net/routing/rpl/rpl_dodag.c +++ b/sys/net/routing/rpl/rpl_dodag.c @@ -357,7 +357,9 @@ void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_ran DEBUG("\tminhoprankincrease :\t%04X\n", my_dodag->minhoprankincrease); DEBUG("\tdefault_lifetime:\t%02X\n", my_dodag->default_lifetime); DEBUG("\tgrounded:\t%02X\n", my_dodag->grounded); - DEBUG("\tmy_preferred_parent:\t%s\n", ipv6_addr_to_str(addr_str, &my_dodag->my_preferred_parent->addr)); + DEBUG("\tmy_preferred_parent:\t%s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &my_dodag->my_preferred_parent->addr)); DEBUG("\tmy_preferred_parent rank\t%02X\n", my_dodag->my_preferred_parent->rank); DEBUG("\tmy_preferred_parent lifetime\t%04X\n", my_dodag->my_preferred_parent->lifetime); diff --git a/sys/net/transport_layer/destiny/socket.c b/sys/net/transport_layer/destiny/socket.c index 2d267aaad3c6..627e0462ac3d 100644 --- a/sys/net/transport_layer/destiny/socket.c +++ b/sys/net/transport_layer/destiny/socket.c @@ -121,9 +121,11 @@ void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, printf("--- %s TCP packet: ---\n", (in_or_out == INC_PACKET ? "Incoming" : "Outgoing")); printf("IPv6 Source: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr)); printf("IPv6 Dest: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr)); printf("TCP Length: %x\n", ipv6_header->length - TCP_HDR_LEN); printf("Source Port: %x, Dest. Port: %x\n", NTOHS(tcp_header->src_port), NTOHS(tcp_header->dst_port)); @@ -148,10 +150,10 @@ void print_socket(socket_t *current_socket) current_socket->type, current_socket->protocol); printf("Local address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->local_address.sin6_addr)); printf("Foreign address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->foreign_address.sin6_addr)); printf("Local Port: %u, Foreign Port: %u\n", NTOHS(current_socket->local_address.sin6_port), @@ -494,13 +496,13 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, } return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - compressed_size); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + compressed_size); #else switch_tcp_packet_byte_order(current_tcp_packet); return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - header_length * 4 + payload_length); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + header_length * 4 + payload_length); #endif } @@ -539,7 +541,7 @@ int destiny_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) current_int_tcp_socket->recv_pid = thread_getpid(); /* Local address information */ - ipv6_iface_get_best_src_addr(&src_addr, &addr->sin6_addr); + ipv6_net_if_get_best_src_addr(&src_addr, &addr->sin6_addr); set_socket_address(¤t_tcp_socket->local_address, PF_INET6, HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr); @@ -1011,7 +1013,7 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN]; memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); - ipv6_iface_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); + ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP); current_udp_packet->dst_port = to->sin6_port; @@ -1022,13 +1024,13 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, temp_ipv6_header->length = UDP_HDR_LEN + len; current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, - (uint8_t*) current_udp_packet, - UDP_HDR_LEN + len, - IPPROTO_UDP); + (uint8_t *) current_udp_packet, + UDP_HDR_LEN + len, + IPPROTO_UDP); return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, - (uint8_t *)(current_udp_packet), - NTOHS(current_udp_packet->length)); + (uint8_t *)(current_udp_packet), + NTOHS(current_udp_packet->length)); } else { return -1; diff --git a/sys/shell/commands/sc_net_if.c b/sys/shell/commands/sc_net_if.c index 790173abe24b..efd54e1dd2fa 100644 --- a/sys/shell/commands/sc_net_if.c +++ b/sys/shell/commands/sc_net_if.c @@ -23,18 +23,21 @@ #include #include -#include "destiny/socket.h" /* for AF_INET6 */ #include "inet_pton.h" #include "inet_ntop.h" #include "net_help.h" #include "net_if.h" #include "transceiver.h" +#ifndef MODULE_SIXLOWPAN #define ADDR_REGISTERED_MAX (6) #define ADDRS_LEN_MAX (16) static uint8_t addr_registered = 0; static uint8_t addrs[ADDR_REGISTERED_MAX][ADDRS_LEN_MAX]; +#else +#include "ipv6.h" +#endif void _net_if_ifconfig_add(int if_id, int argc, char **argv); void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv); @@ -45,8 +48,9 @@ void _net_if_ifconfig_set_hwaddr(int if_id, char *addr); void _net_if_ifconfig_set_pan_id(int if_id, char *pan_id); void _net_if_ifconfig_set_channel(int if_id, char *channel); void _net_if_ifconfig_create(char *transceivers_str); -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len); +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len); void _net_if_ifconfig_list(int if_id); int isnumber(char *str) @@ -335,20 +339,60 @@ void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv) type = NULL; } +#ifdef MODULE_SIXLOWPAN + ipv6_addr_t ipv6_addr; + void *addr_data = &ipv6_addr; +#else + void *addr_data = (void *)&addrs[addr_registered][0]; +#endif + addr_data_str = strtok(addr_str, "/"); addr_data_len = strtok(NULL, "/"); - if (!_net_if_ifconfig_ipv6_addr_convert(&addr, type, addr_data_str, addr_data_len)) { + if (!_net_if_ifconfig_ipv6_addr_convert(&addr, addr_data, type, + addr_data_str, addr_data_len)) { + add_usage(); + return; + } + +#ifdef MODULE_SIXLOWPAN + + if (addr.addr_protocol & NET_IF_L3P_IPV6_PREFIX) { + if (ndp_add_prefix_info(if_id, &ipv6_addr, addr.addr_len, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) != SIXLOWERROR_SUCCESS) { + add_usage(); + return; + } + } + else if (addr.addr_protocol & NET_IF_L3P_IPV6_ADDR) { + uint8_t is_anycast = 0; + + if (addr.addr_protocol & NET_IF_L3P_IPV6_ANYCAST) { + is_anycast = 1; + } + + if (!ipv6_net_if_add_addr(if_id, &ipv6_addr, NDP_ADDR_STATE_PREFERRED, + 0, 0, is_anycast)) { + add_usage(); + return; + } + } + else { add_usage(); return; } +#else + if (net_if_add_address(if_id, &addr) < 0) { add_usage(); return; } addr_registered++; +#endif } void _net_if_ifconfig_add(int if_id, int argc, char **argv) @@ -413,13 +457,21 @@ void _net_if_ifconfig_create(char *transceivers_str) static inline int _is_multicast(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_multicast((ipv6_addr_t *) addr); +#else return *addr == 0xff; +#endif } static inline int _is_link_local(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_link_local((ipv6_addr_t *) addr); +#else return (addr[0] == 0xfe && addr[1] == 0x80) || (_is_multicast(addr) && (addr[1] & 0x0f) == 2); +#endif } int _set_protocol_from_type(char *type, net_if_addr_t *addr) @@ -448,14 +500,15 @@ int _set_protocol_from_type(char *type, net_if_addr_t *addr) } } -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len) +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len) { if (addr_data_len && !isnumber(addr_data_len)) { return 0; } - addr->addr_data = (void *)&addrs[addr_registered][0]; + addr->addr_data = addr_data; if (!inet_pton(AF_INET6, addr_data_str, addr->addr_data)) { return 0; From 6c9578c02863bb11ed5645db3b8d2c64a767c6fb Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sat, 8 Feb 2014 04:22:42 +0100 Subject: [PATCH 16/19] Add sixlowpan to auto_init --- sys/auto_init/auto_init.c | 36 +++++++++++++++++-- .../network_layer/sixlowpan/border/border.c | 4 --- sys/net/routing/rpl/rpl.c | 4 --- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 5652f3ce7ac4..5b3b17b37435 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -51,6 +51,10 @@ #include "rtc.h" #endif +#ifdef MODULE_SIXLOWPAN +#include "sixlowpan.h" +#endif + #ifdef MODULE_DESTINY #include "destiny.h" #endif @@ -63,6 +67,14 @@ #define ENABLE_DEBUG (0) #include "debug.h" +#ifndef CONF_RADIO_ADDR +#define CONF_RADIO_ADDR (1) +#endif + +#ifndef CONF_PAN_ID +#define CONF_PAN_ID (0xabcd) +#endif + extern int main(void); void auto_init(void) @@ -103,6 +115,7 @@ void auto_init(void) MCI_initialize(); #endif #ifdef MODULE_NET_IF + int iface; DEBUG("Auto init net_if module.\n"); transceiver_type_t transceivers = 0; #ifdef MODULE_AT86RF231 @@ -128,13 +141,32 @@ void auto_init(void) if (transceivers != 0) { transceiver_init(transceivers); transceiver_start(); - int iface = net_if_init_interface(0, transceivers); + iface = net_if_init_interface(0, transceivers); + + if (!net_if_get_hardware_address(iface)) { + DEBUG("Auto init radio address on interface %d to 0x%04x\n", iface, CONF_RADIO_ADDR); + DEBUG("Change this value at compile time with macro CONF_RADIO_ADDR\n"); + net_if_set_hardware_address(iface, CONF_RADIO_ADDR); + } + + if (net_if_get_pan_id(iface) <= 0) { + DEBUG("Auto init PAN ID on interface %d to 0x%04x\n", iface, CONF_PAN_ID); + DEBUG("Change this value at compile time with macro CONF_PAN_ID\n"); + net_if_set_pan_id(iface, CONF_PAN_ID); + } if (iface >= 0) { - DEBUG("Interface %d initialized\n", iface); + DEBUG("Auto init interface %d\n", iface); } } + else { + iface = -1; + } +#ifdef MODULE_SIXLOWPAN + DEBUG("Auto init 6LoWPAN module.\n"); + sixlowpan_lowpan_init(); +#endif #endif #ifdef MODULE_PROFILING extern void profiling_init(void); diff --git a/sys/net/network_layer/sixlowpan/border/border.c b/sys/net/network_layer/sixlowpan/border/border.c index f478a7505fc6..2433cf61b075 100644 --- a/sys/net/network_layer/sixlowpan/border/border.c +++ b/sys/net/network_layer/sixlowpan/border/border.c @@ -142,10 +142,6 @@ int sixlowpan_lowpan_border_init(int if_id) return 0; } - if (!sixlowpan_lowpan_init()) { - return 0; - } - if (!sixlowpan_lowpan_init_interface(if_id)) { return 0; } diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index eb1535ec8f45..2d9b2701d00a 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -209,10 +209,6 @@ uint8_t rpl_init(int if_id) objective_functions[0] = rpl_get_of0(); /* objective_functions[1] = rpl_get_of_ETX() */ - if (!sixlowpan_lowpan_init()) { - return 0; - } - sixlowpan_lowpan_init_interface(if_id); /* need link local prefix to query _our_ corresponding address */ ipv6_addr_t ll_address; From 3a8c1770b161fe88e0895e1706877576f8f53d3c Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 16:06:25 +0100 Subject: [PATCH 17/19] Fix apps for previous changes --- examples/rpl_udp/helper.c | 12 ++---------- examples/rpl_udp/main.c | 3 ++- examples/rpl_udp/rpl.c | 33 ++++++++++++++++++++++----------- examples/rpl_udp/udp.c | 4 +++- tests/test_pnet/main.c | 14 +++++++++----- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/examples/rpl_udp/helper.c b/examples/rpl_udp/helper.c index ff431de385cf..d5282b948e40 100644 --- a/examples/rpl_udp/helper.c +++ b/examples/rpl_udp/helper.c @@ -39,15 +39,6 @@ extern uint8_t ipv6_ext_hdr_len; msg_t msg_q[RCV_BUFFER_SIZE]; -/* prints current IPv6 adresses */ -void rpl_udp_ip(int argc, char **argv) -{ - (void) argc; - (void) argv; - - ipv6_iface_print_addrs(); -} - void rpl_udp_set_id(int argc, char **argv) { if (argc != 2) { @@ -95,7 +86,8 @@ void rpl_udp_monitor(void) else if (m.type == IPV6_PACKET_RECEIVED) { ipv6_buf = (ipv6_hdr_t *) m.content.ptr; printf("IPv6 datagram received (next header: %02X)", ipv6_buf->nextheader); - printf(" from %s ", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + printf(" from %s ", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) { icmpv6_buf = (icmpv6_hdr_t *) &ipv6_buf[(LL_HDR_LEN + IPV6_HDR_LEN) + ipv6_ext_hdr_len]; diff --git a/examples/rpl_udp/main.c b/examples/rpl_udp/main.c index 8b1258700c22..09c67d065a40 100644 --- a/examples/rpl_udp/main.c +++ b/examples/rpl_udp/main.c @@ -20,6 +20,7 @@ #include +#include "net_if.h" #include "posix_io.h" #include "shell.h" #include "shell_commands.h" @@ -37,7 +38,6 @@ const shell_command_t shell_commands[] = { {"loop", "", rpl_udp_loop}, {"server", "Starts a UDP server", udp_server}, {"send", "Send a UDP datagram", udp_send}, - {"ip", "Print all assigned IP addresses", rpl_udp_ip}, {"ign", "ignore node", rpl_udp_ignore}, {NULL, NULL, NULL} }; @@ -48,6 +48,7 @@ int main(void) /* start shell */ posix_open(uart0_handler_pid, 0); + net_if_set_src_address_mode(0, NET_IF_TRANS_ADDR_M_SHORT); shell_t shell; shell_init(&shell, shell_commands, UART0_BUFSIZE, uart0_readc, uart0_putc); diff --git a/examples/rpl_udp/rpl.c b/examples/rpl_udp/rpl.c index 8c1deda07725..13f9fdd0656e 100644 --- a/examples/rpl_udp/rpl.c +++ b/examples/rpl_udp/rpl.c @@ -22,6 +22,7 @@ #include #include "vtimer.h" #include "thread.h" +#include "net_if.h" #include "sixlowpan.h" #include "destiny.h" #include "rpl.h" @@ -64,7 +65,9 @@ void rpl_udp_init(int argc, char **argv) return; } - state = rpl_init(TRANSCEIVER, id); + net_if_set_hardware_address(0, id); + + state = rpl_init(0); if (state != SIXLOWERROR_SUCCESS) { printf("Error initializing RPL\n"); @@ -95,11 +98,13 @@ void rpl_udp_init(int argc, char **argv) ipv6_addr_t prefix, tmp; ipv6_addr_init(&std_addr, 0xABCD, 0xEF12, 0, 0, 0x1034, 0x00FF, 0xFE00, id); ipv6_addr_init_prefix(&prefix, &std_addr, 64); - plist_add(&prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1, ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); - ipv6_init_iface_as_router(); + ndp_add_prefix_info(0, &prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); + ipv6_init_as_router(); /* add global address */ - ipv6_addr_set_by_eui64(&tmp, &std_addr); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, NDP_ADDR_STATE_PREFERRED, 0, 0); + ipv6_addr_set_by_eui64(&tmp, 0, &std_addr); + ipv6_net_if_add_addr(0, &tmp, NDP_ADDR_STATE_PREFERRED, 0, 0, 0); /* set channel to 10 */ tcmd.transceivers = TRANSCEIVER; @@ -134,7 +139,8 @@ void rpl_udp_loop(int argc, char **argv) if (!is_root) { printf("my preferred parent:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->my_preferred_parent->addr))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->my_preferred_parent->addr))); printf("parent lifetime: %d\n", mydodag->my_preferred_parent->lifetime); } @@ -142,9 +148,11 @@ void rpl_udp_loop(int argc, char **argv) for (int i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (rtable[i].used) { - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].address))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].address))); puts("next hop"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].next_hop))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].next_hop))); printf("entry %d lifetime %d\n", i, rtable[i].lifetime); if (!rpl_equal_id(&rtable[i].address, &rtable[i].next_hop)) { @@ -171,7 +179,8 @@ void rpl_udp_table(int argc, char **argv) for (int i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (rtable[i].used) { - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].address))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].address))); printf("entry %d lifetime %d\n", i, rtable[i].lifetime); if (!rpl_equal_id(&rtable[i].address, &rtable[i].next_hop)) { @@ -200,12 +209,14 @@ void rpl_udp_dodag(int argc, char **argv) } printf("Part of Dodag:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->dodag_id))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->dodag_id))); printf("my rank: %d\n", mydodag->my_rank); if (!is_root) { printf("my preferred parent:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->my_preferred_parent->addr))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->my_preferred_parent->addr))); } printf("---------------------------\n"); diff --git a/examples/rpl_udp/udp.c b/examples/rpl_udp/udp.c index 286c0be0ad3d..88ef040ab8f8 100644 --- a/examples/rpl_udp/udp.c +++ b/examples/rpl_udp/udp.c @@ -128,7 +128,9 @@ void udp_send(int argc, char **argv) printf("Error sending packet!\n"); } else { - printf("Successful deliverd %i bytes over UDP to %s to 6LoWPAN\n", bytes_sent, ipv6_addr_to_str(addr_str, &ipaddr)); + printf("Successful deliverd %i bytes over UDP to %s to 6LoWPAN\n", + bytes_sent, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipaddr)); } destiny_socket_close(sock); diff --git a/tests/test_pnet/main.c b/tests/test_pnet/main.c index 9b523dff8f86..8cf8fcd630c6 100644 --- a/tests/test_pnet/main.c +++ b/tests/test_pnet/main.c @@ -27,7 +27,7 @@ #include #include -#include "transceiver.h" +#include "net_if.h" #include "ipv6.h" #ifdef MODULE_NATIVENET @@ -42,12 +42,13 @@ #define PORT (1234) -void init_local_address(uint16_t r_addr) +int init_local_address(uint16_t r_addr) { ipv6_addr_t std_addr; ipv6_addr_init(&std_addr, 0xabcd, 0xef12, 0, 0, 0x1034, 0x00ff, 0xfe00, - r_addr); - sixlowpan_lowpan_adhoc_init(TRANSCEIVER, &std_addr, r_addr); + 0); + return net_if_set_hardware_address(r_addr) && + sixlowpan_lowpan_adhoc_init(0, &std_addr); } int main(void) @@ -80,7 +81,10 @@ int main(void) }; char buffer[14]; - init_local_address(R_ADDR); + if (!init_local_address(R_ADDR)) { + fprintf(stderr, "Can not initialize IP for hardware address %d.", R_ADDR); + return 1; + } memcpy(buffer, "Hello, World!", 14); memcpy(&my_addr, &in6addr_any, sizeof(my_addr)); From 2c76f99f04e3e155cacd7b826935e4b3d4b7bb35 Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Thu, 20 Feb 2014 03:05:56 +0100 Subject: [PATCH 18/19] nbr_cache_auto_rem does not need an extra thread --- sys/net/network_layer/sixlowpan/lowpan.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index a4f54979a6fe..d81a81ea54c8 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -1796,13 +1796,7 @@ int sixlowpan_lowpan_init(void) return 0; } - nd_nbr_cache_rem_pid = thread_create(nc_buf, NC_STACKSIZE, - PRIORITY_MAIN - 1, CREATE_STACKTEST, - nbr_cache_auto_rem, "nbr_cache_rem"); - - if (nd_nbr_cache_rem_pid < 0) { - return 0; - } + nbr_cache_auto_rem(); contexts_rem_pid = thread_create(con_buf, CON_STACKSIZE, PRIORITY_MAIN + 1, CREATE_STACKTEST, From bdced318bccfb3679dd9e4a08743d98a0155d12a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 27 Feb 2014 00:10:16 +0100 Subject: [PATCH 19/19] Eliminate side effects in icmpv6_csum and make it public --- sys/net/include/sixlowpan/icmp.h | 11 ++++++++ sys/net/network_layer/sixlowpan/icmp.c | 32 ++++++++++-------------- sys/net/network_layer/sixlowpan/icmp.h | 2 -- sys/net/network_layer/sixlowpan/lowpan.c | 12 ++++----- sys/net/routing/rpl/rpl.c | 3 +-- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/sys/net/include/sixlowpan/icmp.h b/sys/net/include/sixlowpan/icmp.h index 97b08791aa67..4f21e90e7996 100644 --- a/sys/net/include/sixlowpan/icmp.h +++ b/sys/net/include/sixlowpan/icmp.h @@ -232,5 +232,16 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt, uint8_t rso, uint8_t sllao, uint8_t aro); +/** + * @brief Calculates the checksum for ICMPv6 packets. + * + * @param[in] ipv6_buf The initialized IPv6 header of the packet. + * @param[in] icmpv6_buf The initialized ICMPv6_header of the packet + * (except checksum, payload is expected directly + * after the packet header in memory). + * + * @return The internet checksum of the given ICMPv6 packet. + */ +uint16_t icmpv6_csum(ipv6_hdr_t *ipv6_buf, icmpv6_hdr_t *icmpv6_buf); /** @} */ #endif /* SIXLOWPAN_ICMP_H */ diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 31952db2c8e2..f02b96ef48da 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -267,8 +267,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -307,8 +306,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ui ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -365,8 +363,7 @@ void icmpv6_send_router_sol(uint8_t sllao) ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -698,8 +695,7 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); /* calculate checksum */ - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -988,8 +984,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -1261,8 +1256,7 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -1435,17 +1429,18 @@ void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, } } -uint16_t icmpv6_csum(uint8_t proto) +uint16_t icmpv6_csum(ipv6_hdr_t *ipv6_buf, icmpv6_hdr_t *icmpv6_buf) { - ipv6_buf = ipv6_get_buf(); uint16_t sum; uint16_t len = NTOHS(ipv6_buf->length); - sum = len + proto; + + icmpv6_buf->checksum = 0; + sum = len + IPV6_PROTO_NUM_ICMPV6; sum = csum(sum, (uint8_t *)&ipv6_buf->srcaddr, 2 * sizeof(ipv6_addr_t)); - sum = csum(sum, (uint8_t *)get_icmpv6_buf(0), len); + sum = csum(sum, (uint8_t *)icmpv6_buf, len); - return (sum == 0) ? 0xffff : HTONS(sum); + return (sum == 0) ? 0 : ~HTONS(sum); } @@ -1481,8 +1476,7 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index a8fcf12f1533..a1fcf2f12ba0 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -56,6 +56,4 @@ void nbr_cache_auto_rem(void); ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); void abr_remove_context(uint8_t cid); - -uint16_t icmpv6_csum(uint8_t proto); #endif /* _SIXLOWPAN_ICMP_H*/ diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index d81a81ea54c8..7946c2e93033 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -384,22 +384,22 @@ void lowpan_transfer(void) packet_length = current_buf->packet_size - 1; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if ((current_buf->packet[0] & 0xf0) == IPV6_VER && - iphc_status == LOWPAN_IPHC_DISABLE) { + else if (((current_buf->packet[0] & 0xf0) == IPV6_VER) && + (iphc_status == LOWPAN_IPHC_DISABLE)) { ipv6_buf = ipv6_get_buf(); memcpy(ipv6_buf, (current_buf->packet), current_buf->packet_size); m_send.content.ptr = (char *)ipv6_buf; packet_length = current_buf->packet_size; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if ((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH && - iphc_status == LOWPAN_IPHC_ENABLE) { + else if (((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH) && + (iphc_status == LOWPAN_IPHC_ENABLE)) { DEBUG("INFO: IPHC1 dispatch 0x%02x received, decompress\n", current_buf->packet[0]); lowpan_iphc_decoding(current_buf->packet, current_buf->packet_size, - ¤t_buf->s_addr, - ¤t_buf->d_addr); + &(current_buf->s_addr), + &(current_buf->d_addr)); ipv6_buf = ipv6_get_buf(); m_send.content.ptr = (char *) ipv6_buf; diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 2d9b2701d00a..4b76c671a21b 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -931,8 +931,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); - icmp_send_buf->checksum = 0; - icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t *) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); + icmp_send_buf->checksum = icmpv6_csum(ipv6_send_buf, icmp_send_buf); /* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the