From 1e4badf85aad8fdcd5c2784e20f7f3242d7a8f48 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Fri, 31 Jan 2014 14:36:09 +0100 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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; +}