From bc4befb4e9c4c8ff933acf4b26b1d52ffe0cc15a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Wed, 5 Feb 2014 00:12:01 +0100 Subject: [PATCH 01/13] Fix coding conventions for sixlowpan and rpl module --- sys/net/include/sixlowpan/ip.h | 4 +-- sys/net/network_layer/sixlowpan/icmp.c | 2 +- sys/net/network_layer/sixlowpan/icmp.h | 2 +- sys/net/network_layer/sixlowpan/ip.c | 22 +++++++++------ sys/net/network_layer/sixlowpan/lowpan.c | 11 +++++--- sys/net/network_layer/sixlowpan/mac.c | 17 +++++------ sys/net/routing/rpl/etx_beaconing.c | 4 +-- sys/net/routing/rpl/rpl.c | 36 ++++++++++++++++-------- sys/net/routing/rpl/rpl_dodag.c | 1 + sys/net/routing/rpl/trickle.c | 2 ++ 10 files changed, 63 insertions(+), 38 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 6f231a0c93..9b84c401bb 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -92,7 +92,7 @@ ipv6_hdr_t *ipv6_get_buf(void); * is going to try to find a route */ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, - const uint8_t *payload, uint16_t payload_length); + const uint8_t *payload, uint16_t payload_length); /** * @brief Determines if node is a router. @@ -375,7 +375,7 @@ void ipv6_iface_print_addrs(void); * * @param next_hop function that returns the next hop to reach dest */ -void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t* dest)); +void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t *dest)); /** * @brief Calculates the IPv6 upper-layer checksum. diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 0125430ea2..ffb2ed425a 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -1570,7 +1570,7 @@ void def_rtr_lst_rem(ndp_default_router_list_t *entry) /* prefix list functions */ int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) + uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) { if (prefix_count == OPT_PI_LIST_LEN) { return SIXLOWERROR_ARRAYFULL; diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index 297b18e060..6cb502d3fe 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -54,7 +54,7 @@ void recv_nbr_sol(void); void nbr_cache_auto_rem(void); int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); + uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 65553676fb..e6071d341e 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -54,7 +54,7 @@ uint8_t iface_addr_list_count = 0; int udp_packet_handler_pid = 0; int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; -ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t*) = 0; +ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; @@ -100,7 +100,7 @@ uint8_t *get_payload_buf(uint8_t ext_len) } int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, - const uint8_t *payload, uint16_t payload_length) + const uint8_t *payload, uint16_t payload_length) { uint8_t *p_ptr; uint16_t packet_length; @@ -296,7 +296,8 @@ void ipv6_process(void) (ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) { packet_length = IPV6_HDR_LEN + ipv6_buf->length; - ipv6_addr_t* dest; + ipv6_addr_t *dest; + if (ip_get_next_hop == NULL) { dest = &ipv6_buf->destaddr; } @@ -320,10 +321,12 @@ void ipv6_process(void) switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); + /* checksum test*/ - if (ipv6_csum(ipv6_buf, (uint8_t*) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { printf("ERROR: wrong checksum\n"); } + icmpv6_demultiplex(icmp_buf); break; } @@ -695,9 +698,11 @@ void ipv6_register_next_header_handler(uint8_t next_header, int pid) case (IPV6_PROTO_NUM_TCP): set_tcp_packet_handler_pid(pid); break; + case (IPV6_PROTO_NUM_UDP): set_udp_packet_handler_pid(pid); break; + default: /* TODO */ break; @@ -705,7 +710,8 @@ void ipv6_register_next_header_handler(uint8_t next_header, int pid) } /* register routing function */ -void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t* dest)) { +void ipv6_iface_set_routing_provider(ipv6_addr_t *(*next_hop)(ipv6_addr_t *dest)) +{ ip_get_next_hop = next_hop; } @@ -718,9 +724,9 @@ uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t { uint16_t sum = 0; DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), - len, buf, proto); + ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + len, buf, proto); sum = len + proto; sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); sum = csum(sum, buf, len); diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 08cd658440..1af050f709 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -180,8 +180,9 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, } /* check if packet needs to be fragmented */ - DEBUG("sixlowpan_lowpan_sendto(%s, data, %" PRIu16 "): send_packet_length: %" PRIu16 ", header_size: %" PRIu16 "\n", - sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + DEBUG("sixlowpan_lowpan_sendto(%s, data, %"PRIu16"): send_packet_length: %"PRIu16", header_size: %"PRIu16"\n", + sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + if (send_packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { uint8_t fragbuf[send_packet_length + header_size]; uint8_t remaining; @@ -642,7 +643,7 @@ void check_timeout(void) while (temp_buf != NULL) { if ((timex_uint64(now) - timex_uint64(temp_buf->timestamp)) >= LOWPAN_REAS_BUF_TIMEOUT) { printf("TIMEOUT!cur_time: %" PRIu64 ", temp_buf: %" PRIu64 "\n", timex_uint64(now), - timex_uint64(temp_buf->timestamp)); + timex_uint64(temp_buf->timestamp)); temp_buf = collect_garbage(temp_buf); } else { @@ -786,6 +787,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, else { lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_laddr, d_laddr); + if (current_buf && current_buf->packet) { /* Copy packet bytes into corresponding packet space area */ memcpy(current_buf->packet, data, length); @@ -795,6 +797,7 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, else { DEBUG("ERROR: no memory left in packet buffer!\n"); } + if (thread_getstatus(transfer_pid) == STATUS_SLEEPING) { thread_wakeup(transfer_pid); } @@ -1676,7 +1679,7 @@ void lowpan_init(transceiver_type_t trans, uint8_t r_addr, ipv6_addr_set_by_eui64(&tmp, prefix); DEBUG("%s, %d: set unique address to %s, according to prefix %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp), ipv6_addr_to_str(addr_str, prefix)); ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); + NDP_ADDR_STATE_PREFERRED, 0, 0); } DEBUG("%s, %d: set link local prefix to %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index dd7969b1ae..34c71cba6b 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -138,12 +138,13 @@ void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr) laddr->uint8[7] = sixlowpan_mac_get_radio_address(); } -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) { - sprintf(addr_str, - "%02x:%02x:%02x:%02x", - laddr->uint16[0], laddr->uint16[1], - laddr->uint16[2], laddr->uint16[3]); - return addr_str; +char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) +{ + sprintf(addr_str, + "%02x:%02x:%02x:%02x", + laddr->uint16[0], laddr->uint16[1], + laddr->uint16[2], laddr->uint16[3]); + return addr_str; } void recv_ieee802154_frame(void) @@ -238,9 +239,9 @@ void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, memcpy(&buf[hdrlen], frame.payload, frame.payload_len); /* set FCS */ /* RSSI = 0 */ - buf[frame.payload_len+hdrlen] = 0; + buf[frame.payload_len + hdrlen] = 0; /* FCS Valid = 1 / LQI Correlation Value = 0 */ - buf[frame.payload_len+hdrlen+1] = 0x80; + buf[frame.payload_len + hdrlen + 1] = 0x80; DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame.dest_pan_id, frame.src_pan_id, frame.seq_nr); p.length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; diff --git a/sys/net/routing/rpl/etx_beaconing.c b/sys/net/routing/rpl/etx_beaconing.c index 991413873a..cc16ddfb5d 100644 --- a/sys/net/routing/rpl/etx_beaconing.c +++ b/sys/net/routing/rpl/etx_beaconing.c @@ -195,7 +195,7 @@ void etx_beacon(void) packet->length = p_length; sixlowpan_mac_send_ieee802154_frame(&empty_addr, &etx_send_buf[0], - ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); + ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); etx_set_packets_received(); cur_round++; @@ -457,7 +457,7 @@ void etx_update(etx_neighbor_t *candidate) /* * Calculate the current ETX value for my link to this candidate. */ - if (d_f *d_r != 0) { + if (d_f * d_r != 0) { candidate->cur_etx = 1 / (d_f * d_r); } else { diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 24b42d5fb6..ae7bc13131 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -88,23 +88,28 @@ static uint8_t *get_rpl_send_payload_buf(uint8_t ext_len) return &(rpl_send_buffer[IPV6_HDR_LEN + ext_len]); } -static icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len) { +static icmpv6_hdr_t *get_rpl_send_icmpv6_buf(uint8_t ext_len) +{ return ((icmpv6_hdr_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ext_len])); } -static struct rpl_dio_t *get_rpl_send_dio_buf(void) { +static struct rpl_dio_t *get_rpl_send_dio_buf(void) +{ return ((struct rpl_dio_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_t *get_rpl_send_dao_buf(void) { +static struct rpl_dao_t *get_rpl_send_dao_buf(void) +{ return ((struct rpl_dao_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void) { +static struct rpl_dao_ack_t *get_rpl_send_dao_ack_buf(void) +{ return ((struct rpl_dao_ack_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dis_t *get_rpl_send_dis_buf(void) { +static struct rpl_dis_t *get_rpl_send_dis_buf(void) +{ return ((struct rpl_dis_t *) &(rpl_send_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } @@ -129,20 +134,24 @@ static ipv6_hdr_t *get_rpl_ipv6_buf(void) return ((ipv6_hdr_t *) &(rpl_buffer[0])); } -static struct rpl_dio_t *get_rpl_dio_buf(void) { +static struct rpl_dio_t *get_rpl_dio_buf(void) +{ return ((struct rpl_dio_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_t *get_rpl_dao_buf(void) { +static struct rpl_dao_t *get_rpl_dao_buf(void) +{ return ((struct rpl_dao_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } -static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void) { +static struct rpl_dao_ack_t *get_rpl_dao_ack_buf(void) +{ return ((struct rpl_dao_ack_t *) &(buffer[(LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN)])); } -static struct rpl_dis_t *get_rpl_dis_buf(void) { - return ((struct rpl_dis_t *) & (rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); +static struct rpl_dis_t *get_rpl_dis_buf(void) +{ + return ((struct rpl_dis_t *) &(rpl_buffer[IPV6_HDR_LEN + ICMPV6_HDR_LEN])); } static rpl_opt_t *get_rpl_opt_buf(uint8_t rpl_msg_len) @@ -345,6 +354,7 @@ void send_DIS(ipv6_addr_t *destination) void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, uint8_t start_index) { DEBUG("Send DAO\n"); + if (i_am_root) { return; } @@ -364,6 +374,7 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, mutex_unlock(&rpl_send_mutex); return; } + destination = &my_dodag->my_preferred_parent->addr; } @@ -664,6 +675,7 @@ void recv_rpl_dio(void) else { DEBUG("Cannot access DODAG because of DIO with infinite rank\n"); } + return; } @@ -694,7 +706,7 @@ void recv_rpl_dio(void) reset_trickletimer(); } - /* We are root, all done! */ + /* We are root, all done!*/ if (my_dodag->my_rank == ROOT_RANK) { if (rpl_dio_buf->rank != INFINITE_RANK) { trickle_increment_counter(); @@ -924,7 +936,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = 0; - icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t*) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); + icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t *) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); /* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the diff --git a/sys/net/routing/rpl/rpl_dodag.c b/sys/net/routing/rpl/rpl_dodag.c index cad23b33ca..5c356f7d3c 100644 --- a/sys/net/routing/rpl/rpl_dodag.c +++ b/sys/net/routing/rpl/rpl_dodag.c @@ -222,6 +222,7 @@ void rpl_delete_worst_parent(void) void rpl_delete_all_parents(void) { rpl_dodag_t *my_dodag = rpl_get_my_dodag(); + if (my_dodag != NULL) { my_dodag->my_preferred_parent = NULL; } diff --git a/sys/net/routing/rpl/trickle.c b/sys/net/routing/rpl/trickle.c index be0b88d167..eb98dcc4af 100644 --- a/sys/net/routing/rpl/trickle.c +++ b/sys/net/routing/rpl/trickle.c @@ -166,11 +166,13 @@ void trickle_interval_over(void) timex_normalize(&I_time); vtimer_remove(&trickle_t_timer); + if (vtimer_set_wakeup(&trickle_t_timer, t_time, timer_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } vtimer_remove(&trickle_I_timer); + if (vtimer_set_wakeup(&trickle_I_timer, I_time, interval_over_pid) != 0) { puts("[ERROR] setting Wakeup"); } From 90e946eb49016834cbb0b5b8dd87be7f8eecee09 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 07:59:02 +0100 Subject: [PATCH 02/13] Fix ieee802154_frame module --- sys/net/include/ieee802154_frame.h | 40 +++-- .../link_layer/ieee802154/ieee802154_frame.c | 145 ++++++++++++------ 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/sys/net/include/ieee802154_frame.h b/sys/net/include/ieee802154_frame.h index 42af6b5dfa..e983b1682b 100644 --- a/sys/net/include/ieee802154_frame.h +++ b/sys/net/include/ieee802154_frame.h @@ -26,23 +26,44 @@ #include /* maximum 802.15.4 header length */ -#define IEEE_802154_MAX_HDR_LEN 23 +#define IEEE_802154_MAX_HDR_LEN (23) /* ...and FCS*/ -#define IEEE_802154_FCS_LEN 2 +#define IEEE_802154_FCS_LEN (2) -#define IEEE_802154_BEACON_FRAME 0 -#define IEEE_802154_DATA_FRAME 1 -#define IEEE_802154_ACK_FRAME 2 -#define IEEE_802154_MAC_CMD_FRAME 3 +#define IEEE_802154_BEACON_FRAME (0) +#define IEEE_802154_DATA_FRAME (1) +#define IEEE_802154_ACK_FRAME (2) +#define IEEE_802154_MAC_CMD_FRAME (3) -#define IEEE_802154_SHORT_ADDR_M 2 -#define IEEE_802154_LONG_ADDR_M 3 +#define IEEE_802154_SHORT_ADDR_M (2) +#define IEEE_802154_LONG_ADDR_M (3) #define IEEE_802154_SHORT_MCAST_ADDR (0xffff) #define IEEE_802154_LONG_MCAST_ADDR {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \ 0xff, 0xff}} +/** + * @brief Transform 16-bit number from network order (big-endian) to + * little-endian byte order (as used by IEEE 802.15.4). + */ +#define NTOLES(a) (((a) >> 8) | (((a) & 0x00ff) << 8)) -#define IEEE_802154_PAN_ID 0x1234 +/** + * @brief Transform 16-bit number from little-endian byte order to network + * order (big-endian). + */ +#define LETONS(a) NTOLES(a) + +/** + * @brief Transform 16-bit number from host byte order to little-endian byte + * order (as used by IEEE 802.15.4). + */ +#define HTOLES(a) a + +/** + * @brief Transform 16-bit number from little-endian byte order to host byte + * order. + */ +#define LETOHS(a) HTOLES(a) typedef struct __attribute__((packed)) { uint8_t frame_type; @@ -84,6 +105,7 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf); uint8_t ieee802154_frame_get_hdr_len(ieee802154_frame_t *frame); uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, uint8_t len); void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame); +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len); /** @} */ #endif /* IEEE802154_IEEE802154_FRAME */ diff --git a/sys/net/link_layer/ieee802154/ieee802154_frame.c b/sys/net/link_layer/ieee802154/ieee802154_frame.c index 866cb457da..7a9e412a75 100644 --- a/sys/net/link_layer/ieee802154/ieee802154_frame.c +++ b/sys/net/link_layer/ieee802154/ieee802154_frame.c @@ -18,6 +18,13 @@ #include "ieee802154_frame.h" +#define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif +#include "debug.h" + +#define IEEE_802154_FCS_POLY (0x8408) /* x^16 + x^12 + x^5 + 1 for LSB first */ uint8_t ieee802154_hdr_ptr; uint8_t ieee802154_payload_ptr; @@ -28,16 +35,16 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Frame Control Field - 802.15.4 - 2006 - 7.2.1.1 */ uint8_t index = 0; - buf[index] = ((frame->fcf.frame_type) | - (frame->fcf.sec_enb << 3) | - (frame->fcf.frame_pend << 4) | - (frame->fcf.ack_req << 5) | - (frame->fcf.panid_comp << 6)); + buf[index] = (((frame->fcf.frame_type) & 0x07) | + ((frame->fcf.sec_enb << 3) & 0x08) | + ((frame->fcf.frame_pend << 4) & 0x10) | + ((frame->fcf.ack_req << 5) & 0x20) | + ((frame->fcf.panid_comp << 6) & 0x40)); index++; - buf[index] = ((frame->fcf.dest_addr_m << 2) | - (frame->fcf.frame_ver << 4) | - (frame->fcf.src_addr_m << 6)); + buf[index] = (((frame->fcf.dest_addr_m << 2) & 0x0c) | + ((frame->fcf.frame_ver << 4) & 0x30) | + ((frame->fcf.src_addr_m << 6) & 0xc0)); index++; @@ -55,49 +62,62 @@ uint8_t ieee802154_frame_init(ieee802154_frame_t *frame, uint8_t *buf) /* Destination Address - 802.15.4 - 2006 - 7.2.1.4 */ if (frame->fcf.dest_addr_m == 0x02) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; + buf[index] = frame->dest_addr[1]; + buf[index + 1] = frame->dest_addr[0]; index += 2; } else if (frame->fcf.dest_addr_m == 0x03) { - buf[index] = frame->dest_addr[0]; - buf[index + 1] = frame->dest_addr[1]; - buf[index + 2] = frame->dest_addr[2]; - buf[index + 3] = frame->dest_addr[3]; - buf[index + 4] = frame->dest_addr[4]; - buf[index + 5] = frame->dest_addr[5]; - buf[index + 6] = frame->dest_addr[6]; - buf[index + 7] = frame->dest_addr[7]; + buf[index] = frame->dest_addr[7]; + buf[index + 1] = frame->dest_addr[6]; + buf[index + 2] = frame->dest_addr[5]; + buf[index + 3] = frame->dest_addr[4]; + buf[index + 4] = frame->dest_addr[3]; + buf[index + 5] = frame->dest_addr[2]; + buf[index + 6] = frame->dest_addr[1]; + buf[index + 7] = frame->dest_addr[0]; index += 8; } /* Source PAN Identifier - 802.15.4 - 2006 - 7.2.1.5 */ if (!(frame->fcf.panid_comp & 0x01)) { if (frame->fcf.src_addr_m == 0x02 || frame->fcf.src_addr_m == 0x03) { - buf[index] = ((frame->src_pan_id >> 8) & 0xff); - buf[index + 1] = (frame->src_pan_id & 0xff); + buf[index + 1] = ((frame->src_pan_id >> 8) & 0xff); + buf[index] = (frame->src_pan_id & 0xff); index += 2; } } /* Source Address field - 802.15.4 - 2006 - 7.2.1.6 */ if (frame->fcf.src_addr_m == 0x02) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; + buf[index] = frame->src_addr[1]; + buf[index + 1] = frame->src_addr[0]; index += 2; } else if (frame->fcf.src_addr_m == 0x03) { - buf[index] = frame->src_addr[0]; - buf[index + 1] = frame->src_addr[1]; - buf[index + 2] = frame->src_addr[2]; - buf[index + 3] = frame->src_addr[3]; - buf[index + 4] = frame->src_addr[4]; - buf[index + 5] = frame->src_addr[5]; - buf[index + 6] = frame->src_addr[6]; - buf[index + 7] = frame->src_addr[7]; + buf[index] = frame->src_addr[7]; + buf[index + 1] = frame->src_addr[6]; + buf[index + 2] = frame->src_addr[5]; + buf[index + 3] = frame->src_addr[4]; + buf[index + 4] = frame->src_addr[3]; + buf[index + 5] = frame->src_addr[2]; + buf[index + 6] = frame->src_addr[1]; + buf[index + 7] = frame->src_addr[0]; index += 8; } +#ifdef DEBUG_ENABLED + DEBUG("INFO: IEEE 802.15.4 header initialized:\n"); + + for (size_t i = 0; i < index; i++) { + printf("%02x ", buf[i]); + + if (!((i + 1) % 16) || i == index - 1) { + printf("\n"); + } + } + +#endif + return index; } @@ -170,13 +190,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; - switch(frame->fcf.dest_addr_m) { + switch (frame->fcf.dest_addr_m) { case (0): { - printf("fcf.dest_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.dest_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->dest_addr[0] = buf[index]; frame->dest_addr[1] = buf[index + 1]; index += 2; @@ -184,14 +205,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->dest_addr[0] = buf[index]; - frame->dest_addr[1] = buf[index + 1]; - frame->dest_addr[2] = buf[index + 2]; - frame->dest_addr[3] = buf[index + 3]; - frame->dest_addr[4] = buf[index + 4]; - frame->dest_addr[5] = buf[index + 5]; - frame->dest_addr[6] = buf[index + 6]; - frame->dest_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->dest_addr[7] = buf[index]; + frame->dest_addr[6] = buf[index + 1]; + frame->dest_addr[5] = buf[index + 2]; + frame->dest_addr[4] = buf[index + 3]; + frame->dest_addr[3] = buf[index + 4]; + frame->dest_addr[2] = buf[index + 5]; + frame->dest_addr[1] = buf[index + 6]; + frame->dest_addr[0] = buf[index + 7]; index += 8; break; } @@ -202,13 +224,14 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, index += 2; } - switch(frame->fcf.src_addr_m) { + switch (frame->fcf.src_addr_m) { case (0): { - printf("fcf.src_addr_m: pan identifier/address fields empty\n"); + DEBUG("fcf.src_addr_m: pan identifier/address fields empty\n"); break; } case (2): { + /* read address in little-endian order */ frame->src_addr[0] = buf[index]; frame->src_addr[1] = buf[index + 1]; index += 2; @@ -216,14 +239,15 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, } case (3): { - frame->src_addr[0] = buf[index]; - frame->src_addr[1] = buf[index + 1]; - frame->src_addr[2] = buf[index + 2]; - frame->src_addr[3] = buf[index + 3]; - frame->src_addr[4] = buf[index + 4]; - frame->src_addr[5] = buf[index + 5]; - frame->src_addr[6] = buf[index + 6]; - frame->src_addr[7] = buf[index + 7]; + /* read address in network order */ + frame->src_addr[7] = buf[index]; + frame->src_addr[6] = buf[index + 1]; + frame->src_addr[5] = buf[index + 2]; + frame->src_addr[4] = buf[index + 3]; + frame->src_addr[3] = buf[index + 4]; + frame->src_addr[2] = buf[index + 5]; + frame->src_addr[1] = buf[index + 6]; + frame->src_addr[0] = buf[index + 7]; index += 8; break; } @@ -236,6 +260,27 @@ uint8_t ieee802154_frame_read(uint8_t *buf, ieee802154_frame_t *frame, return hdrlen; } +/* crc with lsb first */ +uint16_t ieee802154_frame_get_fcs(const uint8_t *frame, uint8_t frame_len) +{ + uint16_t r = 0; + + for (uint8_t byte = 0; byte < frame_len; ++byte) { + r ^= frame[byte]; + + for (uint8_t bit = 8; bit > 0; --bit) { + if (r & 0x0001) { + r = (r >> 1) ^ IEEE_802154_FCS_POLY; + } + else { + r = (r >> 1); + } + } + } + + return r; +} + void ieee802154_frame_print_fcf_frame(ieee802154_frame_t *frame) { printf("frame type: %02x\n" From 4e39cbdd54b9ba25ed63230e9e2666f1f275703f Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sun, 16 Feb 2014 16:08:48 +0100 Subject: [PATCH 03/13] Put 6LoWPAN border router in its own module --- Makefile.dep | 6 ++++++ sys/Makefile | 3 +++ sys/net/network_layer/sixlowpan/{ => border}/border.c | 0 sys/net/network_layer/sixlowpan/{ => border}/border.h | 0 .../network_layer/sixlowpan/{ => border}/bordermultiplex.c | 0 .../network_layer/sixlowpan/{ => border}/bordermultiplex.h | 0 sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.c | 0 sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.h | 0 sys/net/network_layer/sixlowpan/lowpan.c | 4 +++- 9 files changed, 12 insertions(+), 1 deletion(-) rename sys/net/network_layer/sixlowpan/{ => border}/border.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/border.h (100%) rename sys/net/network_layer/sixlowpan/{ => border}/bordermultiplex.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/bordermultiplex.h (100%) rename sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.c (100%) rename sys/net/network_layer/sixlowpan/{ => border}/flowcontrol.h (100%) diff --git a/Makefile.dep b/Makefile.dep index afa5b34ae1..eff649d8a4 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -79,6 +79,12 @@ ifneq (,$(filter destiny,$(USEMODULE))) endif endif +ifneq (,$(filter sixlowborder,$(USEMODULE))) + ifeq (,$(filter sixlowpan,$(USEMODULE))) + USEMODULE += sixlowpan + endif +endif + ifneq (,$(filter sixlowpan,$(USEMODULE))) ifeq (,$(filter ieee802154,$(USEMODULE))) USEMODULE += ieee802154 diff --git a/sys/Makefile b/sys/Makefile index 0614547c70..69bc1a233a 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -57,6 +57,9 @@ endif ifneq (,$(filter sixlowpan,$(USEMODULE))) DIRS += net/network_layer/sixlowpan endif +ifneq (,$(filter sixlowborder,$(USEMODULE))) + DIRS += net/network_layer/sixlowpan/border +endif ifneq (,$(filter rpl,$(USEMODULE))) DIRS += net/routing/rpl endif diff --git a/sys/net/network_layer/sixlowpan/border.c b/sys/net/network_layer/sixlowpan/border/border.c similarity index 100% rename from sys/net/network_layer/sixlowpan/border.c rename to sys/net/network_layer/sixlowpan/border/border.c diff --git a/sys/net/network_layer/sixlowpan/border.h b/sys/net/network_layer/sixlowpan/border/border.h similarity index 100% rename from sys/net/network_layer/sixlowpan/border.h rename to sys/net/network_layer/sixlowpan/border/border.h diff --git a/sys/net/network_layer/sixlowpan/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c similarity index 100% rename from sys/net/network_layer/sixlowpan/bordermultiplex.c rename to sys/net/network_layer/sixlowpan/border/bordermultiplex.c diff --git a/sys/net/network_layer/sixlowpan/bordermultiplex.h b/sys/net/network_layer/sixlowpan/border/bordermultiplex.h similarity index 100% rename from sys/net/network_layer/sixlowpan/bordermultiplex.h rename to sys/net/network_layer/sixlowpan/border/bordermultiplex.h diff --git a/sys/net/network_layer/sixlowpan/flowcontrol.c b/sys/net/network_layer/sixlowpan/border/flowcontrol.c similarity index 100% rename from sys/net/network_layer/sixlowpan/flowcontrol.c rename to sys/net/network_layer/sixlowpan/border/flowcontrol.c diff --git a/sys/net/network_layer/sixlowpan/flowcontrol.h b/sys/net/network_layer/sixlowpan/border/flowcontrol.h similarity index 100% rename from sys/net/network_layer/sixlowpan/flowcontrol.h rename to sys/net/network_layer/sixlowpan/border/flowcontrol.h diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 1af050f709..e0b6b95b59 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -36,7 +36,9 @@ #include "sixlowpan/ndp.h" #include "lowpan.h" -#include "border.h" +#ifdef MODULE_SIXLOWBORDER +#include "border/border.h" +#endif #include "ip.h" #include "icmp.h" From 78b5f2ae5d9af4aa43928d782ea8e4f458b95219 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 13:37:23 +0100 Subject: [PATCH 04/13] Decouple ICMPv6 from 6LoWPAN --- sys/net/include/sixlowpan/ip.h | 15 +++++++ .../sixlowpan/border/bordermultiplex.c | 2 +- sys/net/network_layer/sixlowpan/icmp.c | 45 ++++++++----------- sys/net/network_layer/sixlowpan/ip.c | 2 +- sys/net/routing/rpl/rpl.c | 10 ++--- 5 files changed, 38 insertions(+), 36 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 9b84c401bb..63c0cda1eb 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -94,6 +94,21 @@ ipv6_hdr_t *ipv6_get_buf(void); int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, const uint8_t *payload, uint16_t payload_length); +/** + * @brief Send an IPv6 packet defined by its header. + * + * @param[in] packet Pointer to an prepared IPv6 packet header. + * The payload is expected directly after the + * packet. + * + * @return length of payload : on success + * -1 : if no route to the given dest could be obtained + * Packet is dropped + * In case of reactive routing: routing is going + * to try to find a route + */ +int ipv6_send_packet(ipv6_hdr_t *packet); + /** * @brief Determines if node is a router. * diff --git a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c index 34e76c1b57..3cd0ed2b38 100644 --- a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c +++ b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c @@ -48,7 +48,7 @@ void demultiplex(border_packet_t *packet) switch (l3_header_buf->ethertype) { case (BORDER_ETHERTYPE_IPV6): { ipv6_hdr_t *ipv6_buf = (ipv6_hdr_t *)(((unsigned char *)packet) + sizeof(border_l3_header_t)); - ipv6_send_bytes(ipv6_buf); + ipv6_send_packet(ipv6_buf); break; } diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index ffb2ed425a..0e3fd4316b 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -35,6 +35,9 @@ #include "net_help.h" #define ENABLE_DEBUG (0) +#if ENABLE_DEBUG +#define DEBUG_ENABLED +#endif #include "debug.h" #define LLHDR_ICMPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN + ICMPV6_HDR_LEN) @@ -269,12 +272,12 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send echo request to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], (uint8_t *)ipv6_buf, packet_length); + ipv6_send_packet(ipv6_buf); } void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) @@ -308,14 +311,12 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send echo request to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } /* send router solicitation message - RFC4861 section 4.1 */ @@ -357,14 +358,12 @@ void icmpv6_send_router_sol(uint8_t sllao) icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router solicitation to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } void recv_echo_req(void) @@ -374,7 +373,7 @@ void recv_echo_req(void) char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REQ_LEN); -#ifdef ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo request from: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); @@ -396,13 +395,13 @@ void recv_echo_req(void) void recv_echo_repl(void) { +#ifdef DEBUG_ENABLED ipv6_buf = ipv6_get_buf(); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + - ipv6_ext_hdr_len + ECHO_REPL_LEN); -#ifdef ENABLE_DEBUG + size_t data_len = ipv6_buf->length - ICMPV6_HDR_LEN - ECHO_REPL_LEN; char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: received echo reply from: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); printf("\n"); @@ -416,6 +415,8 @@ void recv_echo_repl(void) } } +#else + return; #endif } @@ -462,15 +463,11 @@ void recv_rtr_sol(void) icmpv6_send_router_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router advertisment to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - IPV6_HDR_LEN + NTOHS(ipv6_buf->length)); - } uint8_t set_opt_6co_flags(uint8_t compression_flag, uint8_t cid) @@ -848,14 +845,11 @@ void recv_rtr_adv(void) * * if new address was configured, set src to newaddr(gp16) */ icmpv6_send_neighbor_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send neighbor solicitation to: %s\n", ipv6_addr_to_str(addr_str, &(ipv6_buf->destaddr))); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); } } @@ -1109,14 +1103,11 @@ void recv_nbr_sol(void) uint8_t flags = (ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE | ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED); icmpv6_send_neighbor_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), &(alist_targ->addr), flags, 0, OPT_ARO); -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send neighbor advertisment to: %s\n", ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); #endif - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &ipv6_buf->destaddr.uint16[4], - (uint8_t *)ipv6_buf, - packet_length); } } diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index e6071d341e..38fc831306 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -59,7 +59,7 @@ ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; -void ipv6_send_bytes(ipv6_hdr_t *bytes) +int ipv6_send_packet(ipv6_hdr_t *bytes) { uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index ae7bc13131..013c7258a5 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -929,7 +929,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_send_buf->flowlabel = 0; ipv6_send_buf->nextheader = next_header; ipv6_send_buf->hoplimit = MULTIHOP_HOPLIMIT; - ipv6_send_buf->length = p_len; + ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); @@ -949,9 +949,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ packet_length = IPV6_HDR_LEN + p_len; if (ipv6_addr_is_multicast(&ipv6_send_buf->destaddr)) { - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(ipv6_send_buf->destaddr.uint16[4]), - (uint8_t *)ipv6_send_buf, - packet_length); + ipv6_send_packet(ipv6_send_buf); } else { /* find appropriate next hop before sending */ @@ -972,9 +970,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ } } - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &(next_hop->uint16[4]), - (uint8_t *)ipv6_send_buf, - packet_length); + ipv6_send_packet(ipv6_buf); } } From 470d8745e95783b90d854958555cbf797e4718c0 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Mon, 17 Feb 2014 19:37:31 +0100 Subject: [PATCH 05/13] Add capability to set and get variable default hop limit --- sys/net/include/sixlowpan/ip.h | 14 ++++++++++++++ sys/net/network_layer/sixlowpan/icmp.c | 4 ++-- sys/net/network_layer/sixlowpan/ip.c | 14 +++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index 63c0cda1eb..d365a65c33 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -116,6 +116,20 @@ int ipv6_send_packet(ipv6_hdr_t *packet); */ uint8_t ipv6_is_router(void); +/** + * @brief Sets the default hop limit to use with IPv6 packets. + * + * @param[in] hop_limit The hop limit to set the default hop limit to. + */ +void ipv6_set_default_hop_limit(uint8_t hop_limit); + +/** + * @brief Gets the default hop limit that is used for IPv6 packets. + * + * @return The current default hop limit for IPv6 packets. + */ +uint8_t ipv6_get_default_hop_limit(void); + /** * @brief Registers a handler thread for incoming IP packets. * diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 0e3fd4316b..af3881bf9f 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -256,7 +256,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = IPV6_PROTO_NUM_ICMPV6; - ipv6_buf->hoplimit = 0xff; + ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); @@ -295,7 +295,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = IPV6_PROTO_NUM_ICMPV6; - ipv6_buf->hoplimit = 0xff; + ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 38fc831306..73a7566d18 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -56,6 +56,8 @@ int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; +static uint8_t default_hop_limit = MULTIHOP_HOPLIMIT; + /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; @@ -118,7 +120,7 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = next_header; - ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT; + ipv6_buf->hoplimit = default_hop_limit; ipv6_buf->length = payload_length; memcpy(&(ipv6_buf->destaddr), dest, 16); @@ -146,6 +148,16 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, return payload_length; } +void ipv6_set_default_hop_limit(uint8_t hop_limit) +{ + default_hop_limit = hop_limit; +} + +uint8_t ipv6_get_default_hop_limit(void) +{ + return default_hop_limit; +} + /* Register an upper layer thread */ uint8_t ipv6_register_packet_handler(int pid) { From 108989b65d047eeff71ed5575512e8042f6fb633 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 15:18:16 +0100 Subject: [PATCH 06/13] Use net_if in 6LoWPAN MAC layer --- sys/net/include/sixlowpan/mac.h | 83 ++--- sys/net/network_layer/sixlowpan/icmp.c | 24 +- sys/net/network_layer/sixlowpan/ip.c | 1 + sys/net/network_layer/sixlowpan/lowpan.c | 32 +- sys/net/network_layer/sixlowpan/mac.c | 368 +++++++++++++---------- sys/net/routing/rpl/etx_beaconing.c | 15 +- 6 files changed, 272 insertions(+), 251 deletions(-) diff --git a/sys/net/include/sixlowpan/mac.h b/sys/net/include/sixlowpan/mac.h index a09960d788..84dbaef90e 100644 --- a/sys/net/include/sixlowpan/mac.h +++ b/sys/net/include/sixlowpan/mac.h @@ -34,78 +34,29 @@ #define IEEE_802154_MAX_ADDR_STR_LEN (12) /** - * @brief Gets current radio transmitter address. + * @brief Send an IEEE 802.15.4 frame to a long address. * - * @return Current radio address as 8-bit value. + * @param[in] if_id The interface to send over (will be ignored if + * *mcast* is 1). + * @param[in] dest The destination address of the frame (will be + * ignored if *mcast* is 1). + * @param[in] dest_len The lengts of the destination address in byte. + * @param[in] payload The payload of the frame. + * @param[in] length The length of the payload. + * @param[in] mcast send frame as multicast frame (*addr* and *if_id* + * will be ignored). + * + * @return Length of transmitted data in byte */ -uint8_t sixlowpan_mac_get_radio_address(void); +int sixlowpan_mac_send_ieee802154_frame(int if_id, const void *dest, + uint8_t dest_len, const void *payload, uint8_t length, uint8_t mcast); /** - * @brief Sets radio transmitter address. + * @brief Initialise 6LoWPAN MAC layer and register it to interface layer * - * @param[in] addr 8-bit radio address. + * @return PID of the MAC receiver thread. */ -void sixlowpan_mac_set_radio_address(uint8_t addr); - -/** - * @brief Generates EUI-64 from IEEE 802.15.4 PAN ID and - * radio transceiver address. - * - * @param[out] laddr The EUI-64 address of this node. - */ -void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr); - -/** - * @brief Generates IEEE 802.15.4 16-bit short address from radio - * transceiver address. - * - * @param[out] saddr The IEEE 802.15.4 16-bit short address of this - * node. - */ -void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr); - -/** - * @brief Get pointer to potential EUI-64 bit of the IPv6 address. - * - * @param[in] ipaddr An IPv6 address of this node. - * - * @return The EUI-64 address of this node. - */ -ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr); - -/** - * @brief Send an IEEE 802.15.4 frame. - * - * @param[in] addr The destination address of the frame. - * @param[in] payload The payload of the frame. - * @param[in] length The length of the payload. - * @param[in] mcast send frame as multicast frame (identical to - * give a destination address of 0). - */ -void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, - const uint8_t *payload, - uint8_t length, uint8_t mcast); - -/** - * @brief Initialise 6LoWPAN MAC interface - * - * @param[in] type Type of transceiver. - */ -void sixlowpan_mac_init(transceiver_type_t type); - -/** - * @brief Converts IEEE 802.15.4 long address into string. - * Note that addr_str must allocate at least - * IEEE_802154_MAX_ADDR_STR_LEN byte (12 byte). - * - * @param[out] addr_str The IEEE 802.15.4 long address as string. Must - * allocate at least IEEE_802154_ADDR_STR_LEN byte (12 - * byte). - * @param[in] laddr IEEE 802.15.4 address to be converted. - * - * @return Pointer to addr_str. - */ -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr); +int sixlowpan_mac_init(void); /** @} */ #endif /* SIXLOWPAN_MAC_H */ diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index af3881bf9f..5d93f56bbd 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -22,15 +22,13 @@ #include #include -#include "malloc.h" #include "vtimer.h" #include "mutex.h" +#include "net_if.h" #include "sixlowpan/error.h" -#include "sixlowpan/mac.h" #include "ip.h" #include "icmp.h" -#include "lowpan.h" #include "serialnumber.h" #include "net_help.h" @@ -857,6 +855,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * uint8_t sllao, uint8_t aro) { uint16_t packet_length; + int if_id = 0; // TODO: get this somehow ipv6_buf = ipv6_get_buf(); ipv6_buf->version_trafficclass = IPV6_VER; @@ -910,7 +909,14 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * opt_aro_buf->status = 0; opt_aro_buf->reserved1 = 0; opt_aro_buf->reserved2 = 0; - memcpy(&(opt_aro_buf->eui64), sixlowpan_mac_get_eui64(src), 8); + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 1); + } + else if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 0); + } + icmpv6_opt_hdr_len += OPT_ARO_HDR_LEN; packet_length += OPT_ARO_HDR_LEN; @@ -1114,6 +1120,7 @@ void recv_nbr_sol(void) void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt, uint8_t rso, uint8_t sllao, uint8_t aro) { + int if_id = 0; // TODO: get this somehow uint16_t packet_length; ipv6_buf = ipv6_get_buf(); @@ -1156,7 +1163,14 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t opt_aro_buf->status = 0; /* TODO */ opt_aro_buf->reserved1 = 0; opt_aro_buf->reserved2 = 0; - memcpy(&(opt_aro_buf->eui64), sixlowpan_mac_get_eui64(dst), 8); + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 1); + } + else if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + net_if_get_eui64((net_if_eui64_t *) &opt_aro_buf->eui64, if_id, 0); + } + icmpv6_opt_hdr_len += OPT_ARO_HDR_LEN; packet_length += OPT_ARO_HDR_LEN; diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 73a7566d18..7616e69787 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -25,6 +25,7 @@ #include "vtimer.h" #include "mutex.h" #include "msg.h" +#include "net_if.h" #include "sixlowpan/mac.h" #include "ip.h" diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index e0b6b95b59..00a20fff94 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -159,6 +159,7 @@ void lowpan_ipv6_set_dispatch(uint8_t *data); void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, uint8_t *data, uint16_t data_len) { + int if_id = 0; uint8_t mcast = 0; ipv6_buf = (ipv6_hdr_t *) data; @@ -200,10 +201,11 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[2] = tag >> 8; fragbuf[3] = tag; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, + sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, max_frag_initial + header_size + 4, mcast); + /* subsequent fragments */ position = max_frag_initial; max_frag = ((max_frame - 5) / 8) * 8; @@ -220,9 +222,9 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[3] = tag; fragbuf[4] = position / 8; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, - max_frag + 5, mcast); + sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, + max_frame + 5, mcast); data += max_frag; position += max_frag; @@ -240,13 +242,15 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, fragbuf[3] = tag; fragbuf[4] = position / 8; - sixlowpan_mac_send_ieee802154_frame(&laddr, - (uint8_t *)&fragbuf, - remaining + 5, mcast); + if (sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + &fragbuf, remaining + 5, mcast) < 0) { + return -1; + } } else { - sixlowpan_mac_send_ieee802154_frame(&laddr, data, - send_packet_length, mcast); + return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, + data, send_packet_length, + mcast); } tag++; @@ -1649,17 +1653,13 @@ void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, void lowpan_init(transceiver_type_t trans, uint8_t r_addr, const ipv6_addr_t *prefix, int as_border) { + int if_id = 0; ipv6_addr_t tmp; short i; - /* init mac-layer and radio transceiver */ - sixlowpan_mac_init(trans); /* init interface addresses */ memset(&iface, 0, sizeof(iface_t)); - sixlowpan_mac_set_radio_address(r_addr); - sixlowpan_mac_init_802154_short_addr(&(iface.saddr)); - sixlowpan_mac_init_802154_long_addr(&(iface.laddr)); /* init lowpan context mutex */ mutex_init(&lowpan_context_mutex); @@ -1705,6 +1705,8 @@ void lowpan_init(transceiver_type_t trans, uint8_t r_addr, ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, NDP_ADDR_STATE_PREFERRED, 0, 0); + /* init mac-layer and radio transceiver */ + sixlowpan_mac_init(); if (as_border) { ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index 34c71cba6b..ab27207b31 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -24,13 +24,10 @@ #include #include -#include "ltc4150.h" -#include "hwtimer.h" #include "thread.h" #include "msg.h" #include "radio/radio.h" -#include "transceiver.h" -#include "vtimer.h" +#include "net_if.h" #include "sixlowpan/mac.h" #include "ip.h" @@ -49,110 +46,37 @@ #define RADIO_RCV_BUF_SIZE (64) #define RADIO_SENDING_DELAY (1000) +#define DEFAULT_IEEE_802154_PAN_ID (0x1234) +#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) + char radio_stack_buffer[RADIO_STACK_SIZE]; msg_t msg_q[RADIO_RCV_BUF_SIZE]; -static uint8_t r_src_addr; -uint8_t buf[PAYLOAD_SIZE]; +uint8_t lowpan_mac_buf[PAYLOAD_SIZE]; static uint8_t macdsn; -static radio_packet_t p; -static msg_t mesg; -int transceiver_type; -static transceiver_command_t tcmd; - -uint8_t sixlowpan_mac_get_radio_address(void) +static inline void mac_short_to_eui64(net_if_eui64_t *eui64, + uint16_t short_addr) { - int16_t address; - DEBUG("sixlowpan_mac_get_radio_address()\n"); - - tcmd.transceivers = transceiver_type; - tcmd.data = &address; - mesg.content.ptr = (char *)&tcmd; - mesg.type = GET_ADDRESS; - msg_send_receive(&mesg, &mesg, transceiver_pid); - - return (uint8_t)address; -} - -void sixlowpan_mac_set_radio_address(uint8_t addr) -{ - int16_t address = (int16_t)addr; - - tcmd.transceivers = transceiver_type; - tcmd.data = &address; - mesg.content.ptr = (char *)&tcmd; - mesg.type = SET_ADDRESS; - msg_send_receive(&mesg, &mesg, transceiver_pid); -} - -void set_radio_channel(uint8_t channel) -{ - int16_t chan = (int16_t)channel; - - tcmd.transceivers = transceiver_type; - tcmd.data = &chan; - mesg.content.ptr = (char *)&tcmd; - mesg.type = SET_CHANNEL; - msg_send_receive(&mesg, &mesg, transceiver_pid); -} - -void switch_to_rx(void) -{ - mesg.type = SWITCH_RX; - mesg.content.ptr = (char *) &tcmd; - tcmd.transceivers = TRANSCEIVER_CC1100; - msg_send(&mesg, transceiver_pid, 1); -} - -void sixlowpan_mac_init_802154_short_addr(ieee_802154_short_t *saddr) -{ - DEBUG("sixlowpan_mac_init_802154_short_addr(saddr=%02X)\n", *saddr); - saddr->uint8[0] = 0; - saddr->uint8[1] = sixlowpan_mac_get_radio_address(); -} - -ieee_802154_long_t *sixlowpan_mac_get_eui64(const ipv6_addr_t *ipaddr) -{ - return ((ieee_802154_long_t *) &ipaddr->uint8[8]); -} - -void sixlowpan_mac_init_802154_long_addr(ieee_802154_long_t *laddr) -{ -#ifdef DEBUG_ENABLED - char addr_str[IEEE_802154_MAX_ADDR_STR_LEN]; - sixlowpan_mac_802154_long_addr_to_str(addr_str, laddr); - DEBUG("sixlowpan_mac_init_802154_long_addr(laddr=%s)\n", addr_str); -#endif - - // 16bit Pan-ID:16-zero-bits:16-bit-short-addr = 48bit - laddr->uint16[0] = IEEE_802154_PAN_ID; - - /* RFC 4944 Section 6 / RFC 2464 Section 4 */ - laddr->uint8[0] ^= 0x02; - laddr->uint8[2] = 0; - laddr->uint8[3] = 0xFF; - laddr->uint8[4] = 0xFE; - laddr->uint8[5] = 0; - laddr->uint8[6] = 0; - laddr->uint8[7] = sixlowpan_mac_get_radio_address(); -} - -char *sixlowpan_mac_802154_long_addr_to_str(char *addr_str, const ieee_802154_long_t *laddr) -{ - sprintf(addr_str, - "%02x:%02x:%02x:%02x", - laddr->uint16[0], laddr->uint16[1], - laddr->uint16[2], laddr->uint16[3]); - return addr_str; + eui64->uint32[0] = HTONL(0x000000ff); + eui64->uint16[2] = HTONS(0xfe00); + eui64->uint16[3] = LETONS(short_addr); } void recv_ieee802154_frame(void) { msg_t m; +#if (defined(MODULE_AT86RF231) | \ + defined(MODULE_CC2420) | \ + defined(MODULE_MC1322X)) + ieee802154_packet_t *p; +#else radio_packet_t *p; - uint8_t hdrlen, length; + uint8_t hdrlen; +#endif + uint8_t length; ieee802154_frame_t frame; + net_if_eui64_t src, dst; msg_init_queue(msg_q, RADIO_RCV_BUF_SIZE); @@ -160,22 +84,84 @@ void recv_ieee802154_frame(void) msg_receive(&m); if (m.type == PKT_PENDING) { - +#if (defined(MODULE_AT86RF231) | \ + defined(MODULE_CC2420) | \ + defined(MODULE_MC1322X)) + p = (ieee802154_packet_t *) m.content.ptr; + memcpy(&frame, &p->frame, sizeof(ieee802154_frame_t)); + length = p->frame.payload_len; +#else p = (radio_packet_t *) m.content.ptr; hdrlen = ieee802154_frame_read(p->data, &frame, p->length); length = p->length - hdrlen - IEEE_802154_FCS_LEN; +#endif + +#ifdef DEBUG_ENABLED + DEBUG("INFO: Received IEEE 802.15.4. packet (length = %d):\n", length); + DEBUG("INFO: FCF:\n"); + ieee802154_frame_print_fcf_frame(&frame); + + DEBUG("Sender:"); + + for (uint8_t i = 0; i < 8; i++) { + printf("%02x ", frame.src_addr[i]); + } + + DEBUG("\n"); + + DEBUG("Receiver:"); + + for (size_t i = 0; i < 8; i++) { + printf("%02x ", frame.dest_addr[i]); + } + + DEBUG("\n"); + + DEBUG("Payload:\n"); + + for (uint8_t i = 0; i < frame.payload_len; i++) { + printf("%02x ", frame.payload[i]); + + if (!((i + 1) % 16) || i == frame.payload_len - 1) { + printf("\n"); + } + } + +#endif + + if (frame.fcf.src_addr_m == IEEE_802154_SHORT_ADDR_M) { + mac_short_to_eui64(&src, *((uint16_t *)frame.src_addr)); + } + else if (frame.fcf.src_addr_m == IEEE_802154_LONG_ADDR_M) { + memcpy(&src, frame.src_addr, 8); + } + else { + DEBUG("Unknown IEEE 802.15.4 source address mode.\n"); + continue; + } + + if (frame.fcf.dest_addr_m == IEEE_802154_SHORT_ADDR_M) { + mac_short_to_eui64(&dst, *((uint16_t *)frame.dest_addr)); + } + else if (frame.fcf.dest_addr_m == IEEE_802154_LONG_ADDR_M) { + memcpy(&dst, frame.dest_addr, 8); + } + else { + DEBUG("Unknown IEEE 802.15.4 destination address mode.\n"); + continue; + } /* deliver packet to network(6lowpan)-layer */ - lowpan_read(frame.payload, length, (ieee_802154_long_t *)&frame.src_addr, - (ieee_802154_long_t *)&frame.dest_addr); + lowpan_read(frame.payload, length, &src, &dst); + /* TODO: get interface ID somehow */ p->processing--; } else if (m.type == ENOBUFFER) { - puts("Transceiver buffer full"); + DEBUG("Transceiver buffer full"); } else { - puts("Unknown packet received"); + DEBUG("Unknown packet received"); } } } @@ -187,86 +173,158 @@ void set_ieee802154_fcf_values(ieee802154_frame_t *frame, uint8_t dest_mode, frame->fcf.sec_enb = 0; frame->fcf.frame_pend = 0; frame->fcf.ack_req = 0; - frame->fcf.panid_comp = 0; + frame->fcf.panid_comp = (frame->dest_pan_id == frame->src_pan_id); frame->fcf.frame_ver = 0; frame->fcf.src_addr_m = src_mode; frame->fcf.dest_addr_m = dest_mode; -#if ENABLE_DEBUG +#ifdef DEBUG_ENABLED ieee802154_frame_print_fcf_frame(frame); #endif } -void set_ieee802154_frame_values(ieee802154_frame_t *frame) +void set_ieee802154_frame_values(int if_id, uint16_t dest_pan, + ieee802154_frame_t *frame) { + int32_t pan_id = net_if_get_pan_id(if_id); // TODO: addresse aus ip paket auslesen und in frame einfuegen - frame->dest_pan_id = IEEE_802154_PAN_ID; - frame->src_pan_id = IEEE_802154_PAN_ID; + + if (pan_id < 0) { + frame->dest_pan_id = NTOLES(dest_pan); + frame->src_pan_id = HTOLES(DEFAULT_IEEE_802154_PAN_ID); + } + else { + frame->dest_pan_id = NTOLES(dest_pan); + frame->src_pan_id = HTOLES((uint16_t)pan_id); + } + frame->seq_nr = macdsn; macdsn++; } -void sixlowpan_mac_send_ieee802154_frame(const ieee_802154_long_t *addr, - const uint8_t *payload, - uint8_t length, uint8_t mcast) +int sixlowpan_mac_prepare_ieee802144_frame( + ieee802154_frame_t *frame, int if_id, uint16_t dest_pan, const void *dest, + uint8_t dest_len, const void *payload, uint8_t length, uint8_t mcast) { - uint16_t daddr; - /* TODO: check if dedicated response struct is necessary */ - msg_t transceiver_rsp; - r_src_addr = local_address; - mesg.type = SND_PKT; - mesg.content.ptr = (char *) &tcmd; + uint8_t src_mode = net_if_get_src_address_mode(if_id); + uint8_t dest_mode; + uint16_t *fcs; + set_ieee802154_frame_values(if_id, dest_pan, frame); - tcmd.transceivers = transceiver_type; - tcmd.data = &p; - - ieee802154_frame_t frame; - - memset(&frame, 0, sizeof(frame)); - set_ieee802154_fcf_values(&frame, IEEE_802154_LONG_ADDR_M, - IEEE_802154_LONG_ADDR_M); - set_ieee802154_frame_values(&frame); - - memcpy(&(frame.dest_addr[0]), &(addr->uint8[0]), 8); - memcpy(&(frame.src_addr[0]), &(iface.laddr.uint8[0]), 8); - - daddr = HTONS(addr->uint16[3]); - frame.payload = (uint8_t *)payload; // payload won't be changed so cast is legal. - frame.payload_len = length; - uint8_t hdrlen = ieee802154_frame_get_hdr_len(&frame); - - memset(&buf, 0, PAYLOAD_SIZE); - ieee802154_frame_init(&frame, (uint8_t *)&buf); - memcpy(&buf[hdrlen], frame.payload, frame.payload_len); - /* set FCS */ - /* RSSI = 0 */ - buf[frame.payload_len + hdrlen] = 0; - /* FCS Valid = 1 / LQI Correlation Value = 0 */ - buf[frame.payload_len + hdrlen + 1] = 0x80; - DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", buf[0], buf[1], frame.dest_pan_id, frame.src_pan_id, frame.seq_nr); - - p.length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; - - if (mcast == 0) { - p.dst = daddr; + if (dest_len == 8) { + dest_mode = IEEE_802154_LONG_ADDR_M; + } + else if (dest_len == 2) { + dest_mode = IEEE_802154_SHORT_ADDR_M; } else { - p.dst = 0; + DEBUG("Illegal IEEE 802.15.4 address for address length %d\n", dest_len); + return -1; } - p.data = buf; - msg_send_receive(&mesg, &transceiver_rsp, transceiver_pid); + set_ieee802154_fcf_values(frame, dest_mode, src_mode); - hwtimer_wait(5000); + + if (src_mode == IEEE_802154_LONG_ADDR_M) { + net_if_get_eui64((net_if_eui64_t *)&frame->src_addr[0], if_id, 0); + } + else if (src_mode == IEEE_802154_SHORT_ADDR_M) { + uint16_t src = HTONS(net_if_get_hardware_address(if_id)); + memcpy(&frame->src_addr[0], &src, 2); + } + else { + DEBUG("Illegal IEEE 802.15.4 address mode: %d\n", src_mode); + return -1; + } + + if (mcast) { + memset(&frame->dest_addr[0], 0xff, dest_len); + } + else { + memcpy(&frame->dest_addr[0], dest, dest_len); + } + + frame->payload = (uint8_t *)payload; // payload won't be changed so cast is legal. + frame->payload_len = length; + uint8_t hdrlen = ieee802154_frame_get_hdr_len(frame); + + memset(&lowpan_mac_buf, 0, PAYLOAD_SIZE); + ieee802154_frame_init(frame, (uint8_t *)&lowpan_mac_buf); + memcpy(&lowpan_mac_buf[hdrlen], frame->payload, frame->payload_len); + /* set FCS */ + fcs = (uint16_t *)&lowpan_mac_buf[frame->payload_len + hdrlen]; + *fcs = ieee802154_frame_get_fcs(lowpan_mac_buf, frame->payload_len + hdrlen); + DEBUG("IEEE802.15.4 frame - FCF: %02X %02X DPID: %02X SPID: %02X DSN: %02X\n", + lowpan_mac_buf[0], lowpan_mac_buf[1], frame->dest_pan_id, + frame->src_pan_id, frame->seq_nr); + + return hdrlen; } -void sixlowpan_mac_init(transceiver_type_t type) +int sixlowpan_mac_send_data(int if_id, + const void *dest, uint8_t dest_len, + const void *payload, + uint8_t payload_len, uint8_t mcast) +{ + if (mcast) { + return net_if_send_packet_broadcast(IEEE_802154_SHORT_ADDR_M, + payload, + payload_len); + } + else { + if (dest_len == 8) { + return net_if_send_packet_long(if_id, (net_if_eui64_t *) dest, + payload, (size_t)payload_len); + } + else if (dest_len == 2) { + return net_if_send_packet(if_id, NTOHS(*((uint16_t *)dest)), + payload, (size_t)payload_len); + } + } + + return -1; +} + +int sixlowpan_mac_send_ieee802154_frame(int if_id, + const void *dest, uint8_t dest_len, + const void *payload, + uint8_t payload_len, uint8_t mcast) +{ + if (net_if_get_interface(if_id) && + net_if_get_interface(if_id)->transceivers & IEEE802154_TRANSCEIVER) { + return sixlowpan_mac_send_data(if_id, dest, dest_len, payload, + payload_len, mcast); + } + else { + ieee802154_frame_t frame; + uint16_t dest_pan = HTONS(0xabcd); + uint8_t length; + int hdrlen = sixlowpan_mac_prepare_ieee802144_frame(&frame, if_id, + dest_pan, dest, + dest_len, payload, + payload_len, mcast); + + if (hdrlen < 0) { + return -1; + } + + length = hdrlen + frame.payload_len + IEEE_802154_FCS_LEN; + + return sixlowpan_mac_send_data(if_id, dest, dest_len, lowpan_mac_buf, + length, mcast); + } +} + +int sixlowpan_mac_init(void) { int recv_pid = thread_create(radio_stack_buffer, RADIO_STACK_SIZE, PRIORITY_MAIN - 2, CREATE_STACKTEST, recv_ieee802154_frame , "radio"); - transceiver_type = type; - transceiver_init(transceiver_type); - transceiver_start(); - transceiver_register(type, recv_pid); + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + net_if_register(if_id, recv_pid); + } macdsn = rand() % 256; + + return recv_pid; } diff --git a/sys/net/routing/rpl/etx_beaconing.c b/sys/net/routing/rpl/etx_beaconing.c index cc16ddfb5d..e60f86a1da 100644 --- a/sys/net/routing/rpl/etx_beaconing.c +++ b/sys/net/routing/rpl/etx_beaconing.c @@ -169,14 +169,6 @@ void etx_beacon(void) etx_probe_t *packet = etx_get_send_buf(); uint8_t p_length = 0; - /* - * xxx If you get a -Wmissing-braces warning here: - * A -Wmissing-braces warning at this point is a gcc-bug! - * Please delete this information once it's fixed - * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 - */ - ieee_802154_long_t empty_addr = { {0} }; - while (true) { thread_sleep(); mutex_lock(&etx_mutex); @@ -194,7 +186,10 @@ void etx_beacon(void) } packet->length = p_length; - sixlowpan_mac_send_ieee802154_frame(&empty_addr, &etx_send_buf[0], + /* will be send broadcast, so if_id and destination address will be + * ignored (see documentation) + */ + sixlowpan_mac_send_ieee802154_frame(0, NULL, 8, &etx_send_buf[0], ETX_DATA_MAXLEN + ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); etx_set_packets_received(); @@ -394,7 +389,7 @@ void etx_radio(void) ipv6_addr_t candidate_addr; ipv6_addr_set_link_local_prefix(&ll_address); - ipv6_iface_get_best_src_addr(&candidate_addr, &ll_address); + ipv6_net_if_get_best_src_addr(&candidate_addr, &ll_address); while (1) { msg_receive(&m); From c9e8adc41450a2c74debbf32228e2f4a1c1f579a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 15:54:42 +0100 Subject: [PATCH 07/13] Use net_if in 6LoWPAN layer --- sys/net/include/sixlowpan/lowpan.h | 77 +- .../network_layer/sixlowpan/border/border.c | 61 +- sys/net/network_layer/sixlowpan/ip.c | 12 +- sys/net/network_layer/sixlowpan/lowpan.c | 690 ++++++++++-------- sys/net/network_layer/sixlowpan/lowpan.h | 2 + sys/net/network_layer/sixlowpan/mac.c | 1 - 6 files changed, 489 insertions(+), 354 deletions(-) diff --git a/sys/net/include/sixlowpan/lowpan.h b/sys/net/include/sixlowpan/lowpan.h index bc0a1bdac1..67da952f77 100644 --- a/sys/net/include/sixlowpan/lowpan.h +++ b/sys/net/include/sixlowpan/lowpan.h @@ -25,6 +25,8 @@ #include #include "transceiver.h" +#include "net_help.h" +#include "net_if.h" #include "sixlowpan/types.h" /** @@ -178,26 +180,44 @@ typedef struct __attribute__((packed)) { /** - * @brief Initializes 6LoWPAN. + * @brief Initializes all addresses on an interface needed for 6LoWPAN. * - * @param[in] trans Transceiver to use with 6LoWPAN. - * @param[in] r_addr PHY layer address. - * @param[in] as_border 1 if node should act as border router, - * 0 otherwise. + * @param[in] if_id The interface to use with 6LoWPAN. + * + * @return 1 on success, 0 on failure. */ -void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr, - int as_border); +int sixlowpan_lowpan_init_interface(int if_id); /** - * @brief Initializes a 6LoWPAN router with address prefix + * @brief Checks if an EUI-64 was set from a short address. If so + * it returns this address, else 0 * - * @param[in] trans transceiver to use with 6LoWPAN. - * @param[in] prefix the address prefix to advertise. - * @param[in] r_addr PHY layer address. + * @param[in] iid An EUI-64. + * + * @return The short address on success, 0 on failure. */ -void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, - const ipv6_addr_t *prefix, - uint8_t r_addr); +static inline uint16_t sixlowpan_lowpan_eui64_to_short_addr(const net_if_eui64_t *iid) +{ + if (iid->uint32[0] == HTONL(0x000000ff) && + iid->uint16[2] == HTONS(0xfe00)) { + return NTOHS(iid->uint16[3]); + } + + return 0; +} + +/** + * @brief Initializes all addresses and prefixes on an interface needed + * for 6LoWPAN. Calling this function together with + * sixlowpan_lowpan_init_interface() is not necessary. + * + * @param[in] if_id The interface to use with 6LoWPAN. + * @param[in] prefix the address prefix to advertise. + * + * @return 1 on success, 0 on failure. + */ +int sixlowpan_lowpan_init_adhoc_interface(int if_id, + const ipv6_addr_t *prefix); /** * @brief Initializes a 6LoWPAN border router with an address @@ -205,26 +225,26 @@ void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, * @note Currently only working with addresses generated from * IEEE 802.15.4 16-bit short addresses. * - * @param[in] trans transceiver to use with 6LoWPAN. - * @param[in] border_router_addr Address of this border router. + * @param[in] if_id The interface to use with 6LoWPAN. * - * @return SIXLOWERROR_SUCCESS on success, otherwise SIXLOWERROR_ADDRESS if - * address was not generated from IEEE 802.15.4 16-bit short - * address. + * @return 1 on success, 0 on failure. */ -uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans, - const ipv6_addr_t *border_router_addr); +int sixlowpan_lowpan_border_init(int if_id); /** - * @brief Send data via 6LoWPAN to destination node dest. + * @brief Send data via 6LoWPAN to destination node or next hop dest. * - * @param[in] dest EUI-64 of destination node. + * @param[in] if_id The interface to send the data over. + * @param[in] dest Hardware address of the next hop or destination node. + * @param[in] dest_len Length of the destination address in byte. * @param[in] data Data to send to destination node (may be * manipulated). * @param[in] data_len Length of data. + * + * @return length of transmitted data on success, -1 on failure. */ -void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, - uint8_t *data, uint16_t data_len); +int sixlowpan_lowpan_sendto(int if_id, const void *dest, int dest_len, + uint8_t *data, uint16_t data_len); /** * @brief Set header compression status for 6LoWPAN. @@ -272,5 +292,12 @@ void sixlowpan_lowpan_print_fifo_buffers(void); void sixlowpan_lowpan_print_reassembly_buffers(void); #endif +/** + * @brief Initializes 6LoWPAN module. + * + * @return 1 on success, 0 on failure. + */ +int sixlowpan_lowpan_init(void); + /** @} */ #endif /* SIXLOWPAN_LOWPAN_H */ diff --git a/sys/net/network_layer/sixlowpan/border/border.c b/sys/net/network_layer/sixlowpan/border/border.c index fd84d585b5..f478a7505f 100644 --- a/sys/net/network_layer/sixlowpan/border/border.c +++ b/sys/net/network_layer/sixlowpan/border/border.c @@ -16,6 +16,7 @@ * @} */ +/* TODO: Put this in its own module */ #include #include #include @@ -37,9 +38,10 @@ #include "net_help.h" -#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define ENABLE_DEBUG (0) +#include "debug.h" -ipv6_addr_t abr_addr; +#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) char serial_reader_stack[READER_STACK_SIZE]; uint16_t serial_reader_pid; @@ -47,6 +49,8 @@ uint16_t serial_reader_pid; uint8_t serial_out_buf[BORDER_BUFFER_SIZE]; uint8_t serial_in_buf[BORDER_BUFFER_SIZE]; +ipv6_addr_t *abr_addr; + uint8_t *get_serial_out_buffer(int offset) { if (offset > BUFFER_SIZE) { @@ -120,45 +124,52 @@ void serial_reader_f(void) } } -uint8_t sixlowpan_lowpan_border_init(transceiver_type_t trans, - const ipv6_addr_t *border_router_addr) +int sixlowpan_lowpan_border_init(int if_id) { - ipv6_addr_t addr; + ipv6_net_if_addr_t *addr = NULL; + uint8_t abr_addr_initialized = 0; serial_reader_pid = thread_create( serial_reader_stack, READER_STACK_SIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, serial_reader_f, "serial_reader"); + ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + border_process_lowpan, + "border_process_lowpan"); - if (border_router_addr == NULL) { - border_router_addr = &addr; - - addr = flowcontrol_init(); + if (ip_process_pid < 0) { + return 0; } - /* only allow addresses generated accoding to - * RFC 4944 (Section 6) & RFC 2464 (Section 4) from short address - * -- for now - */ - if (border_router_addr->uint16[4] != HTONS(IEEE_802154_PAN_ID ^ 0x0200) || - border_router_addr->uint16[5] != HTONS(0x00FF) || - border_router_addr->uint16[6] != HTONS(0xFE00) - ) { - return SIXLOWERROR_ADDRESS; + if (!sixlowpan_lowpan_init()) { + return 0; } - /* radio-address is 8-bit so this must be tested extra */ - if (border_router_addr->uint8[14] != 0) { - return SIXLOWERROR_ADDRESS; + if (!sixlowpan_lowpan_init_interface(if_id)) { + return 0; } - memcpy(&(abr_addr.uint8[0]), &(border_router_addr->uint8[0]), 16); + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr)) { + if (!ipv6_addr_is_multicast(addr->addr_data) && + !ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_loopback(addr->addr_data) && + !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { + abr_addr_initialized = 1; + abr_addr = addr->addr_data; + break; + } + } - sixlowpan_lowpan_init(trans, border_router_addr->uint8[15], 1); + if (!abr_addr_initialized) { + DEBUG("sixlowpan_lowpan_border_init(): A prefix must be initialized to" + "interface %d first", if_id); + return 0; + } - ipv6_init_iface_as_router(); + ipv6_init_as_router(); - return SIXLOWERROR_SUCCESS; + return 1; } void border_process_lowpan(void) diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 7616e69787..5b2e453836 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -64,6 +64,7 @@ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; int ipv6_send_packet(ipv6_hdr_t *bytes) { + int if_id = 0; uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); bytes->flowlabel = HTONS(bytes->flowlabel); @@ -72,9 +73,12 @@ int ipv6_send_packet(ipv6_hdr_t *bytes) memset(bytes, 0, BUFFER_SIZE); memcpy(bytes + LL_HDR_LEN, bytes, offset); - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &bytes->destaddr.uint16[4], - (uint8_t *)bytes, - offset); + if (sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, + (uint8_t *)packet, length) < 0) { + return -1; + } + + return length; } ipv6_hdr_t *ipv6_get_buf_send(void) @@ -143,7 +147,7 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, return -1; } - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &dest->uint16[4], + sixlowpan_lowpan_sendto(0, &dest->uint16[4], 8, (uint8_t *)ipv6_buf, packet_length); return payload_length; diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 00a20fff94..4a5ca8e321 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -48,14 +48,14 @@ #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; #endif #include "debug.h" -#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN) -#define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) -#define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) -#define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT) #define SIXLOWPAN_MAX_REGISTERED (4) @@ -72,33 +72,42 @@ typedef struct lowpan_interval_list_t { struct lowpan_interval_list_t *next; } lowpan_interval_list_t; +/** + * @brief 6LoWPAN reassembly buffer. + * + * @see + * RFC 4944, section 5.3 + * + */ typedef struct lowpan_reas_buf_t { - /* Source Address */ - ieee_802154_long_t s_laddr; - /* Destination Address */ - ieee_802154_long_t d_laddr; - /* Identification Number */ - uint16_t ident_no; - /* Timestamp of last packet fragment */ - timex_t timestamp; - /* Size of reassembled packet with possible IPHC header */ - uint16_t packet_size; - /* Additive size of currently already received fragments */ - uint16_t current_packet_size; - /* Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte */ - uint8_t *packet; - /* Pointer to list of intervals of received packet fragments (if any) */ - lowpan_interval_list_t *interval_list_head; - /* Pointer to next reassembly buffer (if any) */ + net_if_eui64_t s_addr; ///< Source address + net_if_eui64_t d_addr; ///< Destination address + uint16_t tag; ///< Fragment tag + timex_t timestamp; ///< Timestamp of last packet fragment + /** + * @brief Size of reassembled packet with possible IPHC header + */ + uint16_t packet_size; + /** + * @brief Additive size of currently already received fragments + */ + uint16_t current_packet_size; + /** + * @brief Pointer to allocated memory for reassembled packet + 6LoWPAN + * Dispatch Byte + */ + uint8_t *packet; + /** + * @brief Pointer to list of intervals of received packet fragments + * (if any) + */ + lowpan_interval_list_t *interval_list_head; struct lowpan_reas_buf_t *next; } lowpan_reas_buf_t; extern mutex_t lowpan_context_mutex; -uint16_t tag; -uint8_t header_size = 0; -uint8_t max_frame = 0; +uint16_t tag = 0; uint8_t max_frag_initial = 0; -uint8_t position; uint8_t max_frag; static uint16_t packet_length; @@ -112,22 +121,19 @@ uint16_t comp_len; uint8_t frag_size; uint8_t reas_buf[512]; uint8_t comp_buf[512]; -uint8_t byte_offset; uint8_t first_frag = 0; mutex_t fifo_mutex; -unsigned int ip_process_pid; -unsigned int nd_nbr_cache_rem_pid = 0; -unsigned int contexts_rem_pid = 0; -unsigned int transfer_pid = 0; +int ip_process_pid = 0; +int nd_nbr_cache_rem_pid = 0; +int contexts_rem_pid = 0; +int transfer_pid = 0; -iface_t iface; -ipv6_addr_t lladdr; -ieee_802154_long_t laddr; mutex_t lowpan_context_mutex; /* registered upper layer threads */ int sixlowpan_reg[SIXLOWPAN_MAX_REGISTERED]; +static sixlowpan_lowpan_frame_t current_frame; char ip_process_buf[IP_PROCESS_STACKSIZE]; char nc_buf[NC_STACKSIZE]; @@ -137,73 +143,107 @@ lowpan_context_t contexts[NDP_6LOWPAN_CONTEXT_MAX]; uint8_t context_len = 0; uint16_t local_address = 0; -void lowpan_init(transceiver_type_t trans, uint8_t r_addr, - const ipv6_addr_t *prefix, int as_border); +int lowpan_init(int as_border); void lowpan_context_auto_remove(void); -void lowpan_iphc_encoding(ieee_802154_long_t *dest, - ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr); -void lowpan_iphc_decoding(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr); +uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, + ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr); +void lowpan_iphc_decoding(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr); void add_fifo_packet(lowpan_reas_buf_t *current_packet); lowpan_reas_buf_t *collect_garbage_fifo(lowpan_reas_buf_t *current_buf); lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf); void init_reas_bufs(lowpan_reas_buf_t *buf); void check_timeout(void); +void print_long_local_addr(net_if_eui64_t *saddr); lowpan_context_t *lowpan_context_lookup(ipv6_addr_t *addr); -void lowpan_ipv6_set_dispatch(uint8_t *data); - /* deliver packet to mac*/ -void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, - uint8_t *data, uint16_t data_len) +int sixlowpan_lowpan_sendto(int if_id, const void *dest, int dest_len, + uint8_t *data, uint16_t data_len) { - int if_id = 0; uint8_t mcast = 0; ipv6_buf = (ipv6_hdr_t *) data; uint16_t send_packet_length = data_len; - memcpy(&laddr.uint8[0], &dest->uint8[0], 8); - if (ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { /* send broadcast */ mcast = 1; } + /* check if packet needs to be fragmented */ + DEBUG("sixlowpan_lowpan_sendto(%d, dest, %d, data, %"PRIu16")\n", + if_id, dest_len, data_len); +#ifdef DEBUG_ENABLED + DEBUG("dest: "); + + if (dest_len == 8) { + print_long_local_addr((net_if_eui64_t *)dest); + } + else { + printf("0x%04"PRIx16"\n", NTOHS(*((uint16_t *)dest))); + } + + DEBUG("data: \n"); + + for (int i = 0; i < data_len; i++) { + printf("%02x ", data[i]); + + if (!((i + 1) % 16) || i == data_len - 1) { + printf("\n"); + } + } + +#endif + + if (iphc_status == LOWPAN_IPHC_ENABLE) { - lowpan_iphc_encoding(&laddr, ipv6_buf, data); + if (!lowpan_iphc_encoding(if_id, dest, dest_len, ipv6_buf, data)) { + return -1; + } + data = &comp_buf[0]; send_packet_length = comp_len; } else { - ipv6_buf->length = HTONS(ipv6_buf->length); - lowpan_ipv6_set_dispatch(data); + memmove(data + 1, data, data_len); + data[0] = SIXLOWPAN_IPV6_DISPATCH; + send_packet_length++; } - /* check if packet needs to be fragmented */ - DEBUG("sixlowpan_lowpan_sendto(%s, data, %"PRIu16"): send_packet_length: %"PRIu16", header_size: %"PRIu16"\n", - sixlowpan_mac_802154_long_addr_to_str(addr_str, dest), data_len, send_packet_length, header_size); + if (send_packet_length > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { + uint16_t remaining; + uint16_t position, datagram_size = send_packet_length; + uint8_t max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; + uint8_t fragbuf[max_frame + 5]; + + if (!(net_if_get_interface(if_id)->transceivers & (IEEE802154_TRANSCEIVER))) { + max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; + } + else { + max_frame = PAYLOAD_SIZE; + } - if (send_packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN) { - uint8_t fragbuf[send_packet_length + header_size]; - uint8_t remaining; - uint8_t i = 2; /* first fragment */ - max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN; - max_frag_initial = ((max_frame - 4 - header_size) / 8) * 8; + max_frag_initial = ((max_frame - 4) / 8) * 8; - memcpy(fragbuf + 4, data, max_frag_initial); + if (data[0] == (char)SIXLOWPAN_IPV6_DISPATCH) { + /* XXX: weird, but only this way we get correct packet output */ + max_frag_initial++; + datagram_size--; + } - fragbuf[0] = ((SIXLOWPAN_FRAG1_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAG1_DISPATCH << 8) | send_packet_length; + memcpy(&fragbuf[4], data, max_frag_initial); + + fragbuf[0] = ((SIXLOWPAN_FRAG1_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAG1_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, &fragbuf, - max_frag_initial + header_size + 4, + max_frag_initial + 4, mcast); /* subsequent fragments */ @@ -213,11 +253,11 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, data += position; while (send_packet_length - position > max_frame - 5) { - memset(&fragbuf, 0, send_packet_length + header_size); - memcpy(fragbuf + 5, data, max_frag); + memset(&fragbuf[0], 0, sizeof(fragbuf)); + memcpy(&fragbuf[5], data, max_frag); - fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length; + fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; fragbuf[4] = position / 8; @@ -227,33 +267,32 @@ void sixlowpan_lowpan_sendto(const ieee_802154_long_t *dest, max_frame + 5, mcast); data += max_frag; position += max_frag; - - i++; } remaining = send_packet_length - position; - memset(&fragbuf, 0, send_packet_length + header_size); - memcpy(fragbuf + 5, data, remaining); + memset(&fragbuf[0], 0, sizeof(fragbuf)); + memcpy(&fragbuf[5], data, remaining); - fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length) >> 8; - fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | send_packet_length; + fragbuf[0] = ((SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size) >> 8; + fragbuf[1] = (SIXLOWPAN_FRAGN_DISPATCH << 8) | datagram_size; fragbuf[2] = tag >> 8; fragbuf[3] = tag; fragbuf[4] = position / 8; + tag++; + if (sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, &fragbuf, remaining + 5, mcast) < 0) { return -1; } } else { - return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, - data, send_packet_length, - mcast); + return sixlowpan_mac_send_ieee802154_frame(if_id, dest, dest_len, data, + send_packet_length, mcast); } - tag++; + return data_len; } void sixlowpan_lowpan_set_iphc_status( @@ -262,8 +301,8 @@ void sixlowpan_lowpan_set_iphc_status( iphc_status = status; } -#if ENABLE_DEBUG -void print_long_local_addr(ieee_802154_long_t *saddr) +#ifdef DEBUG_ENABLED +void print_long_local_addr(net_if_eui64_t *saddr) { printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", ((uint8_t *)saddr)[0], ((uint8_t *)saddr)[1], ((uint8_t *)saddr)[2], @@ -280,9 +319,9 @@ void sixlowpan_lowpan_print_reassembly_buffers(void) printf("\n\n--- Reassembly Buffers ---\n"); while (temp_buffer != NULL) { - print_long_local_addr(&temp_buffer->s_laddr); - printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %lu\n", - temp_buffer->ident_no, temp_buffer->current_packet_size, + print_long_local_addr(&temp_buffer->s_addr); + printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %"PRIu64"\n", + temp_buffer->tag, temp_buffer->current_packet_size, temp_buffer->packet_size, timex_uint64(temp_buffer->timestamp)); temp_interval = temp_buffer->interval_list_head; @@ -304,9 +343,9 @@ void sixlowpan_lowpan_print_fifo_buffers(void) printf("\n\n--- Reassembly Buffers ---\n"); while (temp_buffer != NULL) { - print_long_local_addr(&temp_buffer->s_laddr); - printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %lu\n", - temp_buffer->ident_no, temp_buffer->current_packet_size, + print_long_local_addr(&temp_buffer->s_addr); + printf("Ident.: %i, Packet Size: %i/%i, Timestamp: %"PRIu64"\n", + temp_buffer->tag, temp_buffer->current_packet_size, temp_buffer->packet_size, timex_uint64(temp_buffer->timestamp)); temp_interval = temp_buffer->interval_list_head; @@ -336,25 +375,39 @@ void lowpan_transfer(void) if (current_buf != NULL) { mutex_unlock(&fifo_mutex); - if ((current_buf->packet)[0] == SIXLOWPAN_IPV6_DISPATCH) { + if (current_buf->packet[0] == SIXLOWPAN_IPV6_DISPATCH) { + DEBUG("INFO: Uncompressed IPv6 dispatch (0x%02x) received\n", + current_buf->packet[0]); ipv6_buf = ipv6_get_buf(); memcpy(ipv6_buf, (current_buf->packet) + 1, current_buf->packet_size - 1); m_send.content.ptr = (char *)ipv6_buf; packet_length = current_buf->packet_size - 1; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if (((current_buf->packet)[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH) { + else if ((current_buf->packet[0] & 0xf0) == IPV6_VER && + iphc_status == LOWPAN_IPHC_DISABLE) { + ipv6_buf = ipv6_get_buf(); + memcpy(ipv6_buf, (current_buf->packet), current_buf->packet_size); + m_send.content.ptr = (char *)ipv6_buf; + packet_length = current_buf->packet_size; + msg_send_receive(&m_send, &m_recv, ip_process_pid); + } + else if ((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH && + iphc_status == LOWPAN_IPHC_ENABLE) { + DEBUG("INFO: IPHC1 dispatch 0x%02x received, decompress\n", + current_buf->packet[0]); lowpan_iphc_decoding(current_buf->packet, current_buf->packet_size, - &(current_buf->s_laddr), - &(current_buf->d_laddr)); + ¤t_buf->s_addr, + ¤t_buf->d_addr); ipv6_buf = ipv6_get_buf(); m_send.content.ptr = (char *) ipv6_buf; msg_send_receive(&m_send, &m_recv, ip_process_pid); } else { - // printf("ERROR: packet with unknown dispatch received\n"); + DEBUG("ERROR: packet with unknown dispatch 0x%02x received\n", + current_buf->packet[0]); } collect_garbage_fifo(current_buf); @@ -369,11 +422,11 @@ void lowpan_transfer(void) } } -uint8_t ll_get_addr_match(ieee_802154_long_t *src, ieee_802154_long_t *dst) +uint8_t ll_get_addr_match(net_if_eui64_t *src, net_if_eui64_t *dst) { uint8_t val = 0, xor; - for (int i = 0; i < 8; i++) { + for (uint8_t i = 0; i < sizeof(net_if_eui64_t); i++) { /* if bytes are equal add 8 */ if (src->uint8[i] == dst->uint8[i]) { val += 8; @@ -399,8 +452,8 @@ uint8_t ll_get_addr_match(ieee_802154_long_t *src, ieee_802154_long_t *dst) lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr, + net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr, lowpan_reas_buf_t *current_buf, lowpan_reas_buf_t *temp_buf) { @@ -415,10 +468,10 @@ lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, new_buf->packet = malloc(datagram_size); if (new_buf->packet != NULL) { - memcpy(&new_buf->s_laddr, s_laddr, IPV6_LL_ADDR_LEN); - memcpy(&new_buf->d_laddr, d_laddr, IPV6_LL_ADDR_LEN); + memcpy(&new_buf->s_addr, s_addr, 8); + memcpy(&new_buf->d_addr, d_addr, 8); - new_buf->ident_no = datagram_tag; + new_buf->tag = datagram_tag; new_buf->packet_size = datagram_size; vtimer_now(&new_buf->timestamp); @@ -443,17 +496,17 @@ lowpan_reas_buf_t *new_packet_buffer(uint16_t datagram_size, lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) + net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { lowpan_reas_buf_t *current_buf = NULL, *temp_buf = NULL; current_buf = head; while (current_buf != NULL) { - if (((ll_get_addr_match(¤t_buf->s_laddr, s_laddr)) == 64) && - ((ll_get_addr_match(¤t_buf->d_laddr, d_laddr)) == 64) && + if (((ll_get_addr_match(¤t_buf->s_addr, s_addr)) == 64) && + ((ll_get_addr_match(¤t_buf->d_addr, d_addr)) == 64) && (current_buf->packet_size == datagram_size) && - (current_buf->ident_no == datagram_tag) && + (current_buf->tag == datagram_tag) && current_buf->interval_list_head != NULL) { /* Found buffer for current packet fragment */ vtimer_now(¤t_buf->timestamp); @@ -464,7 +517,7 @@ lowpan_reas_buf_t *get_packet_frag_buf(uint16_t datagram_size, current_buf = current_buf->next; } - return new_packet_buffer(datagram_size, datagram_tag, s_laddr, d_laddr, + return new_packet_buffer(datagram_size, datagram_tag, s_addr, d_addr, current_buf, temp_buf); } @@ -603,13 +656,13 @@ lowpan_reas_buf_t *collect_garbage(lowpan_reas_buf_t *current_buf) void handle_packet_fragment(uint8_t *data, uint8_t datagram_offset, uint16_t datagram_size, uint16_t datagram_tag, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr, uint8_t hdr_length, - uint8_t frag_size) + net_if_eui64_t *s_addr, net_if_eui64_t *d_addr, + uint8_t hdr_length, uint8_t frag_size) { lowpan_reas_buf_t *current_buf; /* Is there already a reassembly buffer for this packet fragment? */ - current_buf = get_packet_frag_buf(datagram_size, datagram_tag, s_laddr, d_laddr); + current_buf = get_packet_frag_buf(datagram_size, datagram_tag, s_addr, + d_addr); if ((current_buf != NULL) && (handle_packet_frag_interval(current_buf, datagram_offset, @@ -727,8 +780,8 @@ uint8_t sixlowpan_lowpan_register(int pid) } } -void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) +void lowpan_read(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { /* check if packet is fragmented */ uint8_t hdr_length = 0; @@ -736,7 +789,6 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, uint16_t datagram_size = 0; uint16_t datagram_tag = 0; short i; - sixlowpan_lowpan_frame_t current_frame; check_timeout(); @@ -754,6 +806,9 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, /* Fragmented Packet */ if (((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAG1_DISPATCH) || ((data[0] & SIXLOWPAN_FRAG_HDR_MASK) == SIXLOWPAN_FRAGN_DISPATCH)) { + uint16_t byte_offset; + DEBUG("INFO: fragmentation dispatch 0x%02x received\n", + data[0] & SIXLOWPAN_FRAG_HDR_MASK); /* get 11-bit from first 2 byte*/ datagram_size = (((uint16_t)(data[0] << 8)) | data[1]) & 0x07ff; @@ -765,6 +820,11 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, case (SIXLOWPAN_FRAG1_DISPATCH): { datagram_offset = 0; hdr_length += 4; + + if (data[4] == (char)SIXLOWPAN_IPV6_DISPATCH) { + hdr_length++; + } + break; } @@ -787,12 +847,13 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, } handle_packet_fragment(data, byte_offset, datagram_size, datagram_tag, - s_laddr, d_laddr, hdr_length, frag_size); + s_addr, d_addr, hdr_length, frag_size); } /* Regular Packet */ else { - lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_laddr, - d_laddr); + DEBUG("INFO: unfragmentated packet with first byte 0x%02x received\n", + data[0]); + lowpan_reas_buf_t *current_buf = get_packet_frag_buf(length, 0, s_addr, d_addr); if (current_buf && current_buf->packet) { /* Copy packet bytes into corresponding packet space area */ @@ -811,25 +872,32 @@ void lowpan_read(uint8_t *data, uint8_t length, ieee_802154_long_t *s_laddr, } -void lowpan_ipv6_set_dispatch(uint8_t *data) -{ - memmove(data + 1, data, packet_length); - data[0] = SIXLOWPAN_IPV6_DISPATCH; - packet_length++; -} - /* draft-ietf-6lowpan-hc-13#section-3.1 */ -void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, - uint8_t *ptr) +uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, + ipv6_hdr_t *ipv6_buf_extra, uint8_t *ptr) { - ipv6_buf = ipv6_buf_extra; - - uint16_t payload_length = ipv6_buf->length; + uint16_t payload_length = NTOHS(ipv6_buf->length); uint8_t lowpan_iphc[2]; uint8_t *ipv6_hdr_fields = &comp_buf[2]; lowpan_context_t *con = NULL; uint16_t hdr_pos = 0; uint8_t tc; + net_if_eui64_t own_iid; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + if (!net_if_get_eui64(&own_iid, if_id, 0)) { + return 1; + } + } + else { + if (!net_if_get_eui64(&own_iid, if_id, 1)) { + return 1; + } + + own_iid.uint8[0] ^= 0x02; + } + + ipv6_buf = ipv6_buf_extra; memset(&lowpan_iphc, 0, 2); @@ -926,68 +994,46 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, /* SAC = 1 and SAM = 00 */ lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; } - else if ((con = lowpan_context_lookup(&ipv6_buf->srcaddr)) != NULL) { - /* 1: Source address compression uses stateful, context-based - * compression. */ - lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; - ipv6_hdr_fields[0] |= (con->num << 4); - - if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) { - /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ - lowpan_iphc[1] |= 0x30; - } - else if ((ipv6_buf->srcaddr.uint16[4] == 0) && - (ipv6_buf->srcaddr.uint16[5] == 0) && - (ipv6_buf->srcaddr.uint16[6] == 0) && - ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x20; - } - else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x10; - } - } - else if (ipv6_addr_is_link_local(&ipv6_buf->srcaddr)) { - /* 0: Source address compression uses stateless compression.*/ - if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &(iface.laddr.uint8[0]), 8) == 0) { - /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ - lowpan_iphc[1] |= 0x30; - } - else if ((ipv6_buf->srcaddr.uint16[4] == 0) && - (ipv6_buf->srcaddr.uint16[5] == 0) && - (ipv6_buf->srcaddr.uint16[6] == 0) && - ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x20; - } - else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x10; - } - } else { - /* full address carried inline */ - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint8[0]), 16); - hdr_pos += 16; + if ((con = lowpan_context_lookup(&ipv6_buf->srcaddr)) != NULL) { + /* 1: Source address compression uses stateful, context-based + * compression. */ + lowpan_iphc[1] |= SIXLOWPAN_IPHC2_SAC; + ipv6_hdr_fields[0] |= (con->num << 4); + } + + if (con || ipv6_addr_is_link_local(&ipv6_buf->srcaddr)) { + /* 0: Source address compression uses stateless compression.*/ + if (memcmp(&(ipv6_buf->srcaddr.uint8[8]), &own_iid, 8) == 0) { + /* 0 bits. The address is derived using context information + * and possibly the link-layer addresses.*/ + lowpan_iphc[1] |= 0x30; + } + else if ((ipv6_buf->srcaddr.uint16[4] == 0) && + (ipv6_buf->srcaddr.uint16[5] == 0) && + (ipv6_buf->srcaddr.uint16[6] == 0) && + ((ipv6_buf->srcaddr.uint8[14]) & 0x80) == 0) { + /* 49-bit of interface identifier are 0, so we can compress + * source address-iid to 16-bit */ + memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->srcaddr.uint16[7], 2); + hdr_pos += 2; + /* 16 bits. The address is derived using context information + * and the 16 bits carried inline. */ + lowpan_iphc[1] |= 0x20; + } + else { + memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint16[4]), 8); + hdr_pos += 8; + /* 64 bits. The address is derived using context information + * and the 64 bits carried inline. */ + lowpan_iphc[1] |= 0x10; + } + } + else { + /* full address carried inline */ + memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->srcaddr.uint8[0]), 16); + hdr_pos += 16; + } } /* M: Multicast Compression */ @@ -1049,7 +1095,20 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, lowpan_iphc[1] |= SIXLOWPAN_IPHC2_DAC; ipv6_hdr_fields[0] = con->num; - if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) { + } + + if (con || ipv6_addr_is_link_local(&ipv6_buf->destaddr)) { + if (dest_len == 8 && + ipv6_buf->destaddr.uint8[8] == (dest[0] ^ 0x02) && + memcmp(&ipv6_buf->destaddr.uint8[9], &dest[1], 7) == 0) { + /* 0 bits. The address is derived using context information + * and possibly the link-layer addresses.*/ + lowpan_iphc[1] |= 0x03; + } + else if (dest_len == 2 && + ipv6_buf->destaddr.uint32[2] == HTONL(0x000000ff) && + ipv6_buf->destaddr.uint16[6] == HTONS(0xfe00) && + ipv6_buf->destaddr.uint16[7] == *((uint16_t *) dest)) { /* 0 bits. The address is derived using context information * and possibly the link-layer addresses.*/ lowpan_iphc[1] |= 0x03; @@ -1074,32 +1133,6 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, lowpan_iphc[1] |= 0x01; } } - else if (ipv6_addr_is_link_local(&ipv6_buf->destaddr)) { - if (memcmp(&(ipv6_buf->destaddr.uint8[8]), &(dest->uint8[0]), 8) == 0) { - /* 0 bits. The address is derived using context information - * and possibly the link-layer addresses.*/ - lowpan_iphc[1] |= 0x03; - } - else if ((ipv6_buf->destaddr.uint16[4] == 0) && - (ipv6_buf->destaddr.uint16[5] == 0) && - (ipv6_buf->destaddr.uint16[6] == 0) && - ((ipv6_buf->destaddr.uint8[14]) & 0x80) == 0) { - /* 49-bit of interface identifier are 0, so we can compress - * source address-iid to 16-bit */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ipv6_buf->destaddr.uint16[7], 2); - hdr_pos += 2; - /* 16 bits. The address is derived using context information - * and the 16 bits carried inline. */ - lowpan_iphc[1] |= 0x02; - } - else { - memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->destaddr.uint16[4]), 8); - hdr_pos += 8; - /* 64 bits. The address is derived using context information - * and the 64 bits carried inline. */ - lowpan_iphc[1] |= 0x01; - } - } else { memcpy(&ipv6_hdr_fields[hdr_pos], &(ipv6_buf->destaddr.uint8[0]), 16); hdr_pos += 16; @@ -1124,11 +1157,12 @@ void lowpan_iphc_encoding(ieee_802154_long_t *dest, ipv6_hdr_t *ipv6_buf_extra, memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], ipv6_buf->length); comp_len = 2 + hdr_pos + payload_length; + + return 1; } -void lowpan_iphc_decoding(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr) +void lowpan_iphc_decoding(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr) { uint8_t hdr_pos = 0; uint8_t *ipv6_hdr_fields = data; @@ -1258,7 +1292,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x01): { /* 64-bits */ memcpy(&(ipv6_buf->srcaddr.uint8[8]), &ipv6_hdr_fields[hdr_pos], 8); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); hdr_pos += 8; @@ -1269,7 +1303,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, /* 16-bits */ memset(&(ipv6_buf->srcaddr.uint8[8]), 0, 6); memcpy(&(ipv6_buf->srcaddr.uint8[14]), &ipv6_hdr_fields[hdr_pos], 2); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); hdr_pos += 2; @@ -1278,9 +1312,8 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { /* 0-bits */ - memset(&(ipv6_buf->srcaddr.uint8[8]), 0, 8); - memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_laddr->uint8[0], 8); - /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context + memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_addr->uint8[0], 8); + /* By RFC 6282 3.1.1. Bits covered by context * information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); break; @@ -1319,7 +1352,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, /* 0-bits */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &ll_prefix[0], 2); memset(&(ipv6_buf->srcaddr.uint8[2]), 0, 20); - memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->srcaddr.uint8[8]), &s_addr->uint8[0], 8); break; } @@ -1449,7 +1482,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { memset(&(ipv6_buf->destaddr.uint8[0]), 0, 8); - memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_addr->uint8[0], 8); /* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */ memcpy(&(ipv6_buf->srcaddr.uint8[0]), &con->prefix, con->length); break; @@ -1484,7 +1517,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, case (0x03): { memcpy(&(ipv6_buf->destaddr.uint8[0]), &ll_prefix, 2); memset(&(ipv6_buf->destaddr.uint8[2]), 0, 14); - memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_laddr->uint8[0], 8); + memcpy(&(ipv6_buf->destaddr.uint8[8]), &d_addr->uint8[0], 8); break; } @@ -1503,7 +1536,7 @@ void lowpan_iphc_decoding(uint8_t *data, uint8_t length, memcpy(ptr, &ipv6_hdr_fields[hdr_pos], length - hdr_pos); /* ipv6 length */ - ipv6_buf->length = length - hdr_pos; + ipv6_buf->length = HTONS(length - hdr_pos); packet_length = IPV6_HDR_LEN + ipv6_buf->length; } @@ -1626,40 +1659,126 @@ void lowpan_context_auto_remove(void) void init_reas_bufs(lowpan_reas_buf_t *buf) { - memset(&buf->s_laddr, 0, IPV6_LL_ADDR_LEN); - memset(&buf->d_laddr, 0, IPV6_LL_ADDR_LEN); - buf->ident_no = 0; + memset(&buf->s_addr, 0, sizeof(net_if_eui64_t)); + memset(&buf->d_addr, 0, sizeof(net_if_eui64_t)); + buf->tag = 0; memset(&buf->timestamp, 0, sizeof(timex_t)); - buf->packet_size = 0; - buf->current_packet_size = 0; - buf->packet = NULL; - buf->interval_list_head = NULL; - buf->next = NULL; + buf->packet_size = 0; + buf->current_packet_size = 0; + buf->packet = NULL; + buf->interval_list_head = NULL; + buf->next = NULL; } -void sixlowpan_lowpan_init(transceiver_type_t trans, uint8_t r_addr, - int as_border) +int sixlowpan_lowpan_init_adhoc_interface(int if_id, const ipv6_addr_t *prefix) { - lowpan_init(trans, r_addr, NULL, as_border); -} - -void sixlowpan_lowpan_adhoc_init(transceiver_type_t trans, - const ipv6_addr_t *prefix, - uint8_t r_addr) -{ - lowpan_init(trans, r_addr, prefix, 0); -} - -void lowpan_init(transceiver_type_t trans, uint8_t r_addr, - const ipv6_addr_t *prefix, int as_border) -{ - int if_id = 0; ipv6_addr_t tmp; + + /* if prefix is set */ + if (prefix != NULL) { + /* init network prefix */ + ipv6_addr_t save_prefix; + + ipv6_addr_init_prefix(&save_prefix, prefix, 64); + ndp_add_prefix_info(if_id, &save_prefix, 64, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); + ipv6_init_as_router(); + + /* add global address */ + if (!ipv6_addr_set_by_eui64(&tmp, if_id, prefix)) { + return 0; + } + + DEBUG("%s, %d: set unique address for interface %d to %s, according " + "to prefix %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + return 0; + } + } + + return sixlowpan_lowpan_init_interface(if_id); +} + +int sixlowpan_lowpan_init_interface(int if_id) +{ + ipv6_addr_t tmp; + + /* init link-local prefix */ + ipv6_addr_set_link_local_prefix(&tmp); + + if (!ipv6_addr_set_by_eui64(&tmp, if_id, &tmp)) { + DEBUG("Can not set link-local by EUI-64 on interface %d\n", if_id); + return 0; + } + + DEBUG("%s, %d: sixlowpan_lowpan_init(): add link local address to " + "interface %d: %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add link-local address to interface %d\n", if_id); + return 0; + } + + /* add solicited nodes multicast address of link local address */ + ipv6_addr_set_solicited_node_addr(&tmp, &tmp); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add solicited nodes multicast address " + "to of link layer address interface %d: %s\n", __FILE__, __LINE__, + if_id, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; + } + + /* add all nodes multicast address */ + ipv6_addr_set_all_nodes_addr(&tmp); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add all nodes multicast address " + "to interface %d: %s\n", __FILE__, __LINE__, if_id, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(if_id, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; + } + + /* add loopback address */ + ipv6_addr_set_loopback_addr(&tmp); + DEBUG("%s, %d: sixlowpan_lowpan_init(): add loopback address to interface " + "0: %s\n", __FILE__, __LINE__, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &tmp)); + + if (!ipv6_net_if_add_addr(0, &tmp, NDP_ADDR_STATE_PREFERRED, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 0)) { + DEBUG("Can not add all nodes address to interface %d\n", if_id); + return 0; + } + + icmpv6_send_router_sol(OPT_SLLAO); + + return 1; +} + +int sixlowpan_lowpan_init(void) +{ short i; - - /* init interface addresses */ - memset(&iface, 0, sizeof(iface_t)); + /* init mac-layer and radio transceiver */ + sixlowpan_mac_init(); /* init lowpan context mutex */ mutex_init(&lowpan_context_mutex); @@ -1667,72 +1786,45 @@ void lowpan_init(transceiver_type_t trans, uint8_t r_addr, /* init packet_fifo mutex */ mutex_init(&fifo_mutex); - local_address = r_addr; - - /* if prefix is set */ - if (prefix != NULL) { - /* init network prefix */ - ipv6_addr_t save_prefix; - ipv6_addr_init_prefix(&save_prefix, prefix, 64); - plist_add(&save_prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1, - ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); - ipv6_init_iface_as_router(); - /* add global address */ - ipv6_addr_set_by_eui64(&tmp, prefix); - DEBUG("%s, %d: set unique address to %s, according to prefix %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp), ipv6_addr_to_str(addr_str, prefix)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); - } - - DEBUG("%s, %d: set link local prefix to %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); - /* init link-local address */ - ipv6_addr_set_link_local_prefix(&lladdr); - - /* add link local address */ - memcpy(&(lladdr.uint8[8]), &(iface.laddr.uint8[0]), 8); - DEBUG("%s, %d: sixlowpan_lowpan_init(): add link local address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &lladdr)); - ipv6_iface_add_addr(&lladdr, IPV6_ADDR_TYPE_LINK_LOCAL, - NDP_ADDR_STATE_PREFERRED, 0, 0); - - /* add loopback address */ - ipv6_addr_set_loopback_addr(&tmp); - DEBUG("%s, %d: sixlowpan_lowpan_init(): add loopback address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, - NDP_ADDR_STATE_PREFERRED, 0, 0); - - /* add all nodes multicast address */ - DEBUG("%s, %d: sixlowpan_lowpan_init(): add all nodes multicast address: %s\n", __FILE__, __LINE__, ipv6_addr_to_str(addr_str, &tmp)); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_LOOPBACK, - NDP_ADDR_STATE_PREFERRED, 0, 0); - - /* init mac-layer and radio transceiver */ - sixlowpan_mac_init(); - if (as_border) { - ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, - PRIORITY_MAIN - 1, CREATE_STACKTEST, - border_process_lowpan, - "border_process_lowpan"); - } - else { + if (!ip_process_pid) { ip_process_pid = thread_create(ip_process_buf, IP_PROCESS_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, ipv6_process, "ip_process"); } + if (ip_process_pid < 0) { + return 0; + } + nd_nbr_cache_rem_pid = thread_create(nc_buf, NC_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, nbr_cache_auto_rem, "nbr_cache_rem"); + + if (nd_nbr_cache_rem_pid < 0) { + return 0; + } + contexts_rem_pid = thread_create(con_buf, CON_STACKSIZE, PRIORITY_MAIN + 1, CREATE_STACKTEST, lowpan_context_auto_remove, "lowpan_context_rem"); + + if (contexts_rem_pid < 0) { + return 0; + } + transfer_pid = thread_create(lowpan_transfer_buf, LOWPAN_TRANSFER_BUF_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, lowpan_transfer, "lowpan_transfer"); + if (transfer_pid < 0) { + return 0; + } + for (i = 0; i < SIXLOWIP_MAX_REGISTERED; i++) { sixlowip_reg[i] = 0; } + return 0; } diff --git a/sys/net/network_layer/sixlowpan/lowpan.h b/sys/net/network_layer/sixlowpan/lowpan.h index d4bd59e7d8..38830ae9b4 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.h +++ b/sys/net/network_layer/sixlowpan/lowpan.h @@ -29,6 +29,8 @@ #include "sixlowpan/lowpan.h" +#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) + typedef struct { uint8_t num; ipv6_addr_t prefix; diff --git a/sys/net/network_layer/sixlowpan/mac.c b/sys/net/network_layer/sixlowpan/mac.c index ab27207b31..723dac710e 100644 --- a/sys/net/network_layer/sixlowpan/mac.c +++ b/sys/net/network_layer/sixlowpan/mac.c @@ -47,7 +47,6 @@ #define RADIO_SENDING_DELAY (1000) #define DEFAULT_IEEE_802154_PAN_ID (0x1234) -#define IEEE802154_TRANSCEIVER (TRANSCEIVER_AT86RF231 | TRANSCEIVER_CC2420 | TRANSCEIVER_MC1322X) char radio_stack_buffer[RADIO_STACK_SIZE]; msg_t msg_q[RADIO_RCV_BUF_SIZE]; From e2e62596bedab97cb1249a83df316d5761b2bc4c Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Thu, 27 Feb 2014 00:49:03 +0100 Subject: [PATCH 08/13] Byte order and rpl problems --- sys/net/network_layer/sixlowpan/icmp.c | 4 ++-- sys/net/network_layer/sixlowpan/lowpan.c | 2 +- sys/net/routing/rpl/rpl.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 5d93f56bbd..69005329fe 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -672,7 +672,7 @@ void recv_rtr_adv(void) ipv6_addr_t abro_addr; ipv6_buf = ipv6_get_buf(); - packet_length = IPV6_HDR_LEN + ipv6_buf->length; + packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); icmpv6_opt_hdr_len = RTR_ADV_LEN; rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len); ipv6_addr_t newaddr; @@ -937,7 +937,7 @@ void recv_nbr_sol(void) uint8_t send_na = 0; uint8_t sllao_set = 0; uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; - uint16_t packet_length = IPV6_HDR_LEN + ipv6_buf->length; + uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); /* check whick options are set, we need that because an aro * option condition is that a sllao option is set. thus that we don't diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index 4a5ca8e321..a4f54979a6 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -1154,7 +1154,7 @@ uint8_t lowpan_iphc_encoding(int if_id, const uint8_t *dest, int dest_len, ptr = get_payload_buf(ipv6_ext_hdr_len); } */ - memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], ipv6_buf->length); + memcpy(&ipv6_hdr_fields[hdr_pos], &ptr[IPV6_HDR_LEN], NTOHS(ipv6_buf->length)); comp_len = 2 + hdr_pos + payload_length; diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 013c7258a5..a9a7d6fa3c 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -490,7 +490,7 @@ void rpl_process(void) code = ((uint8_t *)m_recv.content.ptr); /* differentiate packet types */ ipv6_buf = ipv6_get_buf(); - memcpy(&rpl_buffer, ipv6_buf, ipv6_buf->length + IPV6_HDR_LEN); + memcpy(&rpl_buffer, ipv6_buf, NTOHS(ipv6_buf->length) + IPV6_HDR_LEN); switch (*code) { case (ICMP_CODE_DIS): { @@ -583,7 +583,7 @@ void recv_rpl_dio(void) * ipv6_buf->length contains the packet length minus ipv6 and * icmpv6 header, so only ICMPV6_HDR_LEN remains to be * subtracted. */ - while (len < (ipv6_buf->length - ICMPV6_HDR_LEN)) { + while (len < (NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN)) { DEBUG("parsing DIO options\n"); rpl_opt_buf = get_rpl_opt_buf(len); @@ -970,7 +970,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ } } - ipv6_send_packet(ipv6_buf); + ipv6_send_packet(ipv6_send_buf); } } From 00acab920bacbf49dfbe5a68e939926053e54f60 Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 13:57:59 +0100 Subject: [PATCH 09/13] Let IPv6 and ICMP use new 6LoWPAN layer (+fixes) --- Makefile.dep | 10 +- sys/net/include/sixlowpan/icmp.h | 4 +- sys/net/include/sixlowpan/ip.h | 211 ++++-- sys/net/include/sixlowpan/ndp.h | 126 +++- sys/net/include/sixlowpan/types.h | 21 +- .../network_layer/sixlowpan/border/border.h | 2 +- .../sixlowpan/border/bordermultiplex.c | 8 +- sys/net/network_layer/sixlowpan/icmp.c | 606 +++++++++++++----- sys/net/network_layer/sixlowpan/icmp.h | 5 +- sys/net/network_layer/sixlowpan/ip.c | 544 ++++++++-------- sys/net/network_layer/sixlowpan/ip.h | 45 +- sys/net/network_layer/sixlowpan/lowpan.h | 6 +- sys/net/routing/rpl/rpl.c | 16 +- sys/net/routing/rpl/rpl.h | 2 +- sys/net/routing/rpl/rpl_dodag.c | 4 +- sys/net/transport_layer/destiny/socket.c | 32 +- sys/shell/commands/sc_net_if.c | 67 +- 17 files changed, 1140 insertions(+), 569 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index eff649d8a4..f7b80ef62b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -92,13 +92,13 @@ ifneq (,$(filter sixlowpan,$(USEMODULE))) ifeq (,$(filter net_help,$(USEMODULE))) USEMODULE += net_help endif - ifeq (,$(filter semaphore,$(USEMODULE))) + ifeq (,$(filter net_if,$(USEMODULE))) + USEMODULE += net_if + endif + ifeq (,$(filter semaphore, $(USEMODULE))) USEMODULE += semaphore endif - ifeq (,$(filter transceiver,$(USEMODULE))) - USEMODULE += transceiver - endif - ifeq (,$(filter vtimer,$(USEMODULE))) + ifeq (,$(filter vtimer, $(USEMODULE))) USEMODULE += vtimer endif endif diff --git a/sys/net/include/sixlowpan/icmp.h b/sys/net/include/sixlowpan/icmp.h index 6aa417c66c..97b08791aa 100644 --- a/sys/net/include/sixlowpan/icmp.h +++ b/sys/net/include/sixlowpan/icmp.h @@ -150,7 +150,7 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, + uint16_t seq, uint8_t *data, size_t data_len); /** @@ -163,7 +163,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, * @param[in] data_len Length of data payload. */ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, - uint16_t seq, char *data, size_t data_len); + uint16_t seq, uint8_t *data, size_t data_len); /** * @brief Send ICMPv6 router solicitation. diff --git a/sys/net/include/sixlowpan/ip.h b/sys/net/include/sixlowpan/ip.h index d365a65c33..aaf41c44ac 100644 --- a/sys/net/include/sixlowpan/ip.h +++ b/sys/net/include/sixlowpan/ip.h @@ -24,6 +24,9 @@ #include +#include "inet_ntop.h" +#include "net_help.h" +#include "net_if.h" #include "sixlowpan/types.h" /** @@ -32,7 +35,17 @@ #define IPV6_MTU (256) /** - * @brief Maximum length of a IPv6 address represented as string. + * @brief Length of an IPv6 address in byte. + */ +#define IPV6_ADDR_LEN (16) + +/** + * @brief Length of an IPv6 address in bit. + */ +#define IPV6_ADDR_BIT_LEN (128) + +/** + * @brief Maximum length of an IPv6 address represented as string. */ #define IPV6_MAX_ADDR_STR_LEN (40) @@ -160,7 +173,11 @@ void ipv6_register_rpl_handler(int pid); * * @param[in,out] ipv6_addr The address to set. */ -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xfe800000); + ipv6_addr->uint32[1] = 0; +} /** * @brief Sets IPv6 address *out* according to the remaining @@ -181,16 +198,20 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr5, uint16_t addr6, uint16_t addr7); /** - * @brief Sets IPv6 address *out* using the given *prefix* and this - * nodes EUI-64 (i. e. interface must be initialized). + * @brief Sets IPv6 address *out* using the given *prefix* and an interface's + * EUI-64. + * * * @param[out] out Address to be set. + * @param[in] if_id The interface to take the EUI-64 from. * @param[in] prefix 64-bit network prefix to be used for *out* * (only the first 64 bit of the ipv6_addr_t type * are copied to *out*) + * + * @return The Address to be set on success, NULL on error. */ -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, - const ipv6_addr_t *prefix); +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix); /** * @brief Sets IPv6 address *out* with the first *bits* bit taken @@ -213,7 +234,13 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, * * @param[out] ipv6_addr Is set to the loopback address. */ -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = 0; + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr* to a link-local all routers multicast @@ -226,7 +253,13 @@ void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all routers multicast * address. */ -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(2); +} /** * @brief Set *ipv6_addr* to a link-local all nodes multicast address @@ -239,7 +272,13 @@ void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr); * @param[out] ipv6_addr Is set to a link-local all nodes multicast * address. */ -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); +static inline void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) +{ + ipv6_addr->uint32[0] = HTONL(0xff020000); + ipv6_addr->uint32[1] = 0; + ipv6_addr->uint32[2] = 0; + ipv6_addr->uint32[3] = HTONL(1); +} /** * @brief Set *ipv6_addr_out* to the solicited-node multicast address @@ -254,22 +293,34 @@ void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr); * @param[in] ipv6_addr_in The IPv6 address the solicited-node * address. */ -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in); +static inline void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, + const ipv6_addr_t *ipv6_addr_in) +{ + /* copy only the last 24-bit of the ip-address that is beeing resolved */ + ipv6_addr_out->uint32[0] = HTONL(0xff020000); + ipv6_addr_out->uint32[1] = 0; + ipv6_addr_out->uint32[2] = HTONS(1); + ipv6_addr_out->uint8[12] = 0xff; + ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; + ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; +} /** - * @brief Converts IPv6 address into string (unabbrivated notation). - * Note that addr_str must allocate at least - * IPV6_MAX_ADDR_STR_LEN byte (40 byte). + * @brief Converts IPv6 address into string. * * @param[out] addr_str The IPv6 address as string. Must allocate * at least IPV6_MAX_ADDR_STR_LEN byte (40 * byte). + * @param[in] str_len The maximum length available to *addr_str*. * @param[in] ipv6_addr IPv6 address to be converted. * * @return Pointer to addr_str. */ -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); +static inline const char *ipv6_addr_to_str(char *addr_str, uint8_t str_len, + const ipv6_addr_t *ipv6_addr) +{ + return inet_ntop(AF_INET6, ipv6_addr, addr_str, (size_t)str_len); +} /** * @brief Checks if two IPv6 addresses are equal. @@ -279,7 +330,13 @@ char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr); * * @return 1 if *a* and *b* are equal, 0 otherwise. */ -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); +static inline int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) +{ + return (a->uint32[0] == b->uint32[0]) && + (a->uint32[1] == b->uint32[1]) && + (a->uint32[2] == b->uint32[2]) && + (a->uint32[3] == b->uint32[3]); +} /** * @brief Checks if *ipv6_addr* is unspecified (all zero). @@ -292,7 +349,48 @@ int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b); * * @return 1 if *ipv6_addr* is unspecified address, 0 otherwise. */ -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == 0) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == 0) && + (ipv6_addr->uint32[3] == 0); +} + +/** + * @brief Check if *ipv6_addr* is a multicast address. + * + * @see + * RFC 4291 + * + * + * @param[in] ipv6_addr An IPv6 address. + * + * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. + */ +static inline int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint8[0] == 0xff); +} + +/** + * @brief Checks if *ipv6_addr* is a loopback address. + * + * @see + * RFC 4291 + * + * + * @param[in] ipv6_addr An IPv6 address. + * + * @return 1 if *ipv6_addr* is loopback address, 0 otherwise. + */ +static inline int ipv6_addr_is_loopback(const ipv6_addr_t *ipv6_addr) +{ + return ipv6_addr->uint32[0] == 0 && + ipv6_addr->uint32[1] == 0 && + ipv6_addr->uint32[2] == 0 && + NTOHL(ipv6_addr->uint32[3]) == 1; +} /** * @brief Check if *ipv6_addr* is a link-local address. @@ -305,7 +403,13 @@ int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr); * * @return 1 if *ipv6_addr* is link-local address, 0 otherwise. */ -int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint32[0] == HTONL(0xfe800000)) && + (ipv6_addr->uint32[1] == 0)) || + (ipv6_addr_is_multicast(ipv6_addr) && + (ipv6_addr->uint8[1] & 0x0f) == 2); +} /** * @brief Check if *ipv6_addr* is unique local unicast address. @@ -319,20 +423,10 @@ int ipv6_addr_is_link_local(const ipv6_addr_t *ipv6_addr); * @return 1 if *ipv6_addr* is unique local unicast address, * 0 otherwise. */ -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr); - -/** - * @brief Check if *ipv6_addr* is a multicast address. - * - * @see - * RFC 4291 - * - * - * @param[in] ipv6_addr An IPv6 address. - * - * @return 1 if *ipv6_addr* is multicast address, 0 otherwise. - */ -int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *ipv6_addr) +{ + return ((ipv6_addr->uint8[0] == 0xfc) || (ipv6_addr->uint8[0] == 0xfd)); +} /** * @brief Check if *ipv6_addr* is solicited-node multicast address. @@ -346,7 +440,28 @@ int ipv6_addr_is_multicast(const ipv6_addr_t *ipv6_addr); * @return 1 if *ipv6_addr* is solicited-node multicast address, * 0 otherwise. */ -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); +static inline int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) +{ + return (ipv6_addr->uint32[0] == HTONL(0xff020000)) && + (ipv6_addr->uint32[1] == 0) && + (ipv6_addr->uint32[2] == HTONL(1)) && + (ipv6_addr->uint8[12] == 0xff); +} + +/** + * @brief Get pointer to potential EUI-64 bit of the IPv6 address. + * + * @param[in] ipv6_addr An IPv6 address of this node. + * @param[in] prefix_len Length of the prefix. Only multiples of 8 are + * possible. + * + * @return The IID (as EUI-64) of this node. + */ +static inline net_if_eui64_t *ipv6_addr_get_iid(const ipv6_addr_t *ipv6_addr, + uint8_t prefix_len) +{ + return ((net_if_eui64_t *) &ipv6_addr->uint8[prefix_len / 8]); +} /* * TODO to wrap sixlowpan initialisations @@ -354,26 +469,35 @@ int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr); */ /** - * @brief Add an IPv6 address to this nodes interface. + * @brief Add an IPv6 address to one of this nodes interfaces. * * @see * RFC 4862 * * + * @param[in] if_id The interface's ID. * @param[in] addr Address to be added to the interface. * @param[in] type Type of this address. * @param[in] state Initial state of the address. - * @param[in] val_ltime Valid lifetime of this address in seconds. + * @param[in] val_ltime Valid lifetime of this address in seconds. Set 0 + * for unspecified. * @param[in] pref_ltime Preferred lifetime of this address in - * seconds. + * seconds. Set 0 for unspecified. + * @param[in] is_anycast Determines if an address is anycast. Anycast + * addresses are syntactically undistinguishable + * from unicast addresses and can only be identified + * with this flag. If *addr* is no unicast address + * and *is_anycast* is set, this function will fail. + * + * @return 1 on success, 0 on failure. */ -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime); + uint32_t pref_ltime, uint8_t is_anycast); /** * @brief Tries to determine best suitable source address attached to - * the interface of this node based on the given destination + * an interface of this node based on the given destination * address. The use-case for this function is to find a * suitable address for the source address field of an IPv6 * address upon sending. *src* may be empty (all zero) if there @@ -381,16 +505,11 @@ void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, * * @param[out] src The best source address for this node (may be * all zero if ther is none). + * @param[in] if_id The interface's ID. * @param[in] dest The destination address for a packet we search * the source address for. */ -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, - const ipv6_addr_t *dest); - -/** - * @brief Print all addresses attached to the interface to stdout. - */ -void ipv6_iface_print_addrs(void); +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest); /** * @brief Registers a function that decides how to route incomming diff --git a/sys/net/include/sixlowpan/ndp.h b/sys/net/include/sixlowpan/ndp.h index 939844fa53..9bf7b69561 100644 --- a/sys/net/include/sixlowpan/ndp.h +++ b/sys/net/include/sixlowpan/ndp.h @@ -24,6 +24,7 @@ #include +#include "net_if.h" #include "timex.h" #include "sixlowpan/types.h" @@ -32,6 +33,7 @@ #define NDP_OPT_SLLAO_TYPE (1) #define NDP_OPT_TLLAO_TYPE (2) #define NDP_OPT_PI_VLIFETIME_INFINITE (0xffffffff) +#define NDP_OPT_PI_PLIFETIME_INFINITE (0xffffffff) #define NDP_OPT_ARO_STATE_SUCCESS (0) #define NDP_OPT_ARO_STATE_DUP_ADDR (1) #define NDP_OPT_ARO_STATE_NBR_CACHE_FULL (2) @@ -64,18 +66,37 @@ typedef enum __attribute__((packed)) { /** * @brief Prefix list type to store information spread by prefix - * information option. + * information option on the interface. + * + * @see net_if_addr_t */ -typedef struct __attribute__((packed)) { - uint8_t inuse; ///< Prefix is in in use. - uint8_t adv; - ipv6_addr_t addr; ///< The Prefix. - uint8_t length; ///< Length of the prefix. - uint8_t l_a_reserved1; ///< L and A flag of prefix information option - uint32_t val_ltime; ///< valid lifetime - uint32_t pref_ltime; ///< preferred lifetime - uint8_t infinite; ///< flag to set to infinite lifetime -} ndp_prefix_list_t; +typedef struct __attribute__((packed)) ndp_prefix_info_t { + /** + * @brief The next on the interface. Intialise with NULL + */ + struct ndp_prefix_info_t *addr_next; + /** + * @brief The prev address on the interface. Initialise with NULL + */ + struct ndp_prefix_info_t *addr_prev; + /** + * @brief Flags to define upper layer protocols this address applies to. + * For this layer NET_IF_L3P_IPV6_PREFIX must be set. + */ + net_if_l3p_t prefix_protocol; + ipv6_addr_t *prefix_data; ///< The Prefix. + uint8_t prefix_len; ///< Length of the prefix. + uint8_t inuse; ///< Prefix is in in use. + /** + * Use this information in Prefix Information Options of Router + * Advertisements. + */ + uint8_t advertisable; + uint8_t flags; ///< flags of the prefix information option + uint32_t valid_lifetime; ///< valid lifetime + uint32_t preferred_lifetime; ///< preferred lifetime + uint8_t infinite; ///< flag to set to infinite lifetime +} ndp_prefix_info_t; /** * @brief Default router list to store information spread by @@ -84,7 +105,7 @@ typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) { ipv6_addr_t addr; ///< Address of router. timex_t inval_time; ///< remaining time until this entry is - ///< invalid. + ///< invalid. } ndp_default_router_list_t; /** @@ -94,14 +115,16 @@ typedef struct __attribute__((packed)) { * . */ typedef struct __attribute__((packed)) { + int if_id; ///< Interface the IPv6 address is reachable + ///< over ndp_nce_type_t type; ///< Type of neighbor cache entry. ndp_nce_state_t state; ///< State of neighbor cache entry. uint8_t isrouter; ///< Flag to signify that this neighbor - ///< is a router. + ///< is a router. ipv6_addr_t addr; ///< IPv6 address of the neighbor. - ieee_802154_long_t laddr; ///< EUI-64 of neighbor - ieee_802154_short_t saddr; ///< IEEE 802.15.4 16-bit short address - ///< of neighbor. + uint8_t lladdr[8]; ///< Link-layer address of the neighbor + uint8_t lladdr_len; ///< Length of link-layer address of the + ///< neighbor timex_t ltime; ///< lifetime of entry. } ndp_neighbor_cache_t; @@ -118,9 +141,76 @@ typedef struct __attribute__((packed)) { } ndp_a6br_cache_t; ndp_default_router_list_t *ndp_default_router_list_search(ipv6_addr_t *ipaddr); +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime); ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr); -/*TODO: to implement*/ -uint8_t ndp_prefix_list_search(ipv6_addr_t *addr); +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr); +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr); + +/** + * @brief Adds a prefix information to an interface. If it already exists, + * the values *valid_lifetime*, *preferred_lifetime*, *advertisable*, + * and flags will be updated accordingly and the prefix will be marked + * as *in_use*. + * + * @see + * RFC 4861, section 4.6.2 + * . + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix. + * @param[in] prefix_len The length of the prefix in bit. + * @param[in] valid_lifetime The time in seconds this prefix is valid + * for on-link determination. + * NDP_OPT_PI_VLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] preferred_lifetime The time in seconds addresses generated with + * this prefix remain preferred. + * NDP_OPT_PI_PLIFETIME_INFINITE for infinite + * lifetime. + * @param[in] advertisable Set this to a value != 0 to advertise this + * prefix information with the Prefix + * Information Option, set it to 0 if not. + * @param[in] flags Flags for the Prefix Information Option. + * Valid values are + * ICMPV6_NDP_OPT_PI_FLAG_ON_LINK and + * ICMPV6_NDP_OPT_PI_FLAG_AUTONOM + */ +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags); + +/** + * @brief Searches the information for the longest prefix up to *up_to* bits + * on an interface fitting to an address *addr*. + * + * @param[in] if_id The interface's ID. + * @param[in] addr The address to search the prefix for. + * @param[in] up_to The number of bits up to which point the search should + * go. Set to IPV6_ADDR_BIT_LEN for the whole address. + * Values greater then IPV6_ADDR_BIT_LEN are set to + * IPV6_ADDR_BIT_LEN. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to); + +/** + * @brief Searches the information for the prefix that matches *prefix* with + * length *prefix_len*. + * + * @param[in] if_id The interface's ID. + * @param[in] prefix The prefix to search for. + * @param[in] prefix_len The length of the prefix in bit. + * + * @return The found prefix information, NULL when none is found. + */ +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len); ndp_a6br_cache_t *ndp_a6br_cache_get_most_current(void); ndp_a6br_cache_t *ndp_a6br_cache_get_oldest(void); diff --git a/sys/net/include/sixlowpan/types.h b/sys/net/include/sixlowpan/types.h index 879d8e5d1d..d8ebc0334e 100644 --- a/sys/net/include/sixlowpan/types.h +++ b/sys/net/include/sixlowpan/types.h @@ -49,25 +49,6 @@ typedef union __attribute__((packed)) { uint32_t uint32[4]; ///< devided by 4 32-bit words. } ipv6_addr_t; -/** - * @brief Data type to represent IPv6 address types. - * - * @see - * RFC 4291 - * - */ -typedef enum __attribute__((packed)) { - IPV6_ADDR_TYPE_NONE, ///< address has no type/is invalid. - IPV6_ADDR_TYPE_UNICAST, ///< address is an unicast address. - IPV6_ADDR_TYPE_MULTICAST, ///< address is a multicast address. - IPV6_ADDR_TYPE_ANYCAST, ///< address is an anycast address. - IPV6_ADDR_TYPE_SOLICITED_NODE, ///< address is a solicitated node - ///< multicast address. - IPV6_ADDR_TYPE_LOOPBACK, ///< address is a loopback address. - IPV6_ADDR_TYPE_LINK_LOCAL, ///< address is a link-local address. - IPV6_ADDR_TYPE_GLOBAL ///< address is a global address. -} ipv6_addr_type_t; - /** * @brief Data type to represent an IPv6 packet header * @@ -78,7 +59,7 @@ typedef enum __attribute__((packed)) { typedef struct __attribute__((packed)) { uint8_t version_trafficclass; ///< Version field + first 4 bit of Traffic Class. uint8_t trafficclass_flowlabel; ///< last 4 bit of Traffic Class - ///< and first 4 bit of Flow Label. + ///< and first 4 bit of Flow Label. uint16_t flowlabel; ///< last 16 bit of Flow Label. uint16_t length; ///< payload length of this packet. uint8_t nextheader; ///< type of next header in this packet. diff --git a/sys/net/network_layer/sixlowpan/border/border.h b/sys/net/network_layer/sixlowpan/border/border.h index f9a7d0c9a5..fbdfe95be5 100644 --- a/sys/net/network_layer/sixlowpan/border/border.h +++ b/sys/net/network_layer/sixlowpan/border/border.h @@ -29,7 +29,7 @@ #include "ip.h" #include "semaphore.h" -extern ipv6_addr_t abr_addr; +extern ipv6_addr_t *abr_addr; uint16_t border_get_serial_reader(void); diff --git a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c index 3cd0ed2b38..1d113872ee 100644 --- a/sys/net/network_layer/sixlowpan/border/bordermultiplex.c +++ b/sys/net/network_layer/sixlowpan/border/bordermultiplex.c @@ -77,7 +77,7 @@ void demultiplex(border_packet_t *packet) context->context.lifetime ); mutex_unlock(&lowpan_context_mutex); - abr_add_context(context->context.version, &abr_addr, context->context.cid); + abr_add_context(context->context.version, abr_addr, context->context.cid); /* Send router advertisement */ break; } @@ -141,7 +141,7 @@ int readpacket(uint8_t *packet_buf, size_t size) break; } - if ((size_t) (line_buf_ptr - packet_buf) >= size - 1) { + if ((size_t)(line_buf_ptr - packet_buf) >= size - 1) { return -SIXLOWERROR_ARRAYFULL; } @@ -179,8 +179,8 @@ int writepacket(uint8_t *packet_buf, size_t size) { uint8_t *byte_ptr = packet_buf; - while ((size_t) (byte_ptr - packet_buf) < size) { - if ((size_t) (byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { + while ((size_t)(byte_ptr - packet_buf) < size) { + if ((size_t)(byte_ptr - packet_buf) > BORDER_BUFFER_SIZE) { return -1; } diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 69005329fe..31952db2c8 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -94,6 +94,8 @@ /* default router list size */ #define DEF_RTR_LST_SIZE (3) /* geeigneten wert finden */ +#define PREFIX_BUF_LEN (NET_IF_MAX * OPT_PI_LIST_LEN) + /* extern variables */ uint8_t ipv6_ext_hdr_len = 0; @@ -102,17 +104,18 @@ uint8_t abr_count = 0; uint8_t nbr_count = 0; uint8_t def_rtr_count = 0; uint8_t rtr_sol_count = 0; -uint8_t prefix_count = 0; +uint8_t prefix_info_count = 0; +uint8_t prefix_buf_count = 0; /* datastructures */ ndp_a6br_cache_t abr_cache[ABR_CACHE_SIZE]; ndp_neighbor_cache_t nbr_cache[NBR_CACHE_SIZE]; ndp_default_router_list_t def_rtr_lst[DEF_RTR_LST_SIZE]; -ndp_prefix_list_t plist[OPT_PI_LIST_LEN]; +ndp_prefix_info_t prefix_info_buf[PREFIX_BUF_LEN]; +uint8_t prefix_buf[sizeof(ipv6_addr_t) * PREFIX_BUF_LEN]; /* pointer */ static uint8_t *llao; -addr_list_t *addr_list_ptr; static ipv6_hdr_t *ipv6_buf; static icmpv6_hdr_t *icmp_buf; @@ -137,15 +140,11 @@ ndp_default_router_list_t *def_rtr_entry; uint8_t recvd_cids[NDP_6LOWPAN_CONTEXT_MAX]; uint8_t icmpv6_opt_hdr_len = 0; uint8_t recvd_cids_len = 0; -ndp_prefix_list_t *recvd_prefixes[OPT_PI_LIST_LEN]; +ndp_prefix_info_t *recvd_prefixes[PREFIX_BUF_LEN]; uint8_t recvd_pref_len = 0; void def_rtr_lst_add(ipv6_addr_t *ipaddr, uint32_t rtr_ltime); void def_rtr_lst_rem(ndp_default_router_list_t *entry); -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr); void nbr_cache_rem(ipv6_addr_t *addr); /** @@ -153,11 +152,12 @@ void nbr_cache_rem(ipv6_addr_t *addr); * configuration. * * @param[out] sllao The SLLAO to set. + * @param[in] if_id The interface to get the link-layer address from. * @param[in] type The value for the type field of the SLLAO. * @param[in] length The value for the length field of the SLLAO */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, - uint8_t length); +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length); int min(int a, int b) { @@ -239,14 +239,14 @@ static icmpv6_ndp_opt_aro_t *get_opt_aro_buf(uint8_t ext_len, uint8_t opt_len) return ((icmpv6_ndp_opt_aro_t *) &buffer[LLHDR_ICMPV6HDR_LEN + ext_len + opt_len]); } -void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_request_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REQUEST; icmp_buf->code = 0; @@ -257,35 +257,36 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REQ_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo request (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } -void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, char *data, size_t data_len) +void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, uint8_t *data, size_t data_len) { uint16_t packet_length; ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); icmp_buf->type = ICMPV6_TYPE_ECHO_REPLY; icmp_buf->code = 0; @@ -296,23 +297,24 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch ipv6_buf->hoplimit = ipv6_get_default_hop_limit(); memcpy(&ipv6_buf->destaddr, destaddr, sizeof(ipv6_addr_t)); - ipv6_iface_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); - echo_buf->id = id; - echo_buf->seq = seq; + ipv6_net_if_get_best_src_addr(&ipv6_buf->srcaddr, &ipv6_buf->destaddr); + echo_buf->id = HTONS(id); + echo_buf->seq = HTONS(seq); memcpy(echo_data_buf, data, data_len); packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + ECHO_REPL_LEN + data_len; - ipv6_buf->length = packet_length - IPV6_HDR_LEN; + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send echo request to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + printf("INFO: send echo reply (id = %04x, seq = %d, data_len = %d) to: %s\n", + id, seq, data_len, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -321,6 +323,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ch void icmpv6_send_router_sol(uint8_t sllao) { uint16_t packet_length; + int if_id = 0; // TODO get this somehow ipv6_buf = ipv6_get_buf(); icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); @@ -337,29 +340,39 @@ void icmpv6_send_router_sol(uint8_t sllao) //iface_find_src_ipaddr(&ipv6_buf->srcaddr, NDP_ADDR_STATE_PREFERRED, /* IPV6_ADDR_TYPE_MULTICAST); */ - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmpv6_opt_hdr_len = RTR_SOL_LEN; - ipv6_buf->length = HTONS(ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN); if (sllao == OPT_SLLAO) { opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + - RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + + RTR_SOL_LEN + OPT_STLLAO_MIN_LEN; + } } else { packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len + RTR_SOL_LEN; } + ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); + icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: send router solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); #endif ipv6_send_packet(ipv6_buf); } @@ -368,15 +381,17 @@ void recv_echo_req(void) { ipv6_buf = ipv6_get_buf(); icmpv6_echo_request_hdr_t *echo_buf = get_echo_req_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - (IPV6_HDR_LEN + ICMPV6_HDR_LEN + - ipv6_ext_hdr_len + ECHO_REQ_LEN); + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REQ_LEN; + #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo request from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -387,8 +402,8 @@ void recv_echo_req(void) } #endif - icmpv6_send_echo_reply(&ipv6_buf->srcaddr, echo_buf->id, echo_buf->seq, - echo_data_buf, data_len); + icmpv6_send_echo_reply(&ipv6_buf->srcaddr, NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), echo_data_buf, data_len); } void recv_echo_repl(void) @@ -396,14 +411,16 @@ void recv_echo_repl(void) #ifdef DEBUG_ENABLED ipv6_buf = ipv6_get_buf(); icmpv6_echo_reply_hdr_t *echo_buf = get_echo_repl_buf(ipv6_ext_hdr_len); - char *echo_data_buf = ((char *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); - size_t data_len = ipv6_buf->length - ICMPV6_HDR_LEN - ECHO_REPL_LEN; + uint8_t *echo_data_buf = ((uint8_t *)echo_buf) + sizeof(icmpv6_echo_reply_hdr_t); + size_t data_len = NTOHS(ipv6_buf->length) - ICMPV6_HDR_LEN - ECHO_REPL_LEN; char addr_str[IPV6_MAX_ADDR_STR_LEN]; printf("INFO: received echo reply from: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); printf("\n"); - printf("id = 0x%04x, seq = %d\n", echo_buf->id, echo_buf->seq); + printf("id = 0x%04x, seq = %d, data_len = %d\n", NTOHS(echo_buf->id), + NTOHS(echo_buf->seq), data_len); for (size_t i = 0; i < data_len; i++) { printf("%02x ", echo_data_buf[i]); @@ -420,6 +437,7 @@ void recv_echo_repl(void) void recv_rtr_sol(void) { + int if_id = 0; // TODO, get this somehow icmpv6_opt_hdr_len = RTR_SOL_LEN; ipv6_buf = ipv6_get_buf(); @@ -431,25 +449,39 @@ void recv_rtr_sol(void) } if (llao != NULL) { + uint8_t lladdr_len; nbr_entry = ndp_neighbor_cache_search(&ipv6_buf->srcaddr); + if (opt_stllao_buf->length == 2) { + lladdr_len = 8; + } + else if (opt_stllao_buf->length == 1) { + lladdr_len = 2; + } + else { + DEBUG("Unknown length for S/TLLAO: %d * 8 Bytes.\n", opt_stllao_buf->length); + return; + } + if (nbr_entry != NULL) { - /* found neighbor in cache, update values and check long addr */ - if (memcmp(&llao[2], &nbr_entry->laddr, 8) == 0) { + /* found neighbor in cache, update values and check addr */ + if (memcmp(&llao[2], &nbr_entry->lladdr, lladdr_len) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - /* new long addr found, update */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + /* new addr found, update */ + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], lladdr_len); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } } else { /* nothing found, add neigbor into cache*/ - nbr_cache_add(&ipv6_buf->srcaddr, (ieee_802154_long_t *)&llao[2], - 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, &llao[2], lladdr_len, + 0, NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); } } @@ -460,12 +492,6 @@ void recv_rtr_sol(void) else { icmpv6_send_router_adv(&ipv6_buf->srcaddr, 0, 0, OPT_PI, 0, 0); } - -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send router advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif } uint8_t set_opt_6co_flags(uint8_t compression_flag, uint8_t cid) @@ -495,6 +521,7 @@ lowpan_context_t *abr_get_context(ndp_a6br_cache_t *abr, uint8_t cid); void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, uint8_t sixco, uint8_t abro) { + int if_id = 0; // TODO: get this somehow uint16_t packet_length; lowpan_context_t *contexts = NULL; @@ -516,7 +543,7 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 memcpy(&ipv6_buf->destaddr, addr, 16); } - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); icmp_buf->type = ICMPV6_TYPE_ROUTER_ADV; icmp_buf->code = 0; @@ -537,9 +564,17 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 if (sllao == OPT_SLLAO) { /* set link layer address option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 2); - icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; - packet_length += OPT_STLLAO_MAX_LEN; + + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (mtu == OPT_MTU) { @@ -638,17 +673,21 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 } if (pi == OPT_PI) { + ndp_prefix_info_t *prefix = NULL; + /* set prefix option */ - for (int i = 0; i < OPT_PI_LIST_LEN; i++) { - if (plist[i].inuse && plist[i].adv) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX && + prefix->inuse && prefix->advertisable) { opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - memcpy(&(opt_pi_buf->addr.uint8[0]), &(plist[i].addr.uint8[0]), 16); + memset(&opt_pi_buf->addr, 0, sizeof(ipv6_addr_t)); + memcpy(&opt_pi_buf->addr, &prefix->prefix_data, prefix->prefix_len); opt_pi_buf->type = OPT_PI_TYPE; opt_pi_buf->length = OPT_PI_LEN; - opt_pi_buf->prefix_length = plist[i].length; - opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1; - opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime); - opt_pi_buf->pref_ltime = HTONL(plist[i].pref_ltime); + opt_pi_buf->prefix_length = prefix->prefix_len; + opt_pi_buf->l_a_reserved1 = prefix->flags; + opt_pi_buf->val_ltime = HTONL(prefix->valid_lifetime); + opt_pi_buf->pref_ltime = HTONL(prefix->preferred_lifetime); opt_pi_buf->reserved2 = 0; packet_length += OPT_PI_HDR_LEN; icmpv6_opt_hdr_len += OPT_PI_HDR_LEN; @@ -661,10 +700,19 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 /* calculate checksum */ icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send router advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_rtr_adv(void) { + int if_id = 0; // TODO: get this somehow int8_t trigger_ns = -1; int8_t abro_found = 0; int16_t abro_version = 0; /* later replaced, just to supress warnings */ @@ -680,11 +728,19 @@ void recv_rtr_adv(void) /* update interface reachable time and retrans timer */ if (rtr_adv_buf->reachable_time != 0) { - iface.adv_reachable_time = HTONL(rtr_adv_buf->reachable_time); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_reachable_time = NTOHL(rtr_adv_buf->reachable_time); + } } if (rtr_adv_buf->retrans_timer != 0) { - iface.adv_retrans_timer = HTONL(rtr_adv_buf->retrans_timer); + ipv6_net_if_ext_t *iface; + + if ((iface = ipv6_net_if_get_ext(if_id)) == NULL) { + iface->adv_retrans_timer = NTOHL(rtr_adv_buf->retrans_timer); + } } def_rtr_entry = ndp_default_router_list_search(&ipv6_buf->srcaddr); @@ -737,46 +793,51 @@ void recv_rtr_adv(void) } if (opt_pi_buf->l_a_reserved1 & ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) { - addr_list_ptr = ipv6_iface_addr_prefix_eq(&opt_pi_buf->addr); + ipv6_net_if_hit_t addr_hit; - if (addr_list_ptr == NULL) { + if (!ipv6_net_if_addr_prefix_eq(&addr_hit, &opt_pi_buf->addr)) { /* 5.5.3d */ if (opt_pi_buf->val_ltime != 0) { /* iid will also be added here */ - ipv6_addr_set_by_eui64(&newaddr, + ipv6_addr_set_by_eui64(&newaddr, if_id, &opt_pi_buf->addr); /* add into address list * TODO: duplicate address detection is not * implementet yet, so all new addresse will * be added with state PREFFERED */ - ipv6_iface_add_addr(&newaddr, - IPV6_ADDR_TYPE_UNICAST, - NDP_ADDR_STATE_PREFERRED, - opt_pi_buf->val_ltime, - opt_pi_buf->pref_ltime); + ipv6_net_if_add_addr(if_id, &newaddr, + NDP_ADDR_STATE_PREFERRED, + opt_pi_buf->val_ltime, + opt_pi_buf->pref_ltime, 0); DEBUG("INFO: added address to interface\n"); trigger_ns = 1; } } else { /* 5.5.3e */ - set_remaining_time(&(addr_list_ptr->pref_ltime), opt_pi_buf->pref_ltime); + set_remaining_time(&addr_hit.addr->preferred_lifetime, + opt_pi_buf->pref_ltime); /* 7200 = 2hours in seconds */ if (HTONL(opt_pi_buf->val_ltime) > 7200 || HTONL(opt_pi_buf->val_ltime) > - get_remaining_time(&(addr_list_ptr->val_ltime))) { - set_remaining_time(&(addr_list_ptr->val_ltime), HTONL(opt_pi_buf->val_ltime)); + get_remaining_time(&addr_hit.addr->valid_lifetime)) { + set_remaining_time(&addr_hit.addr->valid_lifetime, + HTONL(opt_pi_buf->val_ltime)); } else { /* reset valid lifetime to 2 hours */ - set_remaining_time(&(addr_list_ptr->val_ltime), 7200); + set_remaining_time(&addr_hit.addr->valid_lifetime, + 7200); } } } } - /* TODO: save found prefixes */ + ndp_add_prefix_info(if_id, &opt_pi_buf->addr, opt_pi_buf->length, + opt_pi_buf->val_ltime, opt_pi_buf->pref_ltime, + 0, opt_pi_buf->l_a_reserved1); + break; } @@ -843,11 +904,6 @@ void recv_rtr_adv(void) * * if new address was configured, set src to newaddr(gp16) */ icmpv6_send_neighbor_sol(&newaddr, &(ipv6_buf->srcaddr), &(ipv6_buf->srcaddr), OPT_SLLAO, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor solicitation to: %s\n", - ipv6_addr_to_str(addr_str, &(ipv6_buf->destaddr))); -#endif } } @@ -856,6 +912,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * { uint16_t packet_length; int if_id = 0; // TODO: get this somehow + ipv6_net_if_hit_t hit; ipv6_buf = ipv6_get_buf(); ipv6_buf->version_trafficclass = IPV6_VER; @@ -883,9 +940,9 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN; - if (ipv6_iface_addr_match(targ) == NULL) { + if (!ipv6_net_if_addr_match(&hit, targ)) { if (src == NULL) { - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); } else { memcpy(&(ipv6_buf->srcaddr), src, 16); @@ -894,10 +951,17 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } } @@ -926,17 +990,25 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor solicitation to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_sol(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); llao = NULL; icmpv6_opt_hdr_len = NBR_SOL_LEN; uint8_t send_na = 0; uint8_t sllao_set = 0; - uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); /* check whick options are set, we need that because an aro @@ -971,11 +1043,13 @@ void recv_nbr_sol(void) if (nbr_entry != NULL) { switch (opt_stllao_buf->length) { case (1): { - if (memcmp(&llao[2], &(nbr_entry->saddr), 2) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 2) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->saddr, &llao[2], 2); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 2); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -984,11 +1058,13 @@ void recv_nbr_sol(void) } case (2): { - if (memcmp(&llao[2], &(nbr_entry->laddr), 8) == 0) { + if (memcmp(&llao[2], &(nbr_entry->lladdr), 8) == 0) { + nbr_entry->if_id = if_id; nbr_entry->isrouter = 0; } else { - memcpy(&nbr_entry->laddr, &llao[2], 8); + nbr_entry->if_id = if_id; + memcpy(&nbr_entry->lladdr, &llao[2], 8); nbr_entry->state = NDP_NCE_STATUS_STALE; nbr_entry->isrouter = 0; } @@ -1003,21 +1079,21 @@ void recv_nbr_sol(void) else { switch (opt_stllao_buf->length) { case (1): { - nbr_cache_add(&ipv6_buf->srcaddr, - NULL , 0, NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, - (ieee_802154_short_t *)&llao[2]); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 2, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } case (2): { - nbr_cache_add(&ipv6_buf->srcaddr, - (ieee_802154_long_t *)&llao[2], 0, - NDP_NCE_STATUS_STALE, - NDP_NCE_TYPE_TENTATIVE, - NBR_CACHE_LTIME_TEN, NULL); + ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &llao[2], 8, 0, + NDP_NCE_STATUS_STALE, + NDP_NCE_TYPE_TENTATIVE, + NBR_CACHE_LTIME_TEN); break; } @@ -1035,6 +1111,7 @@ void recv_nbr_sol(void) * isn't unspecified - draft-ietf-6lowpan-nd-15#section-6.5 */ if (!(ipv6_addr_is_unspecified(&ipv6_buf->srcaddr)) && sllao_set == 1) { + uint8_t aro_state = NDP_OPT_ARO_STATE_SUCCESS; opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); @@ -1045,10 +1122,10 @@ void recv_nbr_sol(void) if (nbr_entry == NULL) { /* create neighbor cache */ - aro_state = nbr_cache_add(&ipv6_buf->srcaddr, - &(opt_aro_buf->eui64), 0, - NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, - opt_aro_buf->reg_ltime, NULL); + aro_state = ndp_neighbor_cache_add(if_id, &ipv6_buf->srcaddr, + &(opt_aro_buf->eui64), 8, 0, + NDP_NCE_STATUS_STALE, NDP_NCE_TYPE_TENTATIVE, + opt_aro_buf->reg_ltime); } else { if (memcmp(&(nbr_entry->addr.uint16[4]), @@ -1086,20 +1163,19 @@ void recv_nbr_sol(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *alist_targ, *alist_dest; + ipv6_net_if_hit_t alist_targ, alist_dest; nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len); - alist_targ = ipv6_iface_addr_match(&(nbr_sol_buf->target_addr)); - if (alist_targ != NULL) { - alist_dest = ipv6_iface_addr_match(&(ipv6_buf->destaddr)); + if (ipv6_net_if_addr_match(&alist_targ, &nbr_sol_buf->target_addr) != NULL) { + ipv6_net_if_addr_match(&alist_dest, &ipv6_buf->destaddr); - if ((memcmp(&(alist_targ->addr), &(alist_dest->addr), 16) == 0) || + if ((memcmp(alist_targ.addr->addr_data, alist_dest.addr->addr_data, 16) == 0) || ipv6_addr_is_solicited_node(&ipv6_buf->destaddr)) { memcpy(&(ipv6_buf->destaddr.uint8[0]), - &(ipv6_buf->srcaddr.uint8[0]), 16); + &(ipv6_buf->srcaddr.uint8[0]), sizeof(ipv6_addr_t)); memcpy(&(ipv6_buf->srcaddr.uint8[0]), - &(nbr_sol_buf->target_addr.uint8[0]), 16); + &(nbr_sol_buf->target_addr.uint8[0]), sizeof(ipv6_addr_t)); send_na = 1; } } @@ -1108,12 +1184,7 @@ void recv_nbr_sol(void) /* solicited na */ uint8_t flags = (ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE | ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED); icmpv6_send_neighbor_adv(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr), - &(alist_targ->addr), flags, 0, OPT_ARO); -#ifdef DEBUG_ENABLED - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("INFO: send neighbor advertisment to: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_buf->destaddr)); -#endif + alist_targ.addr->addr_data, flags, 0, OPT_ARO); } } @@ -1135,8 +1206,13 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->type = ICMPV6_TYPE_NEIGHBOR_ADV; icmp_buf->code = 0; - memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); - memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + if (&ipv6_buf->destaddr != dst) { + memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16); + } + + if (&ipv6_buf->srcaddr != src) { + memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16); + } nbr_adv_buf = get_nbr_adv_buf(ipv6_ext_hdr_len); nbr_adv_buf->rso = rso; @@ -1149,10 +1225,17 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t if (sllao == OPT_SLLAO) { /* set sllao option */ opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, icmpv6_opt_hdr_len); - icmpv6_ndp_set_sllao(opt_stllao_buf, NDP_OPT_SLLAO_TYPE, 1); - icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; - packet_length += OPT_STLLAO_MIN_LEN; + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_LONG) { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 2); + icmpv6_opt_hdr_len += OPT_STLLAO_MAX_LEN; + packet_length += OPT_STLLAO_MAX_LEN; + } + else { + icmpv6_ndp_set_sllao(opt_stllao_buf, if_id, NDP_OPT_SLLAO_TYPE, 1); + icmpv6_opt_hdr_len += OPT_STLLAO_MIN_LEN; + packet_length += OPT_STLLAO_MIN_LEN; + } } if (aro == OPT_ARO) { @@ -1180,12 +1263,21 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send neighbor advertisement to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } void recv_nbr_adv(void) { + int if_id = 0; // TODO, get this somehow ipv6_buf = ipv6_get_buf(); - uint16_t packet_length = IPV6_HDR_LEN + ipv6_buf->length; + uint16_t packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); icmpv6_opt_hdr_len = NBR_ADV_LEN; llao = NULL; nbr_entry = NULL; @@ -1211,16 +1303,16 @@ void recv_nbr_adv(void) icmpv6_opt_hdr_len += (opt_buf->length * 8); } - addr_list_t *addr; - addr = ipv6_iface_addr_match(&nbr_adv_buf->target_addr); + ipv6_net_if_hit_t hit; - if (addr == NULL) { + if (ipv6_net_if_addr_match(&hit, &nbr_adv_buf->target_addr) == NULL) { nbr_entry = ndp_neighbor_cache_search(&nbr_adv_buf->target_addr); if (nbr_entry != NULL) { if (llao != 0) { - /* TODO: untersheiden zwischen short und long stllao option */ - new_ll = memcmp(&llao[2], &(nbr_entry->laddr), 8); + new_ll = memcmp(&llao[2], &(nbr_entry->lladdr), + nbr_entry->lladdr_len); + ((icmpv6_ndp_opt_stllao_t *)llao)->length = nbr_entry->lladdr_len / 8 + 1; } if (nbr_entry->state == NDP_NCE_STATUS_INCOMPLETE) { @@ -1228,8 +1320,19 @@ void recv_nbr_adv(void) return; } - /* TODO: untersheiden zwischen short und long stllao option */ - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); + } + else { + return; + } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { nbr_entry->state = NDP_NCE_STATUS_REACHABLE; @@ -1254,7 +1357,19 @@ void recv_nbr_adv(void) (!(nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_OVERRIDE) && llao != 0 && !new_ll)) { if (llao != 0) { - memcpy(&nbr_entry->laddr, &llao[2], 8); + if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 2) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 8; + } + else if (((icmpv6_ndp_opt_stllao_t *)llao)->length == 1) { + nbr_entry->if_id = if_id; + nbr_entry->lladdr_len = 2; + } + else { + return; + } + + memcpy(&nbr_entry->lladdr, &llao[2], nbr_entry->lladdr_len); } if (nbr_adv_buf->rso & ICMPV6_NEIGHBOR_ADV_FLAG_SOLICITED) { @@ -1274,7 +1389,8 @@ void recv_nbr_adv(void) } /* link-layer address option - RFC4861 section 4.6.1/ RFC4944 8. */ -void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t length) +void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, + uint8_t type, uint8_t length) { sllao->type = type; sllao->length = length; @@ -1284,17 +1400,34 @@ void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, uint8_t type, uint8_t /* get link layer address */ switch (length) { case (1): { - memcpy(&llao[2], &(iface.saddr), 2); - memset(&llao[4], 0, 4); - break; + uint16_t addr = net_if_get_hardware_address(if_id); + + if (addr != 0) { + addr = HTONS(addr); + memcpy(&llao[2], &addr, 2); + memset(&llao[4], 0, 4); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } case (2): { - memcpy(&llao[2], &(iface.laddr), 8); - memset(&llao[10], 0, 6); - break; + net_if_eui64_t addr; + + if (net_if_get_eui64(&addr, if_id, 0)) { + memcpy(&llao[2], &addr, 8); + memset(&llao[10], 0, 6); + break; + } + else { + goto SET_SLLAO_DEFAULT; + } } + SET_SLLAO_DEFAULT: + default: { printf("ERROR: llao not set\n"); break; @@ -1350,6 +1483,14 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, icmp_buf->checksum = 0; icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + +#ifdef DEBUG_ENABLED + char addr_str[IPV6_MAX_ADDR_STR_LEN]; + printf("INFO: send parameter problem to: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->destaddr)); +#endif + ipv6_send_packet(ipv6_buf); } //------------------------------------------------------------------------------ @@ -1368,21 +1509,64 @@ ndp_neighbor_cache_t *ndp_neighbor_cache_search(ipv6_addr_t *ipaddr) return NULL; } -uint8_t nbr_cache_add(ipv6_addr_t *ipaddr, ieee_802154_long_t *laddr, - uint8_t isrouter, ndp_nce_state_t state, - ndp_nce_type_t type, uint16_t ltime, - ieee_802154_short_t *saddr) +ndp_neighbor_cache_t *ndp_get_ll_address(ipv6_addr_t *ipaddr) +{ + ndp_neighbor_cache_t *nce = ndp_neighbor_cache_search(ipaddr); + + if (nce == NULL || nce->type == NDP_NCE_TYPE_GC || + nce->state == NDP_NCE_STATUS_INCOMPLETE) { + // TODO: send neighbor solicitation, wait, and recheck cache + return NULL; + } + + return nce; +} + +int ndp_addr_is_on_link(ipv6_addr_t *dest_addr) +{ + ndp_prefix_info_t *pi; + ndp_neighbor_cache_t *nce; + int if_id = -1; + + if (ipv6_addr_is_link_local(dest_addr)) { + return 1; + } + + if ((nce = ndp_neighbor_cache_search(dest_addr))) { + return 1; + } + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if ((pi = ndp_prefix_info_search(if_id, dest_addr, 128))) { + return (pi->flags & ICMPV6_NDP_OPT_PI_FLAG_ON_LINK) != 0; + } + } + + /* TODO Other cases (http://tools.ietf.org/html/rfc4861#page-6): + * * neighboring router specifies address as target of + * redircect message + * * neighbor discovery message is received from address. + */ + + return 0; +} + +uint8_t ndp_neighbor_cache_add(int if_id, const ipv6_addr_t *ipaddr, + const void *lladdr, uint8_t lladdr_len, + uint8_t isrouter, ndp_nce_state_t state, + ndp_nce_type_t type, uint16_t ltime) { (void) ltime; - (void) saddr; if (nbr_count == NBR_CACHE_SIZE) { printf("ERROR: neighbor cache full\n"); return NDP_OPT_ARO_STATE_NBR_CACHE_FULL; } + nbr_cache[nbr_count].if_id = if_id; memcpy(&(nbr_cache[nbr_count].addr), ipaddr, 16); - memcpy(&(nbr_cache[nbr_count].laddr), laddr, 8); + memcpy(&(nbr_cache[nbr_count].lladdr), lladdr, lladdr_len); + nbr_cache[nbr_count].lladdr_len = lladdr_len; nbr_cache[nbr_count].isrouter = isrouter; nbr_cache[nbr_count].state = state; nbr_cache[nbr_count].type = type; @@ -1572,23 +1756,115 @@ void def_rtr_lst_rem(ndp_default_router_list_t *entry) } //------------------------------------------------------------------------------ -/* prefix list functions */ +/* prefix information functions */ -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1) +int ndp_add_prefix_info(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, uint8_t advertisable, + uint8_t flags) { - if (prefix_count == OPT_PI_LIST_LEN) { - return SIXLOWERROR_ARRAYFULL; - } - else { - plist[prefix_count].inuse = 1; - plist[prefix_count].length = size; - plist[prefix_count].adv = adv_opt; - plist[prefix_count].l_a_reserved1 = l_a_reserved1; - plist[prefix_count].val_ltime = HTONL(val_ltime); - plist[prefix_count].pref_ltime = HTONL(pref_ltime); - memcpy(&(plist[prefix_count].addr.uint8[0]), &(addr->uint8[0]), 16); + ndp_prefix_info_t *prefix_info = ndp_prefix_info_match(if_id, prefix, + prefix_len); + + if (prefix_info) { + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); return SIXLOWERROR_SUCCESS; } + + if ((prefix_info_count >= PREFIX_BUF_LEN) || + (prefix_buf_count >= sizeof(prefix_buf))) { + return SIXLOWERROR_ARRAYFULL; + } + + if (prefix_len > 128) { + prefix_len = 128; + } + + prefix_info = &prefix_info_buf[prefix_info_count]; + + if (prefix_len > 0) { + memcpy(&prefix_buf[prefix_buf_count], prefix, (prefix_len / 8) + 1); + } + + prefix_info->prefix_data = (ipv6_addr_t *) &prefix_buf[prefix_buf_count]; + prefix_buf_count += prefix_len; + + prefix_info->prefix_len = prefix_len; + prefix_info->prefix_protocol = NET_IF_L3P_IPV6_PREFIX; + prefix_info->inuse = 1; + prefix_info->advertisable = advertisable; + prefix_info->flags = 0xc0 & flags; + prefix_info->valid_lifetime = HTONL(valid_lifetime); + prefix_info->preferred_lifetime = HTONL(preferred_lifetime); + + if (!net_if_add_address(if_id, (net_if_addr_t *) prefix_info)) { + return SIXLOWERROR_VALUE; + } + + prefix_info_count++; + + return SIXLOWERROR_SUCCESS; +} + +ndp_prefix_info_t *ndp_prefix_info_search(int if_id, const ipv6_addr_t *addr, + uint8_t up_to) +{ + uint8_t best_match = 0; + ndp_prefix_info_t *prefix = NULL, *tmp = NULL; + + if (up_to > 128) { + up_to = 128; + } + + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &prefix)) { + if (prefix->prefix_protocol & NET_IF_L3P_IPV6_PREFIX) { + uint8_t match = 0, len = min(up_to, prefix->prefix_len); + uint8_t byte_len = (len / 8); + + for (int i = 0; i < byte_len; i++) { + if (addr->uint8[i] != prefix->prefix_data->uint8[i]) { + break; + } + + match += 8; + } + + if (byte_len < 16) { + for (int i = len % 8; i > 0; i--) { + if (addr->uint8[byte_len] >> i != + prefix->prefix_data->uint8[byte_len] >> i) { + break; + } + + match += 1; + } + } + + if (prefix->prefix_len == 0 && match > best_match) { + tmp = prefix; + best_match = match; + } + } + } + + return tmp; +} + +ndp_prefix_info_t *ndp_prefix_info_match(int if_id, const ipv6_addr_t *prefix, + uint8_t prefix_len) +{ + ndp_prefix_info_t *res = ndp_prefix_info_search(if_id, prefix, + prefix_len); + + if (res != NULL && res->prefix_len == prefix_len) { + return res; + } + else { + return NULL; + } } diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index 6cb502d3fe..a8fcf12f15 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -42,7 +42,7 @@ enum option_types_t { OPT_DAC, }; -extern unsigned int nd_nbr_cache_rem_pid; +extern int nd_nbr_cache_rem_pid; void recv_echo_req(void); @@ -53,9 +53,6 @@ void recv_nbr_adv(void); void recv_nbr_sol(void); void nbr_cache_auto_rem(void); -int plist_add(ipv6_addr_t *addr, uint8_t size, uint32_t val_ltime, - uint32_t pref_ltime, uint8_t adv_opt, uint8_t l_a_reserved1); - ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); void abr_remove_context(uint8_t cid); diff --git a/sys/net/network_layer/sixlowpan/ip.c b/sys/net/network_layer/sixlowpan/ip.c index 5b2e453836..bf7f31ddbc 100644 --- a/sys/net/network_layer/sixlowpan/ip.c +++ b/sys/net/network_layer/sixlowpan/ip.c @@ -25,6 +25,7 @@ #include "vtimer.h" #include "mutex.h" #include "msg.h" +#include "net_help.h" #include "net_if.h" #include "sixlowpan/mac.h" @@ -32,17 +33,18 @@ #include "icmp.h" #include "lowpan.h" -#include "destiny/socket.h" #include "net_help.h" #define ENABLE_DEBUG (0) #if ENABLE_DEBUG +#define DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; #endif #include "debug.h" #define IP_PKT_RECV_BUF_SIZE (64) #define LLHDR_IPV6HDR_LEN (LL_HDR_LEN + IPV6_HDR_LEN) +#define IPV6_NET_IF_ADDR_BUFFER_LEN (NET_IF_MAX * IPV6_NET_IF_ADDR_LIST_LEN) uint8_t ip_send_buffer[BUFFER_SIZE]; uint8_t buffer[BUFFER_SIZE]; @@ -51,34 +53,79 @@ ipv6_hdr_t *ipv6_buf; icmpv6_hdr_t *icmp_buf; uint8_t *nextheader; -uint8_t iface_addr_list_count = 0; int udp_packet_handler_pid = 0; int tcp_packet_handler_pid = 0; int rpl_process_pid = 0; ipv6_addr_t *(*ip_get_next_hop)(ipv6_addr_t *) = 0; +static ipv6_net_if_ext_t ipv6_net_if_ext[NET_IF_MAX]; +static ipv6_net_if_addr_t ipv6_net_if_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static ipv6_addr_t ipv6_addr_buffer[IPV6_NET_IF_ADDR_BUFFER_LEN]; +static uint8_t ipv6_net_if_addr_buffer_count = 0; + static uint8_t default_hop_limit = MULTIHOP_HOPLIMIT; /* registered upper layer threads */ int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; -int ipv6_send_packet(ipv6_hdr_t *bytes) +int ipv6_send_packet(ipv6_hdr_t *packet) { - int if_id = 0; - uint16_t offset = IPV6_HDR_LEN + HTONS(bytes->length); + uint16_t length = IPV6_HDR_LEN + NTOHS(packet->length); + ndp_neighbor_cache_t *nce; - bytes->flowlabel = HTONS(bytes->flowlabel); - bytes->length = HTONS(bytes->length); + ipv6_net_if_get_best_src_addr(&packet->srcaddr, &packet->destaddr); - memset(bytes, 0, BUFFER_SIZE); - memcpy(bytes + LL_HDR_LEN, bytes, offset); + if (!ipv6_addr_is_multicast(&packet->destaddr) && + ndp_addr_is_on_link(&packet->destaddr)) { + nce = ndp_get_ll_address(&packet->destaddr); - if (sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, - (uint8_t *)packet, length) < 0) { - return -1; + + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, + length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; } + else { + /* see if dest should be routed to a different next hop */ + if (ipv6_addr_is_multicast(&packet->destaddr)) { + /* if_id will be ignored */ + uint16_t addr = 0xffff; + return sixlowpan_lowpan_sendto(0, &addr, 2, (uint8_t *)packet, + length); + } - return length; + if (ip_get_next_hop == NULL) { + return -1; + } + + ipv6_addr_t *dest = ip_get_next_hop(&packet->destaddr); + + if (dest == NULL) { + return -1; + } + + nce = ndp_get_ll_address(&packet->destaddr); + + if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)packet, length) < 0) { + /* XXX: this is wrong, but until ND does not work correctly, + * this is the only way (aka the old way)*/ + uint16_t raddr = NTOHS(packet->destaddr.uint16[7]); + sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length); + /* return -1; */ + } + + return length; + } } ipv6_hdr_t *ipv6_get_buf_send(void) @@ -110,7 +157,6 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, const uint8_t *payload, uint16_t payload_length) { uint8_t *p_ptr; - uint16_t packet_length; if (next_header == IPV6_PROTO_NUM_TCP) { p_ptr = get_payload_buf_send(ipv6_ext_hdr_len); @@ -125,32 +171,14 @@ int ipv6_sendto(const ipv6_addr_t *dest, uint8_t next_header, ipv6_buf->trafficclass_flowlabel = 0; ipv6_buf->flowlabel = 0; ipv6_buf->nextheader = next_header; - ipv6_buf->hoplimit = default_hop_limit; - ipv6_buf->length = payload_length; + ipv6_buf->hoplimit = MULTIHOP_HOPLIMIT; + ipv6_buf->length = HTONS(payload_length); memcpy(&(ipv6_buf->destaddr), dest, 16); - ipv6_iface_get_best_src_addr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr)); memcpy(p_ptr, payload, payload_length); - packet_length = IPV6_HDR_LEN + payload_length; - - /* see if dest should be routed to a different next hop */ - if (ip_get_next_hop == NULL || ipv6_addr_is_multicast(&ipv6_buf->destaddr)) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL) { - return -1; - } - - sixlowpan_lowpan_sendto(0, &dest->uint16[4], 8, - (uint8_t *)ipv6_buf, packet_length); - - return payload_length; + return ipv6_send_packet(ipv6_buf); } void ipv6_set_default_hop_limit(uint8_t hop_limit) @@ -278,19 +306,40 @@ uint8_t ipv6_get_addr_match(const ipv6_addr_t *src, return val; } +int is_our_address(ipv6_addr_t *addr) +{ + ipv6_net_if_ext_t *net_if_ext; + ipv6_net_if_addr_t *myaddr; + uint8_t prefix, suffix; + int if_id = -1; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + net_if_ext = ipv6_net_if_get_ext(if_id); + myaddr = NULL; + prefix = net_if_ext->prefix / 8; + suffix = IPV6_ADDR_LEN - prefix; + + while ((myaddr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **) &myaddr)) != NULL) { + if ((ipv6_get_addr_match(myaddr->addr_data, addr) >= net_if_ext->prefix) && + (memcmp(&addr->uint8[prefix], &myaddr->addr_data->uint8[prefix], suffix) == 0)) { + return 1; + } + } + } + + return 0; +} + void ipv6_process(void) { msg_t m_recv_lowpan, m_send_lowpan; msg_t m_recv, m_send; - ipv6_addr_t myaddr; uint8_t i; uint16_t packet_length; msg_init_queue(ip_msg_queue, IP_PKT_RECV_BUF_SIZE); - ipv6_addr_init(&myaddr, 0xabcd, 0x0, 0x0, 0x0, 0x3612, 0x00ff, 0xfe00, - sixlowpan_mac_get_radio_address()); - while (1) { msg_receive(&m_recv_lowpan); @@ -308,40 +357,16 @@ void ipv6_process(void) } } - /* destination is foreign address */ - if ((ipv6_get_addr_match(&myaddr, &ipv6_buf->destaddr) >= 112) && - (ipv6_buf->destaddr.uint8[15] != myaddr.uint8[15])) { - packet_length = IPV6_HDR_LEN + ipv6_buf->length; - - ipv6_addr_t *dest; - - if (ip_get_next_hop == NULL) { - dest = &ipv6_buf->destaddr; - } - else { - dest = ip_get_next_hop(&ipv6_buf->destaddr); - } - - if (dest == NULL || --ipv6_buf->hoplimit == 0) { - continue; - } - - /* copy received packet to send buffer */ - memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); - /* send packet to node ID derived from dest IP */ - sixlowpan_lowpan_sendto((ieee_802154_long_t *) &dest->uint16[4], - (uint8_t *)ipv6_get_buf_send(), - packet_length); - } /* destination is our address */ - else { + if (is_our_address(&ipv6_buf->destaddr)) { switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); /* checksum test*/ - if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, ipv6_buf->length, IPV6_PROTO_NUM_ICMPV6) != 0xffff) { - printf("ERROR: wrong checksum\n"); + if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, NTOHS(ipv6_buf->length), + IPV6_PROTO_NUM_ICMPV6) != 0xffff) { + DEBUG("ERROR: wrong checksum\n"); } icmpv6_demultiplex(icmp_buf); @@ -354,7 +379,7 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid); } else { - printf("INFO: No TCP handler registered.\n"); + DEBUG("INFO: No TCP handler registered.\n"); } break; @@ -366,14 +391,14 @@ void ipv6_process(void) msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid); } else { - printf("INFO: No UDP handler registered.\n"); + DEBUG("INFO: No UDP handler registered.\n"); } break; } case (IPV6_PROTO_NUM_NONE): { - printf("INFO: Packet with no Header following the IPv6 Header received.\n"); + DEBUG("INFO: Packet with no Header following the IPv6 Header received.\n"); break; } @@ -381,97 +406,205 @@ void ipv6_process(void) break; } } + /* destination is foreign address */ + else { + packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); + ndp_neighbor_cache_t *nce; + + ipv6_addr_t *dest; + + if (ip_get_next_hop == NULL) { + dest = &ipv6_buf->destaddr; + } + else { + dest = ip_get_next_hop(&ipv6_buf->destaddr); + } + + if ((dest == NULL) || ((--ipv6_buf->hoplimit) == 0)) { + continue; + } + + nce = ndp_get_ll_address(dest); + + /* copy received packet to send buffer */ + memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); + + /* send packet to node ID derived from dest IP */ + if (nce != NULL) { + sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, + nce->lladdr_len, + (uint8_t *)ipv6_get_buf_send(), + packet_length); + } + } msg_reply(&m_recv_lowpan, &m_send_lowpan); } } -void ipv6_iface_add_addr(const ipv6_addr_t *addr, ipv6_addr_type_t type, - ndp_addr_state_t state, uint32_t val_ltime, - uint32_t pref_ltime) +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id) { + if (net_if_get_interface(if_id)) { + return &ipv6_net_if_ext[if_id]; + } + else { + return NULL; + } +} + +int ipv6_net_if_add_addr(int if_id, const ipv6_addr_t *addr, + ndp_addr_state_t state, uint32_t val_ltime, + uint32_t pref_ltime, uint8_t is_anycast) +{ + ipv6_net_if_addr_t *addr_entry; + ipv6_net_if_hit_t hit; + if (ipv6_addr_is_unspecified(addr) == 128) { - printf("ERROR: unspecified address (::) can't be assigned to interface.\n"); - return; + DEBUG("ERROR: unspecified address (::) can't be assigned to interface.\n"); + return 0; } - if (ipv6_iface_addr_match(addr) != 0) { - return; + if (ipv6_addr_is_multicast(addr) && is_anycast) { + DEBUG("ERROR: anycast addresses must not be multicast addresses " + "(i.e. start with ff::/2)\n"); + return 0; } - if (iface_addr_list_count < IFACE_ADDR_LIST_LEN) { - memcpy(&(iface.addr_list[iface_addr_list_count].addr.uint8[0]), - &(addr->uint8[0]), 16); - iface.addr_list[iface_addr_list_count].state = state; + if (ipv6_net_if_addr_match(&hit, addr)) { + return 1; + } + + if (ipv6_net_if_addr_buffer_count < IPV6_NET_IF_ADDR_BUFFER_LEN) { timex_t valtime = {val_ltime, 0}; timex_t preftime = {pref_ltime, 0}; timex_t now; + vtimer_now(&now); - iface.addr_list[iface_addr_list_count].val_ltime = timex_add(now, valtime); - iface.addr_list[iface_addr_list_count].pref_ltime = timex_add(now, preftime); - iface.addr_list[iface_addr_list_count].type = type; - iface_addr_list_count++; + + ipv6_addr_t *addr_data = &ipv6_addr_buffer[ipv6_net_if_addr_buffer_count]; + memcpy(addr_data, addr, sizeof(ipv6_addr_t)); + + addr_entry = &ipv6_net_if_addr_buffer[ipv6_net_if_addr_buffer_count]; + addr_entry->addr_data = addr_data; + addr_entry->addr_len = 128; + + if (is_anycast) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_ANYCAST; + } + else if (ipv6_addr_is_multicast(addr_data)) { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_MULTICAST; + } + else { + addr_entry->addr_protocol = NET_IF_L3P_IPV6_UNICAST; + } + + addr_entry->ndp_state = state; + addr_entry->valid_lifetime = timex_add(now, valtime); + addr_entry->preferred_lifetime = timex_add(now, preftime); + addr_entry->is_anycast = is_anycast; + + ipv6_net_if_addr_buffer_count++; + + net_if_add_address(if_id, (net_if_addr_t *)addr_entry); /* Register to Solicited-Node multicast address according to RFC 4291 */ - if (type == IPV6_ADDR_TYPE_ANYCAST || type == IPV6_ADDR_TYPE_LINK_LOCAL || - type == IPV6_ADDR_TYPE_GLOBAL || type == IPV6_ADDR_TYPE_UNICAST) { + if (is_anycast || !ipv6_addr_is_multicast(addr)) { ipv6_addr_t sol_node_mcast_addr; ipv6_addr_set_solicited_node_addr(&sol_node_mcast_addr, addr); - if (ipv6_iface_addr_match(&sol_node_mcast_addr) == NULL) { - ipv6_iface_add_addr(&sol_node_mcast_addr, - IPV6_ADDR_TYPE_SOLICITED_NODE, - state, val_ltime, pref_ltime); + if (ipv6_net_if_addr_match(&hit, &sol_node_mcast_addr) == NULL) { + ipv6_net_if_add_addr(if_id, &sol_node_mcast_addr, state, + val_ltime, pref_ltime, 0); + } + } + + return 1; + } + + return 0; +} + +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, + const ipv6_addr_t *addr) +{ + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + uint8_t byte_al = addr_entry->addr_len / 8; + uint8_t mask[] = {0x00, 0x80, 0xc0, 0xe0, + 0xf0, 0xf8, 0xfc, 0xfe + }; + + if (memcmp(addr_entry->addr_data, addr, byte_al) == 0 && + (addr_entry->addr_len % 8 == 0 || + ((addr_entry->addr_data->uint8[byte_al] - addr->uint8[byte_al]) & mask[addr_entry->addr_len - (byte_al * 8)]))) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } } } } + + return NULL; } -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr) +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, + ipv6_addr_t *addr) { - int i; + int if_id = -1; + ipv6_net_if_addr_t *addr_entry = NULL; - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 16) == 0) { - return &(iface.addr_list[i]); + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + while (net_if_iter_addresses(if_id, (net_if_addr_t **) &addr_entry) != NULL) { + if (addr_entry->addr_protocol & NET_IF_L3P_IPV6) { + if (memcmp(addr_entry->addr_data, &addr, 8) == 0) { + hit->if_id = if_id; + hit->addr = addr_entry; + return hit; + } + } } } return NULL; } -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr) -{ - int i; - - for (i = 0; i < iface_addr_list_count; i++) { - if (memcmp(&(iface.addr_list[i].addr.uint8[0]), - &(addr->uint8[0]), 8) == 0) { - return &(iface.addr_list[i]); - } - } - - return NULL; -} - -void ipv6_iface_print_addrs(void) -{ - for (int i = 0; i < iface_addr_list_count; i++) { - char addr_str[IPV6_MAX_ADDR_STR_LEN]; - printf("%s\n", ipv6_addr_to_str(addr_str, - &(iface.addr_list[i].addr))); - } -} - -void ipv6_addr_set_by_eui64(ipv6_addr_t *out, const ipv6_addr_t *prefix) +/* TODO ipv6_net_if_hit_t returning function similar wrapping + * ipv6_net_if_get_best_src_addr() to search on all interfaces */ + +ipv6_addr_t *ipv6_addr_set_by_eui64(ipv6_addr_t *out, int if_id, + const ipv6_addr_t *prefix) { + uint8_t force_generation = 0; out->uint16[0] = prefix->uint16[0]; out->uint16[1] = prefix->uint16[1]; out->uint16[2] = prefix->uint16[2]; out->uint16[3] = prefix->uint16[3]; - memcpy(&(out->uint8[8]), &(iface.laddr.uint8[0]), 8); + if (net_if_get_src_address_mode(if_id) == NET_IF_TRANS_ADDR_M_SHORT) { + force_generation = 1; + } + + if (net_if_get_eui64((net_if_eui64_t *) &out->uint8[8], if_id, + force_generation)) { +#ifdef MODULE_SIXLOWPAN + + if (!sixlowpan_lowpan_eui64_to_short_addr((net_if_eui64_t *)&out->uint8[8])) { + out->uint8[8] ^= 0x02; + } + +#else + out->uint8[8] ^= 0x02; +#endif + return out; + } + else { + return NULL; + } } void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, @@ -496,96 +629,51 @@ void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, out->uint8[bytes] = prefix->uint8[bytes] & mask; } -void ipv6_addr_set_all_routers_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0002); -} - -void ipv6_addr_set_all_nodes_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xff02); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_addr_set_loopback_addr(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = 0; - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; - ipv6_addr->uint16[4] = 0; - ipv6_addr->uint16[5] = 0; - ipv6_addr->uint16[6] = 0; - ipv6_addr->uint16[7] = HTONS(0x0001); -} - -void ipv6_iface_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) +void ipv6_net_if_get_best_src_addr(ipv6_addr_t *src, const ipv6_addr_t *dest) { /* try to find best match if dest is not mcast or link local */ - int8_t itmp = -1; + int if_id = 0; // TODO: get this somehow uint8_t tmp = 0; uint8_t bmatch = 0; + ipv6_net_if_addr_t *addr = NULL; + ipv6_net_if_addr_t *tmp_addr = NULL; if (!(ipv6_addr_is_link_local(dest)) && !(ipv6_addr_is_multicast(dest))) { - for (int i = 0; i < IFACE_ADDR_LIST_LEN; i++) { - if (iface.addr_list[i].state == NDP_ADDR_STATE_PREFERRED) { - if (!ipv6_addr_is_link_local(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[i].addr)) && - !ipv6_addr_is_unique_local_unicast(&(iface.addr_list[i].addr))) { - tmp = ipv6_get_addr_match(dest, &(iface.addr_list[i].addr)); + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED) { + if (!ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data) && + !ipv6_addr_is_unique_local_unicast(addr->addr_data)) { + tmp = ipv6_get_addr_match(dest, addr->addr_data); if (tmp >= bmatch) { bmatch = tmp; - itmp = i; + tmp_addr = addr; } } } } } else { - for (int j = 0; j < IFACE_ADDR_LIST_LEN; j++) { - if ((iface.addr_list[j].state == NDP_ADDR_STATE_PREFERRED) && - ipv6_addr_is_link_local(&(iface.addr_list[j].addr)) && - !ipv6_addr_is_multicast(&(iface.addr_list[j].addr))) { - itmp = j; + while ((addr = (ipv6_net_if_addr_t *)net_if_iter_addresses(if_id, + (net_if_addr_t **)&addr))) { + if (addr->ndp_state == NDP_ADDR_STATE_PREFERRED && + ipv6_addr_is_link_local(addr->addr_data) && + !ipv6_addr_is_multicast(addr->addr_data)) { + tmp_addr = addr; } } } - if (itmp == -1) { + if (tmp_addr == NULL) { memset(src, 0, 16); } else { - memcpy(src, &(iface.addr_list[itmp].addr), 16); + memcpy(src, tmp_addr->addr_data, 16); } } -int ipv6_addr_is_equal(const ipv6_addr_t *a, const ipv6_addr_t *b) -{ - return (ipv6_get_addr_match(a, b) == 128); -} - -void ipv6_addr_set_link_local_prefix(ipv6_addr_t *ipv6_addr) -{ - ipv6_addr->uint16[0] = HTONS(0xfe80); - ipv6_addr->uint16[1] = 0; - ipv6_addr->uint16[2] = 0; - ipv6_addr->uint16[3] = 0; -} - void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, uint16_t addr2, uint16_t addr3, uint16_t addr4, uint16_t addr5, uint16_t addr6, uint16_t addr7) @@ -600,66 +688,6 @@ void ipv6_addr_init(ipv6_addr_t *out, uint16_t addr0, uint16_t addr1, out->uint16[7] = HTONS(addr7); } -int ipv6_addr_is_link_local(const ipv6_addr_t *addr) -{ - return (addr->uint16[0] == HTONS(0xfe80)); -} - -int ipv6_addr_is_unique_local_unicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xfc || addr->uint8[0] == 0xfd); -} - -int ipv6_addr_is_multicast(const ipv6_addr_t *addr) -{ - return (addr->uint8[0] == 0xff); -} - -int ipv6_addr_is_unspecified(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint32[0] == 0) && (ipv6_addr->uint32[1] == 0) && - (ipv6_addr->uint32[2] == 0) && (ipv6_addr->uint32[3] == 0); -} - -int ipv6_addr_is_solicited_node(const ipv6_addr_t *ipv6_addr) -{ - return (ipv6_addr->uint8[0] == 0xFF) && - (ipv6_addr->uint8[1] == 0x02) && - (ipv6_addr->uint16[1] == 0x00) && - (ipv6_addr->uint16[2] == 0x00) && - (ipv6_addr->uint16[3] == 0x00) && - (ipv6_addr->uint16[4] == 0x00) && - (ipv6_addr->uint8[10] == 0x00) && - (ipv6_addr->uint8[11] == 0x01) && - (ipv6_addr->uint8[12] == 0xFF); -} - -void ipv6_addr_set_solicited_node_addr(ipv6_addr_t *ipv6_addr_out, - const ipv6_addr_t *ipv6_addr_in) -{ - /* copy only the last 24-bit of the ip-address that is beeing resolved */ - ipv6_addr_out->uint16[0] = HTONS(0xff02); - ipv6_addr_out->uint16[1] = 0; - ipv6_addr_out->uint16[2] = 0; - ipv6_addr_out->uint16[3] = 0; - ipv6_addr_out->uint16[4] = 0; - ipv6_addr_out->uint16[5] = HTONS(0x0001); - ipv6_addr_out->uint8[12] = 0xff; - ipv6_addr_out->uint8[13] = ipv6_addr_in->uint8[13]; - ipv6_addr_out->uint16[7] = ipv6_addr_in->uint16[7]; -} - -char *ipv6_addr_to_str(char *addr_str, const ipv6_addr_t *ipv6_addr) -{ - sprintf(addr_str, - "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - NTOHS(ipv6_addr->uint16[0]), NTOHS(ipv6_addr->uint16[1]), - NTOHS(ipv6_addr->uint16[2]), NTOHS(ipv6_addr->uint16[3]), - NTOHS(ipv6_addr->uint16[4]), NTOHS(ipv6_addr->uint16[5]), - NTOHS(ipv6_addr->uint16[6]), NTOHS(ipv6_addr->uint16[7])); - return addr_str; -} - uint32_t get_remaining_time(timex_t *t) { timex_t now; @@ -677,22 +705,32 @@ void set_remaining_time(timex_t *t, uint32_t time) *t = timex_add(now, tmp); } -void ipv6_init_iface_as_router(void) +int ipv6_init_as_router(void) { ipv6_addr_t addr; + int if_id = -1; ipv6_addr_set_all_routers_addr(&addr); - ipv6_iface_add_addr(&addr, NDP_ADDR_STATE_PREFERRED, 0, 0, IPV6_ADDR_TYPE_MULTICAST); + + while ((if_id = net_if_iter_interfaces(if_id)) >= 0) { + if (!ipv6_net_if_add_addr(if_id, &addr, NDP_ADDR_STATE_PREFERRED, 0, 0, + 0)) { + return 0; + } + } + + return 1; } uint8_t ipv6_is_router(void) { ipv6_addr_t addr; + ipv6_net_if_hit_t hit; ipv6_addr_set_all_routers_addr(&addr); - if (ipv6_iface_addr_match(&addr) != NULL) { + if (ipv6_net_if_addr_match(&hit, &addr) != NULL) { return 1; } @@ -741,8 +779,10 @@ uint16_t ipv6_csum(ipv6_hdr_t *ipv6_header, uint8_t *buf, uint16_t len, uint8_t { uint16_t sum = 0; DEBUG("Calculate checksum over src: %s, dst: %s, len: %04X, buf: %p, proto: %u\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr), - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr), + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr), len, buf, proto); sum = len + proto; sum = csum(sum, (uint8_t *)&ipv6_header->srcaddr, 2 * sizeof(ipv6_addr_t)); diff --git a/sys/net/network_layer/sixlowpan/ip.h b/sys/net/network_layer/sixlowpan/ip.h index ec5ecf8291..740ef77b22 100644 --- a/sys/net/network_layer/sixlowpan/ip.h +++ b/sys/net/network_layer/sixlowpan/ip.h @@ -25,8 +25,10 @@ #include +#include "kernel.h" #include "timex.h" #include "mutex.h" +#include "net_if.h" #include "sixlowpan/ip.h" #include "sixlowpan/types.h" @@ -39,52 +41,61 @@ #define MULTIHOP_HOPLIMIT (64) #define SIXLOWIP_MAX_REGISTERED (4) +#define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_MAIN) /* extern variables */ extern uint8_t ipv6_ext_hdr_len; +extern int ip_process_pid; /* base header lengths */ #define LL_HDR_LEN (0x4) #define ICMPV6_HDR_LEN (0x4) #define IPV6_HDR_LEN (0x28) -#define IFACE_ADDR_LIST_LEN (10) // maybe to much +#define IPV6_NET_IF_ADDR_LIST_LEN (10) // maybe to much /* buffer */ extern uint8_t buffer[BUFFER_SIZE]; +extern char ip_process_buf[IP_PROCESS_STACKSIZE]; extern int sixlowip_reg[SIXLOWIP_MAX_REGISTERED]; typedef struct __attribute__((packed)) { - ipv6_addr_t addr; - ipv6_addr_type_t type; - ndp_addr_state_t state; - timex_t val_ltime; - timex_t pref_ltime; -} addr_list_t; + struct net_if_addr_t *addr_next; + struct net_if_addr_t *addr_prev; + net_if_l3p_t addr_protocol; + ipv6_addr_t *addr_data; + uint8_t addr_len; + ndp_addr_state_t ndp_state; + timex_t valid_lifetime; + timex_t preferred_lifetime; + uint8_t is_anycast; +} ipv6_net_if_addr_t; typedef struct __attribute__((packed)) { - ieee_802154_short_t saddr; - ieee_802154_long_t laddr; - addr_list_t addr_list[IFACE_ADDR_LIST_LEN]; + ipv6_net_if_addr_t *addr; + int if_id; +} ipv6_net_if_hit_t; + +typedef struct __attribute__((packed)) { + uint8_t prefix; ///< prefix length of the sub-net uint8_t adv_cur_hop_limit; uint32_t adv_reachable_time; uint32_t adv_retrans_timer; -} iface_t; - -extern iface_t iface; +} ipv6_net_if_ext_t; /* function prototypes */ -void ipv6_send_bytes(ipv6_hdr_t *bytes); +ipv6_net_if_ext_t *ipv6_net_if_get_ext(int if_id); + icmpv6_hdr_t *get_icmpv6_buf(uint8_t ext_len); uint8_t *get_payload_buf(uint8_t ext_len); uint8_t *get_payload_buf_send(uint8_t ext_len); int icmpv6_demultiplex(const icmpv6_hdr_t *hdr); -void ipv6_init_iface_as_router(void); +int ipv6_init_as_router(void); void ipv6_process(void); -addr_list_t *ipv6_iface_addr_prefix_eq(ipv6_addr_t *addr); -addr_list_t *ipv6_iface_addr_match(const ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_prefix_eq(ipv6_net_if_hit_t *hit, ipv6_addr_t *addr); +ipv6_net_if_hit_t *ipv6_net_if_addr_match(ipv6_net_if_hit_t *hit, const ipv6_addr_t *addr); uint32_t get_remaining_time(timex_t *t); void set_remaining_time(timex_t *t, uint32_t time); diff --git a/sys/net/network_layer/sixlowpan/lowpan.h b/sys/net/network_layer/sixlowpan/lowpan.h index 38830ae9b4..e1c1af1a00 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.h +++ b/sys/net/network_layer/sixlowpan/lowpan.h @@ -25,6 +25,7 @@ #define _SIXLOWPAN_LOWPAN_H #include "mutex.h" +#include "net_if.h" #include "vtimer.h" #include "sixlowpan/lowpan.h" @@ -42,9 +43,8 @@ typedef struct { extern uint16_t local_address; extern mutex_t lowpan_context_mutex; -void lowpan_read(uint8_t *data, uint8_t length, - ieee_802154_long_t *s_laddr, - ieee_802154_long_t *d_laddr); +void lowpan_read(uint8_t *data, uint8_t length, net_if_eui64_t *s_addr, + net_if_eui64_t *d_addr); uint8_t lowpan_context_len(void); lowpan_context_t *lowpan_context_update(uint8_t num, const ipv6_addr_t *prefix, diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index a9a7d6fa3c..eb1535ec8f 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -191,15 +191,11 @@ rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp) return NULL; } -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) +uint8_t rpl_init(int if_id) { mutex_init(&rpl_send_mutex); mutex_init(&rpl_recv_mutex); - if (rpl_address == 0) { - return SIXLOWERROR_ADDRESS; - } - rpl_instances_init(); /* initialize routing table */ @@ -213,11 +209,15 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address) objective_functions[0] = rpl_get_of0(); /* objective_functions[1] = rpl_get_of_ETX() */ - sixlowpan_lowpan_init(trans, rpl_address, 0); + if (!sixlowpan_lowpan_init()) { + return 0; + } + + sixlowpan_lowpan_init_interface(if_id); /* need link local prefix to query _our_ corresponding address */ ipv6_addr_t ll_address; ipv6_addr_set_link_local_prefix(&ll_address); - ipv6_iface_get_best_src_addr(&my_address, &ll_address); + ipv6_net_if_get_best_src_addr(&my_address, &ll_address); ipv6_register_rpl_handler(rpl_process_pid); /* initialize ETX-calculation if needed */ @@ -932,7 +932,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_send_buf->length = HTONS(p_len); memcpy(&(ipv6_send_buf->destaddr), destination, 16); - ipv6_iface_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); + ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); icmp_send_buf->checksum = 0; diff --git a/sys/net/routing/rpl/rpl.h b/sys/net/routing/rpl/rpl.h index 31497afc7d..7ab6ef1a9d 100644 --- a/sys/net/routing/rpl/rpl.h +++ b/sys/net/routing/rpl/rpl.h @@ -35,7 +35,7 @@ #define RPL_PKT_RECV_BUF_SIZE 16 #define RPL_PROCESS_STACKSIZE KERNEL_CONF_STACKSIZE_DEFAULT -uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address); +uint8_t rpl_init(int if_id); void rpl_init_root(void); rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp); diff --git a/sys/net/routing/rpl/rpl_dodag.c b/sys/net/routing/rpl/rpl_dodag.c index 5c356f7d3c..7689237307 100644 --- a/sys/net/routing/rpl/rpl_dodag.c +++ b/sys/net/routing/rpl/rpl_dodag.c @@ -357,7 +357,9 @@ void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_ran DEBUG("\tminhoprankincrease :\t%04X\n", my_dodag->minhoprankincrease); DEBUG("\tdefault_lifetime:\t%02X\n", my_dodag->default_lifetime); DEBUG("\tgrounded:\t%02X\n", my_dodag->grounded); - DEBUG("\tmy_preferred_parent:\t%s\n", ipv6_addr_to_str(addr_str, &my_dodag->my_preferred_parent->addr)); + DEBUG("\tmy_preferred_parent:\t%s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &my_dodag->my_preferred_parent->addr)); DEBUG("\tmy_preferred_parent rank\t%02X\n", my_dodag->my_preferred_parent->rank); DEBUG("\tmy_preferred_parent lifetime\t%04X\n", my_dodag->my_preferred_parent->lifetime); diff --git a/sys/net/transport_layer/destiny/socket.c b/sys/net/transport_layer/destiny/socket.c index 2d267aaad3..627e0462ac 100644 --- a/sys/net/transport_layer/destiny/socket.c +++ b/sys/net/transport_layer/destiny/socket.c @@ -121,9 +121,11 @@ void print_tcp_status(int in_or_out, ipv6_hdr_t *ipv6_header, printf("--- %s TCP packet: ---\n", (in_or_out == INC_PACKET ? "Incoming" : "Outgoing")); printf("IPv6 Source: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->srcaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->srcaddr)); printf("IPv6 Dest: %s\n", - ipv6_addr_to_str(addr_str, &ipv6_header->destaddr)); + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_header->destaddr)); printf("TCP Length: %x\n", ipv6_header->length - TCP_HDR_LEN); printf("Source Port: %x, Dest. Port: %x\n", NTOHS(tcp_header->src_port), NTOHS(tcp_header->dst_port)); @@ -148,10 +150,10 @@ void print_socket(socket_t *current_socket) current_socket->type, current_socket->protocol); printf("Local address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->local_address.sin6_addr)); printf("Foreign address: %s\n", - ipv6_addr_to_str(addr_str, + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, ¤t_socket->foreign_address.sin6_addr)); printf("Local Port: %u, Foreign Port: %u\n", NTOHS(current_socket->local_address.sin6_port), @@ -494,13 +496,13 @@ int send_tcp(socket_internal_t *current_socket, tcp_hdr_t *current_tcp_packet, } return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - compressed_size); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + compressed_size); #else switch_tcp_packet_byte_order(current_tcp_packet); return ipv6_sendto(¤t_tcp_socket->foreign_address.sin6_addr, - IPPROTO_TCP, (uint8_t *)(current_tcp_packet), - header_length * 4 + payload_length); + IPPROTO_TCP, (uint8_t *)(current_tcp_packet), + header_length * 4 + payload_length); #endif } @@ -539,7 +541,7 @@ int destiny_socket_connect(int socket, sockaddr6_t *addr, uint32_t addrlen) current_int_tcp_socket->recv_pid = thread_getpid(); /* Local address information */ - ipv6_iface_get_best_src_addr(&src_addr, &addr->sin6_addr); + ipv6_net_if_get_best_src_addr(&src_addr, &addr->sin6_addr); set_socket_address(¤t_tcp_socket->local_address, PF_INET6, HTONS(get_free_source_port(IPPROTO_TCP)), 0, &src_addr); @@ -1011,7 +1013,7 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, uint8_t *payload = &send_buffer[IPV6_HDR_LEN + UDP_HDR_LEN]; memcpy(&(temp_ipv6_header->destaddr), &to->sin6_addr, 16); - ipv6_iface_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); + ipv6_net_if_get_best_src_addr(&(temp_ipv6_header->srcaddr), &(temp_ipv6_header->destaddr)); current_udp_packet->src_port = get_free_source_port(IPPROTO_UDP); current_udp_packet->dst_port = to->sin6_port; @@ -1022,13 +1024,13 @@ int32_t destiny_socket_sendto(int s, const void *buf, uint32_t len, int flags, temp_ipv6_header->length = UDP_HDR_LEN + len; current_udp_packet->checksum = ~ipv6_csum(temp_ipv6_header, - (uint8_t*) current_udp_packet, - UDP_HDR_LEN + len, - IPPROTO_UDP); + (uint8_t *) current_udp_packet, + UDP_HDR_LEN + len, + IPPROTO_UDP); return ipv6_sendto(&to->sin6_addr, IPPROTO_UDP, - (uint8_t *)(current_udp_packet), - NTOHS(current_udp_packet->length)); + (uint8_t *)(current_udp_packet), + NTOHS(current_udp_packet->length)); } else { return -1; diff --git a/sys/shell/commands/sc_net_if.c b/sys/shell/commands/sc_net_if.c index 790173abe2..efd54e1dd2 100644 --- a/sys/shell/commands/sc_net_if.c +++ b/sys/shell/commands/sc_net_if.c @@ -23,18 +23,21 @@ #include #include -#include "destiny/socket.h" /* for AF_INET6 */ #include "inet_pton.h" #include "inet_ntop.h" #include "net_help.h" #include "net_if.h" #include "transceiver.h" +#ifndef MODULE_SIXLOWPAN #define ADDR_REGISTERED_MAX (6) #define ADDRS_LEN_MAX (16) static uint8_t addr_registered = 0; static uint8_t addrs[ADDR_REGISTERED_MAX][ADDRS_LEN_MAX]; +#else +#include "ipv6.h" +#endif void _net_if_ifconfig_add(int if_id, int argc, char **argv); void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv); @@ -45,8 +48,9 @@ void _net_if_ifconfig_set_hwaddr(int if_id, char *addr); void _net_if_ifconfig_set_pan_id(int if_id, char *pan_id); void _net_if_ifconfig_set_channel(int if_id, char *channel); void _net_if_ifconfig_create(char *transceivers_str); -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len); +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len); void _net_if_ifconfig_list(int if_id); int isnumber(char *str) @@ -335,20 +339,60 @@ void _net_if_ifconfig_add_ipv6(int if_id, int argc, char **argv) type = NULL; } +#ifdef MODULE_SIXLOWPAN + ipv6_addr_t ipv6_addr; + void *addr_data = &ipv6_addr; +#else + void *addr_data = (void *)&addrs[addr_registered][0]; +#endif + addr_data_str = strtok(addr_str, "/"); addr_data_len = strtok(NULL, "/"); - if (!_net_if_ifconfig_ipv6_addr_convert(&addr, type, addr_data_str, addr_data_len)) { + if (!_net_if_ifconfig_ipv6_addr_convert(&addr, addr_data, type, + addr_data_str, addr_data_len)) { add_usage(); return; } +#ifdef MODULE_SIXLOWPAN + + if (addr.addr_protocol & NET_IF_L3P_IPV6_PREFIX) { + if (ndp_add_prefix_info(if_id, &ipv6_addr, addr.addr_len, + NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM) != SIXLOWERROR_SUCCESS) { + add_usage(); + return; + } + } + else if (addr.addr_protocol & NET_IF_L3P_IPV6_ADDR) { + uint8_t is_anycast = 0; + + if (addr.addr_protocol & NET_IF_L3P_IPV6_ANYCAST) { + is_anycast = 1; + } + + if (!ipv6_net_if_add_addr(if_id, &ipv6_addr, NDP_ADDR_STATE_PREFERRED, + 0, 0, is_anycast)) { + add_usage(); + return; + } + } + else { + add_usage(); + return; + } + +#else + if (net_if_add_address(if_id, &addr) < 0) { add_usage(); return; } addr_registered++; +#endif } void _net_if_ifconfig_add(int if_id, int argc, char **argv) @@ -413,13 +457,21 @@ void _net_if_ifconfig_create(char *transceivers_str) static inline int _is_multicast(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_multicast((ipv6_addr_t *) addr); +#else return *addr == 0xff; +#endif } static inline int _is_link_local(uint8_t *addr) { +#ifdef MODULE_SIXLOWPAN + return ipv6_addr_is_link_local((ipv6_addr_t *) addr); +#else return (addr[0] == 0xfe && addr[1] == 0x80) || (_is_multicast(addr) && (addr[1] & 0x0f) == 2); +#endif } int _set_protocol_from_type(char *type, net_if_addr_t *addr) @@ -448,14 +500,15 @@ int _set_protocol_from_type(char *type, net_if_addr_t *addr) } } -int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, char *type, - char *addr_data_str, char *addr_data_len) +int _net_if_ifconfig_ipv6_addr_convert(net_if_addr_t *addr, void *addr_data, + char *type, char *addr_data_str, + char *addr_data_len) { if (addr_data_len && !isnumber(addr_data_len)) { return 0; } - addr->addr_data = (void *)&addrs[addr_registered][0]; + addr->addr_data = addr_data; if (!inet_pton(AF_INET6, addr_data_str, addr->addr_data)) { return 0; From 6c9578c02863bb11ed5645db3b8d2c64a767c6fb Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Sat, 8 Feb 2014 04:22:42 +0100 Subject: [PATCH 10/13] Add sixlowpan to auto_init --- sys/auto_init/auto_init.c | 36 +++++++++++++++++-- .../network_layer/sixlowpan/border/border.c | 4 --- sys/net/routing/rpl/rpl.c | 4 --- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 5652f3ce7a..5b3b17b374 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -51,6 +51,10 @@ #include "rtc.h" #endif +#ifdef MODULE_SIXLOWPAN +#include "sixlowpan.h" +#endif + #ifdef MODULE_DESTINY #include "destiny.h" #endif @@ -63,6 +67,14 @@ #define ENABLE_DEBUG (0) #include "debug.h" +#ifndef CONF_RADIO_ADDR +#define CONF_RADIO_ADDR (1) +#endif + +#ifndef CONF_PAN_ID +#define CONF_PAN_ID (0xabcd) +#endif + extern int main(void); void auto_init(void) @@ -103,6 +115,7 @@ void auto_init(void) MCI_initialize(); #endif #ifdef MODULE_NET_IF + int iface; DEBUG("Auto init net_if module.\n"); transceiver_type_t transceivers = 0; #ifdef MODULE_AT86RF231 @@ -128,13 +141,32 @@ void auto_init(void) if (transceivers != 0) { transceiver_init(transceivers); transceiver_start(); - int iface = net_if_init_interface(0, transceivers); + iface = net_if_init_interface(0, transceivers); + + if (!net_if_get_hardware_address(iface)) { + DEBUG("Auto init radio address on interface %d to 0x%04x\n", iface, CONF_RADIO_ADDR); + DEBUG("Change this value at compile time with macro CONF_RADIO_ADDR\n"); + net_if_set_hardware_address(iface, CONF_RADIO_ADDR); + } + + if (net_if_get_pan_id(iface) <= 0) { + DEBUG("Auto init PAN ID on interface %d to 0x%04x\n", iface, CONF_PAN_ID); + DEBUG("Change this value at compile time with macro CONF_PAN_ID\n"); + net_if_set_pan_id(iface, CONF_PAN_ID); + } if (iface >= 0) { - DEBUG("Interface %d initialized\n", iface); + DEBUG("Auto init interface %d\n", iface); } } + else { + iface = -1; + } +#ifdef MODULE_SIXLOWPAN + DEBUG("Auto init 6LoWPAN module.\n"); + sixlowpan_lowpan_init(); +#endif #endif #ifdef MODULE_PROFILING extern void profiling_init(void); diff --git a/sys/net/network_layer/sixlowpan/border/border.c b/sys/net/network_layer/sixlowpan/border/border.c index f478a7505f..2433cf61b0 100644 --- a/sys/net/network_layer/sixlowpan/border/border.c +++ b/sys/net/network_layer/sixlowpan/border/border.c @@ -142,10 +142,6 @@ int sixlowpan_lowpan_border_init(int if_id) return 0; } - if (!sixlowpan_lowpan_init()) { - return 0; - } - if (!sixlowpan_lowpan_init_interface(if_id)) { return 0; } diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index eb1535ec8f..2d9b2701d0 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -209,10 +209,6 @@ uint8_t rpl_init(int if_id) objective_functions[0] = rpl_get_of0(); /* objective_functions[1] = rpl_get_of_ETX() */ - if (!sixlowpan_lowpan_init()) { - return 0; - } - sixlowpan_lowpan_init_interface(if_id); /* need link local prefix to query _our_ corresponding address */ ipv6_addr_t ll_address; From 3a8c1770b161fe88e0895e1706877576f8f53d3c Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 13 Feb 2014 16:06:25 +0100 Subject: [PATCH 11/13] Fix apps for previous changes --- examples/rpl_udp/helper.c | 12 ++---------- examples/rpl_udp/main.c | 3 ++- examples/rpl_udp/rpl.c | 33 ++++++++++++++++++++++----------- examples/rpl_udp/udp.c | 4 +++- tests/test_pnet/main.c | 14 +++++++++----- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/examples/rpl_udp/helper.c b/examples/rpl_udp/helper.c index ff431de385..d5282b948e 100644 --- a/examples/rpl_udp/helper.c +++ b/examples/rpl_udp/helper.c @@ -39,15 +39,6 @@ extern uint8_t ipv6_ext_hdr_len; msg_t msg_q[RCV_BUFFER_SIZE]; -/* prints current IPv6 adresses */ -void rpl_udp_ip(int argc, char **argv) -{ - (void) argc; - (void) argv; - - ipv6_iface_print_addrs(); -} - void rpl_udp_set_id(int argc, char **argv) { if (argc != 2) { @@ -95,7 +86,8 @@ void rpl_udp_monitor(void) else if (m.type == IPV6_PACKET_RECEIVED) { ipv6_buf = (ipv6_hdr_t *) m.content.ptr; printf("IPv6 datagram received (next header: %02X)", ipv6_buf->nextheader); - printf(" from %s ", ipv6_addr_to_str(addr_str, &ipv6_buf->srcaddr)); + printf(" from %s ", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipv6_buf->srcaddr)); if (ipv6_buf->nextheader == IPV6_PROTO_NUM_ICMPV6) { icmpv6_buf = (icmpv6_hdr_t *) &ipv6_buf[(LL_HDR_LEN + IPV6_HDR_LEN) + ipv6_ext_hdr_len]; diff --git a/examples/rpl_udp/main.c b/examples/rpl_udp/main.c index 8b1258700c..09c67d065a 100644 --- a/examples/rpl_udp/main.c +++ b/examples/rpl_udp/main.c @@ -20,6 +20,7 @@ #include +#include "net_if.h" #include "posix_io.h" #include "shell.h" #include "shell_commands.h" @@ -37,7 +38,6 @@ const shell_command_t shell_commands[] = { {"loop", "", rpl_udp_loop}, {"server", "Starts a UDP server", udp_server}, {"send", "Send a UDP datagram", udp_send}, - {"ip", "Print all assigned IP addresses", rpl_udp_ip}, {"ign", "ignore node", rpl_udp_ignore}, {NULL, NULL, NULL} }; @@ -48,6 +48,7 @@ int main(void) /* start shell */ posix_open(uart0_handler_pid, 0); + net_if_set_src_address_mode(0, NET_IF_TRANS_ADDR_M_SHORT); shell_t shell; shell_init(&shell, shell_commands, UART0_BUFSIZE, uart0_readc, uart0_putc); diff --git a/examples/rpl_udp/rpl.c b/examples/rpl_udp/rpl.c index 8c1deda077..13f9fdd065 100644 --- a/examples/rpl_udp/rpl.c +++ b/examples/rpl_udp/rpl.c @@ -22,6 +22,7 @@ #include #include "vtimer.h" #include "thread.h" +#include "net_if.h" #include "sixlowpan.h" #include "destiny.h" #include "rpl.h" @@ -64,7 +65,9 @@ void rpl_udp_init(int argc, char **argv) return; } - state = rpl_init(TRANSCEIVER, id); + net_if_set_hardware_address(0, id); + + state = rpl_init(0); if (state != SIXLOWERROR_SUCCESS) { printf("Error initializing RPL\n"); @@ -95,11 +98,13 @@ void rpl_udp_init(int argc, char **argv) ipv6_addr_t prefix, tmp; ipv6_addr_init(&std_addr, 0xABCD, 0xEF12, 0, 0, 0x1034, 0x00FF, 0xFE00, id); ipv6_addr_init_prefix(&prefix, &std_addr, 64); - plist_add(&prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, 0, 1, ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); - ipv6_init_iface_as_router(); + ndp_add_prefix_info(0, &prefix, 64, NDP_OPT_PI_VLIFETIME_INFINITE, + NDP_OPT_PI_PLIFETIME_INFINITE, 1, + ICMPV6_NDP_OPT_PI_FLAG_AUTONOM); + ipv6_init_as_router(); /* add global address */ - ipv6_addr_set_by_eui64(&tmp, &std_addr); - ipv6_iface_add_addr(&tmp, IPV6_ADDR_TYPE_GLOBAL, NDP_ADDR_STATE_PREFERRED, 0, 0); + ipv6_addr_set_by_eui64(&tmp, 0, &std_addr); + ipv6_net_if_add_addr(0, &tmp, NDP_ADDR_STATE_PREFERRED, 0, 0, 0); /* set channel to 10 */ tcmd.transceivers = TRANSCEIVER; @@ -134,7 +139,8 @@ void rpl_udp_loop(int argc, char **argv) if (!is_root) { printf("my preferred parent:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->my_preferred_parent->addr))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->my_preferred_parent->addr))); printf("parent lifetime: %d\n", mydodag->my_preferred_parent->lifetime); } @@ -142,9 +148,11 @@ void rpl_udp_loop(int argc, char **argv) for (int i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (rtable[i].used) { - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].address))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].address))); puts("next hop"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].next_hop))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].next_hop))); printf("entry %d lifetime %d\n", i, rtable[i].lifetime); if (!rpl_equal_id(&rtable[i].address, &rtable[i].next_hop)) { @@ -171,7 +179,8 @@ void rpl_udp_table(int argc, char **argv) for (int i = 0; i < RPL_MAX_ROUTING_ENTRIES; i++) { if (rtable[i].used) { - printf("%s\n", ipv6_addr_to_str(addr_str, (&rtable[i].address))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&rtable[i].address))); printf("entry %d lifetime %d\n", i, rtable[i].lifetime); if (!rpl_equal_id(&rtable[i].address, &rtable[i].next_hop)) { @@ -200,12 +209,14 @@ void rpl_udp_dodag(int argc, char **argv) } printf("Part of Dodag:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->dodag_id))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->dodag_id))); printf("my rank: %d\n", mydodag->my_rank); if (!is_root) { printf("my preferred parent:\n"); - printf("%s\n", ipv6_addr_to_str(addr_str, (&mydodag->my_preferred_parent->addr))); + printf("%s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + (&mydodag->my_preferred_parent->addr))); } printf("---------------------------\n"); diff --git a/examples/rpl_udp/udp.c b/examples/rpl_udp/udp.c index 286c0be0ad..88ef040ab8 100644 --- a/examples/rpl_udp/udp.c +++ b/examples/rpl_udp/udp.c @@ -128,7 +128,9 @@ void udp_send(int argc, char **argv) printf("Error sending packet!\n"); } else { - printf("Successful deliverd %i bytes over UDP to %s to 6LoWPAN\n", bytes_sent, ipv6_addr_to_str(addr_str, &ipaddr)); + printf("Successful deliverd %i bytes over UDP to %s to 6LoWPAN\n", + bytes_sent, ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, + &ipaddr)); } destiny_socket_close(sock); diff --git a/tests/test_pnet/main.c b/tests/test_pnet/main.c index 9b523dff8f..8cf8fcd630 100644 --- a/tests/test_pnet/main.c +++ b/tests/test_pnet/main.c @@ -27,7 +27,7 @@ #include #include -#include "transceiver.h" +#include "net_if.h" #include "ipv6.h" #ifdef MODULE_NATIVENET @@ -42,12 +42,13 @@ #define PORT (1234) -void init_local_address(uint16_t r_addr) +int init_local_address(uint16_t r_addr) { ipv6_addr_t std_addr; ipv6_addr_init(&std_addr, 0xabcd, 0xef12, 0, 0, 0x1034, 0x00ff, 0xfe00, - r_addr); - sixlowpan_lowpan_adhoc_init(TRANSCEIVER, &std_addr, r_addr); + 0); + return net_if_set_hardware_address(r_addr) && + sixlowpan_lowpan_adhoc_init(0, &std_addr); } int main(void) @@ -80,7 +81,10 @@ int main(void) }; char buffer[14]; - init_local_address(R_ADDR); + if (!init_local_address(R_ADDR)) { + fprintf(stderr, "Can not initialize IP for hardware address %d.", R_ADDR); + return 1; + } memcpy(buffer, "Hello, World!", 14); memcpy(&my_addr, &in6addr_any, sizeof(my_addr)); From 2c76f99f04e3e155cacd7b826935e4b3d4b7bb35 Mon Sep 17 00:00:00 2001 From: Oleg Hahm Date: Thu, 20 Feb 2014 03:05:56 +0100 Subject: [PATCH 12/13] nbr_cache_auto_rem does not need an extra thread --- sys/net/network_layer/sixlowpan/lowpan.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index a4f54979a6..d81a81ea54 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -1796,13 +1796,7 @@ int sixlowpan_lowpan_init(void) return 0; } - nd_nbr_cache_rem_pid = thread_create(nc_buf, NC_STACKSIZE, - PRIORITY_MAIN - 1, CREATE_STACKTEST, - nbr_cache_auto_rem, "nbr_cache_rem"); - - if (nd_nbr_cache_rem_pid < 0) { - return 0; - } + nbr_cache_auto_rem(); contexts_rem_pid = thread_create(con_buf, CON_STACKSIZE, PRIORITY_MAIN + 1, CREATE_STACKTEST, From bdced318bccfb3679dd9e4a08743d98a0155d12a Mon Sep 17 00:00:00 2001 From: Martin Lenders Date: Thu, 27 Feb 2014 00:10:16 +0100 Subject: [PATCH 13/13] Eliminate side effects in icmpv6_csum and make it public --- sys/net/include/sixlowpan/icmp.h | 11 ++++++++ sys/net/network_layer/sixlowpan/icmp.c | 32 ++++++++++-------------- sys/net/network_layer/sixlowpan/icmp.h | 2 -- sys/net/network_layer/sixlowpan/lowpan.c | 12 ++++----- sys/net/routing/rpl/rpl.c | 3 +-- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/sys/net/include/sixlowpan/icmp.h b/sys/net/include/sixlowpan/icmp.h index 97b08791aa..4f21e90e79 100644 --- a/sys/net/include/sixlowpan/icmp.h +++ b/sys/net/include/sixlowpan/icmp.h @@ -232,5 +232,16 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt, uint8_t rso, uint8_t sllao, uint8_t aro); +/** + * @brief Calculates the checksum for ICMPv6 packets. + * + * @param[in] ipv6_buf The initialized IPv6 header of the packet. + * @param[in] icmpv6_buf The initialized ICMPv6_header of the packet + * (except checksum, payload is expected directly + * after the packet header in memory). + * + * @return The internet checksum of the given ICMPv6 packet. + */ +uint16_t icmpv6_csum(ipv6_hdr_t *ipv6_buf, icmpv6_hdr_t *icmpv6_buf); /** @} */ #endif /* SIXLOWPAN_ICMP_H */ diff --git a/sys/net/network_layer/sixlowpan/icmp.c b/sys/net/network_layer/sixlowpan/icmp.c index 31952db2c8..f02b96ef48 100644 --- a/sys/net/network_layer/sixlowpan/icmp.c +++ b/sys/net/network_layer/sixlowpan/icmp.c @@ -267,8 +267,7 @@ void icmpv6_send_echo_request(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -307,8 +306,7 @@ void icmpv6_send_echo_reply(ipv6_addr_t *destaddr, uint16_t id, uint16_t seq, ui ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -365,8 +363,7 @@ void icmpv6_send_router_sol(uint8_t sllao) ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -698,8 +695,7 @@ void icmpv6_send_router_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8 ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); /* calculate checksum */ - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -988,8 +984,7 @@ void icmpv6_send_neighbor_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t * ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -1261,8 +1256,7 @@ void icmpv6_send_neighbor_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *t ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; @@ -1435,17 +1429,18 @@ void icmpv6_ndp_set_sllao(icmpv6_ndp_opt_stllao_t *sllao, int if_id, } } -uint16_t icmpv6_csum(uint8_t proto) +uint16_t icmpv6_csum(ipv6_hdr_t *ipv6_buf, icmpv6_hdr_t *icmpv6_buf) { - ipv6_buf = ipv6_get_buf(); uint16_t sum; uint16_t len = NTOHS(ipv6_buf->length); - sum = len + proto; + + icmpv6_buf->checksum = 0; + sum = len + IPV6_PROTO_NUM_ICMPV6; sum = csum(sum, (uint8_t *)&ipv6_buf->srcaddr, 2 * sizeof(ipv6_addr_t)); - sum = csum(sum, (uint8_t *)get_icmpv6_buf(0), len); + sum = csum(sum, (uint8_t *)icmpv6_buf, len); - return (sum == 0) ? 0xffff : HTONS(sum); + return (sum == 0) ? 0 : ~HTONS(sum); } @@ -1481,8 +1476,7 @@ void icmpv6_send_parameter_prob(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_buf->length = HTONS(packet_length - IPV6_HDR_LEN); - icmp_buf->checksum = 0; - icmp_buf->checksum = ~icmpv6_csum(IPV6_PROTO_NUM_ICMPV6); + icmp_buf->checksum = icmpv6_csum(ipv6_buf, icmp_buf); #ifdef DEBUG_ENABLED char addr_str[IPV6_MAX_ADDR_STR_LEN]; diff --git a/sys/net/network_layer/sixlowpan/icmp.h b/sys/net/network_layer/sixlowpan/icmp.h index a8fcf12f15..a1fcf2f12b 100644 --- a/sys/net/network_layer/sixlowpan/icmp.h +++ b/sys/net/network_layer/sixlowpan/icmp.h @@ -56,6 +56,4 @@ void nbr_cache_auto_rem(void); ndp_a6br_cache_t *abr_add_context(uint16_t version, ipv6_addr_t *abr_addr, uint8_t cid); void abr_remove_context(uint8_t cid); - -uint16_t icmpv6_csum(uint8_t proto); #endif /* _SIXLOWPAN_ICMP_H*/ diff --git a/sys/net/network_layer/sixlowpan/lowpan.c b/sys/net/network_layer/sixlowpan/lowpan.c index d81a81ea54..7946c2e930 100644 --- a/sys/net/network_layer/sixlowpan/lowpan.c +++ b/sys/net/network_layer/sixlowpan/lowpan.c @@ -384,22 +384,22 @@ void lowpan_transfer(void) packet_length = current_buf->packet_size - 1; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if ((current_buf->packet[0] & 0xf0) == IPV6_VER && - iphc_status == LOWPAN_IPHC_DISABLE) { + else if (((current_buf->packet[0] & 0xf0) == IPV6_VER) && + (iphc_status == LOWPAN_IPHC_DISABLE)) { ipv6_buf = ipv6_get_buf(); memcpy(ipv6_buf, (current_buf->packet), current_buf->packet_size); m_send.content.ptr = (char *)ipv6_buf; packet_length = current_buf->packet_size; msg_send_receive(&m_send, &m_recv, ip_process_pid); } - else if ((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH && - iphc_status == LOWPAN_IPHC_ENABLE) { + else if (((current_buf->packet[0] & 0xe0) == SIXLOWPAN_IPHC1_DISPATCH) && + (iphc_status == LOWPAN_IPHC_ENABLE)) { DEBUG("INFO: IPHC1 dispatch 0x%02x received, decompress\n", current_buf->packet[0]); lowpan_iphc_decoding(current_buf->packet, current_buf->packet_size, - ¤t_buf->s_addr, - ¤t_buf->d_addr); + &(current_buf->s_addr), + &(current_buf->d_addr)); ipv6_buf = ipv6_get_buf(); m_send.content.ptr = (char *) ipv6_buf; diff --git a/sys/net/routing/rpl/rpl.c b/sys/net/routing/rpl/rpl.c index 2d9b2701d0..4b76c671a2 100644 --- a/sys/net/routing/rpl/rpl.c +++ b/sys/net/routing/rpl/rpl.c @@ -931,8 +931,7 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_net_if_get_best_src_addr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); - icmp_send_buf->checksum = 0; - icmp_send_buf->checksum = ~ipv6_csum(ipv6_send_buf, (uint8_t *) icmp_send_buf, ipv6_send_buf->length, IPV6_PROTO_NUM_ICMPV6); + icmp_send_buf->checksum = icmpv6_csum(ipv6_send_buf, icmp_send_buf); /* The packet was "assembled" in rpl.c. Therefore rpl_send_buf was used. * Therefore memcpy is not needed because the payload is at the