From bce377db1692521e7bdde56dec14504b17fe9799 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 17 Jul 2015 15:44:32 -0700 Subject: [PATCH 01/41] aodvv2: port to new network stack --- Makefile.dep | 8 +- sys/net/include/aodvv2/aodvv2.h | 53 +++ sys/net/routing/aodvv2/aodv.c | 528 +++++++++++++++++++++ sys/net/routing/aodvv2/aodv.h | 120 +++++ sys/net/routing/aodvv2/reader.c | 806 ++++++++++++++++++++++++++++++++ sys/net/routing/aodvv2/utils.c | 241 ++++++++++ sys/net/routing/aodvv2/utils.h | 115 +++++ 7 files changed, 1870 insertions(+), 1 deletion(-) create mode 100644 sys/net/include/aodvv2/aodvv2.h create mode 100644 sys/net/routing/aodvv2/aodv.c create mode 100644 sys/net/routing/aodvv2/aodv.h create mode 100644 sys/net/routing/aodvv2/reader.c create mode 100644 sys/net/routing/aodvv2/utils.c create mode 100644 sys/net/routing/aodvv2/utils.h diff --git a/Makefile.dep b/Makefile.dep index 93d5761d4157..e0c5a3bb1b96 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -278,7 +278,13 @@ endif ifneq (,$(filter gnrc_ipv6_hdr,$(USEMODULE))) USEMODULE += ipv6_hdr USEMODULE += gnrc_pktbuf -endif + +ifneq (,$(filter aodvv2,$(USEMODULE))) + USEMODULE += ng_sixlowpan_default + USEMODULE += vtimer + USEMODULE += oonf_common + USEMODULE += oonf_rfc5444 + USEMODULE += fib ifneq (,$(filter sixlowpan,$(USEMODULE))) USEMODULE += ipv6_hdr diff --git a/sys/net/include/aodvv2/aodvv2.h b/sys/net/include/aodvv2/aodvv2.h new file mode 100644 index 000000000000..2ebe559dfce2 --- /dev/null +++ b/sys/net/include/aodvv2/aodvv2.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup aodvv2 AODVv2 + * @brief The Ad-hoc On-demand Distance Vector routing protocol, version 2 + * @ingroup net + * @{ + * + * @file + * @brief Interface for the AODVv2 routing protocol + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_H_ +#define AODVV2_H_ + +#include "common/netaddr.h" +#include "rfc5444/rfc5444_print.h" +#include "kernel_types.h" + +#include "aodvv2/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the AODVv2 routing protocol. + */ +void aodv_init(kernel_pid_t interface); + +/** + * @brief Set the metric type. If metric_type does not match any known metric + * types, no changes will be made. + * + * @param[in] metric_type type of new metric + */ +void aodv_set_metric_type(aodvv2_metric_t metric_type); + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_H_ */ +/** @} */ diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c new file mode 100644 index 000000000000..7ba8cce3383f --- /dev/null +++ b/sys/net/routing/aodvv2/aodv.c @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief aodvv2 routing protocol + * + * @author Lotte Steenbrink + */ + +#include "aodv.h" +#include "aodvv2/aodvv2.h" +#include "aodv_debug.h" +#include "ng_fib.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define UDP_BUFFER_SIZE (128) /** with respect to IEEE 802.15.4's MTU */ +#define RCV_MSG_Q_SIZE (32) /* TODO: check if smaller values work, too */ + +static void _init_addresses(void); +static void _init_sock_snd(void); +static void *_aodv_receiver_thread(void *arg); +static void *_aodv_sender_thread(void *arg); +static void *fib_signal_handler_thread(void *arg); + +static void _deep_free_msg_container(struct msg_container *msg_container); +static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), + struct rfc5444_writer_target *iface __attribute__((unused)), + void *buffer, size_t length); +static void print_json_pkt_sent(struct writer_target *wt); + +#if AODV_DEBUG +char addr_str[IPV6_MAX_ADDR_STR_LEN]; +static struct netaddr_str nbuf; +static char addr_str[IPV6_MAX_ADDR_STR_LEN]; +#endif +#if TEST_SETUP +static struct netaddr_str nbuf_origaddr, nbuf_targaddr, nbuf_nexthop; +#endif + +static char aodv_rcv_stack_buf[THREAD_STACKSIZE_MAIN]; +static char aodv_snd_stack_buf[THREAD_STACKSIZE_MAIN]; +static char aodv_fib_stack_buf[THREAD_STACKSIZE_MAIN]; + +static aodvv2_metric_t _metric_type; +static int sender_thread; +static int _sock_snd; +static struct autobuf _hexbuf; +static ng_ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; +static ng_ipv6_addr_t* _v6_addr_local; +static struct netaddr na_local; /* the same as _v6_addr_local, but to save us + * constant calls to ipv6_addr_t_to_netaddr()... */ +static struct writer_target *wt; +static mutex_t rreq_mutex; +static mutex_t rrep_mutex; +static mutex_t rerr_mutex; + +struct netaddr na_mcast; +kernel_pid_t aodvv2_if_id; +ng_ipv6_addr_t aodvv2_prefix; +int aodvv2_prefix_len; + +void aodv_init(kernel_pid_t interface) +{ + AODV_DEBUG("%s()\n", __func__); + + /* init this thread's IPC msg queue */ + msg_t msgq[RCV_MSG_Q_SIZE]; + msg_init_queue(msgq, sizeof msgq); + + aodvv2_prefix_len = sizeof(ng_ipv6_addr_t); + aodvv2_if_id = interface; + ng_ipv6_addr_from_str(&aodvv2_prefix, "fe80:0000:0000:0000:0000:0000:0000:0000"); + + mutex_init(&rreq_mutex); + mutex_init(&rrep_mutex); + mutex_init(&rerr_mutex); + + aodv_set_metric_type(AODVV2_DEFAULT_METRIC_TYPE); + _init_addresses(); + _init_sock_snd(); + + /* init ALL the things! \o, */ + seqnum_init(); + routingtable_init(); + clienttable_init(); + + /* every node is its own client. */ + clienttable_add_client(&na_local); + rreqtable_init(); + + /* init reader and writer */ + aodv_packet_reader_init(); + aodv_packet_writer_init(_write_packet); + + /* start listening & enable sending */ + thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN, + CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); + AODV_DEBUG("listening on port %d\n", HTONS(MANET_PORT)); + sender_thread = thread_create(aodv_snd_stack_buf, sizeof(aodv_snd_stack_buf), + THREAD_PRIORITY_MAIN, CREATE_STACKTEST, _aodv_sender_thread, + NULL, "_aodv_sender_thread"); + thread_create(aodv_fib_stack_buf, sizeof(aodv_fib_stack_buf), + THREAD_PRIORITY_MAIN, CREATE_STACKTEST, fib_signal_handler_thread, + NULL, "fib_signal_handler_thread"); +} + +void aodv_set_metric_type(aodvv2_metric_t metric_type) +{ + if (metric_type != AODVV2_DEFAULT_METRIC_TYPE) { + return; + } + _metric_type = metric_type; +} +/* + * @brief handles callbacks from the FIB when it needs a route + */ +void *fib_signal_handler_thread(void *arg) +{ + (void) arg; + ng_ipv6_addr_t dest; + struct netaddr na_dest; + + int err = fib_register_rp(&aodvv2_prefix.u8[0], aodvv2_prefix_len); + if ( err != 0) { + AODV_DEBUG("ERROR: cannot register at fib, error code:\n"); + exit(1); + } + + while (true) { + msg_t msg; + msg_receive(&msg); + + if (msg.type == FIB_MSG_RP_SIGNAL) { + rp_address_msg_t* rp_msg = (rp_address_msg_t*)msg.content.ptr; + if (rp_msg->address_size == sizeof(ng_ipv6_addr_t)) { + /* We currently only support IPv6*/ + memcpy(&dest, rp_msg->address, rp_msg->address_size); + /* Reply to the FIB so that it can stop blocking */ + msg_reply(&msg, &msg); + + /* perform/initiate a rreq for dst here*/ + ipv6_addr_t_to_netaddr(&dest, &na_dest); + + aodvv2_seqnum_t seqnum = seqnum_get(); + seqnum_inc(); + + /* Build new RREQ */ + struct aodvv2_packet_data rreq_data = (struct aodvv2_packet_data) { + .hoplimit = AODVV2_MAX_HOPCOUNT, + .metricType = _metric_type, + .origNode = (struct node_data) { + .addr = na_local, + .metric = 0, + .seqnum = seqnum, + }, + .targNode = (struct node_data) { + .addr = na_dest, + }, + .timestamp = (timex_t) {0,0} /* this timestamp is never used, it exists + * merely to make the compiler shut up */ + }; + + AODV_DEBUG("\tstarting route discovery towards %s... \n", + ng_ipv6_addr_to_str(addr_str, &dest, IPV6_MAX_ADDR_STR_LEN)); + aodv_send_rreq(&rreq_data); + } + else { + /* Reply to the FIB so that it can stop blocking */ + msg_reply(&msg, &msg); + } + } + } + return NULL; +} + +void aodv_send_rreq(struct aodvv2_packet_data *packet_data) +{ + /* Make sure only one thread is dispatching a RREQ at a time */ + mutex_lock(&rreq_mutex); + + struct aodvv2_packet_data *pd = malloc(sizeof(struct aodvv2_packet_data)); + memcpy(pd, packet_data, sizeof(struct aodvv2_packet_data)); + + struct rreq_rrep_data *rd = malloc(sizeof(struct rreq_rrep_data)); + *rd = (struct rreq_rrep_data) { + .next_hop = &na_mcast, + .packet_data = pd, + }; + + struct msg_container *mc = malloc(sizeof(struct msg_container)); + *mc = (struct msg_container) { + .type = RFC5444_MSGTYPE_RREQ, + .data = rd + }; + + msg_t msg; + msg.content.ptr = (char *) mc; + + msg_try_send(&msg, sender_thread); + mutex_unlock(&rreq_mutex); +} + +void aodv_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop) +{ + /* Make sure only one thread is dispatching a RREP at a time */ + mutex_lock(&rrep_mutex); + + struct aodvv2_packet_data *pd = malloc(sizeof(struct aodvv2_packet_data)); + memcpy(pd, packet_data, sizeof(struct aodvv2_packet_data)); + + struct netaddr *nh = malloc(sizeof(struct netaddr)); + memcpy(nh, next_hop, sizeof(struct netaddr)); + + struct rreq_rrep_data *rd = malloc(sizeof(struct rreq_rrep_data)); + *rd = (struct rreq_rrep_data) { + .next_hop = nh, + .packet_data = pd, + }; + + struct msg_container *mc = malloc(sizeof(struct msg_container)); + *mc = (struct msg_container) { + .type = RFC5444_MSGTYPE_RREP, + .data = rd + }; + + msg_t msg; + msg.content.ptr = (char *) mc; + + msg_try_send(&msg, sender_thread); + mutex_unlock(&rrep_mutex); +} + +void aodv_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, struct netaddr *next_hop) +{ + /* Make sure only one thread is dispatching a RERR at a time */ + mutex_lock(&rerr_mutex); + + struct rerr_data *rerrd = malloc(sizeof(struct rerr_data)); + *rerrd = (struct rerr_data) { + .unreachable_nodes = unreachable_nodes, + .len = len, + .hoplimit = AODVV2_MAX_HOPCOUNT, + .next_hop = next_hop + }; + + struct msg_container *mc2 = malloc(sizeof(struct msg_container)); + *mc2 = (struct msg_container) { + .type = RFC5444_MSGTYPE_RERR, + .data = rerrd + }; + + msg_t msg2; + msg2.content.ptr = (char *) mc2; + + msg_try_send(&msg2, sender_thread); + mutex_unlock(&rerr_mutex); +} + +/* + * init the multicast address all RREQ and RERRS are sent to + * and the local address (source address) of this node + */ +static void _init_addresses(void) +{ + /* init multicast address: set to to a link-local all nodes multicast address */ + ng_ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); + AODV_DEBUG("my multicast address is: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &_v6_addr_mcast)); + + /* get best IP for sending */ + _v6_addr_local = ng_ipv6_netif_find_best_src_addr(aodvv2_if_id,&_v6_addr_mcast); + AODV_DEBUG("my src address is: %s\n", + ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, _v6_addr_local)); + + /* store src & multicast address as netaddr as well for easy interaction + * with oonf based stuff */ + ipv6_addr_t_to_netaddr(_v6_addr_local, &na_local); + ipv6_addr_t_to_netaddr(&_v6_addr_mcast, &na_mcast); + ng_ipv6_addr_set_loopback(&_v6_addr_loopback); +} + +/* init socket communication for sender */ +static void _init_sock_snd(void) +{ + _sock_snd = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + + if (-1 == _sock_snd) { + AODV_DEBUG("Error Creating Socket!\n"); + } +} + +/* Build RREQs, RREPs and RERRs from the information contained in the thread's + * message queue and send them */ +static void *_aodv_sender_thread(void *arg) +{ + (void) arg; + + msg_t msgq[RCV_MSG_Q_SIZE]; + msg_init_queue(msgq, RCV_MSG_Q_SIZE); + + while (true) { + msg_t msg; + msg_receive(&msg); + struct msg_container *mc = (struct msg_container *) msg.content.ptr; + + if (mc->type == RFC5444_MSGTYPE_RREQ) { + struct rreq_rrep_data *rreq_data = (struct rreq_rrep_data *) mc->data; + aodv_packet_writer_send_rreq(rreq_data->packet_data, rreq_data->next_hop); + } + else if (mc->type == RFC5444_MSGTYPE_RREP) { + struct rreq_rrep_data *rrep_data = (struct rreq_rrep_data *) mc->data; + aodv_packet_writer_send_rrep(rrep_data->packet_data, rrep_data->next_hop); + } + else if (mc->type == RFC5444_MSGTYPE_RERR) { + struct rerr_data *rerr_data = (struct rerr_data *) mc->data; + aodv_packet_writer_send_rerr(rerr_data->unreachable_nodes, rerr_data->len, + rerr_data->hoplimit, rerr_data->next_hop); + } + else { + AODV_DEBUG("ERROR: Couldn't identify Message\n"); + } + _deep_free_msg_container(mc); + } + + return NULL; +} + +/* receive RREQs, RREPs and RERRs and handle them */ +static void *_aodv_receiver_thread(void *arg) +{ + (void) arg; + + ng_netreg_entry_t server = { + .next = NULL, + .demux_ctx = NG_NETREG_DEMUX_CTX_ALL, + .pid = KERNEL_PID_UNDEF }; + + AODV_DEBUG("%s()\n", __func__); + char buf_rcv[UDP_BUFFER_SIZE]; + struct netaddr _sender; + + msg_t msg, reply; + msg_t msg_q[RCV_MSG_Q_SIZE]; + + msg_init_queue(msg_q, RCV_MSG_Q_SIZE); + reply.content.value = (uint32_t)(-ENOTSUP); + reply.type = NG_NETAPI_MSG_TYPE_ACK; + + /* start server (which means registering AODVv2 receiver for the chosen port) */ + server.pid = sched_active_pid; /* sched_active_pid is our pid, since we are currently act */ + server.demux_ctx = (uint32_t)HTONS(MANET_PORT); + ng_netreg_register(NG_NETTYPE_UDP, &server); + + while (1) { + msg_receive(&msg); + switch (msg.type) { + case NG_NETAPI_MSG_TYPE_RCV: + AODV_DEBUG("received data:"); + ng_pktsnip_t *pkt = ((ng_pktsnip_t *)msg.content.ptr); + if (pkt->size <= UDP_BUFFER_SIZE) { + memcpy(buf_rcv, pkt->data, pkt->size); + + if(pkt->next->next->type == NG_NETTYPE_IPV6) { + ipv6_addr_t_to_netaddr(&(((ng_ipv6_hdr_t*)(pkt->next->next->data))->src), &_sender); + } + + if (netaddr_cmp(&_sender, &na_local) == 0) { + AODV_DEBUG("received our own packet, dropping it.\n"); + } + else { + aodv_packet_reader_handle_packet((void *) buf_rcv, pkt->size, &_sender); + } + } + ng_pktbuf_release(pkt); + break; + case NG_NETAPI_MSG_TYPE_SND: + break; + case NG_NETAPI_MSG_TYPE_GET: + case NG_NETAPI_MSG_TYPE_SET: + msg_reply(&msg, &reply); + break; + default: + AODV_DEBUG("received something unexpected"); + break; + } + } + + return NULL; +} + +/** + The code o this function was borrowed from: + examples/ng_networking/udp.c:34 - :90 +*/ +static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_length) +{ + ng_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; + + /* convert to correct byteorder */ + port = HTONS(port); + + /* allocate payload */ + payload = ng_pktbuf_add(NULL, data, data_length, NG_NETTYPE_UNDEF); + if (payload == NULL) { + AODV_DEBUG("Error: unable to copy data to packet buffer\n"); + return; + } + /* allocate UDP header, set payload, set source port := destination port */ + pkt_with_udp = ng_udp_hdr_build(payload, (uint8_t*)&port, 2, (uint8_t*)&port, 2); + if (pkt_with_udp == NULL) { + AODV_DEBUG("Error: unable to allocate UDP header\n"); + ng_pktbuf_release(payload); + return; + } + /* allocate IPv6 header, set pkt_with_udp as payload */ + pkt_with_ip = ng_ipv6_hdr_build(pkt_with_udp, NULL, 0, (uint8_t *)&addr, sizeof(addr)); + if (pkt_with_ip == NULL) { + AODV_DEBUG("Error: unable to allocate IPv6 header\n"); + ng_pktbuf_release(pkt_with_udp); + return; + } + /* all headers are set, send packet */ + if(!ng_netapi_dispatch_send(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { + DEBUG("Error sending packet"); + } +} + +/** + * Handle the output of the RFC5444 packet creation process. This callback is + * called by every writer_send_* function. + */ +static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), + struct rfc5444_writer_target *iface __attribute__((unused)), + void *buffer, size_t length) +{ + AODV_DEBUG("%s()\n", __func__); + ng_ipv6_addr_t addr_send; + + /* generate hexdump and human readable representation of packet + * and print to console */ + abuf_hexdump(&_hexbuf, "\t", buffer, length); + rfc5444_print_direct(&_hexbuf, buffer, length); + /* DEBUG("%s", abuf_getptr(&_hexbuf)); */ + abuf_clear(&_hexbuf); + + /* fetch the address the packet is supposed to be sent to (i.e. to a + * specific node or the multicast address) from the writer_target struct + * iface* is stored in. This is a bit hacky, but it does the trick. */ + wt = container_of(iface, struct writer_target, interface); + + print_json_pkt_sent(wt); + netaddr_to_ipv6_addr_t(&wt->target_addr, &addr_send); + + /* When originating a RREQ, add it to our RREQ table/update its predecessor */ + if (wt->type == RFC5444_MSGTYPE_RREQ + && netaddr_cmp(&wt->packet_data.origNode.addr, &na_local) == 0) { + DEBUG("originating RREQ with SeqNum %d towards %s via %s; updating RREQ table...\n", + wt->packet_data.origNode.seqnum, + netaddr_to_string(&nbuf, &wt->packet_data.targNode.addr), + ng_ipv6_addr_to_str(addr_str, &addr_send, IPV6_MAX_ADDR_STR_LEN)); + rreqtable_is_redundant(&wt->packet_data); + } + + send(addr_send, (uint16_t) MANET_PORT, buffer, length); +} + +/* Print the json representation of a sent packet to stdout for debugging */ +static void print_json_pkt_sent(struct writer_target *wt) +{ +#if TEST_SETUP + // note: what if the content at wt has changed until this is printed? memcpy the entire thing? + int msg_type = wt->type; + if (msg_type == RFC5444_MSGTYPE_RREQ) { + printf("{\"log_type\": \"sent_rreq\", \"log_data\": {" + "\"orig_addr\": \"%s\", \"targ_addr\": \"%s\", \"orig_seqnum\": %d, \"metric\": %d}}\n", + netaddr_to_string(&nbuf_origaddr, &wt->packet_data.origNode.addr), + netaddr_to_string(&nbuf_targaddr, &wt->packet_data.targNode.addr), + wt->packet_data.origNode.seqnum, wt->packet_data.origNode.metric); + } + if (msg_type == RFC5444_MSGTYPE_RREP) { + printf("{\"log_type\": \"sent_rrep\", \"log_data\": {" + "\"next_hop\": \"%s\",\"orig_addr\": \"%s\", \"orig_seqnum\": %d," + " \"targ_addr\": \"%s\"}}\n", + netaddr_to_string(&nbuf_nexthop, &wt->target_addr), + netaddr_to_string(&nbuf_origaddr, &wt->packet_data.origNode.addr), + wt->packet_data.origNode.seqnum, + netaddr_to_string(&nbuf_targaddr, &wt->packet_data.targNode.addr)); + } + if (msg_type == RFC5444_MSGTYPE_RERR) { + /* TODO */ + } +#else + (void) wt; /* silence compiler */ +#endif +} + +/* free the matryoshka doll of cobbled-together structs that the sender_thread receives */ +static void _deep_free_msg_container(struct msg_container *mc) +{ + int type = mc->type; + if ((type == RFC5444_MSGTYPE_RREQ) || (type == RFC5444_MSGTYPE_RREP)) { + struct rreq_rrep_data *rreq_rrep_data = (struct rreq_rrep_data *) mc->data; + free(rreq_rrep_data->packet_data); + if (netaddr_cmp(rreq_rrep_data->next_hop, &na_mcast) != 0) { + free(rreq_rrep_data->next_hop); + } + } + else if (type == RFC5444_MSGTYPE_RERR) { + struct rerr_data *rerr_data = (struct rerr_data *) mc->data; + if (netaddr_cmp(rerr_data->next_hop, &na_mcast) != 0) { + free(rerr_data->next_hop); + } + } + free(mc->data); + free(mc); +} diff --git a/sys/net/routing/aodvv2/aodv.h b/sys/net/routing/aodvv2/aodv.h new file mode 100644 index 000000000000..2c7729633512 --- /dev/null +++ b/sys/net/routing/aodvv2/aodv.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief aodvv2 routing protocol + * + * @author Lotte Steenbrink + */ + +#ifndef AODV_H_ +#define AODV_H_ + +#include "kernel.h" +#include "udp.h" +#include "net/ng_ipv6.h" +#include "net/ng_netbase.h" +#include "net/ng_netif.h" +#include "net/ng_udp.h" +#include "net/ng_pkt.h" + +#include "aodvv2/types.h" +#include "constants.h" +#include "seqnum.h" +#include "routingtable.h" +#include "utils.h" +#include "reader.h" +#include "writer.h" +#include "thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This struct contains data which needs to be put into a RREQ or RREP. + * It is used to transport this data in a message to the sender_thread. + * @note Please note that it is for internal use only. To send a RREQ or RREP, + * please use the aodv_send_rreq() and aodv_send_rrep() functions. + */ +struct rreq_rrep_data +{ + struct aodvv2_packet_data *packet_data; /**< Data for the RREQ or RREP */ + struct netaddr *next_hop; /**< Next hop to which the RREQ + * or RREP should be sent */ +}; + +/** + * @brief This struct contains data which needs to be put into a RERR. + * It is used to transport this data in a message to the sender_thread. + * @note Please note that it is for internal use only. To send a RERR, + * please use the aodv_send_rerr() function. + */ +struct rerr_data +{ + struct unreachable_node *unreachable_nodes; /**< All unreachable nodes. Beware, + * this is the start of an array */ + size_t len; /**< Length of the unreachable_nodes array */ + int hoplimit; /**< hoplimit for the RERR */ + struct netaddr *next_hop; /**< Next hop to which the RERR + * should be sent */ +}; + + +/** + * @brief This struct holds the data for a RREQ, RREP or RERR (contained + * in a rreq_rrep_data or rerr_data struct) and the next hop the RREQ, RREP + * or RERR should be sent to. It used for message communication with + * the sender_thread. + * @note Please note that it is for internal use only. To send a RERR, + * please use the aodv_send_rerr() function. + */ +struct msg_container +{ + int type; /**< Message type (i.e. one of + * rfc5444_msg_type) */ + void *data; /**< Pointer to the message data + * (i.e. rreq_rrep_data or rerr_data) */ +}; + +/** + * @brief Dispatch a RREQ + * + * @param[in] packet_data Payload of the RREQ + */ +void aodv_send_rreq(struct aodvv2_packet_data *packet_data); + +/** + * @brief Dispatch a RREP + * + * @param[in] packet_data Payload of the RREP + * @param[in] next_hop Address of the next hop the RREP should be sent to + */ +void aodv_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop); + +/** + * @brief Dispatch a RERR + * + * @param[in] unreachable_nodes All nodes that are marked as unreachable + * by this RERR + * @param[in] len Number of unreachable nodes + * @param[in] next_hop Address of the next hop the RERR should be sent to + */ +void aodv_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, + struct netaddr *next_hop); + +#ifdef __cplusplus +} +#endif + +#endif /* AODV_H_ */ diff --git a/sys/net/routing/aodvv2/reader.c b/sys/net/routing/aodvv2/reader.c new file mode 100644 index 000000000000..fbe2f23c54b9 --- /dev/null +++ b/sys/net/routing/aodvv2/reader.c @@ -0,0 +1,806 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief reading and handling of RFC5444 aodvv2 messages + * + * @author Lotte Steenbrink + */ + +#ifdef RIOT +#include "net_help.h" +#endif + +#include "reader.h" +#include "aodv_debug.h" +#include "ng_fib.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#if ENABLE_DEBUG +/* For PRIu16 etc. */ +#include +#endif + +static enum rfc5444_result _cb_rreq_blocktlv_addresstlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rreq_blocktlv_messagetlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rreq_end_callback( + struct rfc5444_reader_tlvblock_context *cont, bool dropped); + +static enum rfc5444_result _cb_rrep_blocktlv_addresstlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rrep_blocktlv_messagetlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rrep_end_callback( + struct rfc5444_reader_tlvblock_context *cont, bool dropped); + +static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rerr_blocktlv_messagetlvs_okay( + struct rfc5444_reader_tlvblock_context *cont); +static enum rfc5444_result _cb_rerr_end_callback( + struct rfc5444_reader_tlvblock_context *cont, bool dropped); + +/* helper functions */ +static void print_json_received_rreq(void); +static void print_json_received_rrep(void); +static uint8_t _get_link_cost(aodvv2_metric_t metricType); +static uint8_t _get_max_metric(aodvv2_metric_t metricType); +static uint8_t _get_route_cost(aodvv2_metric_t metricType, uint8_t metric); + +/* This is where we store data gathered from packets */ +static struct aodvv2_packet_data packet_data; +static struct unreachable_node unreachable_nodes[AODVV2_MAX_UNREACHABLE_NODES]; +static int num_unreachable_nodes; +static int aodvv2_validity_t = (AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME) * 1000; /* milliseconds */ + +static struct rfc5444_reader reader; +#if AODV_DEBUG +static struct netaddr_str nbuf; +#endif + +/* + * Message consumer, will be called once for every message of + * type RFC5444_MSGTYPE_RREQ that contains all the mandatory message TLVs + */ +static struct rfc5444_reader_tlvblock_consumer _rreq_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RREQ, + .block_callback = _cb_rreq_blocktlv_messagetlvs_okay, + .end_callback = _cb_rreq_end_callback, +}; + +/* + * Address consumer. Will be called once for every address in a message of + * type RFC5444_MSGTYPE_RREQ. + */ +static struct rfc5444_reader_tlvblock_consumer _rreq_address_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RREQ, + .addrblock_consumer = true, + .block_callback = _cb_rreq_blocktlv_addresstlvs_okay, +}; + +/* + * Message consumer, will be called once for every message of + * type RFC5444_MSGTYPE_RREP that contains all the mandatory message TLVs + */ +static struct rfc5444_reader_tlvblock_consumer _rrep_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RREP, + .block_callback = _cb_rrep_blocktlv_messagetlvs_okay, + .end_callback = _cb_rrep_end_callback, +}; + +/* + * Address consumer. Will be called once for every address in a message of + * type RFC5444_MSGTYPE_RREP. + */ +static struct rfc5444_reader_tlvblock_consumer _rrep_address_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RREP, + .addrblock_consumer = true, + .block_callback = _cb_rrep_blocktlv_addresstlvs_okay, +}; + +/* + * Message consumer, will be called once for every message of + * type RFC5444_MSGTYPE_RERR that contains all the mandatory message TLVs + */ +static struct rfc5444_reader_tlvblock_consumer _rerr_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RERR, + .block_callback = _cb_rerr_blocktlv_messagetlvs_okay, + .end_callback = _cb_rerr_end_callback, +}; + +/* + * Address consumer. Will be called once for every address in a message of + * type RFC5444_MSGTYPE_RERR. + */ +static struct rfc5444_reader_tlvblock_consumer _rerr_address_consumer = +{ + .msg_id = RFC5444_MSGTYPE_RERR, + .addrblock_consumer = true, + .block_callback = _cb_rerr_blocktlv_addresstlvs_okay, +}; + + +/* + * Address consumer entries definition + * TLV types RFC5444_MSGTLV__SEQNUM and RFC5444_MSGTLV_METRIC + */ +static struct rfc5444_reader_tlvblock_consumer_entry _rreq_rrep_address_consumer_entries[] = +{ + [RFC5444_MSGTLV_ORIGSEQNUM] = { .type = RFC5444_MSGTLV_ORIGSEQNUM}, + [RFC5444_MSGTLV_TARGSEQNUM] = { .type = RFC5444_MSGTLV_TARGSEQNUM}, + [RFC5444_MSGTLV_METRIC] = { .type = RFC5444_MSGTLV_METRIC } +}; + +/* + * Address consumer entries definition + * TLV types RFC5444_MSGTLV__SEQNUM and RFC5444_MSGTLV_METRIC + */ +static struct rfc5444_reader_tlvblock_consumer_entry _rerr_address_consumer_entries[] = +{ + [RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM] = { + .type = RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM + }, +}; + +/** + * This block callback is called for every address + * + * @param cont + * @return + */ +static enum rfc5444_result _cb_rreq_blocktlv_messagetlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ + if (!cont->has_hoplimit) { + AODV_DEBUG("\tERROR: missing hop limit\n"); + return RFC5444_DROP_PACKET; + } + + packet_data.hoplimit = cont->hoplimit; + if (packet_data.hoplimit == 0) { + AODV_DEBUG("\tERROR: Hoplimit is 0.\n"); + return RFC5444_DROP_PACKET; + } + packet_data.hoplimit--; + + return RFC5444_OKAY; +} + +/** + * This block callback is called for every address of a RREQ Message. + * + * @param cont + * @return + */ +static enum rfc5444_result _cb_rreq_blocktlv_addresstlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ +#if AODV_DEBUG + struct netaddr_str nbuf; +#endif + struct rfc5444_reader_tlvblock_entry *tlv; + bool is_origNode_addr = false; + bool is_targNode_addr = false; + + /* handle OrigNode SeqNum TLV */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_ORIGSEQNUM].tlv; + if (tlv) { + is_origNode_addr = true; + packet_data.origNode.addr = cont->addr; + packet_data.origNode.seqnum = *tlv->single_value; + } + + /* handle TargNode SeqNum TLV */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_TARGSEQNUM].tlv; + if (tlv) { + is_targNode_addr = true; + packet_data.targNode.addr = cont->addr; + packet_data.targNode.seqnum = *tlv->single_value; + } + if (!tlv && !is_origNode_addr) { + /* assume that tlv missing => targNode Address */ + is_targNode_addr = true; + packet_data.targNode.addr = cont->addr; + } + if (!is_origNode_addr && !is_targNode_addr) { + AODV_DEBUG("\tERROR: mandatory RFC5444_MSGTLV_ORIGSEQNUM TLV missing.\n"); + return RFC5444_DROP_PACKET; + } + + /* handle Metric TLV */ + /* cppcheck: suppress false positive on non-trivially initialized arrays. + * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ + /* cppcheck-suppress arrayIndexOutOfBounds */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_METRIC].tlv; + if (!tlv && is_origNode_addr) { + AODV_DEBUG("\tERROR: Missing or unknown metric TLV.\n"); + return RFC5444_DROP_PACKET; + } + if (tlv) { + if (!is_origNode_addr) { + AODV_DEBUG("\tERROR: Metric TLV belongs to wrong address.\n"); + return RFC5444_DROP_PACKET; + } + packet_data.metricType = tlv->type_ext; + packet_data.origNode.metric = *tlv->single_value; + } + + return RFC5444_OKAY; +} + +/** + * This callback is called every time the _rreq_consumer finishes reading a + * packet. + * @param cont + * @param dropped indicates whether the packet has been dropped previously by + * another callback + */ +static enum rfc5444_result _cb_rreq_end_callback( + struct rfc5444_reader_tlvblock_context *cont, bool dropped) +{ + (void) cont; + + struct aodvv2_routing_entry_t *rt_entry; + timex_t now; + + /* We've received a valid RREQ, log this. */ + print_json_received_rreq(); + + /* Check if packet contains the required information */ + if (dropped) { + AODV_DEBUG("\t Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if ((packet_data.origNode.addr._type == AF_UNSPEC) || !packet_data.origNode.seqnum) { + AODV_DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if (packet_data.targNode.addr._type == AF_UNSPEC) { + AODV_DEBUG("\tERROR: missing TargNode Address. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if (packet_data.hoplimit == 0) { + AODV_DEBUG("\tERROR: Hoplimit is 0. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType)) + <= packet_data.origNode.metric) { + AODV_DEBUG("\tMetric Limit reached. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + + /* + The incoming RREQ MUST be checked against previously received + information from the RREQ Table Section 7.6. If the information + in the incoming RteMsg is redundant, then then no further action + is taken. + */ + if (rreqtable_is_redundant(&packet_data)) { + AODV_DEBUG("\tPacket is redundant. Dropping Packet. %i\n", RFC5444_DROP_PACKET); + return RFC5444_DROP_PACKET; + } + + /* Update the cost of the route, since the packet has successfully traversed + * one more hop. */ + packet_data.origNode.metric = _get_route_cost(packet_data.metricType, + packet_data.origNode.metric); + vtimer_now(&now); + packet_data.timestamp = now; + + /* for every relevant + * address (RteMsg.Addr) in the RteMsg, HandlingRtr searches its route + * table to see if there is a route table entry with the same MetricType + * of the RteMsg, matching RteMsg.Addr. + */ + + rt_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType); + + if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { + /* CAUTION SUPER HACKY FIX FIXME ASAP + problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then + AODVv2 gets super confused when they're not in the routing table and starts a + Route discovery to find them and all hell breaks loose. let's see if we can fix + this (horribly). + + (another fix would be to stop bouncing the RREP back to the sender and asking + the routing table for the next hop (or just send towards TargNode and let the + network stack figure out the rest?)) + TODO evaluate that + */ + + /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) + + ng_ipv6_addr_t sender_tmp; + netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); + + ng_ipv6_addr_t nxt_hop; + size_t nxt_hop_size = sizeof(ng_ipv6_addr_t); + uint32_t next_hop_flags = 0; + if(fib_get_next_hop(&aodvv2_if_id, + &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, + &sender_tmp.u8[0], sizeof(ng_ipv6_addr_t), 0) != 0) { + DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + */ + /* HACKY FIX ENDS HERE */ + + struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) + malloc(sizeof(struct aodvv2_routing_entry_t)); + memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry)); + + routingtable_fill_routing_entry_t_rreq(&packet_data, tmp_rt_entry); + routingtable_add_entry(tmp_rt_entry); + + /* add entry to FIB */ + fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), 0, + tmp_rt_entry->nextHopAddr._addr, sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + + free(tmp_rt_entry); + } + else { + if (!routingtable_offers_improvement(rt_entry, &packet_data.origNode)) { + AODV_DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n"); + return RFC5444_DROP_PACKET; + } + /* The incoming routing information is better than existing routing + * table information and SHOULD be used to improve the route table. */ + AODV_DEBUG("\tUpdating Routing Table entry...\n"); + routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry); + + /* update the FIB */ + fib_update_entry(rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), rt_entry->nextHopAddr._addr, + sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + } + + /* + * If TargNode is a client of the router receiving the RREQ, then the + * router generates a RREP message as specified in Section 7.4, and + * subsequently processing for the RREQ is complete. Otherwise, + * processing continues as follows. + */ + if (clienttable_is_client(&packet_data.targNode.addr)) { + AODV_DEBUG("TargNode is in client list, sending RREP\n"); + + /* make sure to start with a clean metric value */ + packet_data.targNode.metric = 0; + aodv_send_rrep(&packet_data, &packet_data.sender); + } + else { + AODV_DEBUG("I am not TargNode, forwarding RREQ\n"); + aodv_send_rreq(&packet_data); + } + return RFC5444_OKAY; +} + +/** + * This block callback is called for every address + * + * @param cont + * @return + */ +static enum rfc5444_result _cb_rrep_blocktlv_messagetlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ + if (!cont->has_hoplimit) { + AODV_DEBUG("\tERROR: missing hop limit\n"); + return RFC5444_DROP_PACKET; + } + + packet_data.hoplimit = cont->hoplimit; + if (packet_data.hoplimit == 0) { + AODV_DEBUG("\tERROR: Hoplimit is 0.\n"); + return RFC5444_DROP_PACKET; + } + + packet_data.hoplimit--; + + return RFC5444_OKAY; +} + +/** + * This block callback is called for every address of a RREP Message. + * + * @param cont + * @return + */ +static enum rfc5444_result _cb_rrep_blocktlv_addresstlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ +#if AODV_DEBUG + /* cppcheck-suppress unusedVariable as nbuf is needed by AODV_DEBUG. */ + struct netaddr_str nbuf; +#endif + struct rfc5444_reader_tlvblock_entry *tlv; + bool is_targNode_addr = false; + + /* handle TargNode SeqNum TLV */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_TARGSEQNUM].tlv; + if (tlv) { + is_targNode_addr = true; + packet_data.targNode.addr = cont->addr; + packet_data.targNode.seqnum = *tlv->single_value; + } + + /* handle OrigNode SeqNum TLV */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_ORIGSEQNUM].tlv; + if (tlv) { + is_targNode_addr = false; + packet_data.origNode.addr = cont->addr; + packet_data.origNode.seqnum = *tlv->single_value; + } + if (!tlv && !is_targNode_addr) { + AODV_DEBUG("\tERROR: mandatory SeqNum TLV missing.\n"); + return RFC5444_DROP_PACKET; + } + + /* handle Metric TLV */ + /* cppcheck: suppress false positive on non-trivially initialized arrays. + * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ + /* cppcheck-suppress arrayIndexOutOfBounds */ + tlv = _rreq_rrep_address_consumer_entries[RFC5444_MSGTLV_METRIC].tlv; + if (!tlv && is_targNode_addr) { + AODV_DEBUG("\tERROR: Missing or unknown metric TLV.\n"); + return RFC5444_DROP_PACKET; + } + if (tlv) { + if (!is_targNode_addr) { + AODV_DEBUG("\tERROR: metric TLV belongs to wrong address.\n"); + return RFC5444_DROP_PACKET; + } + packet_data.metricType = tlv->type_ext; + packet_data.targNode.metric = *tlv->single_value; + } + return RFC5444_OKAY; +} + +/** + * This callback is called every time the _rreq_consumer finishes reading a + * packet. + * @param cont + * @param dropped indicates wehther the packet has been dropped previously by + * another callback + */ +static enum rfc5444_result _cb_rrep_end_callback( + struct rfc5444_reader_tlvblock_context *cont, bool dropped) +{ + (void) cont; + + struct aodvv2_routing_entry_t *rt_entry; +#if AODV_DEBUG + struct netaddr_str nbuf; +#endif + timex_t now; + + /* We've received a valid RREP, log this. */ + print_json_received_rrep(); + + /* Check if packet contains the required information */ + if (dropped) { + AODV_DEBUG("\t Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if ((packet_data.origNode.addr._type == AF_UNSPEC) + || !packet_data.origNode.seqnum) { + AODV_DEBUG("\tERROR: missing OrigNode Address or SeqNum. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if ((packet_data.targNode.addr._type == AF_UNSPEC) + || !packet_data.targNode.seqnum) { + AODV_DEBUG("\tERROR: missing TargNode Address or SeqNum. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + if ((_get_max_metric(packet_data.metricType) - _get_link_cost(packet_data.metricType)) + <= packet_data.targNode.metric) { + AODV_DEBUG("\tMetric Limit reached. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + + /* Update the cost of the route, since the packet has successfully traversed + * one more hop. */ + packet_data.targNode.metric = _get_route_cost(packet_data.metricType, + packet_data.targNode.metric); + vtimer_now(&now); + packet_data.timestamp = now; + + /* for every relevant address (RteMsg.Addr) in the RteMsg, HandlingRtr + searches its route table to see if there is a route table entry with the + same MetricType of the RteMsg, matching RteMsg.Addr. */ + + rt_entry = routingtable_get_entry(&packet_data.targNode.addr, packet_data.metricType); + + if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { + /* CAUTION SUPER HACKY FIX FIXME ASAP + problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then + AODVv2 gets super confused when they're not in the routing table and starts a + Route discovery to find them and all hell breaks loose. let's see if we can fix + this (horribly). + + (another fix would be to stop bouncing the RREP back to the sender and asking + the routing table for the next hop (or just send towards TargNode and let the network stack figure out the rest?)) + TODO evaluate that + */ + + /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) + + ng_ipv6_addr_t sender_tmp; + netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); + + ng_ipv6_addr_t nxt_hop; + size_t nxt_hop_size = sizeof(ng_ipv6_addr_t); + uint32_t next_hop_flags = 0; + if(fib_get_next_hop(&aodvv2_if_id, + &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, + &sender_tmp.u8[0], sizeof(ng_ipv6_addr_t), 0) != 0) { + DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); + return RFC5444_DROP_PACKET; + } + */ + /* HACKY FIX ENDS HERE */ + + struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) + malloc(sizeof(struct aodvv2_routing_entry_t)); + memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry)); + + routingtable_fill_routing_entry_t_rrep(&packet_data, tmp_rt_entry); + routingtable_add_entry(tmp_rt_entry); + + /* add entry to FIB */ + fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), 0, + tmp_rt_entry->nextHopAddr._addr, sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + + free(tmp_rt_entry); + } + else { + if (!routingtable_offers_improvement(rt_entry, &packet_data.targNode)) { + AODV_DEBUG("\tPacket offers no improvement over known route. Dropping Packet.\n"); + return RFC5444_DROP_PACKET; + } + /* The incoming routing information is better than existing routing + * table information and SHOULD be used to improve the route table. */ + AODV_DEBUG("\tUpdating Routing Table entry...\n"); + routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry); + + /* update the FIB */ + fib_update_entry(rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), rt_entry->nextHopAddr._addr, + sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + } + + /* If HandlingRtr is RREQ_Gen then the RREP satisfies RREQ_Gen's + earlier RREQ, and RREP processing is completed. Any packets + buffered for OrigNode should be transmitted. */ + if (clienttable_is_client(&packet_data.origNode.addr)) { + AODV_DEBUG("\t%s: This is my RREP. We are done here!\n", + netaddr_to_string(&nbuf, &packet_data.origNode.addr)); + } + + else { + /* If HandlingRtr is not RREQ_Gen then the outgoing RREP is sent to the + * Route.NextHopAddress for the RREP.AddrBlk[OrigNodeNdx]. */ + AODV_DEBUG("Not my RREP, passing it on to the next hop\n"); + aodv_send_rrep(&packet_data, + routingtable_get_next_hop(&packet_data.origNode.addr,packet_data.metricType)); + } + return RFC5444_OKAY; +} + +static enum rfc5444_result _cb_rerr_blocktlv_messagetlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ + if (!cont->has_hoplimit) { + AODV_DEBUG("\tERROR: missing hop limit\n"); + return RFC5444_DROP_PACKET; + } + + packet_data.hoplimit = cont->hoplimit; + if (packet_data.hoplimit == 0) { + AODV_DEBUG("\tERROR: Hoplimit is 0.\n"); + return RFC5444_DROP_PACKET; + } + + packet_data.hoplimit--; + + /* prepare buffer for unreachable nodes */ + num_unreachable_nodes = 0; + for (unsigned i = 0; i < AODVV2_MAX_UNREACHABLE_NODES; i++) { + memset(&unreachable_nodes[i], 0, sizeof(unreachable_nodes[i])); + } + return RFC5444_OKAY; +} + +static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +{ +#if AODV_DEBUG + /* cppcheck-suppress unusedVariable as nbuf is needed by AODV_DEBUG. */ + struct netaddr_str nbuf; +#endif + struct aodvv2_routing_entry_t *unreachable_entry; + struct rfc5444_reader_tlvblock_entry *tlv; + + AODV_DEBUG("%s()\n", __func__); + AODV_DEBUG("\tmessage type: %d\n", cont->type); + AODV_DEBUG("\taddr: %s\n", netaddr_to_string(&nbuf, &cont->addr)); + + /* Out of buffer size for more unreachable nodes. We're screwed, basically. */ + if (num_unreachable_nodes == AODVV2_MAX_UNREACHABLE_NODES) { + return RFC5444_OKAY; + } + + /* gather packet data */ + packet_data.origNode.addr = cont->addr; + + /* handle this unreachable node's SeqNum TLV */ + /* cppcheck: suppress false positive on non-trivially initialized arrays. + * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ + /* cppcheck-suppress arrayIndexOutOfBounds */ + tlv = _rerr_address_consumer_entries[RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM].tlv; + if (tlv) { + AODV_DEBUG("\ttlv RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM: %d\n", *tlv->single_value); + packet_data.origNode.seqnum = *tlv->single_value; + } + + /* Check if there is an entry for unreachable node in our routing table */ + unreachable_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType); + if (unreachable_entry) { + AODV_DEBUG("\t found possibly unreachable entry.\n"); + + /* check if route to unreachable node has to be marked as broken and RERR has to be forwarded */ + if (netaddr_cmp(&unreachable_entry->nextHopAddr, &packet_data.sender) == 0 + && (!tlv || seqnum_cmp(unreachable_entry->seqnum, packet_data.origNode.seqnum) == 0)) { + unreachable_entry->state = ROUTE_STATE_INVALID; + unreachable_nodes[num_unreachable_nodes].addr = packet_data.origNode.addr; + unreachable_nodes[num_unreachable_nodes].seqnum = packet_data.origNode.seqnum; + num_unreachable_nodes++; + } + + /* remove entry from FIB */ + fib_remove_entry(packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); + } + + return RFC5444_OKAY; +} + +static enum rfc5444_result _cb_rerr_end_callback(struct rfc5444_reader_tlvblock_context *cont, bool dropped) +{ + (void) cont; + + if (dropped) { + AODV_DEBUG("\tDropping packet.\n"); + return RFC5444_DROP_PACKET; + } + + if (num_unreachable_nodes == 0) { + AODV_DEBUG("\tNo unreachable nodes from my routing table. Dropping Packet.\n"); + return RFC5444_DROP_PACKET; + } + /* gather all unreachable nodes and put them into a RERR */ + aodv_send_rerr(unreachable_nodes, num_unreachable_nodes, &na_mcast); + return RFC5444_OKAY; +} + +void aodv_packet_reader_init(void) +{ + AODV_DEBUG("%s()\n", __func__); + + /* initialize reader */ + rfc5444_reader_init(&reader); + + /* register message consumers. We have no message TLVs, so we can leave the + * rfc5444_reader_tlvblock_consumer_entry empty */ + rfc5444_reader_add_message_consumer(&reader, &_rreq_consumer, + NULL, 0); + rfc5444_reader_add_message_consumer(&reader, &_rrep_consumer, + NULL, 0); + rfc5444_reader_add_message_consumer(&reader, &_rerr_consumer, + NULL, 0); + + /* register address consumer */ + rfc5444_reader_add_message_consumer(&reader, &_rreq_address_consumer, + _rreq_rrep_address_consumer_entries, + ARRAYSIZE(_rreq_rrep_address_consumer_entries)); + rfc5444_reader_add_message_consumer(&reader, &_rrep_address_consumer, + _rreq_rrep_address_consumer_entries, + ARRAYSIZE(_rreq_rrep_address_consumer_entries)); + rfc5444_reader_add_message_consumer(&reader, &_rerr_address_consumer, + _rerr_address_consumer_entries, + ARRAYSIZE(_rerr_address_consumer_entries)); +} + +void aodv_packet_reader_cleanup(void) +{ + rfc5444_reader_cleanup(&reader); +} + +int aodv_packet_reader_handle_packet(void *buffer, size_t length, struct netaddr *sender) +{ + memcpy(&packet_data.sender, sender, sizeof(*sender)); + + return rfc5444_reader_handle_packet(&reader, buffer, length); +} + +/*============= HELPER FUNCTIONS =============================================*/ + +static void print_json_received_rreq(void) +{ +#if TEST_SETUP + static struct netaddr_str nbuf_origaddr, nbuf_targaddr, nbuf_send; + + printf("{\"log_type\": \"received_rreq\", " + "\"log_data\":{ \"last_hop\": \"%s\", \"orig_addr\": \"%s\", " + "\"orig_seqnum\": %d, \"targ_addr\": \"%s\", \"metric\": %d}}\n", + netaddr_to_string(&nbuf_send, &packet_data.sender), + netaddr_to_string(&nbuf_origaddr, &packet_data.origNode.addr), + packet_data.origNode.seqnum, + netaddr_to_string(&nbuf_targaddr, &packet_data.targNode.addr), + packet_data.origNode.metric); +#endif +} + +static void print_json_received_rrep(void) +{ +#if TEST_SETUP + static struct netaddr_str nbuf_origaddr, nbuf_targaddr, nbuf_send; + + printf("{\"log_type\": \"received_rrep\", " + "\"log_data\":{ \"last_hop\": \"%s\", \"orig_addr\": \"%s\", " + "\"orig_seqnum\": %d, \"targ_addr\": \"%s\", \"targ_seqnum\":%d}}\n", + netaddr_to_string(&nbuf_send, &packet_data.sender), + netaddr_to_string(&nbuf_origaddr, &packet_data.origNode.addr), + packet_data.origNode.seqnum, + netaddr_to_string(&nbuf_targaddr, &packet_data.targNode.addr), + packet_data.targNode.seqnum); +#endif +} + +/* + * Cost(L): Get Cost of a Link regarding the specified metric. + * (currently only AODVV2_DEFAULT_METRIC_TYPE (HopCount) implemented) + * returns cost if metric is known, 0 otherwise + */ +static uint8_t _get_link_cost(aodvv2_metric_t metricType) +{ + if (metricType == AODVV2_DEFAULT_METRIC_TYPE) { + return 1; + } + return 0; +} + +/* + * MAX_METRIC[MetricType]: + * returns maximum value of the given metric if metric is known, 0 otherwise. + */ +static uint8_t _get_max_metric(aodvv2_metric_t metricType) +{ + if (metricType == AODVV2_DEFAULT_METRIC_TYPE) { + return AODVV2_MAX_HOPCOUNT; + } + return 0; +} + +/* + * Cost(R): Get Cost of a Route regarding the specified metric, based on the + * earlier metric value of the Route. + * (currently only AODVV2_DEFAULT_METRIC_TYPE (HopCount) implemented) + * returns cost if metric is known, 0 otherwise + */ +static uint8_t _get_route_cost(aodvv2_metric_t metricType, uint8_t metric) +{ + if (metricType == AODVV2_DEFAULT_METRIC_TYPE){ + return metric + _get_link_cost(AODVV2_DEFAULT_METRIC_TYPE); + } + return 0; +} diff --git a/sys/net/routing/aodvv2/utils.c b/sys/net/routing/aodvv2/utils.c new file mode 100644 index 000000000000..4d0d3e2022dc --- /dev/null +++ b/sys/net/routing/aodvv2/utils.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief client- and RREQ-table, ipv6 address representation converters + * + * @author Lotte Steenbrink + */ + +#include "utils.h" + +#include "aodv_debug.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* Some aodvv2 utilities (mostly tables) */ +static mutex_t clientt_mutex; +static mutex_t rreqt_mutex; + +/* helper functions */ +static struct aodvv2_rreq_entry *_get_comparable_rreq(struct aodvv2_packet_data *packet_data); +static void _add_rreq(struct aodvv2_packet_data *packet_data); +static void _reset_entry_if_stale(uint8_t i); + +static struct netaddr client_table[AODVV2_MAX_CLIENTS]; +static struct aodvv2_rreq_entry rreq_table[AODVV2_RREQ_BUF]; + +#if ENABLE_DEBUG +static struct netaddr_str nbuf; +#endif +static timex_t null_time, now, _max_idletime; + + +void clienttable_init(void) +{ + mutex_lock(&clientt_mutex); + memset(&client_table, 0, sizeof(client_table)); + mutex_unlock(&clientt_mutex); + + AODV_DEBUG("client table initialized.\n"); +} + +void clienttable_add_client(struct netaddr *addr) +{ + if (clienttable_is_client(addr)){ + return; + } + + /*find free spot in client table and place client address there */ + mutex_lock(&clientt_mutex); + for (unsigned i = 0; i < AODVV2_MAX_CLIENTS; i++) { + if ((client_table[i]._type == AF_UNSPEC) && + (client_table[i]._prefix_len == 0)) { + client_table[i] = *addr; + AODV_DEBUG("clienttable: added client %s\n", + netaddr_to_string(&nbuf, addr)); + mutex_unlock(&clientt_mutex); + return; + } + } + AODV_DEBUG("Error: Client could not be added: Client table is full.\n"); + mutex_unlock(&clientt_mutex); +} + +bool clienttable_is_client(struct netaddr *addr) +{ + mutex_lock(&clientt_mutex); + for (unsigned i = 0; i < AODVV2_MAX_CLIENTS; i++) { + if (!netaddr_cmp(&client_table[i], addr)) { + mutex_unlock(&clientt_mutex); + return true; + } + } + mutex_unlock(&clientt_mutex); + return false; +} + +void clienttable_delete_client(struct netaddr *addr) +{ + if (!clienttable_is_client(addr)) { + return; + } + + mutex_lock(&clientt_mutex); + for (unsigned i = 0; i < AODVV2_MAX_CLIENTS; i++) { + if (!netaddr_cmp(&client_table[i], addr)) { + memset(&client_table[i], 0, sizeof(client_table[i])); + mutex_unlock(&clientt_mutex); + return; + } + } +} + +void rreqtable_init(void) +{ + mutex_lock(&rreqt_mutex); + null_time = timex_set(0, 0); + _max_idletime = timex_set(AODVV2_MAX_IDLETIME, 0); + + memset(&rreq_table, 0, sizeof(rreq_table)); + mutex_unlock(&rreqt_mutex); + AODV_DEBUG("RREQ table initialized.\n"); +} + +bool rreqtable_is_redundant(struct aodvv2_packet_data *packet_data) +{ + struct aodvv2_rreq_entry *comparable_rreq; + timex_t now; + bool result = false; + + mutex_lock(&rreqt_mutex); + comparable_rreq = _get_comparable_rreq(packet_data); + + /* if there is no comparable rreq stored, add one and return false */ + if (comparable_rreq == NULL) { + _add_rreq(packet_data); + } + else { + int seqnum_comparison = seqnum_cmp(packet_data->origNode.seqnum, comparable_rreq->seqnum); + + /* + * If two RREQs have the same + * metric type and OrigNode and Targnode addresses, the information from + * the one with the older Sequence Number is not needed in the table + */ + if (seqnum_comparison == -1) { + result = true; + } + + if (seqnum_comparison == 1) { + /* Update RREQ table entry with new seqnum and metric value */ + comparable_rreq->seqnum = packet_data->origNode.seqnum; + comparable_rreq->metric = packet_data->origNode.metric; + } + + /* + * in case they have the same Sequence Number, the one with the greater + * Metric value is not needed + */ + if (seqnum_comparison == 0) { + if (comparable_rreq->metric <= packet_data->origNode.metric) { + result = true; + } + /* Update RREQ table entry with new metric value */ + comparable_rreq->metric = packet_data->origNode.metric; + } + + /* Since we've changed RREQ info, update the timestamp */ + vtimer_now(&now); + comparable_rreq->timestamp = now; + } + + mutex_unlock(&rreqt_mutex); + return result; +} + +/* + * retrieve pointer to a comparable (according to Section 6.7.) + * RREQ table entry if it exists and NULL otherwise. + * Two AODVv2 RREQ messages are comparable if: + * - they have the same metric type + * - they have the same OrigNode and TargNode addresses + */ +static struct aodvv2_rreq_entry *_get_comparable_rreq(struct aodvv2_packet_data *packet_data) +{ + for (unsigned i = 0; i < AODVV2_RREQ_BUF; i++) { + _reset_entry_if_stale(i); + + if (!netaddr_cmp(&rreq_table[i].origNode, &packet_data->origNode.addr) + && !netaddr_cmp(&rreq_table[i].targNode, &packet_data->targNode.addr) + && rreq_table[i].metricType == packet_data->metricType) { + return &rreq_table[i]; + } + } + + return NULL; +} + + +static void _add_rreq(struct aodvv2_packet_data *packet_data) +{ + if (_get_comparable_rreq(packet_data)) { + return; + } + /*find empty rreq and fill it with packet_data */ + + for (unsigned i = 0; i < AODVV2_RREQ_BUF; i++) { + if (!rreq_table[i].timestamp.seconds && + !rreq_table[i].timestamp.microseconds) { + rreq_table[i].origNode = packet_data->origNode.addr; + rreq_table[i].targNode = packet_data->targNode.addr; + rreq_table[i].metricType = packet_data->metricType; + rreq_table[i].metric = packet_data->origNode.metric; + rreq_table[i].seqnum = packet_data->origNode.seqnum; + rreq_table[i].timestamp = packet_data->timestamp; + return; + } + } +} + +/* + * Check if entry at index i is stale and clear the struct it fills if it is + */ +static void _reset_entry_if_stale(uint8_t i) +{ + vtimer_now(&now); + + if (timex_cmp(rreq_table[i].timestamp, null_time) == 0) { + return; + } + timex_t expiration_time = timex_add(rreq_table[i].timestamp, _max_idletime); + if (timex_cmp(expiration_time, now) < 0) { + /* timestamp+expiration time is in the past: this entry is stale */ + DEBUG("\treset rreq table entry %s\n", + netaddr_to_string(&nbuf, &rreq_table[i].origNode)); + memset(&rreq_table[i], 0, sizeof(rreq_table[i])); + } +} + +void ipv6_addr_t_to_netaddr(ng_ipv6_addr_t *src, struct netaddr *dst) +{ + dst->_type = AF_INET6; + dst->_prefix_len = AODVV2_RIOT_PREFIXLEN; + memcpy(dst->_addr, &src->u8[0], sizeof(dst->_addr)); +} + +void netaddr_to_ipv6_addr_t(struct netaddr *src, ng_ipv6_addr_t *dst) +{ + memcpy(&dst->u8[0], src->_addr, sizeof(uint8_t) * NETADDR_MAX_LENGTH); +} diff --git a/sys/net/routing/aodvv2/utils.h b/sys/net/routing/aodvv2/utils.h new file mode 100644 index 000000000000..7d51e9a502ba --- /dev/null +++ b/sys/net/routing/aodvv2/utils.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief client- and RREQ-table, ipv6 address representation converters + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_UTILS_H_ +#define AODVV2_UTILS_H_ + +#include + +#include "net/ng_ipv6.h" +#include "common/netaddr.h" + +#include "aodvv2/types.h" +#include "constants.h" +#include "seqnum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AODVV2_MAX_CLIENTS 1 /** multiple clients are currently not supported. */ +#define AODVV2_RREQ_BUF 128 /** should be enough for now... */ +#define AODVV2_RREQ_WAIT_TIME 2 /** seconds */ +#define AODVV2_RIOT_PREFIXLEN 128 /** Prefix length of the IPv6 addresses + * used in the network served by AODVv2 () */ +/** + * @brief RREQ Table entry which stores all information about a RREQ that was received + * in order to avoid duplicates. + */ +struct aodvv2_rreq_entry +{ + struct netaddr origNode; /**< Node which originated the RREQ*/ + struct netaddr targNode; /**< Target (destination) of the RREQ */ + aodvv2_metric_t metricType; /**< Metric type of the RREQ */ + uint8_t metric; /**< Metric of the RREQ */ + aodvv2_seqnum_t seqnum; /**< Sequence number of the RREQ */ + timex_t timestamp; /**< Last time this entry was updated */ +}; + +/** + * Initialize table of clients that the router currently serves. + */ +void clienttable_init(void); + +/** + * Add client to the list of clients that the router currently serves. + * @param addr address of the client + * (Since the current version doesn't offer support for + * Client Networks, the prefixlen is currently ignored.) + */ +void clienttable_add_client(struct netaddr *addr); + +/** + * Find out if a client is in the list of clients that the router currently serves. + * @param addr address of the client in question + * (Since the current version doesn't offer support for + * Client Networks, the prefixlen is currently ignored.) + */ +bool clienttable_is_client(struct netaddr *addr); + +/** + * Delete a client from the list of clients that the router currently serves. + * @param addr address of the client to delete + * (Since the current version doesn't offer support for + * Client Networks, the prefixlen is currently ignored.) + */ +void clienttable_delete_client(struct netaddr *addr); + +/** + * Initialize RREQ table. + */ +void rreqtable_init(void); + +/** + * Check if a RREQ is redundant, i.e. was received from another node already. + * Behaves as described in Sections 5.7. and 7.6. + * @param packet_data data of the RREQ in question + * @return true if packet_data is redundant, false otherwise. + */ +bool rreqtable_is_redundant(struct aodvv2_packet_data *packet_data); + +/** + * Convert an IP stored as an ipv6_addr_t to a netaddr + * @param src ng_ipv6_addr_t to convert + * @param dst (empty) netaddr to convert into + */ +void ipv6_addr_t_to_netaddr(ng_ipv6_addr_t *src, struct netaddr *dst); + +/** + * Convert an IP stored as a netaddr to an ipv6_addr_t + * @param src (empty) netaddr to convert into + * @param dst ng_ipv6_addr_t to convert + */ +void netaddr_to_ipv6_addr_t(struct netaddr *src, ng_ipv6_addr_t *dst); + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_UTILS_H_ */ From d75a9f07419f07ad3cdc1088c7e648d319cd3060 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 18 Jul 2015 11:54:06 -0700 Subject: [PATCH 02/41] address comments --- sys/net/routing/aodvv2/aodv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 7ba8cce3383f..74852835cb4f 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -173,7 +173,7 @@ void *fib_signal_handler_thread(void *arg) }; AODV_DEBUG("\tstarting route discovery towards %s... \n", - ng_ipv6_addr_to_str(addr_str, &dest, IPV6_MAX_ADDR_STR_LEN)); + ng_ipv6_addr_to_str(addr_str, &dest, NG_IPV6_ADDR_MAX_STR_LEN)); aodv_send_rreq(&rreq_data); } else { @@ -277,12 +277,12 @@ static void _init_addresses(void) /* init multicast address: set to to a link-local all nodes multicast address */ ng_ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); AODV_DEBUG("my multicast address is: %s\n", - ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &_v6_addr_mcast)); + ng_ipv6_addr_to_str(addr_str, &_v6_addr_mcast, NG_IPV6_ADDR_MAX_STR_LEN)); /* get best IP for sending */ _v6_addr_local = ng_ipv6_netif_find_best_src_addr(aodvv2_if_id,&_v6_addr_mcast); AODV_DEBUG("my src address is: %s\n", - ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, _v6_addr_local)); + ng_ipv6_addr_to_str(addr_str, _v6_addr_local, NG_IPV6_ADDR_MAX_STR_LEN)); /* store src & multicast address as netaddr as well for easy interaction * with oonf based stuff */ From 55f32a617c2ec86b7044bc7302ab35ca522ee1de Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 18 Jul 2015 11:55:49 -0700 Subject: [PATCH 03/41] no more HTONS --- sys/net/routing/aodvv2/aodv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 74852835cb4f..4f2bd03dd538 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -107,7 +107,7 @@ void aodv_init(kernel_pid_t interface) /* start listening & enable sending */ thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN, CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); - AODV_DEBUG("listening on port %d\n", HTONS(MANET_PORT)); + AODV_DEBUG("listening on port %d\n", MANET_PORT); sender_thread = thread_create(aodv_snd_stack_buf, sizeof(aodv_snd_stack_buf), THREAD_PRIORITY_MAIN, CREATE_STACKTEST, _aodv_sender_thread, NULL, "_aodv_sender_thread"); @@ -360,7 +360,7 @@ static void *_aodv_receiver_thread(void *arg) /* start server (which means registering AODVv2 receiver for the chosen port) */ server.pid = sched_active_pid; /* sched_active_pid is our pid, since we are currently act */ - server.demux_ctx = (uint32_t)HTONS(MANET_PORT); + server.demux_ctx = (uint32_t) MANET_PORT; ng_netreg_register(NG_NETTYPE_UDP, &server); while (1) { @@ -409,7 +409,7 @@ static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_len ng_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; /* convert to correct byteorder */ - port = HTONS(port); + port = port; /* allocate payload */ payload = ng_pktbuf_add(NULL, data, data_length, NG_NETTYPE_UNDEF); From b1bff67d0c5fc32a3bff5c2e515249ecb2b5b338 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 18 Jul 2015 11:59:02 -0700 Subject: [PATCH 04/41] add Martin as author --- sys/net/routing/aodvv2/aodv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 4f2bd03dd538..af2f7e08f9d7 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -15,6 +15,7 @@ * @brief aodvv2 routing protocol * * @author Lotte Steenbrink + * @author Martin Landsmann */ #include "aodv.h" From 1299b72c700130eb94c0e003381460d1a97dca9e Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sun, 19 Jul 2015 04:55:18 -0700 Subject: [PATCH 05/41] add missing newlines to debug output --- sys/net/routing/aodvv2/aodv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index af2f7e08f9d7..6325ca284664 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -368,7 +368,7 @@ static void *_aodv_receiver_thread(void *arg) msg_receive(&msg); switch (msg.type) { case NG_NETAPI_MSG_TYPE_RCV: - AODV_DEBUG("received data:"); + AODV_DEBUG("received data:\n"); ng_pktsnip_t *pkt = ((ng_pktsnip_t *)msg.content.ptr); if (pkt->size <= UDP_BUFFER_SIZE) { memcpy(buf_rcv, pkt->data, pkt->size); @@ -393,7 +393,7 @@ static void *_aodv_receiver_thread(void *arg) msg_reply(&msg, &reply); break; default: - AODV_DEBUG("received something unexpected"); + AODV_DEBUG("received something unexpected\n"); break; } } @@ -434,7 +434,7 @@ static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_len } /* all headers are set, send packet */ if(!ng_netapi_dispatch_send(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { - DEBUG("Error sending packet"); + DEBUG("Error sending packet\n"); } } From 2ec91808149e61d42d329cb6f3e32571ccbc58a9 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Mon, 20 Jul 2015 03:33:19 -0700 Subject: [PATCH 06/41] addressed comments (untestedga 3) --- sys/net/routing/aodvv2/aodv.c | 30 +++++++++++++++++++++++++----- sys/net/routing/aodvv2/aodv.h | 1 + 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 6325ca284664..745b13c743aa 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -28,6 +28,7 @@ #define UDP_BUFFER_SIZE (128) /** with respect to IEEE 802.15.4's MTU */ #define RCV_MSG_Q_SIZE (32) /* TODO: check if smaller values work, too */ +#define AODVV2_PREFIX {{ 0xbe, 0xe2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} static void _init_addresses(void); static void _init_sock_snd(void); @@ -67,10 +68,12 @@ static mutex_t rreq_mutex; static mutex_t rrep_mutex; static mutex_t rerr_mutex; +static ng_ipv6_addr_t aodvv2_prefix = AODVV2_PREFIX; +static int aodvv2_prefix_len; +static int aodvv2_address_type_size; + struct netaddr na_mcast; kernel_pid_t aodvv2_if_id; -ng_ipv6_addr_t aodvv2_prefix; -int aodvv2_prefix_len; void aodv_init(kernel_pid_t interface) { @@ -80,9 +83,14 @@ void aodv_init(kernel_pid_t interface) msg_t msgq[RCV_MSG_Q_SIZE]; msg_init_queue(msgq, sizeof msgq); - aodvv2_prefix_len = sizeof(ng_ipv6_addr_t); + if (!interface) { + AODV_DEBUG("Error: AODVv2 interface pid is invalid.\n"); + return; + } aodvv2_if_id = interface; - ng_ipv6_addr_from_str(&aodvv2_prefix, "fe80:0000:0000:0000:0000:0000:0000:0000"); + + aodvv2_address_type_size = sizeof(ng_ipv6_addr_t); + aodvv2_prefix_len = 16; mutex_init(&rreq_mutex); mutex_init(&rrep_mutex); @@ -275,13 +283,25 @@ void aodv_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, str */ static void _init_addresses(void) { + eui64_t iid; + /* init multicast address: set to to a link-local all nodes multicast address */ ng_ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); AODV_DEBUG("my multicast address is: %s\n", ng_ipv6_addr_to_str(addr_str, &_v6_addr_mcast, NG_IPV6_ADDR_MAX_STR_LEN)); /* get best IP for sending */ - _v6_addr_local = ng_ipv6_netif_find_best_src_addr(aodvv2_if_id,&_v6_addr_mcast); + if (!(ng_netapi_get(aodvv2_if_id, NETCONF_OPT_IPV6_IID, 0, &iid, + sizeof(eui64_t)) < 0)) { + AODV_DEBUG("Error: failed to get iid\n"); + return; + } + + /* Set addr according to our interface id */ + ng_ipv6_addr_set_aiid(_v6_addr_local, iid.uint8); + /* Set (global!) prefix */ + ng_ipv6_addr_init_prefix(_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); + AODV_DEBUG("my src address is: %s\n", ng_ipv6_addr_to_str(addr_str, _v6_addr_local, NG_IPV6_ADDR_MAX_STR_LEN)); diff --git a/sys/net/routing/aodvv2/aodv.h b/sys/net/routing/aodvv2/aodv.h index 2c7729633512..6af74047b874 100644 --- a/sys/net/routing/aodvv2/aodv.h +++ b/sys/net/routing/aodvv2/aodv.h @@ -27,6 +27,7 @@ #include "net/ng_netif.h" #include "net/ng_udp.h" #include "net/ng_pkt.h" +#include "net/eui64.h" #include "aodvv2/types.h" #include "constants.h" From 529af3790f4823a4d2abe1ca2041861b8658731d Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 23 Jul 2015 07:10:28 -0700 Subject: [PATCH 07/41] remove silly error --- sys/net/routing/aodvv2/aodv.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 745b13c743aa..f25b9e21b2c7 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -429,9 +429,6 @@ static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_len { ng_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; - /* convert to correct byteorder */ - port = port; - /* allocate payload */ payload = ng_pktbuf_add(NULL, data, data_length, NG_NETTYPE_UNDEF); if (payload == NULL) { From f78a0685d6f7658d88b6c5202c55838fc9193f45 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 27 Aug 2015 09:59:27 -0700 Subject: [PATCH 08/41] fix iid and address registration --- sys/net/routing/aodvv2/aodv.c | 38 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index f25b9e21b2c7..d93fbe919632 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -60,7 +60,7 @@ static int sender_thread; static int _sock_snd; static struct autobuf _hexbuf; static ng_ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; -static ng_ipv6_addr_t* _v6_addr_local; +static ng_ipv6_addr_t _v6_addr_local; static struct netaddr na_local; /* the same as _v6_addr_local, but to save us * constant calls to ipv6_addr_t_to_netaddr()... */ static struct writer_target *wt; @@ -77,20 +77,20 @@ kernel_pid_t aodvv2_if_id; void aodv_init(kernel_pid_t interface) { - AODV_DEBUG("%s()\n", __func__); + DEBUG("%s()\n", __func__); /* init this thread's IPC msg queue */ msg_t msgq[RCV_MSG_Q_SIZE]; msg_init_queue(msgq, sizeof msgq); if (!interface) { - AODV_DEBUG("Error: AODVv2 interface pid is invalid.\n"); + DEBUG("Error: AODVv2 interface pid is invalid.\n"); return; } aodvv2_if_id = interface; aodvv2_address_type_size = sizeof(ng_ipv6_addr_t); - aodvv2_prefix_len = 16; + aodvv2_prefix_len = 64; mutex_init(&rreq_mutex); mutex_init(&rrep_mutex); @@ -140,10 +140,11 @@ void *fib_signal_handler_thread(void *arg) (void) arg; ng_ipv6_addr_t dest; struct netaddr na_dest; + int address_type_size = 16; - int err = fib_register_rp(&aodvv2_prefix.u8[0], aodvv2_prefix_len); + int err = fib_register_rp(&aodvv2_prefix.u8[0], address_type_size); if ( err != 0) { - AODV_DEBUG("ERROR: cannot register at fib, error code:\n"); + DEBUG("ERROR: cannot register at fib, error code:\n"); exit(1); } @@ -287,28 +288,33 @@ static void _init_addresses(void) /* init multicast address: set to to a link-local all nodes multicast address */ ng_ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); - AODV_DEBUG("my multicast address is: %s\n", + DEBUG("my multicast address is: %s\n", ng_ipv6_addr_to_str(addr_str, &_v6_addr_mcast, NG_IPV6_ADDR_MAX_STR_LEN)); - /* get best IP for sending */ - if (!(ng_netapi_get(aodvv2_if_id, NETCONF_OPT_IPV6_IID, 0, &iid, - sizeof(eui64_t)) < 0)) { - AODV_DEBUG("Error: failed to get iid\n"); + /* get id (of type eui46_t) of the interface we're sending on */ + int err_code = ng_netapi_get(aodvv2_if_id, NETCONF_OPT_IPV6_IID, 0, &iid, + sizeof(eui64_t)); + if (err_code < 0) { + DEBUG("Error: failed to get iid, error code: %d\n", err_code); return; } /* Set addr according to our interface id */ - ng_ipv6_addr_set_aiid(_v6_addr_local, iid.uint8); + ng_ipv6_addr_set_aiid(&_v6_addr_local, &iid.uint8[0]); /* Set (global!) prefix */ - ng_ipv6_addr_init_prefix(_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); + ng_ipv6_addr_init_prefix(&_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); + /* Add our homemade address to our interface (aodvv2_if_id) */ + ng_ipv6_netif_add_addr(aodvv2_if_id, &_v6_addr_local, aodvv2_prefix_len, 0); - AODV_DEBUG("my src address is: %s\n", - ng_ipv6_addr_to_str(addr_str, _v6_addr_local, NG_IPV6_ADDR_MAX_STR_LEN)); + DEBUG("my src address is: %s\n", + ng_ipv6_addr_to_str(addr_str, &_v6_addr_local, NG_IPV6_ADDR_MAX_STR_LEN)); /* store src & multicast address as netaddr as well for easy interaction * with oonf based stuff */ - ipv6_addr_t_to_netaddr(_v6_addr_local, &na_local); + ipv6_addr_t_to_netaddr(&_v6_addr_local, &na_local); ipv6_addr_t_to_netaddr(&_v6_addr_mcast, &na_mcast); + + /* TODO: do I need this?*/ ng_ipv6_addr_set_loopback(&_v6_addr_loopback); } From eb428e0bd5e61f14ef24da109c3ec77594205514 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 27 Aug 2015 10:24:03 -0700 Subject: [PATCH 09/41] set correct src address --- sys/net/routing/aodvv2/aodv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index d93fbe919632..82560ed7a0a2 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -140,9 +140,8 @@ void *fib_signal_handler_thread(void *arg) (void) arg; ng_ipv6_addr_t dest; struct netaddr na_dest; - int address_type_size = 16; - int err = fib_register_rp(&aodvv2_prefix.u8[0], address_type_size); + int err = fib_register_rp(&aodvv2_prefix.u8[0], aodvv2_address_type_size); if ( err != 0) { DEBUG("ERROR: cannot register at fib, error code:\n"); exit(1); @@ -438,20 +437,21 @@ static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_len /* allocate payload */ payload = ng_pktbuf_add(NULL, data, data_length, NG_NETTYPE_UNDEF); if (payload == NULL) { - AODV_DEBUG("Error: unable to copy data to packet buffer\n"); + DEBUG("Error: unable to copy data to packet buffer\n"); return; } /* allocate UDP header, set payload, set source port := destination port */ pkt_with_udp = ng_udp_hdr_build(payload, (uint8_t*)&port, 2, (uint8_t*)&port, 2); if (pkt_with_udp == NULL) { - AODV_DEBUG("Error: unable to allocate UDP header\n"); + DEBUG("Error: unable to allocate UDP header\n"); ng_pktbuf_release(payload); return; } /* allocate IPv6 header, set pkt_with_udp as payload */ - pkt_with_ip = ng_ipv6_hdr_build(pkt_with_udp, NULL, 0, (uint8_t *)&addr, sizeof(addr)); + pkt_with_ip = ng_ipv6_hdr_build(pkt_with_udp, (uint8_t*)&_v6_addr_local, aodvv2_address_type_size, + (uint8_t *)&addr, sizeof(addr)); if (pkt_with_ip == NULL) { - AODV_DEBUG("Error: unable to allocate IPv6 header\n"); + DEBUG("Error: unable to allocate IPv6 header\n"); ng_pktbuf_release(pkt_with_udp); return; } From af4a3e1bc64596f65ed6c7234f79264e572332b1 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Mon, 31 Aug 2015 16:57:16 -0700 Subject: [PATCH 10/41] fix rebase fuckup in Makefile.dep --- Makefile.dep | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.dep b/Makefile.dep index e0c5a3bb1b96..99306f3efc63 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -278,6 +278,7 @@ endif ifneq (,$(filter gnrc_ipv6_hdr,$(USEMODULE))) USEMODULE += ipv6_hdr USEMODULE += gnrc_pktbuf +endif ifneq (,$(filter aodvv2,$(USEMODULE))) USEMODULE += ng_sixlowpan_default @@ -285,6 +286,7 @@ ifneq (,$(filter aodvv2,$(USEMODULE))) USEMODULE += oonf_common USEMODULE += oonf_rfc5444 USEMODULE += fib +endif ifneq (,$(filter sixlowpan,$(USEMODULE))) USEMODULE += ipv6_hdr From f36f6b13b10f10a550f8d66d3380728940a0783f Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 12 Jan 2016 07:21:57 -0800 Subject: [PATCH 11/41] re-add deleted files --- sys/net/include/aodvv2/types.h | 102 ++++++++ sys/net/routing/aodvv2/Makefile | 1 + sys/net/routing/aodvv2/aodv_debug.h | 53 ++++ sys/net/routing/aodvv2/constants.h | 64 +++++ sys/net/routing/aodvv2/reader.h | 62 +++++ sys/net/routing/aodvv2/routingtable.c | 299 ++++++++++++++++++++++ sys/net/routing/aodvv2/routingtable.h | 160 ++++++++++++ sys/net/routing/aodvv2/seqnum.c | 49 ++++ sys/net/routing/aodvv2/seqnum.h | 63 +++++ sys/net/routing/aodvv2/writer.c | 348 ++++++++++++++++++++++++++ sys/net/routing/aodvv2/writer.h | 101 ++++++++ 11 files changed, 1302 insertions(+) create mode 100644 sys/net/include/aodvv2/types.h create mode 100644 sys/net/routing/aodvv2/Makefile create mode 100644 sys/net/routing/aodvv2/aodv_debug.h create mode 100644 sys/net/routing/aodvv2/constants.h create mode 100644 sys/net/routing/aodvv2/reader.h create mode 100644 sys/net/routing/aodvv2/routingtable.c create mode 100644 sys/net/routing/aodvv2/routingtable.h create mode 100644 sys/net/routing/aodvv2/seqnum.c create mode 100644 sys/net/routing/aodvv2/seqnum.h create mode 100644 sys/net/routing/aodvv2/writer.c create mode 100644 sys/net/routing/aodvv2/writer.h diff --git a/sys/net/include/aodvv2/types.h b/sys/net/include/aodvv2/types.h new file mode 100644 index 000000000000..311530ea2601 --- /dev/null +++ b/sys/net/include/aodvv2/types.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief data types for the aodvv2 routing protocol + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_TYPES_H +#define AODVV2_TYPES_H + +#include "common/netaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief AODVv2 metric types. Extend to include alternate metrics. + */ +typedef enum { + HOP_COUNT = 3, /**< see RFC6551*/ +} aodvv2_metric_t; + +typedef uint16_t aodvv2_seqnum_t; + +#define AODVV2_DEFAULT_METRIC_TYPE HOP_COUNT + +/** + * @brief AODVv2 message types + */ +enum rfc5444_msg_type +{ + RFC5444_MSGTYPE_RREQ = 10, + RFC5444_MSGTYPE_RREP = 11, + RFC5444_MSGTYPE_RERR = 12, +}; + +/** + * @brief AODVv2 TLV types + */ +enum rfc5444_tlv_type +{ + RFC5444_MSGTLV_ORIGSEQNUM, + RFC5444_MSGTLV_TARGSEQNUM, + RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM, + RFC5444_MSGTLV_METRIC, +}; + +/** + * @brief Data about an OrigNode or TargNode, typically embedded in an + * aodvv2_packet_data struct. + */ +struct node_data +{ + struct netaddr addr; /**< IP address of the node */ + uint8_t metric; /**< Metric value */ + aodvv2_seqnum_t seqnum; /**< Sequence Number */ +}; + +/** + * @brief all data contained in a RREQ or RREP. + */ +struct aodvv2_packet_data +{ + uint8_t hoplimit; /**< Hop limit */ + struct netaddr sender; /**< IP address of the neighboring router + * which sent the RREQ/RREP*/ + aodvv2_metric_t metricType; /**< Metric type */ + struct node_data origNode; /**< Data about the originating node */ + struct node_data targNode; /**< Data about the originating node */ + timex_t timestamp; /**< point at which the packet was (roughly) + * received. Note that this timestamp + * will be set after the packet has been + * successfully parsed. */ +}; + +/** + * @brief Data about an unreachable node to be embedded in a RERR. + */ +struct unreachable_node +{ + struct netaddr addr; /**< IP address */ + aodvv2_seqnum_t seqnum; /**< Sequence Number */ +}; + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_TYPES_H */ diff --git a/sys/net/routing/aodvv2/Makefile b/sys/net/routing/aodvv2/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/sys/net/routing/aodvv2/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/routing/aodvv2/aodv_debug.h b/sys/net/routing/aodvv2/aodv_debug.h new file mode 100644 index 000000000000..f4612a4a5659 --- /dev/null +++ b/sys/net/routing/aodvv2/aodv_debug.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @brief Debug-header for aodvv2 debug messages + * + * + * @author Lotte Steenbrink + */ + +#ifndef AODV_DEBUG_H_ +#define AODV_DEBUG_H_ + +#include +#include "sched.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#if ENABLE_DEBUG +#define ENABLE_AODV_DEBUG (1) +#endif + +/** + * @brief Print aodvv2 specific debug information to std-out with [aodvv2] prefix + * + */ +#if ENABLE_AODV_DEBUG +#include "tcb.h" +#define AODV_DEBUG(...) \ + do { \ + printf("[aodvv2] "); \ + printf(__VA_ARGS__); \ + } while (0) +#else +#define AODV_DEBUG(...) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_DEBUG_H_*/ +/** @} */ diff --git a/sys/net/routing/aodvv2/constants.h b/sys/net/routing/aodvv2/constants.h new file mode 100644 index 000000000000..344b6c04378d --- /dev/null +++ b/sys/net/routing/aodvv2/constants.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief constants for the aodvv2 routing protocol + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_CONSTANTS_H_ +#define AODVV2_CONSTANTS_H_ + +#include "aodvv2/types.h" + +#include "common/netaddr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MANET_PORT 269 /** RFC5498 */ + +enum aodvv2_constants { + AODVV2_MAX_HOPCOUNT = 250, /**< see AODVv2 draft, section 14.2.*/ + AODVV2_MAX_ROUTING_ENTRIES = 255, /**< maximum number of entries + * in the routing table */ + AODVV2_ACTIVE_INTERVAL = 5, /**< seconds */ + AODVV2_MAX_IDLETIME = 250, /**< seconds */ + AODVV2_MAX_SEQNUM_LIFETIME = 300, /**< seconds */ + AODVV2_MAX_UNREACHABLE_NODES = 15, /**< TODO: choose value (wisely) */ +}; + +/** + * @brief TLV type array indices + */ +enum tlv_index +{ + TLV_ORIGSEQNUM, + TLV_TARGSEQNUM, + TLV_UNREACHABLE_NODE_SEQNUM, + TLV_METRIC, +}; + +/* my multicast address */ +extern struct netaddr na_mcast; + +/* the interface this protocol operates on */ +extern kernel_pid_t aodvv2_if_id; + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_CONSTANTS_H_ */ diff --git a/sys/net/routing/aodvv2/reader.h b/sys/net/routing/aodvv2/reader.h new file mode 100644 index 000000000000..c47b5a06b5bd --- /dev/null +++ b/sys/net/routing/aodvv2/reader.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief reading and handling of RFC5444 aodvv2 messages + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_READER_H_ +#define AODVV2_READER_H_ + +#include +#include + +#include "common/netaddr.h" +#include "rfc5444/rfc5444_reader.h" + +#include "utils.h" +#include "routingtable.h" +#include "constants.h" +#include "seqnum.h" +#include "aodv.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize reader. + */ +void aodv_packet_reader_init(void); + +/** + * @brief Clean up after reader. Only needs to be called upon shutdown. + */ +void aodv_packet_reader_cleanup(void); + +/** + * @brief Read data buffer as RFC5444 packet and handle the data it contains + * + * @param[in] buffer Data to be read and handled + * @param[in] length Length of data + * @param[in] sender Address of the node from which the packet was received + */ +int aodv_packet_reader_handle_packet(void *buffer, size_t length, struct netaddr *sender); + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_READER_H_ */ diff --git a/sys/net/routing/aodvv2/routingtable.c b/sys/net/routing/aodvv2/routingtable.c new file mode 100644 index 000000000000..bf574d2e62d8 --- /dev/null +++ b/sys/net/routing/aodvv2/routingtable.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief Cobbled-together routing table. + * + * @author Lotte Steenbrink + */ + +#include +#include + +#include "routingtable.h" +#include "aodv_debug.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* helper functions */ +static void _reset_entry_if_stale(uint8_t i); +static void print_json_added_rt_entry(struct aodvv2_routing_entry_t *entry); + +static struct aodvv2_routing_entry_t routing_table[AODVV2_MAX_ROUTING_ENTRIES]; +static timex_t null_time, max_seqnum_lifetime, active_interval, max_idletime, validity_t; +timex_t now; +#if ENABLE_DEBUG +static struct netaddr_str nbuf; +#endif + +void routingtable_init(void) +{ + null_time = timex_set(0, 0); + max_seqnum_lifetime = timex_set(AODVV2_MAX_SEQNUM_LIFETIME, 0); + active_interval = timex_set(AODVV2_ACTIVE_INTERVAL, 0); + max_idletime = timex_set(AODVV2_MAX_IDLETIME, 0); + validity_t = timex_set(AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME, 0); + + memset(&routing_table, 0, sizeof(routing_table)); + AODV_DEBUG("routing table initialized.\n"); +} + +struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t metricType) +{ + struct aodvv2_routing_entry_t *entry = routingtable_get_entry(dest, metricType); + if (!entry) { + return NULL; + } + return (&entry->nextHopAddr); +} + +void routingtable_add_entry(struct aodvv2_routing_entry_t *entry) +{ + print_json_added_rt_entry(entry); + + /* only add if we don't already know the address */ + if (routingtable_get_entry(&(entry->addr), entry->metricType)) { + return; + } + /*find free spot in RT and place rt_entry there */ + for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { + if (routing_table[i].addr._type == AF_UNSPEC) { + memcpy(&routing_table[i], entry, sizeof(struct aodvv2_routing_entry_t)); + return; + } + } +} + +struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, + aodvv2_metric_t metricType) +{ + for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { + _reset_entry_if_stale(i); + + if (!netaddr_cmp(&routing_table[i].addr, addr) + && routing_table[i].metricType == metricType) { + DEBUG("[routing] found entry for %s :", netaddr_to_string(&nbuf, addr)); +#if ENABLE_DEBUG + print_routingtable_entry(&routing_table[i]); +#endif + return &routing_table[i]; + } + } + return NULL; +} + +void routingtable_delete_entry(struct netaddr *addr, aodvv2_metric_t metricType) +{ + for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { + _reset_entry_if_stale(i); + + if (!netaddr_cmp(&routing_table[i].addr, addr) + && routing_table[i].metricType == metricType) { + memset(&routing_table[i], 0, sizeof(routing_table[i])); + return; + } + } +} + +void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, + struct unreachable_node unreachable_nodes[], + size_t *len) +{ + *len = 0; /* to be sure */ + + for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { + _reset_entry_if_stale(i); + + if (netaddr_cmp(&routing_table[i].nextHopAddr, hop) == 0) { + if (routing_table[i].state == ROUTE_STATE_ACTIVE && + *len < AODVV2_MAX_UNREACHABLE_NODES) { + /* when the max number of unreachable nodes is reached we're screwed. + * the above check is just damage control. */ + unreachable_nodes[*len].addr = routing_table[i].addr; + unreachable_nodes[*len].seqnum = routing_table[i].seqnum; + + (*len)++; + DEBUG("\t[routing] unreachable node found: %s\n", netaddr_to_string(&nbuf, &routing_table[i].nextHopAddr)); + } + routing_table[i].state = ROUTE_STATE_INVALID; + DEBUG("\t[routing] number of unreachable nodes: %i\n", *len); + } + } +} + +/* + * Check if entry at index i is stale as described in Section 6.3. + * and clear the struct it fills if it is + */ +static void _reset_entry_if_stale(uint8_t i) +{ + vtimer_now(&now); + timex_t lastUsed, expirationTime; + + if (timex_cmp(routing_table[i].expirationTime, null_time) == 0) { + return; + } + + int state = routing_table[i].state; + lastUsed = routing_table[i].lastUsed; + expirationTime = routing_table[i].expirationTime; + + /* an Active route is considered to remain Active as long as it is used at least once + * during every ACTIVE_INTERVAL. When a route is no longer Active, it becomes an Idle route. */ + + /* if the node is younger than the active interval, don't bother */ + if (timex_cmp(now, active_interval) < 0) { + return; + } + + if ((state == ROUTE_STATE_ACTIVE) && + (timex_cmp(timex_sub(now, active_interval), lastUsed) == 1)) { + DEBUG("\t[routing] route towards %s Idle\n", + netaddr_to_string(&nbuf, &routing_table[i].addr)); + routing_table[i].state = ROUTE_STATE_IDLE; + routing_table[i].lastUsed = now; /* mark the time entry was set to Idle */ + } + + /* After an Idle route remains Idle for MAX_IDLETIME, it becomes an Invalid route. */ + + /* if the node is younger than the expiration time, don't bother */ + if (timex_cmp(now, expirationTime) < 0) { + return; + } + + /* If Current_Time > Route.ExpirationTime, set Route.State := Invalid. */ + if ((state == ROUTE_STATE_IDLE) && + (timex_cmp(now, expirationTime) > 0)) { + DEBUG("\t[routing] route towards %s became Invalid\n", + netaddr_to_string(&nbuf, &routing_table[i].addr)); + routing_table[i].state = ROUTE_STATE_INVALID; + routing_table[i].lastUsed = now; /* mark the time entry was set to Invalid */ + } + + /* If (Current_Time - Route.LastUsed) > (ACTIVE_INTERVAL + MAX_IDLETIME), + * and if (Route.Timed == FALSE), set Route.State := Invalid. */ + if ((timex_cmp(timex_sub(now, lastUsed), timex_add(active_interval, max_idletime)) > 0) && + (state != ROUTE_STATE_TIMED)) { + routing_table[i].state = ROUTE_STATE_INVALID; + } + + /* After that time, old sequence number information is considered no longer + * valid and the Invalid route MUST BE expunged */ + if (timex_cmp(timex_sub(now, lastUsed), max_seqnum_lifetime) >= 0) { + DEBUG("\t[routing] Expunged routing table entry for %s at %i\n", + netaddr_to_string(&nbuf, &routing_table[i].addr), i); + memset(&routing_table[i], 0, sizeof(routing_table[i])); + } +} + +bool routingtable_offers_improvement(struct aodvv2_routing_entry_t *rt_entry, + struct node_data *node_data) +{ + /* (TODO only guaranteed for AODVV2_DEFAULT_METRIC_TYPE!)*/ + bool is_loop_free = node_data->metric <= rt_entry->metric; + int stale = seqnum_cmp(node_data->seqnum, rt_entry->seqnum); + + if ((stale == 1) /* New info is more recent and MUST be used */ + || ((stale == 0) && (node_data->metric < rt_entry->metric)) /* New info offers a better route and SHOULD be used */ + || ((stale == 0) && (node_data->metric >= rt_entry->metric) /* Route is not an improvement, */ + && (rt_entry->state == ROUTE_STATE_INVALID) /* but repairs an invalid route */ + && is_loop_free) /* and contains no loops */ + ) { + return true; + } + return false; +} + +void routingtable_fill_routing_entry_t_rreq(struct aodvv2_packet_data *packet_data, + struct aodvv2_routing_entry_t *rt_entry) +{ + rt_entry->addr = packet_data->origNode.addr; + rt_entry->seqnum = packet_data->origNode.seqnum; + rt_entry->nextHopAddr = packet_data->sender; + rt_entry->lastUsed = packet_data->timestamp; + rt_entry->expirationTime = timex_add(packet_data->timestamp, validity_t); + rt_entry->metricType = packet_data->metricType; + rt_entry->metric = packet_data->origNode.metric; + rt_entry->state = ROUTE_STATE_ACTIVE; +} + +void routingtable_fill_routing_entry_t_rrep(struct aodvv2_packet_data *packet_data, + struct aodvv2_routing_entry_t *rt_entry) +{ + rt_entry->addr = packet_data->targNode.addr; + rt_entry->seqnum = packet_data->targNode.seqnum; + rt_entry->nextHopAddr = packet_data->sender; + rt_entry->lastUsed = packet_data->timestamp; + rt_entry->expirationTime = timex_add(packet_data->timestamp, validity_t); + rt_entry->metricType = packet_data->metricType; + rt_entry->metric = packet_data->targNode.metric; + rt_entry->state = ROUTE_STATE_ACTIVE; +} + +#if TEST_SETUP +/* Write JSON representation of rt_entry to json_str */ +static void routingtable_entry_to_json(struct aodvv2_routing_entry_t *rt_entry, char* json_str) +{ + + struct netaddr_str nbuf_addr, nbuf_nexthop; + + sprintf(json_str,"{\"addr\": \"%s\", \"next_hop\": \"%s\", \"seqnum\": %d," + "\"metric\": %d, \"state\": %d}", + netaddr_to_string(&nbuf_addr, &rt_entry->addr), + netaddr_to_string(&nbuf_nexthop, &rt_entry->nextHopAddr), + rt_entry->seqnum, rt_entry->metric, rt_entry->state); +} +#endif + +static void print_json_added_rt_entry(struct aodvv2_routing_entry_t *entry) +{ +#if TEST_SETUP + char rt_entry_json [500]; + routingtable_entry_to_json(entry, rt_entry_json); + printf("{\"log_type\": \"added_rt_entry\", \"log_data\": %s}\n", rt_entry_json); +#else + (void) entry; /* silence compiler */ +#endif +} + +void print_routingtable(void) +{ + printf("===== BEGIN ROUTING TABLE ===================\n"); + for (int i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { + /* route has been used before => non-empty entry */ + if (routing_table[i].lastUsed.seconds + || routing_table[i].lastUsed.microseconds) { + print_routingtable_entry(&routing_table[i]); + } + } + printf("===== END ROUTING TABLE =====================\n"); +} + +void print_routingtable_entry(struct aodvv2_routing_entry_t *rt_entry) +{ + struct netaddr_str nbuf; + + printf(".................................\n"); + printf("\t address: %s\n", netaddr_to_string(&nbuf, &(rt_entry->addr))); + printf("\t seqnum: %i\n", rt_entry->seqnum); + printf("\t nextHopAddress: %s\n", + netaddr_to_string(&nbuf, &(rt_entry->nextHopAddr))); + printf("\t lastUsed: %"PRIu32":%"PRIu32"\n", + rt_entry->lastUsed.seconds, rt_entry->lastUsed.microseconds); + printf("\t expirationTime: %"PRIu32":%"PRIu32"\n", + rt_entry->expirationTime.seconds, rt_entry->expirationTime.microseconds); + printf("\t metricType: %i\n", rt_entry->metricType); + printf("\t metric: %d\n", rt_entry->metric); + printf("\t state: %d\n", rt_entry->state); +} diff --git a/sys/net/routing/aodvv2/routingtable.h b/sys/net/routing/aodvv2/routingtable.h new file mode 100644 index 000000000000..c4bd9f5e2b3b --- /dev/null +++ b/sys/net/routing/aodvv2/routingtable.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief Cobbled-together routing table. + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_ROUTINGTABLE_H_ +#define AODVV2_ROUTINGTABLE_H_ + +#include + +#include "common/netaddr.h" + +#include "aodvv2/types.h" +#include "constants.h" +#include "seqnum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * A route table entry (i.e., a route) may be in one of the following states: + */ +enum aodvv2_routing_states +{ + ROUTE_STATE_ACTIVE, + ROUTE_STATE_IDLE, + ROUTE_STATE_INVALID, + ROUTE_STATE_TIMED +}; + +/** + * all fields of a routing table entry + */ +struct aodvv2_routing_entry_t +{ + struct netaddr addr; /**< IP address of this route's destination */ + aodvv2_seqnum_t seqnum; /**< The Sequence Number obtained from the + * last packet that updated the entry */ + struct netaddr nextHopAddr; /**< IP address of the the next hop towards + * the destination */ + timex_t lastUsed; /**< IP address of this route's destination */ + timex_t expirationTime; /**< Time at which this route expires */ + aodvv2_metric_t metricType; /**< Metric type of this route */ + uint8_t metric; /**< Metric value of this route*/ + uint8_t state; /**< State of this route + * (i.e. one of aodvv2_routing_states) */ +}; + +/** + * @brief Initialize routing table. + */ +void routingtable_init(void); + +/** + * @brief Get next hop towards dest. + * Returns NULL if dest is not in routing table. + * + * @param[in] dest Destination of the packet + * @param[in] metricType Metric Type of the desired route + * @return next hop towards dest if it exists, NULL otherwise + */ +struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t metricType); + +/** + * @brief Add new entry to routing table, if there is no other entry + * to the same destination. + * + * @param[in] entry The routing table entry to add + */ +void routingtable_add_entry(struct aodvv2_routing_entry_t *entry); + +/** + * @brief Retrieve pointer to a routing table entry. + * To edit, simply follow the pointer. + * Returns NULL if addr is not in routing table. + * + * @param[in] addr The address towards which the route should point + * @param[in] metricType Metric Type of the desired route + * @return Routing table entry if it exists, NULL otherwise + */ +struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, aodvv2_metric_t metricType); + +/** + * @brief Delete routing table entry towards addr with metric type MetricType, + * if it exists. + * + * @param[in] addr The address towards which the route should point + * @param[in] metricType Metric Type of the desired route + */ +void routingtable_delete_entry(struct netaddr *addr, aodvv2_metric_t metricType); + +/** + * Find all routing table entries that use hop as their nextHopAddress, mark them + * as broken, write the active one into unreachable_nodes[] and increment len + * accordingly. (Sorry about the Name.) + * + * @param hop Address of the newly unreachable next hop + * @param unreachable_nodes[] array of newlu unreachable nodes to be filled. + * should be empty. + * @param len size_t* which will contain the length of + * unreachable_nodes[] after execution + */ +void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, + struct unreachable_node unreachable_nodes[], + size_t *len); + +/** + * Check if the data of a RREQ or RREP offers improvement for an existing routing + * table entry. + * @param rt_entry the routing table entry to check + * @param node_data The data to check against. When handling a RREQ, + * the OrigNode's information (i.e. packet_data.origNode) + * must be passed. When handling a RREP, the + * TargNode's data (i.e. packet_data.targNode) must + * be passed. + */ +bool routingtable_offers_improvement(struct aodvv2_routing_entry_t *rt_entry, + struct node_data *node_data); + +/** + * Fills a routing table entry with the data of a RREQ. + * @param packet_data the RREQ's data + * @param rt_entry the routing table entry to fill + * @param link_cost the link cost for this RREQ + */ +void routingtable_fill_routing_entry_t_rreq(struct aodvv2_packet_data *packet_data, + struct aodvv2_routing_entry_t *rt_entry); + +/** + * Fills a routing table entry with the data of a RREP. + * @param packet_data the RREP's data + * @param rt_entry the routing table entry to fill + * @param link_cost the link cost for this RREP + */ +void routingtable_fill_routing_entry_t_rrep(struct aodvv2_packet_data *packet_data, + struct aodvv2_routing_entry_t *rt_entry); + +void print_routingtable(void); +void print_routingtable_entry(struct aodvv2_routing_entry_t *rt_entry); + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_ROUTINGTABLE_H_*/ diff --git a/sys/net/routing/aodvv2/seqnum.c b/sys/net/routing/aodvv2/seqnum.c new file mode 100644 index 000000000000..0cfec95f761e --- /dev/null +++ b/sys/net/routing/aodvv2/seqnum.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief aodvv2 sequence number + * + * @author Lotte Steenbrink + */ + + +#include "seqnum.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static aodvv2_seqnum_t seqnum; + +void seqnum_init(void) +{ + seqnum = 1; +} + +void seqnum_inc(void) +{ + if (seqnum == 65535) { + seqnum = 1; + } + else if (seqnum == 0) { + DEBUG("ERROR: SeqNum shouldn't be 0! \n"); /* TODO handle properly */ + } + else { + seqnum++; + } +} + +aodvv2_seqnum_t seqnum_get(void) +{ + return seqnum; +} diff --git a/sys/net/routing/aodvv2/seqnum.h b/sys/net/routing/aodvv2/seqnum.h new file mode 100644 index 000000000000..c47ee224e2f3 --- /dev/null +++ b/sys/net/routing/aodvv2/seqnum.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief aodvv2 sequence number + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_SEQNUM_H_ +#define AODVV2_SEQNUM_H_ + +#include + +#include "aodvv2/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize sequence number. + */ +void seqnum_init(void); + +/** + * @brief Get sequence number. + * + * @return sequence number + */ +aodvv2_seqnum_t seqnum_get(void); + +/** + * @brief Increment the sequence number by 1. + */ +void seqnum_inc(void); + +/** + * @brief Compare 2 sequence numbers. + * @param[in] s1 first sequence number + * @param[in] s2 second sequence number + * @return -1 when s1 is smaller, 0 if equal, 1 if s1 is bigger. + */ +static inline int seqnum_cmp(aodvv2_seqnum_t s1, aodvv2_seqnum_t s2) +{ + return s1 == s2 ? 0 : (s1 > s2 ? +1 : -1); +} + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_SEQNUM_H_ */ diff --git a/sys/net/routing/aodvv2/writer.c b/sys/net/routing/aodvv2/writer.c new file mode 100644 index 000000000000..275082425147 --- /dev/null +++ b/sys/net/routing/aodvv2/writer.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief writer to create RFC5444 aodvv2 messages + * + * @author Lotte Steenbrink + */ + +#ifdef RIOT +#include "net_help.h" +#endif + +#include "writer.h" + +#include "aodv_debug.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static void _cb_addMessageHeader(struct rfc5444_writer *wr, + struct rfc5444_writer_message *message); + +static void _cb_rreq_addAddresses(struct rfc5444_writer *wr); +static void _cb_rrep_addAddresses(struct rfc5444_writer *wr); +static void _cb_rerr_addAddresses(struct rfc5444_writer *wr); + +struct rfc5444_writer writer; +static struct writer_target _target; + +static struct unreachable_node *_unreachable_nodes; +static size_t _num_unreachable_nodes; + +static uint8_t _msg_buffer[128]; +static uint8_t _msg_addrtlvs[1000]; +static uint8_t _packet_buffer[128]; + +static struct rfc5444_writer_message *_rreq_msg; +static struct rfc5444_writer_message *_rrep_msg; +static struct rfc5444_writer_message *_rerr_msg; + +/* + * message content provider that will add message TLVs, + * addresses and address block TLVs to all messages of type RREQ. + */ +static struct rfc5444_writer_content_provider _rreq_message_content_provider = +{ + .msg_type = RFC5444_MSGTYPE_RREQ, + .addAddresses = _cb_rreq_addAddresses, +}; + +/* declaration of all address TLVs added to the RREQ message */ +static struct rfc5444_writer_tlvtype _rreq_addrtlvs[] = +{ + [RFC5444_MSGTLV_ORIGSEQNUM] = { .type = RFC5444_MSGTLV_ORIGSEQNUM }, + [RFC5444_MSGTLV_METRIC] = { + .type = RFC5444_MSGTLV_METRIC, + .exttype = AODVV2_DEFAULT_METRIC_TYPE + }, +}; + +/* + * message content provider that will add message TLVs, + * addresses and address block TLVs to all messages of type RREQ. + */ +static struct rfc5444_writer_content_provider _rrep_message_content_provider = +{ + .msg_type = RFC5444_MSGTYPE_RREP, + .addAddresses = _cb_rrep_addAddresses, +}; + +/* declaration of all address TLVs added to the RREP message */ +static struct rfc5444_writer_tlvtype _rrep_addrtlvs[] = +{ + [RFC5444_MSGTLV_ORIGSEQNUM] = { .type = RFC5444_MSGTLV_ORIGSEQNUM}, + [RFC5444_MSGTLV_TARGSEQNUM] = { .type = RFC5444_MSGTLV_TARGSEQNUM}, + [RFC5444_MSGTLV_METRIC] = { + .type = RFC5444_MSGTLV_METRIC, + .exttype = AODVV2_DEFAULT_METRIC_TYPE + }, +}; + +/* + * message content provider that will add message TLVs, + * addresses and address block TLVs to all messages of type RREQ. + */ +static struct rfc5444_writer_content_provider _rerr_message_content_provider = +{ + .msg_type = RFC5444_MSGTYPE_RERR, + .addAddresses = _cb_rerr_addAddresses, +}; + +/* declaration of all address TLVs added to the RREP message */ +static struct rfc5444_writer_tlvtype _rerr_addrtlvs[] = +{ + [RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM] = { .type = RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM}, +}; + +/** + * Callback to define the message header for a RFC5444 RREQ message + * @param message + */ +static void +_cb_addMessageHeader(struct rfc5444_writer *wr, struct rfc5444_writer_message *message) +{ + AODV_DEBUG("%s()\n", __func__); + + /* no originator, no hopcount, has hoplimit, no seqno */ + rfc5444_writer_set_msg_header(wr, message, false, false, true, false); + rfc5444_writer_set_msg_hoplimit(wr, message, _target.packet_data.hoplimit); +} + +/** + * Callback to add addresses and address TLVs to a RFC5444 RREQ message + */ +static void +_cb_rreq_addAddresses(struct rfc5444_writer *wr) +{ + AODV_DEBUG("%s()\n", __func__); + + struct rfc5444_writer_address *origNode_addr; + + /* add origNode address (has no address tlv); is mandatory address */ + origNode_addr = rfc5444_writer_add_address(wr, _rreq_message_content_provider.creator, + &_target.packet_data.origNode.addr, true); + + /* add targNode address (has no address tlv); is mandatory address */ + rfc5444_writer_add_address(wr, _rreq_message_content_provider.creator, + &_target.packet_data.targNode.addr, true); + + /* add SeqNum TLV and metric TLV to origNode */ + /* TODO: allow_dup true or false? */ + rfc5444_writer_add_addrtlv(wr, origNode_addr, &_rreq_addrtlvs[RFC5444_MSGTLV_ORIGSEQNUM], + &_target.packet_data.origNode.seqnum, + sizeof(_target.packet_data.origNode.seqnum), false); + /* cppcheck: suppress false positive on non-trivially initialized arrays. + * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ + /* cppcheck-suppress arrayIndexOutOfBounds */ + rfc5444_writer_add_addrtlv(wr, origNode_addr, &_rreq_addrtlvs[RFC5444_MSGTLV_METRIC], + &_target.packet_data.origNode.metric, + sizeof(_target.packet_data.origNode.metric), false); +} + +/** + * Callback to add addresses and address TLVs to a RFC5444 RREQ message + */ +static void +_cb_rrep_addAddresses(struct rfc5444_writer *wr) +{ + AODV_DEBUG("%s()\n", __func__); + + struct rfc5444_writer_address *origNode_addr, *targNode_addr; + + uint16_t origNode_seqnum = _target.packet_data.origNode.seqnum; + + uint16_t targNode_seqnum = seqnum_get(); + seqnum_inc(); + + uint8_t targNode_hopCt = _target.packet_data.targNode.metric; + + /* add origNode address (has no address tlv); is mandatory address */ + origNode_addr = rfc5444_writer_add_address(wr, _rrep_message_content_provider.creator, + &_target.packet_data.origNode.addr, true); + + /* add targNode address (has no address tlv); is mandatory address */ + targNode_addr = rfc5444_writer_add_address(wr, _rrep_message_content_provider.creator, + &_target.packet_data.targNode.addr, true); + + /* add OrigNode and TargNode SeqNum TLVs */ + /* TODO: allow_dup true or false? */ + rfc5444_writer_add_addrtlv(wr, origNode_addr, &_rrep_addrtlvs[RFC5444_MSGTLV_ORIGSEQNUM], + &origNode_seqnum, sizeof(origNode_seqnum), false); + rfc5444_writer_add_addrtlv(wr, targNode_addr, &_rrep_addrtlvs[RFC5444_MSGTLV_TARGSEQNUM], + &targNode_seqnum, sizeof(targNode_seqnum), false); + + /* Add Metric TLV to targNode Address */ + rfc5444_writer_add_addrtlv(wr, targNode_addr, &_rrep_addrtlvs[RFC5444_MSGTLV_METRIC], + &targNode_hopCt, sizeof(targNode_hopCt), false); +} + +/** + * Callback to add addresses and address TLVs to a RFC5444 RERR message + */ +static void +_cb_rerr_addAddresses(struct rfc5444_writer *wr) +{ + AODV_DEBUG("%s()\n", __func__); + + for (unsigned i = 0; i < _num_unreachable_nodes; i++) { + /* add unreachableNode addresses (has no address tlv); is mandatory address */ + struct rfc5444_writer_address *unreachableNode_addr = rfc5444_writer_add_address( + wr, _rerr_message_content_provider.creator, + &_unreachable_nodes[i].addr, true); + + /* add SeqNum TLV to unreachableNode */ + /* TODO: allow_dup true or false? */ + /* cppcheck: suppress false positive on non-trivially initialized arrays. + * this is a known bug: http://trac.cppcheck.net/ticket/5497 */ + /* cppcheck-suppress arrayIndexOutOfBounds */ + rfc5444_writer_add_addrtlv(wr, unreachableNode_addr, + &_rerr_addrtlvs[RFC5444_MSGTLV_UNREACHABLE_NODE_SEQNUM], + &_unreachable_nodes[i].seqnum, + sizeof(_unreachable_nodes[i].seqnum), false); + } +} + +void aodv_packet_writer_init(write_packet_func_ptr ptr) +{ + AODV_DEBUG("%s()\n", __func__); + + /* define interface for generating rfc5444 packets */ + _target.interface.packet_buffer = _packet_buffer; + _target.interface.packet_size = sizeof(_packet_buffer); + + /* set function to send binary packet content */ + _target.interface.sendPacket = ptr; + + /* define the rfc5444 writer */ + writer.msg_buffer = _msg_buffer; + writer.msg_size = sizeof(_msg_buffer); + writer.addrtlv_buffer = _msg_addrtlvs; + writer.addrtlv_size = sizeof(_msg_addrtlvs); + + /* initialize writer */ + rfc5444_writer_init(&writer); + + /* register a target (for sending messages to) in writer */ + rfc5444_writer_register_target(&writer, &_target.interface); + + /* register a message content providers for RREQ and RREP */ + rfc5444_writer_register_msgcontentprovider(&writer, &_rreq_message_content_provider, + _rreq_addrtlvs, ARRAYSIZE(_rreq_addrtlvs)); + rfc5444_writer_register_msgcontentprovider(&writer, &_rrep_message_content_provider, + _rrep_addrtlvs, ARRAYSIZE(_rrep_addrtlvs)); + rfc5444_writer_register_msgcontentprovider(&writer, &_rerr_message_content_provider, + _rerr_addrtlvs, ARRAYSIZE(_rerr_addrtlvs)); + + /* register rreq and rrep messages with 16 byte (ipv6) addresses. + * AddPacketHeader & addMessageHeader callbacks are triggered here. */ + _rreq_msg = rfc5444_writer_register_message(&writer, RFC5444_MSGTYPE_RREQ, + false, RFC5444_MAX_ADDRLEN); + _rrep_msg = rfc5444_writer_register_message(&writer, RFC5444_MSGTYPE_RREP, + false, RFC5444_MAX_ADDRLEN); + _rerr_msg = rfc5444_writer_register_message(&writer, RFC5444_MSGTYPE_RERR, + false, RFC5444_MAX_ADDRLEN); + + _rreq_msg->addMessageHeader = _cb_addMessageHeader; + _rrep_msg->addMessageHeader = _cb_addMessageHeader; + _rerr_msg->addMessageHeader = _cb_addMessageHeader; +} + +/** + * Send a RREQ. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RREQs, use aodv_send_rreq(). + * @param packet_data parameters of the RREQ + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rreq(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop) +{ + AODV_DEBUG("%s()\n", __func__); + + if ((packet_data == NULL) || (next_hop == NULL)) { + return; + } + + /* Make sure no other thread is using the writer right now */ + memcpy(&_target.packet_data, packet_data, sizeof(struct aodvv2_packet_data)); + _target.type = RFC5444_MSGTYPE_RREQ; + _target.packet_data.hoplimit = packet_data->hoplimit; + + /* set address to which the write_packet callback should send our RREQ */ + memcpy(&_target.target_addr, next_hop, sizeof (struct netaddr)); + + rfc5444_writer_create_message_alltarget(&writer, RFC5444_MSGTYPE_RREQ); + rfc5444_writer_flush(&writer, &_target.interface, false); +} + + +/** + * Send a RREP. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RREPs, use aodv_send_rrep(). + * @param packet_data parameters of the RREP + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop) +{ + AODV_DEBUG("%s()\n", __func__); + + if ((packet_data == NULL) || (next_hop == NULL)) { + return; + } + + memcpy(&_target.packet_data, packet_data, sizeof(struct aodvv2_packet_data)); + _target.type = RFC5444_MSGTYPE_RREP; + _target.packet_data.hoplimit = AODVV2_MAX_HOPCOUNT; + + /* set address to which the write_packet callback should send our RREQ */ + memcpy(&_target.target_addr, next_hop, sizeof (struct netaddr)); + + rfc5444_writer_create_message_alltarget(&writer, RFC5444_MSGTYPE_RREP); + rfc5444_writer_flush(&writer, &_target.interface, false); +} + +/** + * Send a RERR. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RERRs, use aodv_send_rerr(). + * @param unreachable_nodes[] array containing all newly unreachable nodes. each + * in a struct unreachable_node + * @param len length of unreachable_nodes[] + * @param hoplimit the message's hop limit + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, + int hoplimit, struct netaddr *next_hop) +{ + AODV_DEBUG("%s()\n", __func__); + + if ((unreachable_nodes == NULL) || (next_hop == NULL)) { + return; + } + + _target.packet_data.hoplimit = hoplimit; + _target.type = RFC5444_MSGTYPE_RERR; + _unreachable_nodes = unreachable_nodes; + _num_unreachable_nodes = len; + + /* set address to which the write_packet callback should send our RREQ */ + memcpy(&_target.target_addr, next_hop, sizeof (struct netaddr)); + + rfc5444_writer_create_message_alltarget(&writer, RFC5444_MSGTYPE_RERR); + rfc5444_writer_flush(&writer, &_target.interface, false); +} + +void aodv_packet_writer_cleanup(void) +{ + AODV_DEBUG("%s()\n", __func__); + rfc5444_writer_cleanup(&writer); +} diff --git a/sys/net/routing/aodvv2/writer.h b/sys/net/routing/aodvv2/writer.h new file mode 100644 index 000000000000..24fa54386f6e --- /dev/null +++ b/sys/net/routing/aodvv2/writer.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup aodvv2 + * @{ + * + * @file + * @brief writer to create RFC5444 aodvv2 messages + * + * @author Lotte Steenbrink + */ + +#ifndef AODVV2_WRITER_H_ +#define AODVV2_WRITER_H_ + +#include "common/netaddr.h" +#include "rfc5444/rfc5444_writer.h" +#include "mutex.h" + +#include "constants.h" +#include "seqnum.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Wrapper for the rfc5444_writer_target that the _write_packet() callback receives. + * _write_packet() needs to know the type, payload and target address + * of the RFC5444 message to be sent as well, but the oonf api does not + * offer this feature. Having this wrapper enables the use of the + * container_of macro to fetch this information. + * It is hacky, but it does the trick. + */ +struct writer_target +{ + struct rfc5444_writer_target interface; /**< Interface for generating rfc5444 packets */ + struct netaddr target_addr; /**< Address to which the packet should be sent */ + struct aodvv2_packet_data packet_data; /**< Payload of the AODVv2 Message */ + int type; /**< Type of the AODVv2 Message (i.e. rfc5444_msg_type) */ +}; + +/** + * @brief oonf api voodo. Pointer to a callback function which is passed to + * writer_init() and called when the packet is ready to send. + */ +typedef void (*write_packet_func_ptr)( + struct rfc5444_writer *wr, struct rfc5444_writer_target *iface, + void *buffer, size_t length); + +/** + * @brief Initialize RFC5444 writer + * @param ptr pointer to "send_packet" callback + */ +void aodv_packet_writer_init(write_packet_func_ptr ptr); + +/** + * @brief Clean up after the RFC5444 writer + */ +void aodv_packet_writer_cleanup(void); + +/** + * @brief Send a RREQ. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RREQs, use aodv_send_rreq(). + * @param packet_data parameters of the RREQ + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rreq(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop); + +/** + * @brief Send a RREP. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RREPs, use aodv_send_rrep(). + * @param packet_data parameters of the RREP + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop); + +/** + * @brief Send a RERR. DO NOT use this function to dispatch packets from anything else + * than the sender_thread. To send RERRs, use aodv_send_rerr(). + * @param unreachable_nodes[] array containing all newly unreachable nodes. each + * in a struct unreachable_node + * @param len length of unreachable_nodes[] + * @param hoplimit the message's hop limit + * @param next_hop Address the RREP is sent to + */ +void aodv_packet_writer_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, + int hoplimit, struct netaddr *next_hop); + +#ifdef __cplusplus +} +#endif + +#endif /* AODVV2_WRITER_H_ */ From 8736403d38fe3238984f394875e02b8b7a5bfece Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 12 Jan 2016 08:56:13 -0800 Subject: [PATCH 12/41] include timex.h --- sys/net/include/aodvv2/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/net/include/aodvv2/types.h b/sys/net/include/aodvv2/types.h index 311530ea2601..4a0e1e756f33 100644 --- a/sys/net/include/aodvv2/types.h +++ b/sys/net/include/aodvv2/types.h @@ -21,6 +21,7 @@ #define AODVV2_TYPES_H #include "common/netaddr.h" +#include "timex.h" #ifdef __cplusplus extern "C" { From 8242cc5d06d8c1dfa1a8e1b59ca7fdfc9670b9a5 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 12 Jan 2016 16:06:20 -0800 Subject: [PATCH 13/41] get rid of sock_snd --- sys/net/routing/aodvv2/aodv.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/routing/aodvv2/aodv.c index 82560ed7a0a2..c46d639c357d 100644 --- a/sys/net/routing/aodvv2/aodv.c +++ b/sys/net/routing/aodvv2/aodv.c @@ -31,7 +31,6 @@ #define AODVV2_PREFIX {{ 0xbe, 0xe2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} static void _init_addresses(void); -static void _init_sock_snd(void); static void *_aodv_receiver_thread(void *arg); static void *_aodv_sender_thread(void *arg); static void *fib_signal_handler_thread(void *arg); @@ -57,7 +56,6 @@ static char aodv_fib_stack_buf[THREAD_STACKSIZE_MAIN]; static aodvv2_metric_t _metric_type; static int sender_thread; -static int _sock_snd; static struct autobuf _hexbuf; static ng_ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; static ng_ipv6_addr_t _v6_addr_local; @@ -98,7 +96,6 @@ void aodv_init(kernel_pid_t interface) aodv_set_metric_type(AODVV2_DEFAULT_METRIC_TYPE); _init_addresses(); - _init_sock_snd(); /* init ALL the things! \o, */ seqnum_init(); @@ -317,16 +314,6 @@ static void _init_addresses(void) ng_ipv6_addr_set_loopback(&_v6_addr_loopback); } -/* init socket communication for sender */ -static void _init_sock_snd(void) -{ - _sock_snd = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - - if (-1 == _sock_snd) { - AODV_DEBUG("Error Creating Socket!\n"); - } -} - /* Build RREQs, RREPs and RERRs from the information contained in the thread's * message queue and send them */ static void *_aodv_sender_thread(void *arg) From 90276761559edb5b4ee9f50782b6d7e46cc1a1f3 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 14 Jan 2016 10:04:43 -0800 Subject: [PATCH 14/41] add gnrc_ipv6_router_default and gnrc_conn_udp to MAkefile.dep, rm ng_module --- Makefile.dep | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.dep b/Makefile.dep index 99306f3efc63..f1d081c0fbb5 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -281,7 +281,8 @@ ifneq (,$(filter gnrc_ipv6_hdr,$(USEMODULE))) endif ifneq (,$(filter aodvv2,$(USEMODULE))) - USEMODULE += ng_sixlowpan_default + USEMODULE += gnrc_ipv6_router_default + USEMODULE += gnrc_conn_udp USEMODULE += vtimer USEMODULE += oonf_common USEMODULE += oonf_rfc5444 From e9a1e9438d03f9a781a9d129cca35d465641694d Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 11 Mar 2016 12:12:54 -0800 Subject: [PATCH 15/41] move files from net/routing to net/gnrc/routing --- sys/net/gnrc/Makefile | 3 +++ sys/net/{ => gnrc}/routing/aodvv2/Makefile | 2 ++ sys/net/{ => gnrc}/routing/aodvv2/aodv.c | 0 sys/net/{ => gnrc}/routing/aodvv2/aodv.h | 0 sys/net/{ => gnrc}/routing/aodvv2/aodv_debug.h | 0 sys/net/{ => gnrc}/routing/aodvv2/constants.h | 0 sys/net/{ => gnrc}/routing/aodvv2/reader.c | 0 sys/net/{ => gnrc}/routing/aodvv2/reader.h | 0 sys/net/{ => gnrc}/routing/aodvv2/routingtable.c | 0 sys/net/{ => gnrc}/routing/aodvv2/routingtable.h | 0 sys/net/{ => gnrc}/routing/aodvv2/seqnum.c | 0 sys/net/{ => gnrc}/routing/aodvv2/seqnum.h | 0 sys/net/{ => gnrc}/routing/aodvv2/utils.c | 0 sys/net/{ => gnrc}/routing/aodvv2/utils.h | 0 sys/net/{ => gnrc}/routing/aodvv2/writer.c | 0 sys/net/{ => gnrc}/routing/aodvv2/writer.h | 0 16 files changed, 5 insertions(+) rename sys/net/{ => gnrc}/routing/aodvv2/Makefile (66%) rename sys/net/{ => gnrc}/routing/aodvv2/aodv.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/aodv.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/aodv_debug.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/constants.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/reader.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/reader.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/routingtable.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/routingtable.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/seqnum.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/seqnum.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/utils.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/utils.h (100%) rename sys/net/{ => gnrc}/routing/aodvv2/writer.c (100%) rename sys/net/{ => gnrc}/routing/aodvv2/writer.h (100%) diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index d011157b43f1..cb210cba2a77 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -1,3 +1,6 @@ +ifneq (,$(filter aodvv2,$(USEMODULE))) + DIRS += routing/aodvv2 +endif ifneq (,$(filter gnrc_conn,$(USEMODULE))) DIRS += conn endif diff --git a/sys/net/routing/aodvv2/Makefile b/sys/net/gnrc/routing/aodvv2/Makefile similarity index 66% rename from sys/net/routing/aodvv2/Makefile rename to sys/net/gnrc/routing/aodvv2/Makefile index 48422e909a47..c9e6aabb992c 100644 --- a/sys/net/routing/aodvv2/Makefile +++ b/sys/net/gnrc/routing/aodvv2/Makefile @@ -1 +1,3 @@ +MODULE = aodvv2 + include $(RIOTBASE)/Makefile.base diff --git a/sys/net/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c similarity index 100% rename from sys/net/routing/aodvv2/aodv.c rename to sys/net/gnrc/routing/aodvv2/aodv.c diff --git a/sys/net/routing/aodvv2/aodv.h b/sys/net/gnrc/routing/aodvv2/aodv.h similarity index 100% rename from sys/net/routing/aodvv2/aodv.h rename to sys/net/gnrc/routing/aodvv2/aodv.h diff --git a/sys/net/routing/aodvv2/aodv_debug.h b/sys/net/gnrc/routing/aodvv2/aodv_debug.h similarity index 100% rename from sys/net/routing/aodvv2/aodv_debug.h rename to sys/net/gnrc/routing/aodvv2/aodv_debug.h diff --git a/sys/net/routing/aodvv2/constants.h b/sys/net/gnrc/routing/aodvv2/constants.h similarity index 100% rename from sys/net/routing/aodvv2/constants.h rename to sys/net/gnrc/routing/aodvv2/constants.h diff --git a/sys/net/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c similarity index 100% rename from sys/net/routing/aodvv2/reader.c rename to sys/net/gnrc/routing/aodvv2/reader.c diff --git a/sys/net/routing/aodvv2/reader.h b/sys/net/gnrc/routing/aodvv2/reader.h similarity index 100% rename from sys/net/routing/aodvv2/reader.h rename to sys/net/gnrc/routing/aodvv2/reader.h diff --git a/sys/net/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c similarity index 100% rename from sys/net/routing/aodvv2/routingtable.c rename to sys/net/gnrc/routing/aodvv2/routingtable.c diff --git a/sys/net/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h similarity index 100% rename from sys/net/routing/aodvv2/routingtable.h rename to sys/net/gnrc/routing/aodvv2/routingtable.h diff --git a/sys/net/routing/aodvv2/seqnum.c b/sys/net/gnrc/routing/aodvv2/seqnum.c similarity index 100% rename from sys/net/routing/aodvv2/seqnum.c rename to sys/net/gnrc/routing/aodvv2/seqnum.c diff --git a/sys/net/routing/aodvv2/seqnum.h b/sys/net/gnrc/routing/aodvv2/seqnum.h similarity index 100% rename from sys/net/routing/aodvv2/seqnum.h rename to sys/net/gnrc/routing/aodvv2/seqnum.h diff --git a/sys/net/routing/aodvv2/utils.c b/sys/net/gnrc/routing/aodvv2/utils.c similarity index 100% rename from sys/net/routing/aodvv2/utils.c rename to sys/net/gnrc/routing/aodvv2/utils.c diff --git a/sys/net/routing/aodvv2/utils.h b/sys/net/gnrc/routing/aodvv2/utils.h similarity index 100% rename from sys/net/routing/aodvv2/utils.h rename to sys/net/gnrc/routing/aodvv2/utils.h diff --git a/sys/net/routing/aodvv2/writer.c b/sys/net/gnrc/routing/aodvv2/writer.c similarity index 100% rename from sys/net/routing/aodvv2/writer.c rename to sys/net/gnrc/routing/aodvv2/writer.c diff --git a/sys/net/routing/aodvv2/writer.h b/sys/net/gnrc/routing/aodvv2/writer.h similarity index 100% rename from sys/net/routing/aodvv2/writer.h rename to sys/net/gnrc/routing/aodvv2/writer.h From f49c1f44fd86c8e31506935870ffd51ad6ef003b Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 11 Mar 2016 13:12:45 -0800 Subject: [PATCH 16/41] ng_ -> gnrc_ --- sys/net/gnrc/routing/aodvv2/aodv.c | 83 ++++++++++++++-------------- sys/net/gnrc/routing/aodvv2/aodv.h | 12 ++-- sys/net/gnrc/routing/aodvv2/reader.c | 32 +++++------ sys/net/gnrc/routing/aodvv2/utils.c | 4 +- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index c46d639c357d..e987d12f77bf 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -57,8 +57,8 @@ static char aodv_fib_stack_buf[THREAD_STACKSIZE_MAIN]; static aodvv2_metric_t _metric_type; static int sender_thread; static struct autobuf _hexbuf; -static ng_ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; -static ng_ipv6_addr_t _v6_addr_local; +static ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; +static ipv6_addr_t _v6_addr_local; static struct netaddr na_local; /* the same as _v6_addr_local, but to save us * constant calls to ipv6_addr_t_to_netaddr()... */ static struct writer_target *wt; @@ -66,7 +66,7 @@ static mutex_t rreq_mutex; static mutex_t rrep_mutex; static mutex_t rerr_mutex; -static ng_ipv6_addr_t aodvv2_prefix = AODVV2_PREFIX; +static ipv6_addr_t aodvv2_prefix = AODVV2_PREFIX; static int aodvv2_prefix_len; static int aodvv2_address_type_size; @@ -87,7 +87,7 @@ void aodv_init(kernel_pid_t interface) } aodvv2_if_id = interface; - aodvv2_address_type_size = sizeof(ng_ipv6_addr_t); + aodvv2_address_type_size = sizeof(ipv6_addr_t); aodvv2_prefix_len = 64; mutex_init(&rreq_mutex); @@ -112,13 +112,13 @@ void aodv_init(kernel_pid_t interface) /* start listening & enable sending */ thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN, - CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); + THREAD_CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); AODV_DEBUG("listening on port %d\n", MANET_PORT); sender_thread = thread_create(aodv_snd_stack_buf, sizeof(aodv_snd_stack_buf), - THREAD_PRIORITY_MAIN, CREATE_STACKTEST, _aodv_sender_thread, + THREAD_PRIORITY_MAIN, THREAD_CREATE_STACKTEST, _aodv_sender_thread, NULL, "_aodv_sender_thread"); thread_create(aodv_fib_stack_buf, sizeof(aodv_fib_stack_buf), - THREAD_PRIORITY_MAIN, CREATE_STACKTEST, fib_signal_handler_thread, + THREAD_PRIORITY_MAIN, THREAD_CREATE_STACKTEST, fib_signal_handler_thread, NULL, "fib_signal_handler_thread"); } @@ -135,7 +135,7 @@ void aodv_set_metric_type(aodvv2_metric_t metric_type) void *fib_signal_handler_thread(void *arg) { (void) arg; - ng_ipv6_addr_t dest; + ipv6_addr_t dest; struct netaddr na_dest; int err = fib_register_rp(&aodvv2_prefix.u8[0], aodvv2_address_type_size); @@ -150,7 +150,7 @@ void *fib_signal_handler_thread(void *arg) if (msg.type == FIB_MSG_RP_SIGNAL) { rp_address_msg_t* rp_msg = (rp_address_msg_t*)msg.content.ptr; - if (rp_msg->address_size == sizeof(ng_ipv6_addr_t)) { + if (rp_msg->address_size == sizeof(ipv6_addr_t)) { /* We currently only support IPv6*/ memcpy(&dest, rp_msg->address, rp_msg->address_size); /* Reply to the FIB so that it can stop blocking */ @@ -179,7 +179,7 @@ void *fib_signal_handler_thread(void *arg) }; AODV_DEBUG("\tstarting route discovery towards %s... \n", - ng_ipv6_addr_to_str(addr_str, &dest, NG_IPV6_ADDR_MAX_STR_LEN)); + ipv6_addr_to_str(addr_str, &dest, IPV6_ADDR_MAX_STR_LEN)); aodv_send_rreq(&rreq_data); } else { @@ -283,12 +283,12 @@ static void _init_addresses(void) eui64_t iid; /* init multicast address: set to to a link-local all nodes multicast address */ - ng_ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); + ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, IPV6_ADDR_MCAST_SCP_LINK_LOCAL); DEBUG("my multicast address is: %s\n", - ng_ipv6_addr_to_str(addr_str, &_v6_addr_mcast, NG_IPV6_ADDR_MAX_STR_LEN)); + ipv6_addr_to_str(addr_str, &_v6_addr_mcast, IPV6_ADDR_MAX_STR_LEN)); /* get id (of type eui46_t) of the interface we're sending on */ - int err_code = ng_netapi_get(aodvv2_if_id, NETCONF_OPT_IPV6_IID, 0, &iid, + int err_code = gnrc_netapi_get(aodvv2_if_id, NETOPT_IPV6_IID, 0, &iid, sizeof(eui64_t)); if (err_code < 0) { DEBUG("Error: failed to get iid, error code: %d\n", err_code); @@ -296,14 +296,14 @@ static void _init_addresses(void) } /* Set addr according to our interface id */ - ng_ipv6_addr_set_aiid(&_v6_addr_local, &iid.uint8[0]); + ipv6_addr_set_aiid(&_v6_addr_local, &iid.uint8[0]); /* Set (global!) prefix */ - ng_ipv6_addr_init_prefix(&_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); + ipv6_addr_init_prefix(&_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); /* Add our homemade address to our interface (aodvv2_if_id) */ - ng_ipv6_netif_add_addr(aodvv2_if_id, &_v6_addr_local, aodvv2_prefix_len, 0); + gnrc_ipv6_netif_add_addr(aodvv2_if_id, &_v6_addr_local, aodvv2_prefix_len, 0); DEBUG("my src address is: %s\n", - ng_ipv6_addr_to_str(addr_str, &_v6_addr_local, NG_IPV6_ADDR_MAX_STR_LEN)); + ipv6_addr_to_str(addr_str, &_v6_addr_local, IPV6_ADDR_MAX_STR_LEN)); /* store src & multicast address as netaddr as well for easy interaction * with oonf based stuff */ @@ -311,7 +311,7 @@ static void _init_addresses(void) ipv6_addr_t_to_netaddr(&_v6_addr_mcast, &na_mcast); /* TODO: do I need this?*/ - ng_ipv6_addr_set_loopback(&_v6_addr_loopback); + ipv6_addr_set_loopback(&_v6_addr_loopback); } /* Build RREQs, RREPs and RERRs from the information contained in the thread's @@ -355,9 +355,9 @@ static void *_aodv_receiver_thread(void *arg) { (void) arg; - ng_netreg_entry_t server = { + gnrc_netreg_entry_t server = { .next = NULL, - .demux_ctx = NG_NETREG_DEMUX_CTX_ALL, + .demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL, .pid = KERNEL_PID_UNDEF }; AODV_DEBUG("%s()\n", __func__); @@ -369,24 +369,24 @@ static void *_aodv_receiver_thread(void *arg) msg_init_queue(msg_q, RCV_MSG_Q_SIZE); reply.content.value = (uint32_t)(-ENOTSUP); - reply.type = NG_NETAPI_MSG_TYPE_ACK; + reply.type = GNRC_NETAPI_MSG_TYPE_ACK; /* start server (which means registering AODVv2 receiver for the chosen port) */ server.pid = sched_active_pid; /* sched_active_pid is our pid, since we are currently act */ server.demux_ctx = (uint32_t) MANET_PORT; - ng_netreg_register(NG_NETTYPE_UDP, &server); + gnrc_netreg_register(GNRC_NETTYPE_UDP, &server); while (1) { msg_receive(&msg); switch (msg.type) { - case NG_NETAPI_MSG_TYPE_RCV: + case GNRC_NETAPI_MSG_TYPE_RCV: AODV_DEBUG("received data:\n"); - ng_pktsnip_t *pkt = ((ng_pktsnip_t *)msg.content.ptr); + gnrc_pktsnip_t *pkt = ((gnrc_pktsnip_t *)msg.content.ptr); if (pkt->size <= UDP_BUFFER_SIZE) { memcpy(buf_rcv, pkt->data, pkt->size); - if(pkt->next->next->type == NG_NETTYPE_IPV6) { - ipv6_addr_t_to_netaddr(&(((ng_ipv6_hdr_t*)(pkt->next->next->data))->src), &_sender); + if(pkt->next->next->type == GNRC_NETTYPE_IPV6) { + ipv6_addr_t_to_netaddr(&(((ipv6_hdr_t*)(pkt->next->next->data))->src), &_sender); } if (netaddr_cmp(&_sender, &na_local) == 0) { @@ -396,12 +396,12 @@ static void *_aodv_receiver_thread(void *arg) aodv_packet_reader_handle_packet((void *) buf_rcv, pkt->size, &_sender); } } - ng_pktbuf_release(pkt); + gnrc_pktbuf_release(pkt); break; - case NG_NETAPI_MSG_TYPE_SND: + case GNRC_NETAPI_MSG_TYPE_SND: break; - case NG_NETAPI_MSG_TYPE_GET: - case NG_NETAPI_MSG_TYPE_SET: + case GNRC_NETAPI_MSG_TYPE_GET: + case GNRC_NETAPI_MSG_TYPE_SET: msg_reply(&msg, &reply); break; default: @@ -416,34 +416,35 @@ static void *_aodv_receiver_thread(void *arg) /** The code o this function was borrowed from: examples/ng_networking/udp.c:34 - :90 + TODO: merge into write callback */ -static void send(ng_ipv6_addr_t addr, uint16_t port, void *data, size_t data_length) +static void _aodv_send(ipv6_addr_t addr, uint16_t port, void *data, size_t data_length) { - ng_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; + gnrc_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; /* allocate payload */ - payload = ng_pktbuf_add(NULL, data, data_length, NG_NETTYPE_UNDEF); + payload = gnrc_pktbuf_add(NULL, data, data_length, GNRC_NETTYPE_UNDEF); if (payload == NULL) { DEBUG("Error: unable to copy data to packet buffer\n"); return; } /* allocate UDP header, set payload, set source port := destination port */ - pkt_with_udp = ng_udp_hdr_build(payload, (uint8_t*)&port, 2, (uint8_t*)&port, 2); + pkt_with_udp = gnrc_udp_hdr_build(payload, (uint8_t*)&port, 2, (uint8_t*)&port, 2); if (pkt_with_udp == NULL) { DEBUG("Error: unable to allocate UDP header\n"); - ng_pktbuf_release(payload); + gnrc_pktbuf_release(payload); return; } /* allocate IPv6 header, set pkt_with_udp as payload */ - pkt_with_ip = ng_ipv6_hdr_build(pkt_with_udp, (uint8_t*)&_v6_addr_local, aodvv2_address_type_size, + pkt_with_ip = gnrc_ipv6_hdr_build(pkt_with_udp, (uint8_t*)&_v6_addr_local, aodvv2_address_type_size, (uint8_t *)&addr, sizeof(addr)); if (pkt_with_ip == NULL) { DEBUG("Error: unable to allocate IPv6 header\n"); - ng_pktbuf_release(pkt_with_udp); + gnrc_pktbuf_release(pkt_with_udp); return; } /* all headers are set, send packet */ - if(!ng_netapi_dispatch_send(NG_NETTYPE_UDP, NG_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { + if(!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { DEBUG("Error sending packet\n"); } } @@ -457,7 +458,7 @@ static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), void *buffer, size_t length) { AODV_DEBUG("%s()\n", __func__); - ng_ipv6_addr_t addr_send; + ipv6_addr_t addr_send; /* generate hexdump and human readable representation of packet * and print to console */ @@ -480,11 +481,11 @@ static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), DEBUG("originating RREQ with SeqNum %d towards %s via %s; updating RREQ table...\n", wt->packet_data.origNode.seqnum, netaddr_to_string(&nbuf, &wt->packet_data.targNode.addr), - ng_ipv6_addr_to_str(addr_str, &addr_send, IPV6_MAX_ADDR_STR_LEN)); + ipv6_addr_to_str(addr_str, &addr_send, IPV6_MAX_ADDR_STR_LEN)); rreqtable_is_redundant(&wt->packet_data); } - send(addr_send, (uint16_t) MANET_PORT, buffer, length); + _aodv_send(addr_send, (uint16_t) MANET_PORT, buffer, length); } /* Print the json representation of a sent packet to stdout for debugging */ diff --git a/sys/net/gnrc/routing/aodvv2/aodv.h b/sys/net/gnrc/routing/aodvv2/aodv.h index 6af74047b874..6bb299e84155 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.h +++ b/sys/net/gnrc/routing/aodvv2/aodv.h @@ -21,12 +21,12 @@ #define AODV_H_ #include "kernel.h" -#include "udp.h" -#include "net/ng_ipv6.h" -#include "net/ng_netbase.h" -#include "net/ng_netif.h" -#include "net/ng_udp.h" -#include "net/ng_pkt.h" +#include "net/gnrc/udp.h" +#include "net/gnrc/ipv6.h" +#include "net/gnrc.h" // note to self: anstatt ng_netbase (TODO delete me) +#include "net/gnrc/ipv6/netif.h" +//#include "net/ng_udp.h" +#include "net/gnrc/pkt.h" #include "net/eui64.h" #include "aodvv2/types.h" diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index fbe2f23c54b9..0c935bbc56c2 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -327,15 +327,15 @@ static enum rfc5444_result _cb_rreq_end_callback( /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) - ng_ipv6_addr_t sender_tmp; + ipv6_addr_t sender_tmp; netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); - ng_ipv6_addr_t nxt_hop; - size_t nxt_hop_size = sizeof(ng_ipv6_addr_t); + ipv6_addr_t nxt_hop; + size_t nxt_hop_size = sizeof(ipv6_addr_t); uint32_t next_hop_flags = 0; if(fib_get_next_hop(&aodvv2_if_id, &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, - &sender_tmp.u8[0], sizeof(ng_ipv6_addr_t), 0) != 0) { + &sender_tmp.u8[0], sizeof(ipv6_addr_t), 0) != 0) { DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); return RFC5444_DROP_PACKET; } @@ -350,8 +350,8 @@ static enum rfc5444_result _cb_rreq_end_callback( routingtable_add_entry(tmp_rt_entry); /* add entry to FIB */ - fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), 0, - tmp_rt_entry->nextHopAddr._addr, sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0, + tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); free(tmp_rt_entry); } @@ -366,8 +366,8 @@ static enum rfc5444_result _cb_rreq_end_callback( routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry); /* update the FIB */ - fib_update_entry(rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), rt_entry->nextHopAddr._addr, - sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr, + sizeof(ipv6_addr_t), 0, aodvv2_validity_t); } /* @@ -538,15 +538,15 @@ static enum rfc5444_result _cb_rrep_end_callback( /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) - ng_ipv6_addr_t sender_tmp; + ipv6_addr_t sender_tmp; netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); - ng_ipv6_addr_t nxt_hop; - size_t nxt_hop_size = sizeof(ng_ipv6_addr_t); + ipv6_addr_t nxt_hop; + size_t nxt_hop_size = sizeof(ipv6_addr_t); uint32_t next_hop_flags = 0; if(fib_get_next_hop(&aodvv2_if_id, &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, - &sender_tmp.u8[0], sizeof(ng_ipv6_addr_t), 0) != 0) { + &sender_tmp.u8[0], sizeof(ipv6_addr_t), 0) != 0) { DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); return RFC5444_DROP_PACKET; } @@ -561,8 +561,8 @@ static enum rfc5444_result _cb_rrep_end_callback( routingtable_add_entry(tmp_rt_entry); /* add entry to FIB */ - fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), 0, - tmp_rt_entry->nextHopAddr._addr, sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0, + tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); free(tmp_rt_entry); } @@ -577,8 +577,8 @@ static enum rfc5444_result _cb_rrep_end_callback( routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry); /* update the FIB */ - fib_update_entry(rt_entry->addr._addr, sizeof(ng_ipv6_addr_t), rt_entry->nextHopAddr._addr, - sizeof(ng_ipv6_addr_t), 0, aodvv2_validity_t); + fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr, + sizeof(ipv6_addr_t), 0, aodvv2_validity_t); } /* If HandlingRtr is RREQ_Gen then the RREP satisfies RREQ_Gen's diff --git a/sys/net/gnrc/routing/aodvv2/utils.c b/sys/net/gnrc/routing/aodvv2/utils.c index 4d0d3e2022dc..4379b8e3c2c2 100644 --- a/sys/net/gnrc/routing/aodvv2/utils.c +++ b/sys/net/gnrc/routing/aodvv2/utils.c @@ -228,14 +228,14 @@ static void _reset_entry_if_stale(uint8_t i) } } -void ipv6_addr_t_to_netaddr(ng_ipv6_addr_t *src, struct netaddr *dst) +void ipv6_addr_t_to_netaddr(ipv6_addr_t *src, struct netaddr *dst) { dst->_type = AF_INET6; dst->_prefix_len = AODVV2_RIOT_PREFIXLEN; memcpy(dst->_addr, &src->u8[0], sizeof(dst->_addr)); } -void netaddr_to_ipv6_addr_t(struct netaddr *src, ng_ipv6_addr_t *dst) +void netaddr_to_ipv6_addr_t(struct netaddr *src, ipv6_addr_t *dst) { memcpy(&dst->u8[0], src->_addr, sizeof(uint8_t) * NETADDR_MAX_LENGTH); } From 1054ae6d7d7a9b6c94d36b06cd237ccf765cb572 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 11 Mar 2016 13:37:12 -0800 Subject: [PATCH 17/41] more ng_ -> gnrc_ --- sys/net/gnrc/routing/aodvv2/utils.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/utils.h b/sys/net/gnrc/routing/aodvv2/utils.h index 7d51e9a502ba..bf30afae7ac7 100644 --- a/sys/net/gnrc/routing/aodvv2/utils.h +++ b/sys/net/gnrc/routing/aodvv2/utils.h @@ -22,7 +22,7 @@ #include -#include "net/ng_ipv6.h" +#include "net/gnrc/ipv6.h" #include "common/netaddr.h" #include "aodvv2/types.h" @@ -96,17 +96,17 @@ bool rreqtable_is_redundant(struct aodvv2_packet_data *packet_data); /** * Convert an IP stored as an ipv6_addr_t to a netaddr - * @param src ng_ipv6_addr_t to convert + * @param src ipv6_addr_t to convert * @param dst (empty) netaddr to convert into */ -void ipv6_addr_t_to_netaddr(ng_ipv6_addr_t *src, struct netaddr *dst); +void ipv6_addr_t_to_netaddr(ipv6_addr_t *src, struct netaddr *dst); /** * Convert an IP stored as a netaddr to an ipv6_addr_t * @param src (empty) netaddr to convert into - * @param dst ng_ipv6_addr_t to convert + * @param dst ipv6_addr_t to convert */ -void netaddr_to_ipv6_addr_t(struct netaddr *src, ng_ipv6_addr_t *dst); +void netaddr_to_ipv6_addr_t(struct netaddr *src, ipv6_addr_t *dst); #ifdef __cplusplus } From 85cada54006ac670e45256a4745b355fb906c158 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 11 Mar 2016 13:37:47 -0800 Subject: [PATCH 18/41] adjust to fib changes --- sys/net/gnrc/routing/aodvv2/aodv.c | 6 +++--- sys/net/gnrc/routing/aodvv2/reader.c | 26 ++++++++++++-------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index e987d12f77bf..b2dbab504b62 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -21,7 +21,7 @@ #include "aodv.h" #include "aodvv2/aodvv2.h" #include "aodv_debug.h" -#include "ng_fib.h" +#include "net/fib.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -138,7 +138,7 @@ void *fib_signal_handler_thread(void *arg) ipv6_addr_t dest; struct netaddr na_dest; - int err = fib_register_rp(&aodvv2_prefix.u8[0], aodvv2_address_type_size); + int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], aodvv2_address_type_size); if ( err != 0) { DEBUG("ERROR: cannot register at fib, error code:\n"); exit(1); @@ -148,7 +148,7 @@ void *fib_signal_handler_thread(void *arg) msg_t msg; msg_receive(&msg); - if (msg.type == FIB_MSG_RP_SIGNAL) { + if (msg.type == FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION) { rp_address_msg_t* rp_msg = (rp_address_msg_t*)msg.content.ptr; if (rp_msg->address_size == sizeof(ipv6_addr_t)) { /* We currently only support IPv6*/ diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index 0c935bbc56c2..ba1d027894b0 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -17,13 +17,9 @@ * @author Lotte Steenbrink */ -#ifdef RIOT -#include "net_help.h" -#endif - #include "reader.h" #include "aodv_debug.h" -#include "ng_fib.h" +#include "net/fib.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -350,8 +346,9 @@ static enum rfc5444_result _cb_rreq_end_callback( routingtable_add_entry(tmp_rt_entry); /* add entry to FIB */ - fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0, - tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); + fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, tmp_rt_entry->addr._addr, + sizeof(ipv6_addr_t), 0, tmp_rt_entry->nextHopAddr._addr, + sizeof(ipv6_addr_t), 0, aodvv2_validity_t); free(tmp_rt_entry); } @@ -366,8 +363,8 @@ static enum rfc5444_result _cb_rreq_end_callback( routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry); /* update the FIB */ - fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr, - sizeof(ipv6_addr_t), 0, aodvv2_validity_t); + fib_update_entry(&gnrc_ipv6_fib_table, rt_entry->addr._addr, sizeof(ipv6_addr_t), + rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); } /* @@ -561,8 +558,9 @@ static enum rfc5444_result _cb_rrep_end_callback( routingtable_add_entry(tmp_rt_entry); /* add entry to FIB */ - fib_add_entry(aodvv2_if_id, tmp_rt_entry->addr._addr, sizeof(ipv6_addr_t), 0, - tmp_rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); + fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, tmp_rt_entry->addr._addr, + sizeof(ipv6_addr_t), 0, tmp_rt_entry->nextHopAddr._addr, + sizeof(ipv6_addr_t), 0, aodvv2_validity_t); free(tmp_rt_entry); } @@ -577,8 +575,8 @@ static enum rfc5444_result _cb_rrep_end_callback( routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry); /* update the FIB */ - fib_update_entry(rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr, - sizeof(ipv6_addr_t), 0, aodvv2_validity_t); + fib_update_entry(&gnrc_ipv6_fib_table, rt_entry->addr._addr, sizeof(ipv6_addr_t), + rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); } /* If HandlingRtr is RREQ_Gen then the RREP satisfies RREQ_Gen's @@ -668,7 +666,7 @@ static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_rea } /* remove entry from FIB */ - fib_remove_entry(packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); + fib_remove_entry(&gnrc_ipv6_fib_table, packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); } return RFC5444_OKAY; From 5537359439002d1aa1ad7528d25e45d09ecda50b Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Fri, 11 Mar 2016 14:38:00 -0800 Subject: [PATCH 19/41] cleanup --- sys/net/gnrc/routing/aodvv2/aodv.h | 3 +-- sys/net/gnrc/routing/aodvv2/routingtable.c | 2 ++ sys/net/gnrc/routing/aodvv2/writer.c | 4 ---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.h b/sys/net/gnrc/routing/aodvv2/aodv.h index 6bb299e84155..f2fbd46fb443 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.h +++ b/sys/net/gnrc/routing/aodvv2/aodv.h @@ -23,9 +23,8 @@ #include "kernel.h" #include "net/gnrc/udp.h" #include "net/gnrc/ipv6.h" -#include "net/gnrc.h" // note to self: anstatt ng_netbase (TODO delete me) +#include "net/gnrc.h" #include "net/gnrc/ipv6/netif.h" -//#include "net/ng_udp.h" #include "net/gnrc/pkt.h" #include "net/eui64.h" diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index bf574d2e62d8..fbcecf5b545a 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -20,6 +20,8 @@ #include #include +#include "vtimer.h" + #include "routingtable.h" #include "aodv_debug.h" diff --git a/sys/net/gnrc/routing/aodvv2/writer.c b/sys/net/gnrc/routing/aodvv2/writer.c index 275082425147..c6d67cddf1f0 100644 --- a/sys/net/gnrc/routing/aodvv2/writer.c +++ b/sys/net/gnrc/routing/aodvv2/writer.c @@ -17,10 +17,6 @@ * @author Lotte Steenbrink */ -#ifdef RIOT -#include "net_help.h" -#endif - #include "writer.h" #include "aodv_debug.h" From a3d8c655da4b6853964186b066eaafd0c8950d7c Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 29 Mar 2016 20:12:40 -0700 Subject: [PATCH 20/41] add message queue to fib thread, rename other queues --- sys/net/gnrc/routing/aodvv2/aodv.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index b2dbab504b62..eb2858c92df4 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -28,6 +28,7 @@ #define UDP_BUFFER_SIZE (128) /** with respect to IEEE 802.15.4's MTU */ #define RCV_MSG_Q_SIZE (32) /* TODO: check if smaller values work, too */ +#define FIB_MSG_Q_SIZE (16) /* TODO: check if smaller values work, too */ #define AODVV2_PREFIX {{ 0xbe, 0xe2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} static void _init_addresses(void); @@ -134,16 +135,22 @@ void aodv_set_metric_type(aodvv2_metric_t metric_type) */ void *fib_signal_handler_thread(void *arg) { + // TODO: warum wird der erst gestartet wenn ifconfig aufgerufen wird? (void) arg; + msg_t fib_msgq[FIB_MSG_Q_SIZE]; ipv6_addr_t dest; struct netaddr na_dest; + msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE); + int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], aodvv2_address_type_size); if ( err != 0) { DEBUG("ERROR: cannot register at fib, error code:\n"); exit(1); } + printf("my pid is: %d\n", sched_active_pid); + while (true) { msg_t msg; msg_receive(&msg); @@ -320,8 +327,8 @@ static void *_aodv_sender_thread(void *arg) { (void) arg; - msg_t msgq[RCV_MSG_Q_SIZE]; - msg_init_queue(msgq, RCV_MSG_Q_SIZE); + msg_t snd_msgq[RCV_MSG_Q_SIZE]; + msg_init_queue(snd_msgq, RCV_MSG_Q_SIZE); while (true) { msg_t msg; @@ -365,9 +372,9 @@ static void *_aodv_receiver_thread(void *arg) struct netaddr _sender; msg_t msg, reply; - msg_t msg_q[RCV_MSG_Q_SIZE]; + msg_t rcv_msgq[RCV_MSG_Q_SIZE]; - msg_init_queue(msg_q, RCV_MSG_Q_SIZE); + msg_init_queue(rcv_msgq, RCV_MSG_Q_SIZE); reply.content.value = (uint32_t)(-ENOTSUP); reply.type = GNRC_NETAPI_MSG_TYPE_ACK; From 626036952420ff1a24c01b0974546ad167711ee5 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 29 Mar 2016 22:12:48 -0700 Subject: [PATCH 21/41] some fib-realted renamings --- sys/net/gnrc/routing/aodvv2/aodv.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index eb2858c92df4..b6a7bb8dfaa7 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -141,7 +141,11 @@ void *fib_signal_handler_thread(void *arg) ipv6_addr_t dest; struct netaddr na_dest; - msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE); + if (msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE) !=0) + { + printf("ERROR: Couldn't init message queue for fib_signal_handler_thread\n"); + exit(1); + } int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], aodvv2_address_type_size); if ( err != 0) { @@ -149,19 +153,20 @@ void *fib_signal_handler_thread(void *arg) exit(1); } - printf("my pid is: %d\n", sched_active_pid); + printf("\nmy pid is: %d\n", sched_active_pid); while (true) { - msg_t msg; - msg_receive(&msg); + msg_t fib_msg; + msg_receive(&fib_msg); + printf("received msg: %p\n", fib_msg.content.ptr); - if (msg.type == FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION) { - rp_address_msg_t* rp_msg = (rp_address_msg_t*)msg.content.ptr; + if (fib_msg.type == FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION) { + rp_address_msg_t* rp_msg = (rp_address_msg_t*)fib_msg.content.ptr; if (rp_msg->address_size == sizeof(ipv6_addr_t)) { /* We currently only support IPv6*/ memcpy(&dest, rp_msg->address, rp_msg->address_size); /* Reply to the FIB so that it can stop blocking */ - msg_reply(&msg, &msg); + msg_reply(&fib_msg, &fib_msg); /* perform/initiate a rreq for dst here*/ ipv6_addr_t_to_netaddr(&dest, &na_dest); @@ -191,7 +196,7 @@ void *fib_signal_handler_thread(void *arg) } else { /* Reply to the FIB so that it can stop blocking */ - msg_reply(&msg, &msg); + msg_reply(&fib_msg, &fib_msg); } } } From f80e55cf31bb1a293a13187e4092a4b45cb6c0b6 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 31 Mar 2016 12:53:03 -0700 Subject: [PATCH 22/41] small fixes --- sys/net/gnrc/routing/aodvv2/aodv.c | 2 +- sys/net/gnrc/routing/aodvv2/aodv.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index b6a7bb8dfaa7..834f343fee43 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -143,7 +143,7 @@ void *fib_signal_handler_thread(void *arg) if (msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE) !=0) { - printf("ERROR: Couldn't init message queue for fib_signal_handler_thread\n"); + DEBUG("ERROR: Couldn't init message queue for fib_signal_handler_thread\n"); exit(1); } diff --git a/sys/net/gnrc/routing/aodvv2/aodv.h b/sys/net/gnrc/routing/aodvv2/aodv.h index f2fbd46fb443..63781f75f0f1 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.h +++ b/sys/net/gnrc/routing/aodvv2/aodv.h @@ -20,7 +20,6 @@ #ifndef AODV_H_ #define AODV_H_ -#include "kernel.h" #include "net/gnrc/udp.h" #include "net/gnrc/ipv6.h" #include "net/gnrc.h" From 3da9b40046b48149dfe678e299a5bcedac940980 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 9 Apr 2016 13:21:04 -0700 Subject: [PATCH 23/41] reader: improve comments --- sys/net/gnrc/routing/aodvv2/reader.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index ba1d027894b0..972ba7920a22 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -158,7 +158,8 @@ static struct rfc5444_reader_tlvblock_consumer_entry _rerr_address_consumer_entr }; /** - * This block callback is called for every address + * Check if the header is valid. This block callback is called for every + * message tlv block of a RREQ Message. * * @param cont * @return @@ -181,7 +182,8 @@ static enum rfc5444_result _cb_rreq_blocktlv_messagetlvs_okay(struct rfc5444_rea } /** - * This block callback is called for every address of a RREQ Message. + * Check if all address TLVs are valid. This block callback is called for every + * address of a RREQ Message. * * @param cont * @return @@ -467,7 +469,7 @@ static enum rfc5444_result _cb_rrep_blocktlv_addresstlvs_okay(struct rfc5444_rea } /** - * This callback is called every time the _rreq_consumer finishes reading a + * This callback is called every time the _rrep_consumer finishes reading a * packet. * @param cont * @param dropped indicates wehther the packet has been dropped previously by From ab84a687edf92dfd054dadda823e7ef9710b171f Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 9 Apr 2016 14:15:15 -0700 Subject: [PATCH 24/41] adjust thread prios --- sys/net/gnrc/routing/aodvv2/aodv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index 834f343fee43..77573e90f637 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -112,14 +112,14 @@ void aodv_init(kernel_pid_t interface) aodv_packet_writer_init(_write_packet); /* start listening & enable sending */ - thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN, + thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); AODV_DEBUG("listening on port %d\n", MANET_PORT); sender_thread = thread_create(aodv_snd_stack_buf, sizeof(aodv_snd_stack_buf), - THREAD_PRIORITY_MAIN, THREAD_CREATE_STACKTEST, _aodv_sender_thread, + THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _aodv_sender_thread, NULL, "_aodv_sender_thread"); thread_create(aodv_fib_stack_buf, sizeof(aodv_fib_stack_buf), - THREAD_PRIORITY_MAIN, THREAD_CREATE_STACKTEST, fib_signal_handler_thread, + THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, fib_signal_handler_thread, NULL, "fib_signal_handler_thread"); } From 912029c8ad49013f85796177538214efffbc2cce Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sat, 9 Apr 2016 14:27:30 -0700 Subject: [PATCH 25/41] rm debug output --- sys/net/gnrc/routing/aodvv2/aodv.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index 77573e90f637..b2d4efbc8037 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -153,12 +153,9 @@ void *fib_signal_handler_thread(void *arg) exit(1); } - printf("\nmy pid is: %d\n", sched_active_pid); - while (true) { msg_t fib_msg; msg_receive(&fib_msg); - printf("received msg: %p\n", fib_msg.content.ptr); if (fib_msg.type == FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION) { rp_address_msg_t* rp_msg = (rp_address_msg_t*)fib_msg.content.ptr; From f9ef4f64a9ef660e8582682aa9c30e38880c9234 Mon Sep 17 00:00:00 2001 From: smlng Date: Tue, 28 Jun 2016 21:16:54 +0200 Subject: [PATCH 26/41] aodvv2: update to latest RIOT master - move includes, - replace vtimer with xtimer - add example application --- Makefile.dep | 3 +- examples/gnrc_aodvv2/Makefile | 49 +++++ examples/gnrc_aodvv2/README.md | 142 +++++++++++++++ examples/gnrc_aodvv2/main.c | 65 +++++++ examples/gnrc_aodvv2/udp.c | 168 ++++++++++++++++++ examples/gnrc_networking/Makefile | 4 +- .../aodvv2 => include/net/gnrc}/aodvv2.h | 2 +- .../net/gnrc}/aodvv2/types.h | 0 sys/net/gnrc/routing/aodvv2/aodv.c | 14 +- sys/net/gnrc/routing/aodvv2/aodv.h | 2 +- sys/net/gnrc/routing/aodvv2/constants.h | 2 +- sys/net/gnrc/routing/aodvv2/reader.c | 4 +- sys/net/gnrc/routing/aodvv2/routingtable.c | 5 +- sys/net/gnrc/routing/aodvv2/routingtable.h | 2 +- sys/net/gnrc/routing/aodvv2/seqnum.h | 2 +- sys/net/gnrc/routing/aodvv2/utils.c | 5 +- sys/net/gnrc/routing/aodvv2/utils.h | 2 +- 17 files changed, 446 insertions(+), 25 deletions(-) create mode 100644 examples/gnrc_aodvv2/Makefile create mode 100644 examples/gnrc_aodvv2/README.md create mode 100644 examples/gnrc_aodvv2/main.c create mode 100644 examples/gnrc_aodvv2/udp.c rename sys/{net/include/aodvv2 => include/net/gnrc}/aodvv2.h (97%) rename sys/{net/include => include/net/gnrc}/aodvv2/types.h (100%) diff --git a/Makefile.dep b/Makefile.dep index f1d081c0fbb5..563fc21bf758 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -283,10 +283,11 @@ endif ifneq (,$(filter aodvv2,$(USEMODULE))) USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_conn_udp - USEMODULE += vtimer + USEMODULE += xtimer USEMODULE += oonf_common USEMODULE += oonf_rfc5444 USEMODULE += fib + USEMODULE += timex endif ifneq (,$(filter sixlowpan,$(USEMODULE))) diff --git a/examples/gnrc_aodvv2/Makefile b/examples/gnrc_aodvv2/Makefile new file mode 100644 index 000000000000..5eed5b4ddc54 --- /dev/null +++ b/examples/gnrc_aodvv2/Makefile @@ -0,0 +1,49 @@ +# name of your application +APPLICATION = gnrc_aodvv2 + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. +CFLAGS += -DTEST_SETUP #-DDEVELHELP + +BOARD_INSUFFICIENT_MEMORY := airfy-beacon chronos msb-430 msb-430h nrf51dongle \ + nrf6310 nucleo-f103 nucleo-f334 pca10000 pca10005 spark-core \ + stm32f0discovery telosb weio wsn430-v1_3b wsn430-v1_4 \ + yunjia-nrf51822 z1 nucleo-f072 + +# Include packages that pull up and auto-init the link layer. +# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present +USEMODULE += gnrc_netdev_default +USEMODULE += auto_init_gnrc_netif +# Specify the mandatory networking modules for IPv6 and UDP +USEMODULE += gnrc_ipv6_router_default +USEMODULE += gnrc_udp +# Add a routing protocol +USEMODULE += aodvv2 +#USEMODULE += auto_init_gnrc_rpl +# This application dumps received packets to STDIO using the pktdump module +USEMODULE += gnrc_pktdump +# Additional networking modules that can be dropped if not needed +USEMODULE += gnrc_icmpv6_echo +# Add also the shell, some shell commands +USEMODULE += shell +USEMODULE += shell_commands +USEMODULE += ps +USEMODULE += netstats_l2 +USEMODULE += netstats_ipv6 + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +CFLAGS += -DDEVELHELP + +# Comment this out to join RPL DODAGs even if DIOs do not contain +# DODAG Configuration Options (see the doc for more info) +# CFLAGS += -DGNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/gnrc_aodvv2/README.md b/examples/gnrc_aodvv2/README.md new file mode 100644 index 000000000000..fd32831fea10 --- /dev/null +++ b/examples/gnrc_aodvv2/README.md @@ -0,0 +1,142 @@ +# gnrc_networking example + +This example shows you how to try out the code in two different ways: Either by communicating +between the RIOT machine and its Linux host, or by communicating between two RIOT instances. +Note that the former only works with native, i.e. if you run RIOT on your Linux machine. + +## Connecting RIOT native and the Linux host + +> **Note:** RIOT does not support IPv4, so you need to stick to IPv6 anytime. To +establish a connection between RIOT and the Linux host, you will need `netcat` +(with IPv6 support). Ubuntu 14.04 comes with netcat IPv6 support pre-installed. +On Debian it's available in the package `netcat-openbsd`. Be aware that many +programs require you to add an option such as -6 to tell them to use IPv6, otherwise they +will fail. If you're using a _Raspberry Pi_, run `sudo modprobe ipv6` before trying +this example, because raspbian does not load the IPv6 module automatically. +On some systems (openSUSE for example), the _firewall_ may interfere, and prevent +some packets to arrive at the application (they will however show up in Wireshark, +which can be confusing). So be sure to adjust your firewall rules, or turn it off +(who needs security anyway). + +First, create a tap interface: + + sudo ip tuntap add tap0 mode tap user ${USER} + sudo ip link set tap0 up + +Now you can start the `gnrc_networking` example by invoking `make term`. This should +automatically connect to the `tap0` interface. If this doesn't work for any reason, +run make term with the tap0 interface as the PORT environment variable: + + PORT=tap0 make term + +To verify that there is connectivity between RIOT and Linux, go to the RIOT console and run `ifconfig`: + + > ifconfig + Iface 7 HWaddr: ce:f5:e1:c5:f7:5a + inet6 addr: ff02::1/128 scope: local [multicast] + inet6 addr: fe80::ccf5:e1ff:fec5:f75a/64 scope: local + inet6 addr: ff02::1:ffc5:f75a/128 scope: local [multicast] + +Copy the [link-local address](https://en.wikipedia.org/wiki/Link-local_address) +of the RIOT node (prefixed with `fe80`) and try to ping it **from the Linux node**: + + ping6 fe80::ccf5:e1ff:fec5:f75a%tap0 + +Note that the interface on which to send the ping needs to be appended to the IPv6 +address, `%tap0` in the above example. When talking to the RIOT node, you always want +to send to/receive from the `tap0` interface. + +If the pings succeed you can go on to send UDP packets. To do that, first start a +UDP server on the RIOT node: + + > udp server start 8808 + Success: started UDP server on port 8808 + +Now, on the Linux host, you can run netcat to connect with RIOT's UDP server: + + nc -6uv fe80::ccf5:e1ff:fec5:f75a%tap0 8808 + +The `-6` option is necessary to tell netcat to use IPv6 only, the `-u` option tells +it to use UDP only, and the `-v` option makes it give more verbose output (this one is optional). + +You should now see that UDP messages are received on the RIOT side. Opening a UDP +server on the Linux side is also possible. To do that, write down the IP address +of the host (run on Linux): + + ifconfig tap0 + tap0 Link encap:Ethernet HWaddr ce:f5:e1:c5:f7:59 + inet6 addr: fe80::4049:5fff:fe17:b3ae/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:6 errors:0 dropped:0 overruns:0 frame:0 + TX packets:36 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:488 (488.0 B) TX bytes:3517 (3.5 KB) + +Then open a UDP server on Linux (the `-l` option makes netcat listen for incoming connections): + + nc -6ul 8808 + +Now, on the RIOT side, send a UDP packet using: + + udp send fe80::4049:5fff:fe17:b3ae 8808 testmessage + +You should see `testmessage` appear in netcat. Instead of using netcat, you can of +course write your own software, but you may have to bind the socket to a specific +interface (tap0 in this case). For an example that shows how to do so, see +[here](https://gist.github.com/backenklee/dad5e80b764b3b3d0d3e). + +## Connecting two RIOT instances + +When using native (i.e. when you're trying this on your Linux machine), you first +need to set up two tap devices and a bridge that connects them. This constitutes a +virtual network that the RIOT instances can use to communicate. + + ./../../dist/tools/tapsetup/tapsetup --create 2 + +Then, make sure you've compiled the application by calling `make` and start the +first RIOT instance by invoking `make term`. In the RIOT shell, get to know the +IP address of this node: + + > ifconfig + Iface 7 HWaddr: ce:f5:e1:c5:f7:5a + inet6 addr: ff02::1/128 scope: local [multicast] + inet6 addr: fe80::ccf5:e1ff:fec5:f75a/64 scope: local + inet6 addr: ff02::1:ffc5:f75a/128 scope: local [multicast] + +and start a UDP server. + + > udp server start 8808 + +This node is now ready to receive data on port `8808`. + +In a second terminal, start a second RIOT instance, this time listening on `tap1`: + + PORT=tap1 make term + +In the RIOT shell, you can now send a message to the first RIOT instance: + + > udp send fe80::ccf5:e1ff:fec5:f75 8808 testmessage + +*(Make sure to copy the actual +[link-local address](https://en.wikipedia.org/wiki/Link-local_address) of your first +RIOT instance into the above command)* + +In your first terminal, you should now see output that looks like this. + + > PKTDUMP: data received: + ~~ SNIP 0 - size: 11 byte, type: NETTYPE_UNDEF (0) + 000000 74 65 73 74 6d 65 73 73 61 67 65 + ~~ SNIP 1 - size: 8 byte, type: NETTYPE_UDP (3) + src-port: 8808 dst-port: 8808 + length: 19 cksum: 0x4d95f + ~~ SNIP 2 - size: 40 byte, type: NETTYPE_IPV6 (1) + traffic class: 0x00 (ECN: 0x0, DSCP: 0x00) + flow label: 0x00000 + length: 19 next header: 17 hop limit: 64 + source address: fe80::a08a:84ff:fe68:544f + destination address: fe80::60fc:3cff:fe5e:40df + ~~ SNIP 3 - size: 20 byte, type: NETTYPE_NETIF (-1) + if_pid: 6 rssi: 0 lqi: 0 + src_l2addr: a2:8a:84:68:54:4f + dst_l2addr: 62:fc:3c:5e:40:df + ~~ PKT - 4 snips, total size: 79 byte diff --git a/examples/gnrc_aodvv2/main.c b/examples/gnrc_aodvv2/main.c new file mode 100644 index 000000000000..e743caf907ae --- /dev/null +++ b/examples/gnrc_aodvv2/main.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Example application for demonstrating the RIOT network stack + * + * @author Hauke Petersen + * + * @} + */ + +#include + +#include "shell.h" +#include "msg.h" +#include "net/ipv6/addr.h" +#include "net/gnrc/netif.h" +#include "net/gnrc/ipv6/netif.h" +#include "net/gnrc/aodvv2.h" + +#define MAIN_QUEUE_SIZE (8) +static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; + +extern int udp_cmd(int argc, char **argv); + +static const shell_command_t shell_commands[] = { + { "udp", "send data over UDP and listen on UDP ports", udp_cmd }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + /* we need a message queue for the thread running the shell in order to + * receive potentially fast incoming networking packets */ + msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); + + /* get interface on which aodv is running */ + kernel_pid_t ifs[GNRC_NETIF_NUMOF]; + size_t numof = gnrc_netif_get(ifs); + if(numof <= 0) { + printf("no interface available: dropping packet."); + return -1; + } + /* use the first interface */ + aodv_init(ifs[0]); + + puts("RIOT network stack example application"); + + /* start shell */ + puts("All up, running the shell now"); + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + + /* should be never reached */ + return 0; +} diff --git a/examples/gnrc_aodvv2/udp.c b/examples/gnrc_aodvv2/udp.c new file mode 100644 index 000000000000..9fe7004a6639 --- /dev/null +++ b/examples/gnrc_aodvv2/udp.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Demonstrating the sending and receiving of UDP data + * + * @author Hauke Petersen + * + * @} + */ + +#include +#include + +#include "net/gnrc.h" +#include "net/gnrc/ipv6.h" +#include "net/gnrc/udp.h" +#include "net/gnrc/pktdump.h" +#include "timex.h" +#include "xtimer.h" + +static gnrc_netreg_entry_t server = { NULL, GNRC_NETREG_DEMUX_CTX_ALL, KERNEL_PID_UNDEF }; + + +static void send(char *addr_str, char *port_str, char *data, unsigned int num, + unsigned int delay) +{ + uint16_t port; + ipv6_addr_t addr; + + /* parse destination address */ + if (ipv6_addr_from_str(&addr, addr_str) == NULL) { + puts("Error: unable to parse destination address"); + return; + } + /* parse port */ + port = (uint16_t)atoi(port_str); + if (port == 0) { + puts("Error: unable to parse destination port"); + return; + } + + for (unsigned int i = 0; i < num; i++) { + gnrc_pktsnip_t *payload, *udp, *ip; + /* allocate payload */ + payload = gnrc_pktbuf_add(NULL, data, strlen(data), GNRC_NETTYPE_UNDEF); + if (payload == NULL) { + puts("Error: unable to copy data to packet buffer"); + return; + } + /* allocate UDP header, set source port := destination port */ + udp = gnrc_udp_hdr_build(payload, port, port); + if (udp == NULL) { + puts("Error: unable to allocate UDP header"); + gnrc_pktbuf_release(payload); + return; + } + /* allocate IPv6 header */ + ip = gnrc_ipv6_hdr_build(udp, NULL, &addr); + if (ip == NULL) { + puts("Error: unable to allocate IPv6 header"); + gnrc_pktbuf_release(udp); + return; + } + /* send packet */ + if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, ip)) { + puts("Error: unable to locate UDP thread"); + gnrc_pktbuf_release(ip); + return; + } + printf("Success: send %u byte to [%s]:%u\n", (unsigned)payload->size, + addr_str, port); + xtimer_usleep(delay); + } +} + +static void start_server(char *port_str) +{ + uint16_t port; + + /* check if server is already running */ + if (server.pid != KERNEL_PID_UNDEF) { + printf("Error: server already running on port %" PRIu32 "\n", + server.demux_ctx); + return; + } + /* parse port */ + port = (uint16_t)atoi(port_str); + if (port == 0) { + puts("Error: invalid port specified"); + return; + } + /* start server (which means registering pktdump for the chosen port) */ + server.pid = gnrc_pktdump_pid; + server.demux_ctx = (uint32_t)port; + gnrc_netreg_register(GNRC_NETTYPE_UDP, &server); + printf("Success: started UDP server on port %" PRIu16 "\n", port); +} + +static void stop_server(void) +{ + /* check if server is running at all */ + if (server.pid == KERNEL_PID_UNDEF) { + printf("Error: server was not running\n"); + return; + } + /* stop server */ + gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &server); + server.pid = KERNEL_PID_UNDEF; + puts("Success: stopped UDP server"); +} + +int udp_cmd(int argc, char **argv) +{ + if (argc < 2) { + printf("usage: %s [send|server]\n", argv[0]); + return 1; + } + + if (strcmp(argv[1], "send") == 0) { + uint32_t num = 1; + uint32_t delay = 1000000; + if (argc < 5) { + printf("usage: %s send [ []]\n", + argv[0]); + return 1; + } + if (argc > 5) { + num = (uint32_t)atoi(argv[5]); + } + if (argc > 6) { + delay = (uint32_t)atoi(argv[6]); + } + send(argv[2], argv[3], argv[4], num, delay); + } + else if (strcmp(argv[1], "server") == 0) { + if (argc < 3) { + printf("usage: %s server [start|stop]\n", argv[0]); + return 1; + } + if (strcmp(argv[2], "start") == 0) { + if (argc < 4) { + printf("usage %s server start \n", argv[0]); + return 1; + } + start_server(argv[3]); + } + else if (strcmp(argv[2], "stop") == 0) { + stop_server(); + } + else { + puts("error: invalid command"); + } + } + else { + puts("error: invalid command"); + } + return 0; +} diff --git a/examples/gnrc_networking/Makefile b/examples/gnrc_networking/Makefile index 7412b8ff673f..263d13e26658 100644 --- a/examples/gnrc_networking/Makefile +++ b/examples/gnrc_networking/Makefile @@ -20,8 +20,8 @@ USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_udp # Add a routing protocol -USEMODULE += gnrc_rpl -USEMODULE += auto_init_gnrc_rpl +USEMODULE += aodvv2 +#USEMODULE += auto_init_gnrc_rpl # This application dumps received packets to STDIO using the pktdump module USEMODULE += gnrc_pktdump # Additional networking modules that can be dropped if not needed diff --git a/sys/net/include/aodvv2/aodvv2.h b/sys/include/net/gnrc/aodvv2.h similarity index 97% rename from sys/net/include/aodvv2/aodvv2.h rename to sys/include/net/gnrc/aodvv2.h index 2ebe559dfce2..b52ad7e78bff 100644 --- a/sys/net/include/aodvv2/aodvv2.h +++ b/sys/include/net/gnrc/aodvv2.h @@ -26,7 +26,7 @@ #include "rfc5444/rfc5444_print.h" #include "kernel_types.h" -#include "aodvv2/types.h" +#include "net/gnrc/aodvv2/types.h" #ifdef __cplusplus extern "C" { diff --git a/sys/net/include/aodvv2/types.h b/sys/include/net/gnrc/aodvv2/types.h similarity index 100% rename from sys/net/include/aodvv2/types.h rename to sys/include/net/gnrc/aodvv2/types.h diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index b2d4efbc8037..b9d737945e75 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -19,9 +19,9 @@ */ #include "aodv.h" -#include "aodvv2/aodvv2.h" #include "aodv_debug.h" #include "net/fib.h" +#include "net/gnrc/aodvv2.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -141,12 +141,7 @@ void *fib_signal_handler_thread(void *arg) ipv6_addr_t dest; struct netaddr na_dest; - if (msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE) !=0) - { - DEBUG("ERROR: Couldn't init message queue for fib_signal_handler_thread\n"); - exit(1); - } - + msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE); int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], aodvv2_address_type_size); if ( err != 0) { DEBUG("ERROR: cannot register at fib, error code:\n"); @@ -438,15 +433,14 @@ static void _aodv_send(ipv6_addr_t addr, uint16_t port, void *data, size_t data_ return; } /* allocate UDP header, set payload, set source port := destination port */ - pkt_with_udp = gnrc_udp_hdr_build(payload, (uint8_t*)&port, 2, (uint8_t*)&port, 2); + pkt_with_udp = gnrc_udp_hdr_build(payload, port, port); if (pkt_with_udp == NULL) { DEBUG("Error: unable to allocate UDP header\n"); gnrc_pktbuf_release(payload); return; } /* allocate IPv6 header, set pkt_with_udp as payload */ - pkt_with_ip = gnrc_ipv6_hdr_build(pkt_with_udp, (uint8_t*)&_v6_addr_local, aodvv2_address_type_size, - (uint8_t *)&addr, sizeof(addr)); + pkt_with_ip = gnrc_ipv6_hdr_build(pkt_with_udp, &_v6_addr_local, &addr); if (pkt_with_ip == NULL) { DEBUG("Error: unable to allocate IPv6 header\n"); gnrc_pktbuf_release(pkt_with_udp); diff --git a/sys/net/gnrc/routing/aodvv2/aodv.h b/sys/net/gnrc/routing/aodvv2/aodv.h index 63781f75f0f1..e553e9a3d54e 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.h +++ b/sys/net/gnrc/routing/aodvv2/aodv.h @@ -23,11 +23,11 @@ #include "net/gnrc/udp.h" #include "net/gnrc/ipv6.h" #include "net/gnrc.h" +#include "net/gnrc/aodvv2/types.h" #include "net/gnrc/ipv6/netif.h" #include "net/gnrc/pkt.h" #include "net/eui64.h" -#include "aodvv2/types.h" #include "constants.h" #include "seqnum.h" #include "routingtable.h" diff --git a/sys/net/gnrc/routing/aodvv2/constants.h b/sys/net/gnrc/routing/aodvv2/constants.h index 344b6c04378d..e77968f8f5e4 100644 --- a/sys/net/gnrc/routing/aodvv2/constants.h +++ b/sys/net/gnrc/routing/aodvv2/constants.h @@ -20,7 +20,7 @@ #ifndef AODVV2_CONSTANTS_H_ #define AODVV2_CONSTANTS_H_ -#include "aodvv2/types.h" +#include "net/gnrc/aodvv2/types.h" #include "common/netaddr.h" diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index 972ba7920a22..248667f4d254 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -299,7 +299,7 @@ static enum rfc5444_result _cb_rreq_end_callback( * one more hop. */ packet_data.origNode.metric = _get_route_cost(packet_data.metricType, packet_data.origNode.metric); - vtimer_now(&now); + xtimer_now_timex(&now); packet_data.timestamp = now; /* for every relevant @@ -514,7 +514,7 @@ static enum rfc5444_result _cb_rrep_end_callback( * one more hop. */ packet_data.targNode.metric = _get_route_cost(packet_data.metricType, packet_data.targNode.metric); - vtimer_now(&now); + xtimer_now_timex(&now); packet_data.timestamp = now; /* for every relevant address (RteMsg.Addr) in the RteMsg, HandlingRtr diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index fbcecf5b545a..3fc42210f51b 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -20,7 +20,8 @@ #include #include -#include "vtimer.h" +#include "xtimer.h" +#include "timex.h" #include "routingtable.h" #include "aodv_debug.h" @@ -140,7 +141,7 @@ void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, */ static void _reset_entry_if_stale(uint8_t i) { - vtimer_now(&now); + xtimer_now_timex(&now); timex_t lastUsed, expirationTime; if (timex_cmp(routing_table[i].expirationTime, null_time) == 0) { diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h index c4bd9f5e2b3b..b39bef99e724 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.h +++ b/sys/net/gnrc/routing/aodvv2/routingtable.h @@ -24,7 +24,7 @@ #include "common/netaddr.h" -#include "aodvv2/types.h" +#include "net/gnrc/aodvv2/types.h" #include "constants.h" #include "seqnum.h" diff --git a/sys/net/gnrc/routing/aodvv2/seqnum.h b/sys/net/gnrc/routing/aodvv2/seqnum.h index c47ee224e2f3..d83886214752 100644 --- a/sys/net/gnrc/routing/aodvv2/seqnum.h +++ b/sys/net/gnrc/routing/aodvv2/seqnum.h @@ -22,7 +22,7 @@ #include -#include "aodvv2/types.h" +#include "net/gnrc/aodvv2/types.h" #ifdef __cplusplus extern "C" { diff --git a/sys/net/gnrc/routing/aodvv2/utils.c b/sys/net/gnrc/routing/aodvv2/utils.c index 4379b8e3c2c2..9cf30d896be8 100644 --- a/sys/net/gnrc/routing/aodvv2/utils.c +++ b/sys/net/gnrc/routing/aodvv2/utils.c @@ -18,6 +18,7 @@ */ #include "utils.h" +#include "timex.h" #include "aodv_debug.h" @@ -157,7 +158,7 @@ bool rreqtable_is_redundant(struct aodvv2_packet_data *packet_data) } /* Since we've changed RREQ info, update the timestamp */ - vtimer_now(&now); + xtimer_now_timex(&now); comparable_rreq->timestamp = now; } @@ -214,7 +215,7 @@ static void _add_rreq(struct aodvv2_packet_data *packet_data) */ static void _reset_entry_if_stale(uint8_t i) { - vtimer_now(&now); + xtimer_now_timex(&now); if (timex_cmp(rreq_table[i].timestamp, null_time) == 0) { return; diff --git a/sys/net/gnrc/routing/aodvv2/utils.h b/sys/net/gnrc/routing/aodvv2/utils.h index bf30afae7ac7..3af0832bc4ff 100644 --- a/sys/net/gnrc/routing/aodvv2/utils.h +++ b/sys/net/gnrc/routing/aodvv2/utils.h @@ -25,7 +25,7 @@ #include "net/gnrc/ipv6.h" #include "common/netaddr.h" -#include "aodvv2/types.h" +#include "net/gnrc/aodvv2/types.h" #include "constants.h" #include "seqnum.h" From b08eb6a864cd6900baee425975eb42e9e29bad20 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 30 Jun 2016 16:41:21 -0700 Subject: [PATCH 27/41] Makefile: whitelist native --- examples/gnrc_aodvv2/Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/gnrc_aodvv2/Makefile b/examples/gnrc_aodvv2/Makefile index 5eed5b4ddc54..86293e8be903 100644 --- a/examples/gnrc_aodvv2/Makefile +++ b/examples/gnrc_aodvv2/Makefile @@ -8,10 +8,7 @@ BOARD ?= native RIOTBASE ?= $(CURDIR)/../.. CFLAGS += -DTEST_SETUP #-DDEVELHELP -BOARD_INSUFFICIENT_MEMORY := airfy-beacon chronos msb-430 msb-430h nrf51dongle \ - nrf6310 nucleo-f103 nucleo-f334 pca10000 pca10005 spark-core \ - stm32f0discovery telosb weio wsn430-v1_3b wsn430-v1_4 \ - yunjia-nrf51822 z1 nucleo-f072 +BOARD_WHITELIST := native # Include packages that pull up and auto-init the link layer. # NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present From 2cc2328a15ae0b5b7f321135c64333e386943f79 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 30 Jun 2016 16:43:20 -0700 Subject: [PATCH 28/41] Makefile: rm unnecessary includes --- examples/gnrc_aodvv2/Makefile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/gnrc_aodvv2/Makefile b/examples/gnrc_aodvv2/Makefile index 86293e8be903..1c28fdbdc9b6 100644 --- a/examples/gnrc_aodvv2/Makefile +++ b/examples/gnrc_aodvv2/Makefile @@ -19,11 +19,8 @@ USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_udp # Add a routing protocol USEMODULE += aodvv2 -#USEMODULE += auto_init_gnrc_rpl # This application dumps received packets to STDIO using the pktdump module USEMODULE += gnrc_pktdump -# Additional networking modules that can be dropped if not needed -USEMODULE += gnrc_icmpv6_echo # Add also the shell, some shell commands USEMODULE += shell USEMODULE += shell_commands @@ -36,10 +33,6 @@ USEMODULE += netstats_ipv6 # development process: CFLAGS += -DDEVELHELP -# Comment this out to join RPL DODAGs even if DIOs do not contain -# DODAG Configuration Options (see the doc for more info) -# CFLAGS += -DGNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN - # Change this to 0 show compiler invocation lines by default: QUIET ?= 1 From 4fa036da3f069911f8bd9a6352fbc79cc60379a8 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Thu, 30 Jun 2016 16:44:53 -0700 Subject: [PATCH 29/41] undo changes to gnrc_networking makefile --- examples/gnrc_networking/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gnrc_networking/Makefile b/examples/gnrc_networking/Makefile index 263d13e26658..7412b8ff673f 100644 --- a/examples/gnrc_networking/Makefile +++ b/examples/gnrc_networking/Makefile @@ -20,8 +20,8 @@ USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_udp # Add a routing protocol -USEMODULE += aodvv2 -#USEMODULE += auto_init_gnrc_rpl +USEMODULE += gnrc_rpl +USEMODULE += auto_init_gnrc_rpl # This application dumps received packets to STDIO using the pktdump module USEMODULE += gnrc_pktdump # Additional networking modules that can be dropped if not needed From 99f92e40f5342825ea0228da111294b39592264c Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 19 Jul 2016 03:21:36 -0700 Subject: [PATCH 30/41] rm dead SUPER HACKY FIX code --- sys/net/gnrc/routing/aodvv2/reader.c | 55 ---------------------------- 1 file changed, 55 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index 248667f4d254..840e20ba2ae7 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -311,34 +311,6 @@ static enum rfc5444_result _cb_rreq_end_callback( rt_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType); if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { - /* CAUTION SUPER HACKY FIX FIXME ASAP - problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then - AODVv2 gets super confused when they're not in the routing table and starts a - Route discovery to find them and all hell breaks loose. let's see if we can fix - this (horribly). - - (another fix would be to stop bouncing the RREP back to the sender and asking - the routing table for the next hop (or just send towards TargNode and let the - network stack figure out the rest?)) - TODO evaluate that - */ - - /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) - - ipv6_addr_t sender_tmp; - netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); - - ipv6_addr_t nxt_hop; - size_t nxt_hop_size = sizeof(ipv6_addr_t); - uint32_t next_hop_flags = 0; - if(fib_get_next_hop(&aodvv2_if_id, - &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, - &sender_tmp.u8[0], sizeof(ipv6_addr_t), 0) != 0) { - DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); - return RFC5444_DROP_PACKET; - } - */ - /* HACKY FIX ENDS HERE */ struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) malloc(sizeof(struct aodvv2_routing_entry_t)); @@ -524,33 +496,6 @@ static enum rfc5444_result _cb_rrep_end_callback( rt_entry = routingtable_get_entry(&packet_data.targNode.addr, packet_data.metricType); if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { - /* CAUTION SUPER HACKY FIX FIXME ASAP - problem: sometimes we get broadcasted RREQs from 2 hop neighbors and then - AODVv2 gets super confused when they're not in the routing table and starts a - Route discovery to find them and all hell breaks loose. let's see if we can fix - this (horribly). - - (another fix would be to stop bouncing the RREP back to the sender and asking - the routing table for the next hop (or just send towards TargNode and let the network stack figure out the rest?)) - TODO evaluate that - */ - - /* TODO: proper bidirectionality detection as described in the draft now (v10 or higher) - - ipv6_addr_t sender_tmp; - netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp); - - ipv6_addr_t nxt_hop; - size_t nxt_hop_size = sizeof(ipv6_addr_t); - uint32_t next_hop_flags = 0; - if(fib_get_next_hop(&aodvv2_if_id, - &nxt_hop.u8[0], &nxt_hop_size, &next_hop_flags, - &sender_tmp.u8[0], sizeof(ipv6_addr_t), 0) != 0) { - DEBUG("OH NOES! No bidirectional link to sender. Dropping packet.\n"); - return RFC5444_DROP_PACKET; - } - */ - /* HACKY FIX ENDS HERE */ struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) malloc(sizeof(struct aodvv2_routing_entry_t)); From 1d46e30ab30b040ac486dd3ab0afeb895907df40 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 19 Jul 2016 06:16:12 -0700 Subject: [PATCH 31/41] don't malloc tmp_rt_entry, make routingtable api more convenient to do so instead of first filling a tmp routing_entry_t to then populate the routing table (and manually update existing table entries by calling routingtable_fill_routing_entry_t_rreq() etc on them), add an update function and get rid of the temporary entries altogether. also, rename routing_table[] to routingtable[] in routingtable.c for consistency. --- sys/net/gnrc/routing/aodvv2/reader.c | 44 +++---- sys/net/gnrc/routing/aodvv2/routingtable.c | 132 +++++++++++---------- sys/net/gnrc/routing/aodvv2/routingtable.h | 32 ++++- 3 files changed, 118 insertions(+), 90 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index 840e20ba2ae7..df11fe2b43ec 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -312,19 +312,17 @@ static enum rfc5444_result _cb_rreq_end_callback( if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { - struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) - malloc(sizeof(struct aodvv2_routing_entry_t)); - memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry)); - - routingtable_fill_routing_entry_t_rreq(&packet_data, tmp_rt_entry); - routingtable_add_entry(tmp_rt_entry); + routingtable_add_entry(&packet_data.origNode.addr, + &packet_data.origNode.seqnum, + &packet_data.sender, &packet_data.metricType, + packet_data.origNode.metric, ROUTE_STATE_ACTIVE, + &packet_data.timestamp); /* add entry to FIB */ - fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, tmp_rt_entry->addr._addr, - sizeof(ipv6_addr_t), 0, tmp_rt_entry->nextHopAddr._addr, + fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, + packet_data.origNode.addr._addr, + sizeof(ipv6_addr_t), 0, packet_data.sender._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); - - free(tmp_rt_entry); } else { if (!routingtable_offers_improvement(rt_entry, &packet_data.origNode)) { @@ -334,7 +332,10 @@ static enum rfc5444_result _cb_rreq_end_callback( /* The incoming routing information is better than existing routing * table information and SHOULD be used to improve the route table. */ AODV_DEBUG("\tUpdating Routing Table entry...\n"); - routingtable_fill_routing_entry_t_rreq(&packet_data, rt_entry); + + routingtable_update_entry(rt_entry, &packet_data.origNode.seqnum, + &packet_data.sender, packet_data.origNode.metric, + ROUTE_STATE_ACTIVE, &packet_data.timestamp); /* update the FIB */ fib_update_entry(&gnrc_ipv6_fib_table, rt_entry->addr._addr, sizeof(ipv6_addr_t), @@ -497,19 +498,16 @@ static enum rfc5444_result _cb_rrep_end_callback( if (!rt_entry || (rt_entry->metricType != packet_data.metricType)) { - struct aodvv2_routing_entry_t *tmp_rt_entry = (struct aodvv2_routing_entry_t *) - malloc(sizeof(struct aodvv2_routing_entry_t)); - memset(tmp_rt_entry, 0, sizeof(*tmp_rt_entry)); - - routingtable_fill_routing_entry_t_rrep(&packet_data, tmp_rt_entry); - routingtable_add_entry(tmp_rt_entry); + routingtable_add_entry(&packet_data.targNode.addr, + &packet_data.targNode.seqnum, + &packet_data.sender, &packet_data.metricType, + packet_data.targNode.metric, ROUTE_STATE_ACTIVE, + &packet_data.timestamp); /* add entry to FIB */ - fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, tmp_rt_entry->addr._addr, - sizeof(ipv6_addr_t), 0, tmp_rt_entry->nextHopAddr._addr, + fib_add_entry(&gnrc_ipv6_fib_table, aodvv2_if_id, packet_data.targNode.addr._addr, + sizeof(ipv6_addr_t), 0, packet_data.sender._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); - - free(tmp_rt_entry); } else { if (!routingtable_offers_improvement(rt_entry, &packet_data.targNode)) { @@ -519,8 +517,10 @@ static enum rfc5444_result _cb_rrep_end_callback( /* The incoming routing information is better than existing routing * table information and SHOULD be used to improve the route table. */ AODV_DEBUG("\tUpdating Routing Table entry...\n"); - routingtable_fill_routing_entry_t_rrep(&packet_data, rt_entry); + routingtable_update_entry(rt_entry, &packet_data.targNode.seqnum, + &packet_data.sender, packet_data.targNode.metric, + ROUTE_STATE_ACTIVE, &packet_data.timestamp); /* update the FIB */ fib_update_entry(&gnrc_ipv6_fib_table, rt_entry->addr._addr, sizeof(ipv6_addr_t), rt_entry->nextHopAddr._addr, sizeof(ipv6_addr_t), 0, aodvv2_validity_t); diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index 3fc42210f51b..f771b6bb914f 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -26,6 +26,8 @@ #include "routingtable.h" #include "aodv_debug.h" +#include "common/netaddr.h" + #define ENABLE_DEBUG (0) #include "debug.h" @@ -33,13 +35,14 @@ static void _reset_entry_if_stale(uint8_t i); static void print_json_added_rt_entry(struct aodvv2_routing_entry_t *entry); -static struct aodvv2_routing_entry_t routing_table[AODVV2_MAX_ROUTING_ENTRIES]; +static struct aodvv2_routing_entry_t routingtable[AODVV2_MAX_ROUTING_ENTRIES]; static timex_t null_time, max_seqnum_lifetime, active_interval, max_idletime, validity_t; -timex_t now; #if ENABLE_DEBUG static struct netaddr_str nbuf; #endif +timex_t now; + void routingtable_init(void) { null_time = timex_set(0, 0); @@ -48,7 +51,7 @@ void routingtable_init(void) max_idletime = timex_set(AODVV2_MAX_IDLETIME, 0); validity_t = timex_set(AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME, 0); - memset(&routing_table, 0, sizeof(routing_table)); + memset(&routingtable, 0, sizeof(routingtable)); AODV_DEBUG("routing table initialized.\n"); } @@ -61,18 +64,31 @@ struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t return (&entry->nextHopAddr); } -void routingtable_add_entry(struct aodvv2_routing_entry_t *entry) +void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, + struct netaddr *nextHopAddr, aodvv2_metric_t *metricType, + uint8_t metric, uint8_t state, timex_t *timestamp) { - print_json_added_rt_entry(entry); - /* only add if we don't already know the address */ - if (routingtable_get_entry(&(entry->addr), entry->metricType)) { + if (routingtable_get_entry(addr, *metricType)) { + /* stop compiler from complaining about unused entries + (TODO am I shooting myself in the foot here?)*/ + (void) seqnum; + (void) nextHopAddr; + (void) metric; + (void) state; + (void) timestamp; return; } /*find free spot in RT and place rt_entry there */ for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { - if (routing_table[i].addr._type == AF_UNSPEC) { - memcpy(&routing_table[i], entry, sizeof(struct aodvv2_routing_entry_t)); + if (routingtable[i].addr._type == AF_UNSPEC) { + // TODO: is the memcpy here correct or do I need another & ? + memcpy(&(routingtable[i].addr), addr, sizeof(struct netaddr)); + (routingtable[i].metricType) = *metricType; + routingtable_update_entry(&routingtable[i], seqnum, nextHopAddr, + metric, state, timestamp); + + print_json_added_rt_entry(&routingtable[i]); return; } } @@ -84,26 +100,40 @@ struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { _reset_entry_if_stale(i); - if (!netaddr_cmp(&routing_table[i].addr, addr) - && routing_table[i].metricType == metricType) { + if (!netaddr_cmp(&routingtable[i].addr, addr) + && routingtable[i].metricType == metricType) { DEBUG("[routing] found entry for %s :", netaddr_to_string(&nbuf, addr)); #if ENABLE_DEBUG - print_routingtable_entry(&routing_table[i]); + print_routingtable_entry(&routingtable[i]); #endif - return &routing_table[i]; + return &routingtable[i]; } } return NULL; } +struct aodvv2_routing_entry_t *routingtable_update_entry( + struct aodvv2_routing_entry_t *entry, + aodvv2_seqnum_t *seqnum, struct netaddr *nextHopAddr, + uint8_t metric, uint8_t state, timex_t *timestamp) +{ + entry->seqnum = *seqnum; + memcpy(&entry->nextHopAddr, nextHopAddr, sizeof(struct netaddr)); + memcpy(&entry->lastUsed, timestamp, sizeof(timex_t)); + entry->expirationTime = timex_add(*timestamp, validity_t); + entry->metric = metric; + entry->state = state; + return entry; +} + void routingtable_delete_entry(struct netaddr *addr, aodvv2_metric_t metricType) { for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { _reset_entry_if_stale(i); - if (!netaddr_cmp(&routing_table[i].addr, addr) - && routing_table[i].metricType == metricType) { - memset(&routing_table[i], 0, sizeof(routing_table[i])); + if (!netaddr_cmp(&routingtable[i].addr, addr) + && routingtable[i].metricType == metricType) { + memset(&routingtable[i], 0, sizeof(routingtable[i])); return; } } @@ -118,18 +148,18 @@ void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, for (unsigned i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { _reset_entry_if_stale(i); - if (netaddr_cmp(&routing_table[i].nextHopAddr, hop) == 0) { - if (routing_table[i].state == ROUTE_STATE_ACTIVE && + if (netaddr_cmp(&routingtable[i].nextHopAddr, hop) == 0) { + if (routingtable[i].state == ROUTE_STATE_ACTIVE && *len < AODVV2_MAX_UNREACHABLE_NODES) { /* when the max number of unreachable nodes is reached we're screwed. * the above check is just damage control. */ - unreachable_nodes[*len].addr = routing_table[i].addr; - unreachable_nodes[*len].seqnum = routing_table[i].seqnum; + unreachable_nodes[*len].addr = routingtable[i].addr; + unreachable_nodes[*len].seqnum = routingtable[i].seqnum; (*len)++; - DEBUG("\t[routing] unreachable node found: %s\n", netaddr_to_string(&nbuf, &routing_table[i].nextHopAddr)); + DEBUG("\t[routing] unreachable node found: %s\n", netaddr_to_string(&nbuf, &routingtable[i].nextHopAddr)); } - routing_table[i].state = ROUTE_STATE_INVALID; + routingtable[i].state = ROUTE_STATE_INVALID; DEBUG("\t[routing] number of unreachable nodes: %i\n", *len); } } @@ -144,13 +174,13 @@ static void _reset_entry_if_stale(uint8_t i) xtimer_now_timex(&now); timex_t lastUsed, expirationTime; - if (timex_cmp(routing_table[i].expirationTime, null_time) == 0) { + if (timex_cmp(routingtable[i].expirationTime, null_time) == 0) { return; } - int state = routing_table[i].state; - lastUsed = routing_table[i].lastUsed; - expirationTime = routing_table[i].expirationTime; + int state = routingtable[i].state; + lastUsed = routingtable[i].lastUsed; + expirationTime = routingtable[i].expirationTime; /* an Active route is considered to remain Active as long as it is used at least once * during every ACTIVE_INTERVAL. When a route is no longer Active, it becomes an Idle route. */ @@ -163,9 +193,9 @@ static void _reset_entry_if_stale(uint8_t i) if ((state == ROUTE_STATE_ACTIVE) && (timex_cmp(timex_sub(now, active_interval), lastUsed) == 1)) { DEBUG("\t[routing] route towards %s Idle\n", - netaddr_to_string(&nbuf, &routing_table[i].addr)); - routing_table[i].state = ROUTE_STATE_IDLE; - routing_table[i].lastUsed = now; /* mark the time entry was set to Idle */ + netaddr_to_string(&nbuf, &routingtable[i].addr)); + routingtable[i].state = ROUTE_STATE_IDLE; + routingtable[i].lastUsed = now; /* mark the time entry was set to Idle */ } /* After an Idle route remains Idle for MAX_IDLETIME, it becomes an Invalid route. */ @@ -179,24 +209,24 @@ static void _reset_entry_if_stale(uint8_t i) if ((state == ROUTE_STATE_IDLE) && (timex_cmp(now, expirationTime) > 0)) { DEBUG("\t[routing] route towards %s became Invalid\n", - netaddr_to_string(&nbuf, &routing_table[i].addr)); - routing_table[i].state = ROUTE_STATE_INVALID; - routing_table[i].lastUsed = now; /* mark the time entry was set to Invalid */ + netaddr_to_string(&nbuf, &routingtable[i].addr)); + routingtable[i].state = ROUTE_STATE_INVALID; + routingtable[i].lastUsed = now; /* mark the time entry was set to Invalid */ } /* If (Current_Time - Route.LastUsed) > (ACTIVE_INTERVAL + MAX_IDLETIME), * and if (Route.Timed == FALSE), set Route.State := Invalid. */ if ((timex_cmp(timex_sub(now, lastUsed), timex_add(active_interval, max_idletime)) > 0) && (state != ROUTE_STATE_TIMED)) { - routing_table[i].state = ROUTE_STATE_INVALID; + routingtable[i].state = ROUTE_STATE_INVALID; } /* After that time, old sequence number information is considered no longer * valid and the Invalid route MUST BE expunged */ if (timex_cmp(timex_sub(now, lastUsed), max_seqnum_lifetime) >= 0) { DEBUG("\t[routing] Expunged routing table entry for %s at %i\n", - netaddr_to_string(&nbuf, &routing_table[i].addr), i); - memset(&routing_table[i], 0, sizeof(routing_table[i])); + netaddr_to_string(&nbuf, &routingtable[i].addr), i); + memset(&routingtable[i], 0, sizeof(routingtable[i])); } } @@ -218,32 +248,6 @@ bool routingtable_offers_improvement(struct aodvv2_routing_entry_t *rt_entry, return false; } -void routingtable_fill_routing_entry_t_rreq(struct aodvv2_packet_data *packet_data, - struct aodvv2_routing_entry_t *rt_entry) -{ - rt_entry->addr = packet_data->origNode.addr; - rt_entry->seqnum = packet_data->origNode.seqnum; - rt_entry->nextHopAddr = packet_data->sender; - rt_entry->lastUsed = packet_data->timestamp; - rt_entry->expirationTime = timex_add(packet_data->timestamp, validity_t); - rt_entry->metricType = packet_data->metricType; - rt_entry->metric = packet_data->origNode.metric; - rt_entry->state = ROUTE_STATE_ACTIVE; -} - -void routingtable_fill_routing_entry_t_rrep(struct aodvv2_packet_data *packet_data, - struct aodvv2_routing_entry_t *rt_entry) -{ - rt_entry->addr = packet_data->targNode.addr; - rt_entry->seqnum = packet_data->targNode.seqnum; - rt_entry->nextHopAddr = packet_data->sender; - rt_entry->lastUsed = packet_data->timestamp; - rt_entry->expirationTime = timex_add(packet_data->timestamp, validity_t); - rt_entry->metricType = packet_data->metricType; - rt_entry->metric = packet_data->targNode.metric; - rt_entry->state = ROUTE_STATE_ACTIVE; -} - #if TEST_SETUP /* Write JSON representation of rt_entry to json_str */ static void routingtable_entry_to_json(struct aodvv2_routing_entry_t *rt_entry, char* json_str) @@ -275,9 +279,9 @@ void print_routingtable(void) printf("===== BEGIN ROUTING TABLE ===================\n"); for (int i = 0; i < AODVV2_MAX_ROUTING_ENTRIES; i++) { /* route has been used before => non-empty entry */ - if (routing_table[i].lastUsed.seconds - || routing_table[i].lastUsed.microseconds) { - print_routingtable_entry(&routing_table[i]); + if (routingtable[i].lastUsed.seconds + || routingtable[i].lastUsed.microseconds) { + print_routingtable_entry(&routingtable[i]); } } printf("===== END ROUTING TABLE =====================\n"); diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h index b39bef99e724..b358cbec4130 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.h +++ b/sys/net/gnrc/routing/aodvv2/routingtable.h @@ -80,21 +80,45 @@ struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t * @brief Add new entry to routing table, if there is no other entry * to the same destination. * - * @param[in] entry The routing table entry to add + * @param[in] addr The destination address of the new route + * @param[in] seqnum The sequence number associated with the route towrds addr + * @param[in] nextHopAddr The next hop towards addr + * @param[in] metricType The metric type of the route towards addr + * @param[in] metric The metric value of the route + * @param[in] state The state of the route + * @param[in] timestamp The time at wich the route info was received */ -void routingtable_add_entry(struct aodvv2_routing_entry_t *entry); +void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, + struct netaddr *nextHopAddr, aodvv2_metric_t *metricType, + uint8_t metric, uint8_t state, timex_t *timestamp); /** * @brief Retrieve pointer to a routing table entry. - * To edit, simply follow the pointer. * Returns NULL if addr is not in routing table. * - * @param[in] addr The address towards which the route should point + * @param[in] addr The destination address of the desired route * @param[in] metricType Metric Type of the desired route * @return Routing table entry if it exists, NULL otherwise */ struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, aodvv2_metric_t metricType); +/** + * @brief Edit routing table entry @param entry. + * Returns NULL if addr is not in routing table. + * + * @param[in] entry The routing table entry to be edited + * @param[in] seqnum The (new) sequence number + * @param[in] nextHopAddr The (new) next hop towards addr + * @param[in] metric The (new) metric value + * @param[in] state The (new) route state + * @param[in] timestamp The time at wich the new route info was received + * @return Routing table entry if it exists, NULL otherwise + */ +struct aodvv2_routing_entry_t *routingtable_update_entry( + struct aodvv2_routing_entry_t *entry, + aodvv2_seqnum_t *seqnum, struct netaddr *nextHopAddr, + uint8_t metric, uint8_t state, timex_t *timestamp); + /** * @brief Delete routing table entry towards addr with metric type MetricType, * if it exists. From d99d49c8193cdda2d4508122794a24da941dbea8 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 19 Jul 2016 08:09:13 -0700 Subject: [PATCH 32/41] example app: update copyright info --- examples/gnrc_aodvv2/main.c | 4 ++-- examples/gnrc_aodvv2/udp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/gnrc_aodvv2/main.c b/examples/gnrc_aodvv2/main.c index e743caf907ae..9632581786d4 100644 --- a/examples/gnrc_aodvv2/main.c +++ b/examples/gnrc_aodvv2/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Freie Universität Berlin + * Copyright (C) 2016 HAW Hamburg * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -13,7 +13,7 @@ * @file * @brief Example application for demonstrating the RIOT network stack * - * @author Hauke Petersen + * @author Sebastian Meiling * * @} */ diff --git a/examples/gnrc_aodvv2/udp.c b/examples/gnrc_aodvv2/udp.c index 9fe7004a6639..5952b27cda82 100644 --- a/examples/gnrc_aodvv2/udp.c +++ b/examples/gnrc_aodvv2/udp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 Freie Universität Berlin + * Copyright (C) 2016 HAW Hamburg * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -13,7 +13,7 @@ * @file * @brief Demonstrating the sending and receiving of UDP data * - * @author Hauke Petersen + * @author Sebastian Meiling * * @} */ From 625f97d3d19435a4c8d4a4eb24645c8c448090ff Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 19 Jul 2016 08:22:54 -0700 Subject: [PATCH 33/41] add test folder --- tests/gnrc_aodvv2/Makefile | 13 +++++++++++ tests/gnrc_aodvv2/main.c | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/gnrc_aodvv2/Makefile create mode 100644 tests/gnrc_aodvv2/main.c diff --git a/tests/gnrc_aodvv2/Makefile b/tests/gnrc_aodvv2/Makefile new file mode 100644 index 000000000000..5a03575825be --- /dev/null +++ b/tests/gnrc_aodvv2/Makefile @@ -0,0 +1,13 @@ +APPLICATION = gnrc_aodvv2 +include ../Makefile.tests_common + +# TODO: these includes shouldn't be necessary, should they... +USEMODULE += gnrc_netdev_default +USEMODULE += auto_init_gnrc_netif + +USEMODULE += gnrc_ipv6_router_default +USEMODULE += gnrc_udp + +USEMODULE += aodvv2 + +include $(RIOTBASE)/Makefile.include diff --git a/tests/gnrc_aodvv2/main.c b/tests/gnrc_aodvv2/main.c new file mode 100644 index 000000000000..fd4cb49cc4d6 --- /dev/null +++ b/tests/gnrc_aodvv2/main.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 Lotte Steenbrink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test AODVv2 functionalities + * + * @author Lotte Steenbrink + * + * @} + */ + +#include "net/gnrc/aodvv2.h" +#include "net/ipv6/addr.h" + +int main(void) +{ + aodv_init(0); + + printf("Start.\r\n"); + + // TODO add tests :D + + printf("Done.\r\n"); + return 0; +} From 544b266c0c2f9a27f735a5b7de971b4f529652d2 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 16 Aug 2016 11:41:30 -0700 Subject: [PATCH 34/41] add unit tests (first steps) --- .../._tests-gnrc_aodvv2_tables.c | Bin 0 -> 4096 bytes tests/unittests/tests-gnrc_aodvv2/Makefile | 3 + .../tests-gnrc_aodvv2/Makefile.include | 9 +++ .../tests-gnrc_aodvv2/tests-gnrc_aodvv2.c | 17 ++++++ .../tests-gnrc_aodvv2/tests-gnrc_aodvv2.h | 51 ++++++++++++++++ .../tests-gnrc_aodvv2_seqnum.c | 56 ++++++++++++++++++ .../tests-gnrc_aodvv2_tables.c | 35 +++++++++++ 7 files changed, 171 insertions(+) create mode 100644 tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c create mode 100644 tests/unittests/tests-gnrc_aodvv2/Makefile create mode 100644 tests/unittests/tests-gnrc_aodvv2/Makefile.include create mode 100644 tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c create mode 100644 tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h create mode 100644 tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_seqnum.c create mode 100644 tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c diff --git a/tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c b/tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c new file mode 100644 index 0000000000000000000000000000000000000000..5d5f95f19e92ca4ba7bc89ba005b6248000655fa GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vVqmC` zhUj3ZAfS9ydNc$^Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1gH`Mj6hRB7!2e> zGBS%5ic*X7ON)|I71HvHvK2D(N>cMmGV}8ib8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9 L?iCpZx&QwGah4ol literal 0 HcmV?d00001 diff --git a/tests/unittests/tests-gnrc_aodvv2/Makefile b/tests/unittests/tests-gnrc_aodvv2/Makefile new file mode 100644 index 000000000000..63d1a375416b --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/Makefile @@ -0,0 +1,3 @@ +INCLUDES += -I$(RIOTBASE)/sys/net/gnrc/routing/aodvv2/ + +include $(RIOTBASE)/Makefile.base \ No newline at end of file diff --git a/tests/unittests/tests-gnrc_aodvv2/Makefile.include b/tests/unittests/tests-gnrc_aodvv2/Makefile.include new file mode 100644 index 000000000000..408fdaaf330e --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/Makefile.include @@ -0,0 +1,9 @@ +# TODO: these includes shouldn't be necessary, should they... +#USEMODULE += gnrc_netdev_default +#USEMODULE += auto_init_gnrc_netif +# Specify the mandatory networking modules for IPv6 and UDP +#USEMODULE += gnrc_ipv6_router_default +#USEMODULE += gnrc_udp + + +USEMODULE += aodvv2 diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c new file mode 100644 index 000000000000..5daf370768c4 --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2016 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include "tests-gnrc_aodvv2.h" + +void tests_gnrc_aodvv2(void) +{ + TESTS_RUN(tests_gnrc_aodvv2_seqnum_tests()); + TESTS_RUN(tests_gnrc_aodvv2_table_tests()); +} + +/** @} */ \ No newline at end of file diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h new file mode 100644 index 000000000000..8aba4cd41c02 --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup unittests + * @{ + * + * @file tests-gnrc_aodvv2.h + * @brief Unittests for the ``aodvv2`` module + * + * @author Lotte Steenbrink + */ +#ifndef TESTS_GNRC_AODVV2_H_ +#define TESTS_GNRC_AODVV2_H_ + +#include "embUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The entry point of this test suite. + */ +void tests_gnrc_aodvv2(void); + +/** + * @brief Generates tests for aodvv2/seqnum.h + * + * @return embUnit tests if successful, NULL if not. + */ +Test *tests_gnrc_aodvv2_seqnum_tests(void); + +/** + * @brief Generates tests for aodvv2/routingtable.h and aodvv2/utils.h + * + * @return embUnit tests if successful, NULL if not. + */ +Test *tests_gnrc_aodvv2_table_tests(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TESTS_GNRC_AODVV2_H_ */ +/** @} */ diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_seqnum.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_seqnum.c new file mode 100644 index 000000000000..3d92758989aa --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_seqnum.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include "embUnit.h" + +#include "seqnum.h" + +#include "tests-gnrc_aodvv2.h" + +static void test_seqnum_get(void) +{ + aodvv2_seqnum_t seqnum; + + seqnum = seqnum_get(); + TEST_ASSERT_EQUAL_INT(seqnum, 1); + + /* silence compiler */ + (void) seqnum; +} + +/* Check if seqnum correctly wraps around from 65535 to 1*/ +static void test_seqnum_wraparound(void) +{ + int cmp_result; + aodvv2_seqnum_t seqnum; + + for (int i = 0; i < 65535; ++i){ + seqnum_inc(); + } + + seqnum = seqnum_get(); + cmp_result = seqnum_cmp(seqnum, (aodvv2_seqnum_t) 1); + TEST_ASSERT_EQUAL_INT(cmp_result, 0); +} + +static void setUp(void) +{ + seqnum_init(); +} + +Test *tests_gnrc_aodvv2_seqnum_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_seqnum_get), + new_TestFixture(test_seqnum_wraparound), + }; + + EMB_UNIT_TESTCALLER(gnrc_aodvv2_tests, setUp, NULL, fixtures); + + return (Test *)&gnrc_aodvv2_tests; +} \ No newline at end of file diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c new file mode 100644 index 000000000000..d72088a5ff3a --- /dev/null +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Lotte Steenbrink + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include "embUnit.h" + +#include "routingtable.h" + +#include "tests-gnrc_aodvv2.h" + +static void test_table_test(void) +{ + printf("xoxo"); +} + +static void setUp(void) +{ + routingtable_init(); +} + +Test *tests_gnrc_aodvv2_table_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_table_test), + }; + + EMB_UNIT_TESTCALLER(gnrc_aodvv2_tests, setUp, NULL, fixtures); + + return (Test *)&gnrc_aodvv2_tests; +} \ No newline at end of file From 30ffa709926cb54b6f663f802551a82f49462947 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 16 Aug 2016 13:10:30 -0700 Subject: [PATCH 35/41] routingtable.h: rm outdated functions --- sys/net/gnrc/routing/aodvv2/routingtable.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h index b358cbec4130..0bcc95421ad8 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.h +++ b/sys/net/gnrc/routing/aodvv2/routingtable.h @@ -156,24 +156,6 @@ void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, bool routingtable_offers_improvement(struct aodvv2_routing_entry_t *rt_entry, struct node_data *node_data); -/** - * Fills a routing table entry with the data of a RREQ. - * @param packet_data the RREQ's data - * @param rt_entry the routing table entry to fill - * @param link_cost the link cost for this RREQ - */ -void routingtable_fill_routing_entry_t_rreq(struct aodvv2_packet_data *packet_data, - struct aodvv2_routing_entry_t *rt_entry); - -/** - * Fills a routing table entry with the data of a RREP. - * @param packet_data the RREP's data - * @param rt_entry the routing table entry to fill - * @param link_cost the link cost for this RREP - */ -void routingtable_fill_routing_entry_t_rrep(struct aodvv2_packet_data *packet_data, - struct aodvv2_routing_entry_t *rt_entry); - void print_routingtable(void); void print_routingtable_entry(struct aodvv2_routing_entry_t *rt_entry); From 8b839db8fcd09e5190de8a8b181e031050783542 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 30 Aug 2016 14:24:32 -0700 Subject: [PATCH 36/41] routingtable: small editorial fixes, unify api --- sys/net/gnrc/routing/aodvv2/reader.c | 4 ++-- sys/net/gnrc/routing/aodvv2/routingtable.c | 6 ++--- sys/net/gnrc/routing/aodvv2/routingtable.h | 26 ++++++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index df11fe2b43ec..bdbd6df4d57c 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -314,7 +314,7 @@ static enum rfc5444_result _cb_rreq_end_callback( routingtable_add_entry(&packet_data.origNode.addr, &packet_data.origNode.seqnum, - &packet_data.sender, &packet_data.metricType, + &packet_data.sender, packet_data.metricType, packet_data.origNode.metric, ROUTE_STATE_ACTIVE, &packet_data.timestamp); @@ -500,7 +500,7 @@ static enum rfc5444_result _cb_rrep_end_callback( routingtable_add_entry(&packet_data.targNode.addr, &packet_data.targNode.seqnum, - &packet_data.sender, &packet_data.metricType, + &packet_data.sender, packet_data.metricType, packet_data.targNode.metric, ROUTE_STATE_ACTIVE, &packet_data.timestamp); diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index f771b6bb914f..7fe0f8b194be 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -65,11 +65,11 @@ struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t } void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, - struct netaddr *nextHopAddr, aodvv2_metric_t *metricType, + struct netaddr *nextHopAddr, aodvv2_metric_t metricType, uint8_t metric, uint8_t state, timex_t *timestamp) { /* only add if we don't already know the address */ - if (routingtable_get_entry(addr, *metricType)) { + if (routingtable_get_entry(addr, metricType)) { /* stop compiler from complaining about unused entries (TODO am I shooting myself in the foot here?)*/ (void) seqnum; @@ -84,7 +84,7 @@ void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, if (routingtable[i].addr._type == AF_UNSPEC) { // TODO: is the memcpy here correct or do I need another & ? memcpy(&(routingtable[i].addr), addr, sizeof(struct netaddr)); - (routingtable[i].metricType) = *metricType; + (routingtable[i].metricType) = metricType; routingtable_update_entry(&routingtable[i], seqnum, nextHopAddr, metric, state, timestamp); diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h index 0bcc95421ad8..9e0f4a5c7ce4 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.h +++ b/sys/net/gnrc/routing/aodvv2/routingtable.h @@ -67,21 +67,22 @@ struct aodvv2_routing_entry_t void routingtable_init(void); /** - * @brief Get next hop towards dest. - * Returns NULL if dest is not in routing table. + * @brief Get next hop towards @param dest. + * Returns NULL if @param dest is not in the routing table. * * @param[in] dest Destination of the packet * @param[in] metricType Metric Type of the desired route * @return next hop towards dest if it exists, NULL otherwise */ -struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t metricType); +struct netaddr *routingtable_get_next_hop(struct netaddr *dest, + aodvv2_metric_t metricType); /** * @brief Add new entry to routing table, if there is no other entry * to the same destination. * * @param[in] addr The destination address of the new route - * @param[in] seqnum The sequence number associated with the route towrds addr + * @param[in] seqnum The sequence number associated with the route towards addr * @param[in] nextHopAddr The next hop towards addr * @param[in] metricType The metric type of the route towards addr * @param[in] metric The metric value of the route @@ -89,18 +90,19 @@ struct netaddr *routingtable_get_next_hop(struct netaddr *dest, aodvv2_metric_t * @param[in] timestamp The time at wich the route info was received */ void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, - struct netaddr *nextHopAddr, aodvv2_metric_t *metricType, + struct netaddr *nextHopAddr, aodvv2_metric_t metricType, uint8_t metric, uint8_t state, timex_t *timestamp); /** * @brief Retrieve pointer to a routing table entry. - * Returns NULL if addr is not in routing table. + * Returns NULL if @param addr is not in routing table. * * @param[in] addr The destination address of the desired route * @param[in] metricType Metric Type of the desired route * @return Routing table entry if it exists, NULL otherwise */ -struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, aodvv2_metric_t metricType); +struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, + aodvv2_metric_t metricType); /** * @brief Edit routing table entry @param entry. @@ -120,8 +122,8 @@ struct aodvv2_routing_entry_t *routingtable_update_entry( uint8_t metric, uint8_t state, timex_t *timestamp); /** - * @brief Delete routing table entry towards addr with metric type MetricType, - * if it exists. + * @brief Delete routing table entry towards @param addr with metric type + * MetricType, if it exists. * * @param[in] addr The address towards which the route should point * @param[in] metricType Metric Type of the desired route @@ -130,11 +132,11 @@ void routingtable_delete_entry(struct netaddr *addr, aodvv2_metric_t metricType) /** * Find all routing table entries that use hop as their nextHopAddress, mark them - * as broken, write the active one into unreachable_nodes[] and increment len - * accordingly. (Sorry about the Name.) + * as broken, write the active one into unreachable_nodes[] and increment + * @param len accordingly. (Sorry about the Name.) * * @param hop Address of the newly unreachable next hop - * @param unreachable_nodes[] array of newlu unreachable nodes to be filled. + * @param unreachable_nodes[] array of newly unreachable nodes to be filled. * should be empty. * @param len size_t* which will contain the length of * unreachable_nodes[] after execution From d88edda676393607bf63d20d643d8e87827888c5 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 27 Sep 2016 12:23:08 -0700 Subject: [PATCH 37/41] small editorial fixes, finish basic routing table tests --- sys/net/gnrc/routing/aodvv2/reader.c | 3 + sys/net/gnrc/routing/aodvv2/routingtable.c | 2 + sys/net/gnrc/routing/aodvv2/routingtable.h | 4 +- .../tests-gnrc_aodvv2_tables.c | 203 +++++++++++++++++- 4 files changed, 207 insertions(+), 5 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index bdbd6df4d57c..9dc521b7e985 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -616,6 +616,9 @@ static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_rea fib_remove_entry(&gnrc_ipv6_fib_table, packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); } + /* TODO: run routingtable_break_and_get_all_hopping_over() in addr, remove + from fib also and include in RERR! */ + return RFC5444_OKAY; } diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index 7fe0f8b194be..eee11790c7a4 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -157,8 +157,10 @@ void routingtable_break_and_get_all_hopping_over(struct netaddr *hop, unreachable_nodes[*len].seqnum = routingtable[i].seqnum; (*len)++; + DEBUG("\t[routing] unreachable node found: %s\n", netaddr_to_string(&nbuf, &routingtable[i].nextHopAddr)); } + routingtable[i].state = ROUTE_STATE_INVALID; DEBUG("\t[routing] number of unreachable nodes: %i\n", *len); } diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.h b/sys/net/gnrc/routing/aodvv2/routingtable.h index 9e0f4a5c7ce4..078fee7cb70b 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.h +++ b/sys/net/gnrc/routing/aodvv2/routingtable.h @@ -87,7 +87,7 @@ struct netaddr *routingtable_get_next_hop(struct netaddr *dest, * @param[in] metricType The metric type of the route towards addr * @param[in] metric The metric value of the route * @param[in] state The state of the route - * @param[in] timestamp The time at wich the route info was received + * @param[in] timestamp The time at which the route info was received */ void routingtable_add_entry(struct netaddr *addr, aodvv2_seqnum_t *seqnum, struct netaddr *nextHopAddr, aodvv2_metric_t metricType, @@ -113,7 +113,7 @@ struct aodvv2_routing_entry_t *routingtable_get_entry(struct netaddr *addr, * @param[in] nextHopAddr The (new) next hop towards addr * @param[in] metric The (new) metric value * @param[in] state The (new) route state - * @param[in] timestamp The time at wich the new route info was received + * @param[in] timestamp The time at which the new route info was received * @return Routing table entry if it exists, NULL otherwise */ struct aodvv2_routing_entry_t *routingtable_update_entry( diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c index d72088a5ff3a..e2dd5bfb7bff 100644 --- a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c @@ -9,24 +9,221 @@ #include #include "embUnit.h" +#include "xtimer.h" + #include "routingtable.h" #include "tests-gnrc_aodvv2.h" -static void test_table_test(void) +/* test data */ +struct netaddr addr_1, addr_2; +timex_t ts; + +aodvv2_seqnum_t test_seqnum_1 = 1; +aodvv2_seqnum_t test_seqnum_2 = 2; +uint8_t test_metric_1 = 3; +uint8_t test_metric_2 = 4; + +/* test basic routingtable add & get functions */ +static void test_routingtable_add_get(void) +{ + struct aodvv2_routing_entry_t* entry; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(entry != NULL); +} + +/* test if 2 entries are added correctly */ +static void test_routingtable_add_2(void) +{ + struct aodvv2_routing_entry_t* entry_1; + struct aodvv2_routing_entry_t* entry_2; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + routingtable_add_entry(&addr_2, &test_seqnum_2, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, + ROUTE_STATE_ACTIVE, &ts); + + entry_1 = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + entry_2 = routingtable_get_entry(&addr_2, AODVV2_DEFAULT_METRIC_TYPE); + + TEST_ASSERT(0 == netaddr_cmp(&entry_1->addr, &addr_1)); + TEST_ASSERT(entry_1->seqnum == test_seqnum_1); + TEST_ASSERT(0 == netaddr_cmp(&entry_1->nextHopAddr, &addr_2)); + TEST_ASSERT(entry_1->metricType == AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(entry_1->metric == test_metric_1); + TEST_ASSERT(entry_1->state == ROUTE_STATE_IDLE); + + TEST_ASSERT(0 == netaddr_cmp(&entry_2->addr, &addr_2)); + TEST_ASSERT(entry_2->seqnum == test_seqnum_2); + TEST_ASSERT(0 == netaddr_cmp(&entry_2->nextHopAddr, &addr_2)); + TEST_ASSERT(entry_2->metricType == AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(entry_2->metric == test_metric_2); + TEST_ASSERT(entry_2->state == ROUTE_STATE_ACTIVE); +} + +static void test_routingtable_get_next_hop(void) { - printf("xoxo"); + struct netaddr* next_hop; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + + next_hop = routingtable_get_next_hop(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(0 == netaddr_cmp(next_hop, &addr_2)); +} + +static void test_routingtable_update_entry(void) +{ + struct aodvv2_routing_entry_t* entry; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + + entry = routingtable_update_entry(entry, &test_seqnum_2, &addr_1, test_metric_2, + ROUTE_STATE_ACTIVE, &ts); + + TEST_ASSERT(entry->seqnum == test_seqnum_2); + TEST_ASSERT(0 == netaddr_cmp(&entry->nextHopAddr, &addr_1)); + TEST_ASSERT(entry->metric == test_metric_2); + TEST_ASSERT(entry->state == ROUTE_STATE_ACTIVE); } +static void test_routingtable_delete_entry(void) +{ + struct aodvv2_routing_entry_t* entry; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + + routingtable_delete_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(entry == NULL); +} + +static void test_routingtable_break_and_get_all_hopping_over(void) +{ + struct unreachable_node unreachable_nodes[2]; + size_t len; + struct aodvv2_routing_entry_t* entry_1; + struct aodvv2_routing_entry_t* entry_2; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + routingtable_add_entry(&addr_2, &test_seqnum_2, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, + ROUTE_STATE_ACTIVE, &ts); + + routingtable_break_and_get_all_hopping_over(&addr_2, unreachable_nodes, &len); + + entry_1 = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + entry_2 = routingtable_get_entry(&addr_2, AODVV2_DEFAULT_METRIC_TYPE); + + TEST_ASSERT(len == 1); + + /* The information from entry_1 shouldn't be in unreachable_nodes[], because + routes with state ROUTE_STATE_IDLE should not be reported in a RERR (unless + ENABLE_IDLE_IN_RERR is configured, which it isn't.) */ + TEST_ASSERT(entry_1->state == ROUTE_STATE_INVALID); + + TEST_ASSERT(0 == netaddr_cmp(&(unreachable_nodes[0].addr), &addr_2)); + TEST_ASSERT(unreachable_nodes[0].seqnum == test_seqnum_2); + TEST_ASSERT(entry_2->state == ROUTE_STATE_INVALID); +} + +static void test_routingtable_offers_improvement__seqnum(void) +{ + struct aodvv2_routing_entry_t* entry; + struct node_data new_data = + { + .addr = addr_1, + .metric = test_metric_1, + .seqnum = test_seqnum_2, + }; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == true); +} + +static void test_routingtable_offers_improvement__metric(void) +{ + struct aodvv2_routing_entry_t* entry; + struct node_data new_data = + { + .addr = addr_1, + .metric = test_metric_1, + .seqnum = test_seqnum_1, + }; + + routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, + ROUTE_STATE_IDLE, &ts); + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + + TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == true); +} + +static void test_routingtable_offers_improvement__loopFree(void) +{ + struct aodvv2_routing_entry_t* entry; + struct node_data new_data = + { + .addr = addr_1, + .metric = test_metric_1, + .seqnum = test_seqnum_1, + }; + + routingtable_add_entry(&addr_1, &test_seqnum_2, &addr_2, + AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, + ROUTE_STATE_IDLE, &ts); + + entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); + TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == false); +} + + static void setUp(void) { + xtimer_now_timex(&ts); + + /* init test data */ + int foo = netaddr_from_string(&addr_1, "::23"); + int bar = netaddr_from_string(&addr_2, "::42"); + (void) foo; /* silence compiler*/ + (void) bar; /* silence compiler*/ + + /* init routing table */ routingtable_init(); } Test *tests_gnrc_aodvv2_table_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_table_test), + new_TestFixture(test_routingtable_add_get), + new_TestFixture(test_routingtable_add_2), + new_TestFixture(test_routingtable_get_next_hop), + new_TestFixture(test_routingtable_update_entry), + new_TestFixture(test_routingtable_delete_entry), + new_TestFixture(test_routingtable_break_and_get_all_hopping_over), + new_TestFixture(test_routingtable_offers_improvement__seqnum), + new_TestFixture(test_routingtable_offers_improvement__metric), + new_TestFixture(test_routingtable_offers_improvement__loopFree), }; EMB_UNIT_TESTCALLER(gnrc_aodvv2_tests, setUp, NULL, fixtures); From 264b65a5967244ac12c7467c82a6349e0e8f3a6c Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Tue, 27 Sep 2016 12:39:58 -0700 Subject: [PATCH 38/41] cleanup, renaming --- .../._tests-gnrc_aodvv2_tables.c | Bin 4096 -> 0 bytes .../tests-gnrc_aodvv2/tests-gnrc_aodvv2.c | 4 +- .../tests-gnrc_aodvv2/tests-gnrc_aodvv2.h | 6 +- .../tests-gnrc_aodvv2_tables.c | 232 ------------------ 4 files changed, 5 insertions(+), 237 deletions(-) delete mode 100644 tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c delete mode 100644 tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c diff --git a/tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c b/tests/unittests/tests-gnrc_aodvv2/._tests-gnrc_aodvv2_tables.c deleted file mode 100644 index 5d5f95f19e92ca4ba7bc89ba005b6248000655fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vVqmC` zhUj3ZAfS9ydNc$^Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1gH`Mj6hRB7!2e> zGBS%5ic*X7ON)|I71HvHvK2D(N>cMmGV}8ib8;#ba#GVu6q0fh^Rj_`VW_SlO`-Z9 L?iCpZx&QwGah4ol diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c index 5daf370768c4..1da59fbfd927 100644 --- a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Lotte Steenbrink + * Copyright (C) 2016 Lotte Steenbrink * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -11,7 +11,7 @@ void tests_gnrc_aodvv2(void) { TESTS_RUN(tests_gnrc_aodvv2_seqnum_tests()); - TESTS_RUN(tests_gnrc_aodvv2_table_tests()); + TESTS_RUN(tests_gnrc_aodvv2_routingtable_tests()); } /** @} */ \ No newline at end of file diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h index 8aba4cd41c02..21bf6bea2bc2 100644 --- a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h +++ b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2.h @@ -13,7 +13,7 @@ * @file tests-gnrc_aodvv2.h * @brief Unittests for the ``aodvv2`` module * - * @author Lotte Steenbrink + * @author Lotte Steenbrink */ #ifndef TESTS_GNRC_AODVV2_H_ #define TESTS_GNRC_AODVV2_H_ @@ -37,11 +37,11 @@ void tests_gnrc_aodvv2(void); Test *tests_gnrc_aodvv2_seqnum_tests(void); /** - * @brief Generates tests for aodvv2/routingtable.h and aodvv2/utils.h + * @brief Generates tests for aodvv2/routingtable.h * * @return embUnit tests if successful, NULL if not. */ -Test *tests_gnrc_aodvv2_table_tests(void); +Test *tests_gnrc_aodvv2_routingtable_tests(void); #ifdef __cplusplus } diff --git a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c b/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c deleted file mode 100644 index e2dd5bfb7bff..000000000000 --- a/tests/unittests/tests-gnrc_aodvv2/tests-gnrc_aodvv2_tables.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2016 Lotte Steenbrink - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#include -#include "embUnit.h" - -#include "xtimer.h" - -#include "routingtable.h" - -#include "tests-gnrc_aodvv2.h" - -/* test data */ -struct netaddr addr_1, addr_2; -timex_t ts; - -aodvv2_seqnum_t test_seqnum_1 = 1; -aodvv2_seqnum_t test_seqnum_2 = 2; -uint8_t test_metric_1 = 3; -uint8_t test_metric_2 = 4; - -/* test basic routingtable add & get functions */ -static void test_routingtable_add_get(void) -{ - struct aodvv2_routing_entry_t* entry; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(entry != NULL); -} - -/* test if 2 entries are added correctly */ -static void test_routingtable_add_2(void) -{ - struct aodvv2_routing_entry_t* entry_1; - struct aodvv2_routing_entry_t* entry_2; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - routingtable_add_entry(&addr_2, &test_seqnum_2, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, - ROUTE_STATE_ACTIVE, &ts); - - entry_1 = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - entry_2 = routingtable_get_entry(&addr_2, AODVV2_DEFAULT_METRIC_TYPE); - - TEST_ASSERT(0 == netaddr_cmp(&entry_1->addr, &addr_1)); - TEST_ASSERT(entry_1->seqnum == test_seqnum_1); - TEST_ASSERT(0 == netaddr_cmp(&entry_1->nextHopAddr, &addr_2)); - TEST_ASSERT(entry_1->metricType == AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(entry_1->metric == test_metric_1); - TEST_ASSERT(entry_1->state == ROUTE_STATE_IDLE); - - TEST_ASSERT(0 == netaddr_cmp(&entry_2->addr, &addr_2)); - TEST_ASSERT(entry_2->seqnum == test_seqnum_2); - TEST_ASSERT(0 == netaddr_cmp(&entry_2->nextHopAddr, &addr_2)); - TEST_ASSERT(entry_2->metricType == AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(entry_2->metric == test_metric_2); - TEST_ASSERT(entry_2->state == ROUTE_STATE_ACTIVE); -} - -static void test_routingtable_get_next_hop(void) -{ - struct netaddr* next_hop; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - - next_hop = routingtable_get_next_hop(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(0 == netaddr_cmp(next_hop, &addr_2)); -} - -static void test_routingtable_update_entry(void) -{ - struct aodvv2_routing_entry_t* entry; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - - entry = routingtable_update_entry(entry, &test_seqnum_2, &addr_1, test_metric_2, - ROUTE_STATE_ACTIVE, &ts); - - TEST_ASSERT(entry->seqnum == test_seqnum_2); - TEST_ASSERT(0 == netaddr_cmp(&entry->nextHopAddr, &addr_1)); - TEST_ASSERT(entry->metric == test_metric_2); - TEST_ASSERT(entry->state == ROUTE_STATE_ACTIVE); -} - -static void test_routingtable_delete_entry(void) -{ - struct aodvv2_routing_entry_t* entry; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - - routingtable_delete_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(entry == NULL); -} - -static void test_routingtable_break_and_get_all_hopping_over(void) -{ - struct unreachable_node unreachable_nodes[2]; - size_t len; - struct aodvv2_routing_entry_t* entry_1; - struct aodvv2_routing_entry_t* entry_2; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - routingtable_add_entry(&addr_2, &test_seqnum_2, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, - ROUTE_STATE_ACTIVE, &ts); - - routingtable_break_and_get_all_hopping_over(&addr_2, unreachable_nodes, &len); - - entry_1 = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - entry_2 = routingtable_get_entry(&addr_2, AODVV2_DEFAULT_METRIC_TYPE); - - TEST_ASSERT(len == 1); - - /* The information from entry_1 shouldn't be in unreachable_nodes[], because - routes with state ROUTE_STATE_IDLE should not be reported in a RERR (unless - ENABLE_IDLE_IN_RERR is configured, which it isn't.) */ - TEST_ASSERT(entry_1->state == ROUTE_STATE_INVALID); - - TEST_ASSERT(0 == netaddr_cmp(&(unreachable_nodes[0].addr), &addr_2)); - TEST_ASSERT(unreachable_nodes[0].seqnum == test_seqnum_2); - TEST_ASSERT(entry_2->state == ROUTE_STATE_INVALID); -} - -static void test_routingtable_offers_improvement__seqnum(void) -{ - struct aodvv2_routing_entry_t* entry; - struct node_data new_data = - { - .addr = addr_1, - .metric = test_metric_1, - .seqnum = test_seqnum_2, - }; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == true); -} - -static void test_routingtable_offers_improvement__metric(void) -{ - struct aodvv2_routing_entry_t* entry; - struct node_data new_data = - { - .addr = addr_1, - .metric = test_metric_1, - .seqnum = test_seqnum_1, - }; - - routingtable_add_entry(&addr_1, &test_seqnum_1, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_2, - ROUTE_STATE_IDLE, &ts); - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - - TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == true); -} - -static void test_routingtable_offers_improvement__loopFree(void) -{ - struct aodvv2_routing_entry_t* entry; - struct node_data new_data = - { - .addr = addr_1, - .metric = test_metric_1, - .seqnum = test_seqnum_1, - }; - - routingtable_add_entry(&addr_1, &test_seqnum_2, &addr_2, - AODVV2_DEFAULT_METRIC_TYPE, test_metric_1, - ROUTE_STATE_IDLE, &ts); - - entry = routingtable_get_entry(&addr_1, AODVV2_DEFAULT_METRIC_TYPE); - TEST_ASSERT(routingtable_offers_improvement(entry, &new_data) == false); -} - - -static void setUp(void) -{ - xtimer_now_timex(&ts); - - /* init test data */ - int foo = netaddr_from_string(&addr_1, "::23"); - int bar = netaddr_from_string(&addr_2, "::42"); - (void) foo; /* silence compiler*/ - (void) bar; /* silence compiler*/ - - /* init routing table */ - routingtable_init(); -} - -Test *tests_gnrc_aodvv2_table_tests(void) -{ - EMB_UNIT_TESTFIXTURES(fixtures) { - new_TestFixture(test_routingtable_add_get), - new_TestFixture(test_routingtable_add_2), - new_TestFixture(test_routingtable_get_next_hop), - new_TestFixture(test_routingtable_update_entry), - new_TestFixture(test_routingtable_delete_entry), - new_TestFixture(test_routingtable_break_and_get_all_hopping_over), - new_TestFixture(test_routingtable_offers_improvement__seqnum), - new_TestFixture(test_routingtable_offers_improvement__metric), - new_TestFixture(test_routingtable_offers_improvement__loopFree), - }; - - EMB_UNIT_TESTCALLER(gnrc_aodvv2_tests, setUp, NULL, fixtures); - - return (Test *)&gnrc_aodvv2_tests; -} \ No newline at end of file From d8bc5800f9c73110a9ff3d5c755d6c4aa746bf0c Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sun, 16 Oct 2016 17:12:30 -0700 Subject: [PATCH 39/41] rm mallocs. !! WIP; contrains race condition, debug output & TODOs !! --- sys/net/gnrc/routing/aodvv2/aodv.c | 91 +++++++++++++--------- sys/net/gnrc/routing/aodvv2/constants.h | 3 + sys/net/gnrc/routing/aodvv2/reader.c | 2 + sys/net/gnrc/routing/aodvv2/routingtable.c | 1 + sys/net/gnrc/routing/aodvv2/writer.c | 3 +- 5 files changed, 64 insertions(+), 36 deletions(-) diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index b9d737945e75..348f6e72212a 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -36,7 +36,7 @@ static void *_aodv_receiver_thread(void *arg); static void *_aodv_sender_thread(void *arg); static void *fib_signal_handler_thread(void *arg); -static void _deep_free_msg_container(struct msg_container *msg_container); +//static void _deep_free_msg_container(struct msg_container *msg_container); static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), struct rfc5444_writer_target *iface __attribute__((unused)), void *buffer, size_t length); @@ -59,7 +59,7 @@ static aodvv2_metric_t _metric_type; static int sender_thread; static struct autobuf _hexbuf; static ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; -static ipv6_addr_t _v6_addr_local; +/*static*/ ipv6_addr_t _v6_addr_local; static struct netaddr na_local; /* the same as _v6_addr_local, but to save us * constant calls to ipv6_addr_t_to_netaddr()... */ static struct writer_target *wt; @@ -74,6 +74,20 @@ static int aodvv2_address_type_size; struct netaddr na_mcast; kernel_pid_t aodvv2_if_id; +/* TODO: can I share some of those (& the mutexes) without creating a bottleneck?*/ +struct aodvv2_packet_data rreq_packet_data; +struct rreq_rrep_data rreq_data; +struct msg_container rreq_msg_container; + +struct aodvv2_packet_data rrep_packet_data; +struct rreq_rrep_data rrep_data; +struct netaddr rrep_next_hop; +struct msg_container rrep_msg_container; + +struct rerr_data rerr_data; +struct netaddr rerr_next_hop; +struct msg_container rerr_msg_container; + void aodv_init(kernel_pid_t interface) { DEBUG("%s()\n", __func__); @@ -167,7 +181,7 @@ void *fib_signal_handler_thread(void *arg) seqnum_inc(); /* Build new RREQ */ - struct aodvv2_packet_data rreq_data = (struct aodvv2_packet_data) { + struct aodvv2_packet_data rreq_init_data = (struct aodvv2_packet_data) { .hoplimit = AODVV2_MAX_HOPCOUNT, .metricType = _metric_type, .origNode = (struct node_data) { @@ -184,7 +198,7 @@ void *fib_signal_handler_thread(void *arg) AODV_DEBUG("\tstarting route discovery towards %s... \n", ipv6_addr_to_str(addr_str, &dest, IPV6_ADDR_MAX_STR_LEN)); - aodv_send_rreq(&rreq_data); + aodv_send_rreq(&rreq_init_data); } else { /* Reply to the FIB so that it can stop blocking */ @@ -200,23 +214,21 @@ void aodv_send_rreq(struct aodvv2_packet_data *packet_data) /* Make sure only one thread is dispatching a RREQ at a time */ mutex_lock(&rreq_mutex); - struct aodvv2_packet_data *pd = malloc(sizeof(struct aodvv2_packet_data)); - memcpy(pd, packet_data, sizeof(struct aodvv2_packet_data)); + /* TODO do I need this memcpy? */ + memcpy(&rreq_packet_data, packet_data, sizeof(struct aodvv2_packet_data)); - struct rreq_rrep_data *rd = malloc(sizeof(struct rreq_rrep_data)); - *rd = (struct rreq_rrep_data) { + rreq_data = (struct rreq_rrep_data) { .next_hop = &na_mcast, - .packet_data = pd, + .packet_data = &rreq_packet_data, }; - struct msg_container *mc = malloc(sizeof(struct msg_container)); - *mc = (struct msg_container) { + rreq_msg_container = (struct msg_container) { .type = RFC5444_MSGTYPE_RREQ, - .data = rd + .data = &rreq_data, }; msg_t msg; - msg.content.ptr = (char *) mc; + msg.content.ptr = &rreq_msg_container; msg_try_send(&msg, sender_thread); mutex_unlock(&rreq_mutex); @@ -227,26 +239,31 @@ void aodv_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next /* Make sure only one thread is dispatching a RREP at a time */ mutex_lock(&rrep_mutex); - struct aodvv2_packet_data *pd = malloc(sizeof(struct aodvv2_packet_data)); - memcpy(pd, packet_data, sizeof(struct aodvv2_packet_data)); - - struct netaddr *nh = malloc(sizeof(struct netaddr)); - memcpy(nh, next_hop, sizeof(struct netaddr)); - - struct rreq_rrep_data *rd = malloc(sizeof(struct rreq_rrep_data)); - *rd = (struct rreq_rrep_data) { - .next_hop = nh, - .packet_data = pd, + memcpy(&rrep_packet_data, packet_data, sizeof(struct aodvv2_packet_data)); + memcpy(&rrep_next_hop, next_hop, sizeof(struct netaddr)); + + // TODO DELETEME (for debugging only) + struct netaddr_str nbuf; + char addr_str[40]; + printf("[@ send 1] %s next hop %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), + netaddr_to_string(&nbuf, next_hop)); + printf("[@ send 1] %s origaddr %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), + netaddr_to_string(&nbuf, &packet_data->origNode.addr)); + printf("[@ send 1] %s targaddr %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), + netaddr_to_string(&nbuf, &packet_data->targNode.addr)); + + rrep_data = (struct rreq_rrep_data) { + .next_hop = &rrep_next_hop, + .packet_data = &rrep_packet_data, }; - struct msg_container *mc = malloc(sizeof(struct msg_container)); - *mc = (struct msg_container) { + rrep_msg_container = (struct msg_container) { .type = RFC5444_MSGTYPE_RREP, - .data = rd + .data = &rrep_data }; msg_t msg; - msg.content.ptr = (char *) mc; + msg.content.ptr = &rrep_msg_container; msg_try_send(&msg, sender_thread); mutex_unlock(&rrep_mutex); @@ -257,22 +274,22 @@ void aodv_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, str /* Make sure only one thread is dispatching a RERR at a time */ mutex_lock(&rerr_mutex); - struct rerr_data *rerrd = malloc(sizeof(struct rerr_data)); - *rerrd = (struct rerr_data) { + memcpy(&rerr_next_hop, next_hop, sizeof(struct netaddr)); + + rerr_data = (struct rerr_data) { .unreachable_nodes = unreachable_nodes, .len = len, .hoplimit = AODVV2_MAX_HOPCOUNT, - .next_hop = next_hop + .next_hop = &rerr_next_hop }; - struct msg_container *mc2 = malloc(sizeof(struct msg_container)); - *mc2 = (struct msg_container) { + rerr_msg_container = (struct msg_container) { .type = RFC5444_MSGTYPE_RERR, - .data = rerrd + .data = &rerr_data }; msg_t msg2; - msg2.content.ptr = (char *) mc2; + msg2.content.ptr = &rerr_msg_container; msg_try_send(&msg2, sender_thread); mutex_unlock(&rerr_mutex); @@ -348,7 +365,7 @@ static void *_aodv_sender_thread(void *arg) else { AODV_DEBUG("ERROR: Couldn't identify Message\n"); } - _deep_free_msg_container(mc); + //_deep_free_msg_container(mc); } return NULL; @@ -449,6 +466,7 @@ static void _aodv_send(ipv6_addr_t addr, uint16_t port, void *data, size_t data_ /* all headers are set, send packet */ if(!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { DEBUG("Error sending packet\n"); + gnrc_pktbuf_release(pkt_with_ip); } } @@ -479,6 +497,7 @@ static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), netaddr_to_ipv6_addr_t(&wt->target_addr, &addr_send); /* When originating a RREQ, add it to our RREQ table/update its predecessor */ + // TOOD: shouldn't this be moved to the fib thread?! if (wt->type == RFC5444_MSGTYPE_RREQ && netaddr_cmp(&wt->packet_data.origNode.addr, &na_local) == 0) { DEBUG("originating RREQ with SeqNum %d towards %s via %s; updating RREQ table...\n", @@ -522,6 +541,7 @@ static void print_json_pkt_sent(struct writer_target *wt) } /* free the matryoshka doll of cobbled-together structs that the sender_thread receives */ +/* TODO deleteme static void _deep_free_msg_container(struct msg_container *mc) { int type = mc->type; @@ -541,3 +561,4 @@ static void _deep_free_msg_container(struct msg_container *mc) free(mc->data); free(mc); } +*/ \ No newline at end of file diff --git a/sys/net/gnrc/routing/aodvv2/constants.h b/sys/net/gnrc/routing/aodvv2/constants.h index e77968f8f5e4..ea44c4b9a443 100644 --- a/sys/net/gnrc/routing/aodvv2/constants.h +++ b/sys/net/gnrc/routing/aodvv2/constants.h @@ -54,6 +54,9 @@ enum tlv_index /* my multicast address */ extern struct netaddr na_mcast; +// TODO DELETEME (for debugging only) +extern ipv6_addr_t _v6_addr_local; + /* the interface this protocol operates on */ extern kernel_pid_t aodvv2_if_id; diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index 9dc521b7e985..a51bb4ffc7ae 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -675,6 +675,8 @@ void aodv_packet_reader_cleanup(void) int aodv_packet_reader_handle_packet(void *buffer, size_t length, struct netaddr *sender) { + /* clear leftover data & init*/ + packet_data = (struct aodvv2_packet_data) {0}; memcpy(&packet_data.sender, sender, sizeof(*sender)); return rfc5444_reader_handle_packet(&reader, buffer, length); diff --git a/sys/net/gnrc/routing/aodvv2/routingtable.c b/sys/net/gnrc/routing/aodvv2/routingtable.c index eee11790c7a4..8c970fb7beb3 100644 --- a/sys/net/gnrc/routing/aodvv2/routingtable.c +++ b/sys/net/gnrc/routing/aodvv2/routingtable.c @@ -276,6 +276,7 @@ static void print_json_added_rt_entry(struct aodvv2_routing_entry_t *entry) #endif } +// TODO: add ifdef DEBUGs or something void print_routingtable(void) { printf("===== BEGIN ROUTING TABLE ===================\n"); diff --git a/sys/net/gnrc/routing/aodvv2/writer.c b/sys/net/gnrc/routing/aodvv2/writer.c index c6d67cddf1f0..fa774ee17a8b 100644 --- a/sys/net/gnrc/routing/aodvv2/writer.c +++ b/sys/net/gnrc/routing/aodvv2/writer.c @@ -269,7 +269,7 @@ void aodv_packet_writer_send_rreq(struct aodvv2_packet_data *packet_data, struct return; } - /* Make sure no other thread is using the writer right now */ + // TODO: memcpy necessary? memcpy(&_target.packet_data, packet_data, sizeof(struct aodvv2_packet_data)); _target.type = RFC5444_MSGTYPE_RREQ; _target.packet_data.hoplimit = packet_data->hoplimit; @@ -296,6 +296,7 @@ void aodv_packet_writer_send_rrep(struct aodvv2_packet_data *packet_data, struct return; } + // TODO: memcpy necessary? memcpy(&_target.packet_data, packet_data, sizeof(struct aodvv2_packet_data)); _target.type = RFC5444_MSGTYPE_RREP; _target.packet_data.hoplimit = AODVV2_MAX_HOPCOUNT; From 10fbc4e2008bc16930bf57c448bf7fb2b39e3ac8 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Sun, 16 Oct 2016 17:15:23 -0700 Subject: [PATCH 40/41] rm unnecessary folder in tests (has all been moved to tests/unittests) --- tests/gnrc_aodvv2/Makefile | 13 ----------- tests/gnrc_aodvv2/main.c | 45 -------------------------------------- 2 files changed, 58 deletions(-) delete mode 100644 tests/gnrc_aodvv2/Makefile delete mode 100644 tests/gnrc_aodvv2/main.c diff --git a/tests/gnrc_aodvv2/Makefile b/tests/gnrc_aodvv2/Makefile deleted file mode 100644 index 5a03575825be..000000000000 --- a/tests/gnrc_aodvv2/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -APPLICATION = gnrc_aodvv2 -include ../Makefile.tests_common - -# TODO: these includes shouldn't be necessary, should they... -USEMODULE += gnrc_netdev_default -USEMODULE += auto_init_gnrc_netif - -USEMODULE += gnrc_ipv6_router_default -USEMODULE += gnrc_udp - -USEMODULE += aodvv2 - -include $(RIOTBASE)/Makefile.include diff --git a/tests/gnrc_aodvv2/main.c b/tests/gnrc_aodvv2/main.c deleted file mode 100644 index fd4cb49cc4d6..000000000000 --- a/tests/gnrc_aodvv2/main.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016 Lotte Steenbrink - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -/** - * @ingroup tests - * @{ - * - * @file - * @brief Test AODVv2 functionalities - * - * @author Lotte Steenbrink - * - * @} - */ - -#include "net/gnrc/aodvv2.h" -#include "net/ipv6/addr.h" - -int main(void) -{ - aodv_init(0); - - printf("Start.\r\n"); - - // TODO add tests :D - - printf("Done.\r\n"); - return 0; -} From 6d1fef39acc30665f2a32387b17afcfe3257d196 Mon Sep 17 00:00:00 2001 From: Lotte Steenbrink Date: Mon, 17 Oct 2016 02:14:03 -0700 Subject: [PATCH 41/41] redo aodv.c, switch from 3 threads to 1 (WIP; UNTESTED) --- sys/include/net/gnrc/aodvv2.h | 2 + sys/net/gnrc/routing/aodvv2/aodv.c | 535 +++++++----------------- sys/net/gnrc/routing/aodvv2/constants.h | 7 +- sys/net/gnrc/routing/aodvv2/reader.c | 35 +- sys/net/gnrc/routing/aodvv2/utils.h | 4 +- sys/net/gnrc/routing/aodvv2/writer.c | 1 + 6 files changed, 184 insertions(+), 400 deletions(-) diff --git a/sys/include/net/gnrc/aodvv2.h b/sys/include/net/gnrc/aodvv2.h index b52ad7e78bff..e4e72368e1c6 100644 --- a/sys/include/net/gnrc/aodvv2.h +++ b/sys/include/net/gnrc/aodvv2.h @@ -34,6 +34,8 @@ extern "C" { /** * @brief Initialize the AODVv2 routing protocol. + * + * @param interface The interface AODVv2 operates on and finds routes for. */ void aodv_init(kernel_pid_t interface); diff --git a/sys/net/gnrc/routing/aodvv2/aodv.c b/sys/net/gnrc/routing/aodvv2/aodv.c index 348f6e72212a..dc40d512a2e7 100644 --- a/sys/net/gnrc/routing/aodvv2/aodv.c +++ b/sys/net/gnrc/routing/aodvv2/aodv.c @@ -19,294 +19,95 @@ */ #include "aodv.h" -#include "aodv_debug.h" -#include "net/fib.h" #include "net/gnrc/aodvv2.h" #define ENABLE_DEBUG (0) #include "debug.h" -#define UDP_BUFFER_SIZE (128) /** with respect to IEEE 802.15.4's MTU */ -#define RCV_MSG_Q_SIZE (32) /* TODO: check if smaller values work, too */ -#define FIB_MSG_Q_SIZE (16) /* TODO: check if smaller values work, too */ #define AODVV2_PREFIX {{ 0xbe, 0xe2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }} - -static void _init_addresses(void); -static void *_aodv_receiver_thread(void *arg); -static void *_aodv_sender_thread(void *arg); -static void *fib_signal_handler_thread(void *arg); - -//static void _deep_free_msg_container(struct msg_container *msg_container); -static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), - struct rfc5444_writer_target *iface __attribute__((unused)), - void *buffer, size_t length); +#define AODV_MSG_Q_SIZE (32) /**< TODO: check if smaller values work, too */ +#define UDP_BUFFER_SIZE (128) /**< with respect to IEEE 802.15.4's MTU */ + +static void aodv_init_addresses(void); +static void *aodv_thread(void *arg); +static void aodv_send_packet(struct rfc5444_writer *wr __attribute__ ((unused)), + struct rfc5444_writer_target *iface __attribute__((unused)), + void *buffer, size_t length); static void print_json_pkt_sent(struct writer_target *wt); -#if AODV_DEBUG -char addr_str[IPV6_MAX_ADDR_STR_LEN]; -static struct netaddr_str nbuf; -static char addr_str[IPV6_MAX_ADDR_STR_LEN]; -#endif #if TEST_SETUP static struct netaddr_str nbuf_origaddr, nbuf_targaddr, nbuf_nexthop; #endif -static char aodv_rcv_stack_buf[THREAD_STACKSIZE_MAIN]; -static char aodv_snd_stack_buf[THREAD_STACKSIZE_MAIN]; -static char aodv_fib_stack_buf[THREAD_STACKSIZE_MAIN]; - -static aodvv2_metric_t _metric_type; -static int sender_thread; -static struct autobuf _hexbuf; -static ipv6_addr_t _v6_addr_mcast, _v6_addr_loopback; -/*static*/ ipv6_addr_t _v6_addr_local; -static struct netaddr na_local; /* the same as _v6_addr_local, but to save us - * constant calls to ipv6_addr_t_to_netaddr()... */ -static struct writer_target *wt; -static mutex_t rreq_mutex; -static mutex_t rrep_mutex; -static mutex_t rerr_mutex; +kernel_pid_t aodvv2_if_id; /* The interface AODVv2 operates on & finds routes for */ + +/* The metric type AODVv2 uses. (In case a different type is ever added, consider + * adding getter & setter functions and moving them to a metric.c, along with + * loopFree(), cost() etc functions) */ +static aodvv2_metric_t aodv_metric_type; static ipv6_addr_t aodvv2_prefix = AODVV2_PREFIX; static int aodvv2_prefix_len; static int aodvv2_address_type_size; -struct netaddr na_mcast; -kernel_pid_t aodvv2_if_id; +static ipv6_addr_t aodv_ipv6_addr_local; /* The IP address of this router */ +static ipv6_addr_t aodv_ipv6_addr_mcast; -/* TODO: can I share some of those (& the mutexes) without creating a bottleneck?*/ -struct aodvv2_packet_data rreq_packet_data; -struct rreq_rrep_data rreq_data; -struct msg_container rreq_msg_container; +/* netaddr representation of this router's addresses (for oonf api interaction) */ +static struct netaddr aodvv2_netaddr_local; +struct netaddr aodvv2_netaddr_mcast; -struct aodvv2_packet_data rrep_packet_data; -struct rreq_rrep_data rrep_data; -struct netaddr rrep_next_hop; -struct msg_container rrep_msg_container; +static char aodv_stack_buf[THREAD_STACKSIZE_MAIN]; -struct rerr_data rerr_data; -struct netaddr rerr_next_hop; -struct msg_container rerr_msg_container; +/* + TODO: + - old_aodv durchgehen um sicher zu gehen dass ich nix übersehen hab +*/ void aodv_init(kernel_pid_t interface) { DEBUG("%s()\n", __func__); - /* init this thread's IPC msg queue */ - msg_t msgq[RCV_MSG_Q_SIZE]; - msg_init_queue(msgq, sizeof msgq); - if (!interface) { DEBUG("Error: AODVv2 interface pid is invalid.\n"); return; } - aodvv2_if_id = interface; - aodvv2_address_type_size = sizeof(ipv6_addr_t); - aodvv2_prefix_len = 64; - - mutex_init(&rreq_mutex); - mutex_init(&rrep_mutex); - mutex_init(&rerr_mutex); - - aodv_set_metric_type(AODVV2_DEFAULT_METRIC_TYPE); - _init_addresses(); - - /* init ALL the things! \o, */ + /* initialize AODVv2 internals */ + aodvv2_if_id = interface; + aodv_metric_type = AODVV2_DEFAULT_METRIC_TYPE; seqnum_init(); routingtable_init(); clienttable_init(); - - /* every node is its own client. */ - clienttable_add_client(&na_local); rreqtable_init(); - /* init reader and writer */ - aodv_packet_reader_init(); - aodv_packet_writer_init(_write_packet); - - /* start listening & enable sending */ - thread_create(aodv_rcv_stack_buf, sizeof(aodv_rcv_stack_buf), THREAD_PRIORITY_MAIN - 1, - THREAD_CREATE_STACKTEST, _aodv_receiver_thread, NULL, "_aodv_receiver_thread"); - AODV_DEBUG("listening on port %d\n", MANET_PORT); - sender_thread = thread_create(aodv_snd_stack_buf, sizeof(aodv_snd_stack_buf), - THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, _aodv_sender_thread, - NULL, "_aodv_sender_thread"); - thread_create(aodv_fib_stack_buf, sizeof(aodv_fib_stack_buf), - THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, fib_signal_handler_thread, - NULL, "fib_signal_handler_thread"); -} - -void aodv_set_metric_type(aodvv2_metric_t metric_type) -{ - if (metric_type != AODVV2_DEFAULT_METRIC_TYPE) { - return; - } - _metric_type = metric_type; -} -/* - * @brief handles callbacks from the FIB when it needs a route - */ -void *fib_signal_handler_thread(void *arg) -{ - // TODO: warum wird der erst gestartet wenn ifconfig aufgerufen wird? - (void) arg; - msg_t fib_msgq[FIB_MSG_Q_SIZE]; - ipv6_addr_t dest; - struct netaddr na_dest; - - msg_init_queue(fib_msgq, FIB_MSG_Q_SIZE); - int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], aodvv2_address_type_size); - if ( err != 0) { - DEBUG("ERROR: cannot register at fib, error code:\n"); - exit(1); - } - - while (true) { - msg_t fib_msg; - msg_receive(&fib_msg); - - if (fib_msg.type == FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION) { - rp_address_msg_t* rp_msg = (rp_address_msg_t*)fib_msg.content.ptr; - if (rp_msg->address_size == sizeof(ipv6_addr_t)) { - /* We currently only support IPv6*/ - memcpy(&dest, rp_msg->address, rp_msg->address_size); - /* Reply to the FIB so that it can stop blocking */ - msg_reply(&fib_msg, &fib_msg); - - /* perform/initiate a rreq for dst here*/ - ipv6_addr_t_to_netaddr(&dest, &na_dest); - - aodvv2_seqnum_t seqnum = seqnum_get(); - seqnum_inc(); - - /* Build new RREQ */ - struct aodvv2_packet_data rreq_init_data = (struct aodvv2_packet_data) { - .hoplimit = AODVV2_MAX_HOPCOUNT, - .metricType = _metric_type, - .origNode = (struct node_data) { - .addr = na_local, - .metric = 0, - .seqnum = seqnum, - }, - .targNode = (struct node_data) { - .addr = na_dest, - }, - .timestamp = (timex_t) {0,0} /* this timestamp is never used, it exists - * merely to make the compiler shut up */ - }; - - AODV_DEBUG("\tstarting route discovery towards %s... \n", - ipv6_addr_to_str(addr_str, &dest, IPV6_ADDR_MAX_STR_LEN)); - aodv_send_rreq(&rreq_init_data); - } - else { - /* Reply to the FIB so that it can stop blocking */ - msg_reply(&fib_msg, &fib_msg); - } - } - } - return NULL; -} - -void aodv_send_rreq(struct aodvv2_packet_data *packet_data) -{ - /* Make sure only one thread is dispatching a RREQ at a time */ - mutex_lock(&rreq_mutex); - - /* TODO do I need this memcpy? */ - memcpy(&rreq_packet_data, packet_data, sizeof(struct aodvv2_packet_data)); - - rreq_data = (struct rreq_rrep_data) { - .next_hop = &na_mcast, - .packet_data = &rreq_packet_data, - }; - - rreq_msg_container = (struct msg_container) { - .type = RFC5444_MSGTYPE_RREQ, - .data = &rreq_data, - }; - - msg_t msg; - msg.content.ptr = &rreq_msg_container; - - msg_try_send(&msg, sender_thread); - mutex_unlock(&rreq_mutex); -} - -void aodv_send_rrep(struct aodvv2_packet_data *packet_data, struct netaddr *next_hop) -{ - /* Make sure only one thread is dispatching a RREP at a time */ - mutex_lock(&rrep_mutex); - - memcpy(&rrep_packet_data, packet_data, sizeof(struct aodvv2_packet_data)); - memcpy(&rrep_next_hop, next_hop, sizeof(struct netaddr)); - - // TODO DELETEME (for debugging only) - struct netaddr_str nbuf; - char addr_str[40]; - printf("[@ send 1] %s next hop %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), - netaddr_to_string(&nbuf, next_hop)); - printf("[@ send 1] %s origaddr %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), - netaddr_to_string(&nbuf, &packet_data->origNode.addr)); - printf("[@ send 1] %s targaddr %s\n", ipv6_addr_to_str(addr_str, &_v6_addr_local, 40), - netaddr_to_string(&nbuf, &packet_data->targNode.addr)); - - rrep_data = (struct rreq_rrep_data) { - .next_hop = &rrep_next_hop, - .packet_data = &rrep_packet_data, - }; - - rrep_msg_container = (struct msg_container) { - .type = RFC5444_MSGTYPE_RREP, - .data = &rrep_data - }; - - msg_t msg; - msg.content.ptr = &rrep_msg_container; - - msg_try_send(&msg, sender_thread); - mutex_unlock(&rrep_mutex); -} - -void aodv_send_rerr(struct unreachable_node unreachable_nodes[], size_t len, struct netaddr *next_hop) -{ - /* Make sure only one thread is dispatching a RERR at a time */ - mutex_lock(&rerr_mutex); - - memcpy(&rerr_next_hop, next_hop, sizeof(struct netaddr)); - - rerr_data = (struct rerr_data) { - .unreachable_nodes = unreachable_nodes, - .len = len, - .hoplimit = AODVV2_MAX_HOPCOUNT, - .next_hop = &rerr_next_hop - }; + /* initialize addresses */ + aodvv2_address_type_size = sizeof(ipv6_addr_t); + aodvv2_prefix_len = 64; + aodv_init_addresses(); - rerr_msg_container = (struct msg_container) { - .type = RFC5444_MSGTYPE_RERR, - .data = &rerr_data - }; + /* every node is its own client. */ + clienttable_add_client(&aodvv2_netaddr_local); - msg_t msg2; - msg2.content.ptr = &rerr_msg_container; + /* init RFC 5444 reader and writer */ + aodv_packet_reader_init(); + aodv_packet_writer_init(aodv_send_packet); - msg_try_send(&msg2, sender_thread); - mutex_unlock(&rerr_mutex); + /* start listening & sending packets */ + thread_create(aodv_stack_buf, sizeof(aodv_stack_buf), THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, aodv_thread, NULL, "aodv_thread"); } /* * init the multicast address all RREQ and RERRS are sent to * and the local address (source address) of this node */ -static void _init_addresses(void) +static void aodv_init_addresses(void) { eui64_t iid; /* init multicast address: set to to a link-local all nodes multicast address */ - ipv6_addr_set_all_nodes_multicast(&_v6_addr_mcast, IPV6_ADDR_MCAST_SCP_LINK_LOCAL); - DEBUG("my multicast address is: %s\n", - ipv6_addr_to_str(addr_str, &_v6_addr_mcast, IPV6_ADDR_MAX_STR_LEN)); + ipv6_addr_set_all_nodes_multicast(&aodv_ipv6_addr_mcast, IPV6_ADDR_MCAST_SCP_LINK_LOCAL); /* get id (of type eui46_t) of the interface we're sending on */ int err_code = gnrc_netapi_get(aodvv2_if_id, NETOPT_IPV6_IID, 0, &iid, @@ -317,116 +118,131 @@ static void _init_addresses(void) } /* Set addr according to our interface id */ - ipv6_addr_set_aiid(&_v6_addr_local, &iid.uint8[0]); + ipv6_addr_set_aiid(&aodv_ipv6_addr_local, &iid.uint8[0]); /* Set (global!) prefix */ - ipv6_addr_init_prefix(&_v6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); + ipv6_addr_init_prefix(&aodv_ipv6_addr_local, &aodvv2_prefix, aodvv2_prefix_len); /* Add our homemade address to our interface (aodvv2_if_id) */ - gnrc_ipv6_netif_add_addr(aodvv2_if_id, &_v6_addr_local, aodvv2_prefix_len, 0); - - DEBUG("my src address is: %s\n", - ipv6_addr_to_str(addr_str, &_v6_addr_local, IPV6_ADDR_MAX_STR_LEN)); + gnrc_ipv6_netif_add_addr(aodvv2_if_id, &aodv_ipv6_addr_local, aodvv2_prefix_len, 0); /* store src & multicast address as netaddr as well for easy interaction - * with oonf based stuff */ - ipv6_addr_t_to_netaddr(&_v6_addr_local, &na_local); - ipv6_addr_t_to_netaddr(&_v6_addr_mcast, &na_mcast); - - /* TODO: do I need this?*/ - ipv6_addr_set_loopback(&_v6_addr_loopback); + * with oonf api (i.e. reader & writer code) */ + ipv6_addr_t_to_netaddr(&aodv_ipv6_addr_local, &aodvv2_netaddr_local); + ipv6_addr_t_to_netaddr(&aodv_ipv6_addr_mcast, &aodvv2_netaddr_mcast); } -/* Build RREQs, RREPs and RERRs from the information contained in the thread's - * message queue and send them */ -static void *_aodv_sender_thread(void *arg) -{ - (void) arg; - - msg_t snd_msgq[RCV_MSG_Q_SIZE]; - msg_init_queue(snd_msgq, RCV_MSG_Q_SIZE); - - while (true) { - msg_t msg; - msg_receive(&msg); - struct msg_container *mc = (struct msg_container *) msg.content.ptr; - - if (mc->type == RFC5444_MSGTYPE_RREQ) { - struct rreq_rrep_data *rreq_data = (struct rreq_rrep_data *) mc->data; - aodv_packet_writer_send_rreq(rreq_data->packet_data, rreq_data->next_hop); - } - else if (mc->type == RFC5444_MSGTYPE_RREP) { - struct rreq_rrep_data *rrep_data = (struct rreq_rrep_data *) mc->data; - aodv_packet_writer_send_rrep(rrep_data->packet_data, rrep_data->next_hop); - } - else if (mc->type == RFC5444_MSGTYPE_RERR) { - struct rerr_data *rerr_data = (struct rerr_data *) mc->data; - aodv_packet_writer_send_rerr(rerr_data->unreachable_nodes, rerr_data->len, - rerr_data->hoplimit, rerr_data->next_hop); - } - else { - AODV_DEBUG("ERROR: Couldn't identify Message\n"); - } - //_deep_free_msg_container(mc); - } - - return NULL; -} - -/* receive RREQs, RREPs and RERRs and handle them */ -static void *_aodv_receiver_thread(void *arg) +static void *aodv_thread(void *arg) { (void) arg; + /* general message handling stuff */ gnrc_netreg_entry_t server = { .next = NULL, .demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL, - .pid = KERNEL_PID_UNDEF }; + .pid = KERNEL_PID_UNDEF + }; - AODV_DEBUG("%s()\n", __func__); - char buf_rcv[UDP_BUFFER_SIZE]; - struct netaddr _sender; + msg_t aodv_msgq[AODV_MSG_Q_SIZE]; + msg_init_queue(aodv_msgq, AODV_MSG_Q_SIZE); msg_t msg, reply; - msg_t rcv_msgq[RCV_MSG_Q_SIZE]; - - msg_init_queue(rcv_msgq, RCV_MSG_Q_SIZE); reply.content.value = (uint32_t)(-ENOTSUP); reply.type = GNRC_NETAPI_MSG_TYPE_ACK; - /* start server (which means registering AODVv2 receiver for the chosen port) */ - server.pid = sched_active_pid; /* sched_active_pid is our pid, since we are currently act */ + /* start server & register AODVv2 receiver for MANET_PORT */ + server.pid = sched_active_pid; /* sched_active_pid is currently our pid ;) */ server.demux_ctx = (uint32_t) MANET_PORT; gnrc_netreg_register(GNRC_NETTYPE_UDP, &server); + /* GNRC_NETAPI_MSG_TYPE_RCV message stuff */ + char pkt_rcv_buf[UDP_BUFFER_SIZE]; + struct netaddr pkt_sender; + + /* FIB_MSG_RP_SIGNAL messages stuff*/ + ipv6_addr_t ipv6_dest; + struct netaddr netaddr_dest; + + int err = fib_register_rp(&gnrc_ipv6_fib_table, &aodvv2_prefix.u8[0], + aodvv2_address_type_size); + if ( err != 0) { + DEBUG("[aodvv2] ERROR: cannot register at fib, error code:\n"); + exit(1); + } + + /* start listening for incoming AODVv2 packets and FIB control messages */ while (1) { msg_receive(&msg); switch (msg.type) { case GNRC_NETAPI_MSG_TYPE_RCV: - AODV_DEBUG("received data:\n"); - gnrc_pktsnip_t *pkt = ((gnrc_pktsnip_t *)msg.content.ptr); + { + gnrc_pktsnip_t *pkt = (gnrc_pktsnip_t *) msg.content.ptr; if (pkt->size <= UDP_BUFFER_SIZE) { - memcpy(buf_rcv, pkt->data, pkt->size); + memcpy(pkt_rcv_buf, pkt->data, pkt->size); if(pkt->next->next->type == GNRC_NETTYPE_IPV6) { - ipv6_addr_t_to_netaddr(&(((ipv6_hdr_t*)(pkt->next->next->data))->src), &_sender); - } - - if (netaddr_cmp(&_sender, &na_local) == 0) { - AODV_DEBUG("received our own packet, dropping it.\n"); + ipv6_addr_t_to_netaddr(&(((ipv6_hdr_t*) + (pkt->next->next->data))->src), + &pkt_sender); } - else { - aodv_packet_reader_handle_packet((void *) buf_rcv, pkt->size, &_sender); + if (!netaddr_cmp(&pkt_sender, &aodvv2_netaddr_local) == 0) { + /* didn't receive our own packet: handle, don't drop */ + aodv_packet_reader_handle_packet((void *) pkt_rcv_buf, + pkt->size, &pkt_sender); } } - gnrc_pktbuf_release(pkt); break; + } case GNRC_NETAPI_MSG_TYPE_SND: break; case GNRC_NETAPI_MSG_TYPE_GET: case GNRC_NETAPI_MSG_TYPE_SET: msg_reply(&msg, &reply); break; + case FIB_MSG_RP_SIGNAL_UNREACHABLE_DESTINATION: + { + rp_address_msg_t* rp_msg = (rp_address_msg_t*)msg.content.ptr; + if (rp_msg->address_size == sizeof(ipv6_addr_t)) { + /* We currently only support IPv6*/ + memcpy(&ipv6_dest, rp_msg->address, rp_msg->address_size); + /* Reply to the FIB so that it can stop blocking */ + msg_reply(&msg, &msg); + + /* perform/initiate a rreq for dst here*/ + ipv6_addr_t_to_netaddr(&ipv6_dest, &netaddr_dest); + + aodvv2_seqnum_t seqnum = seqnum_get(); + seqnum_inc(); + + /* Build new RREQ */ + struct aodvv2_packet_data new_rreq_data = (struct aodvv2_packet_data) { + .hoplimit = AODVV2_MAX_HOPCOUNT, + .metricType = aodv_metric_type, + .origNode = (struct node_data) { + .addr = aodvv2_netaddr_local, + .metric = 0, + .seqnum = seqnum, + }, + .targNode = (struct node_data) { + .addr = netaddr_dest, + }, + .timestamp = (timex_t) {0,0} /* never used, exists merely + * to silence compiler*/ + }; + + /* since we're originating the RREQ, add it to the RREQ + * table or add its predecessor (if any) */ + rreqtable_is_redundant(&new_rreq_data); + + aodv_packet_writer_send_rreq(&new_rreq_data, + &aodvv2_netaddr_mcast); + } + else { + /* Reply to the FIB so that it can stop blocking */ + msg_reply(&msg, &msg); + } + break; + } default: - AODV_DEBUG("received something unexpected\n"); + DEBUG("[aodvv2] received msg of unexpected type: %d\n", msg.type); break; } } @@ -435,82 +251,56 @@ static void *_aodv_receiver_thread(void *arg) } /** - The code o this function was borrowed from: - examples/ng_networking/udp.c:34 - :90 - TODO: merge into write callback -*/ -static void _aodv_send(ipv6_addr_t addr, uint16_t port, void *data, size_t data_length) + * Send finalized RFC 5444 packets. This callback is called by every + * aodv_packet_writer_send_* function. + */ +static void aodv_send_packet(struct rfc5444_writer *wr __attribute__ ((unused)), + struct rfc5444_writer_target *iface __attribute__((unused)), + void *buffer, size_t length) { + ipv6_addr_t addr_send; gnrc_pktsnip_t *payload, *pkt_with_udp, *pkt_with_ip; - /* allocate payload */ - payload = gnrc_pktbuf_add(NULL, data, data_length, GNRC_NETTYPE_UNDEF); + /* fetch the address the packet is supposed to be sent to (i.e. to a + * specific node or the multicast address) from the writer_target struct + * iface* is stored in. This is a bit hacky, but it does the trick. */ + struct writer_target *wt = container_of(iface, struct writer_target, interface); + + print_json_pkt_sent(wt); + netaddr_to_ipv6_addr_t(&wt->target_addr, &addr_send); + + /* allocate payload (i.e. the RFC5444 packet)*/ + payload = gnrc_pktbuf_add(NULL, buffer, length, GNRC_NETTYPE_UNDEF); if (payload == NULL) { DEBUG("Error: unable to copy data to packet buffer\n"); return; } /* allocate UDP header, set payload, set source port := destination port */ - pkt_with_udp = gnrc_udp_hdr_build(payload, port, port); + pkt_with_udp = gnrc_udp_hdr_build(payload, MANET_PORT, MANET_PORT); if (pkt_with_udp == NULL) { DEBUG("Error: unable to allocate UDP header\n"); gnrc_pktbuf_release(payload); return; } /* allocate IPv6 header, set pkt_with_udp as payload */ - pkt_with_ip = gnrc_ipv6_hdr_build(pkt_with_udp, &_v6_addr_local, &addr); + pkt_with_ip = gnrc_ipv6_hdr_build(pkt_with_udp, &aodv_ipv6_addr_local, + &addr_send); if (pkt_with_ip == NULL) { DEBUG("Error: unable to allocate IPv6 header\n"); gnrc_pktbuf_release(pkt_with_udp); return; } /* all headers are set, send packet */ - if(!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, pkt_with_ip)) { + if(!gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, + pkt_with_ip)) { DEBUG("Error sending packet\n"); gnrc_pktbuf_release(pkt_with_ip); } } -/** - * Handle the output of the RFC5444 packet creation process. This callback is - * called by every writer_send_* function. - */ -static void _write_packet(struct rfc5444_writer *wr __attribute__ ((unused)), - struct rfc5444_writer_target *iface __attribute__((unused)), - void *buffer, size_t length) -{ - AODV_DEBUG("%s()\n", __func__); - ipv6_addr_t addr_send; - - /* generate hexdump and human readable representation of packet - * and print to console */ - abuf_hexdump(&_hexbuf, "\t", buffer, length); - rfc5444_print_direct(&_hexbuf, buffer, length); - /* DEBUG("%s", abuf_getptr(&_hexbuf)); */ - abuf_clear(&_hexbuf); - - /* fetch the address the packet is supposed to be sent to (i.e. to a - * specific node or the multicast address) from the writer_target struct - * iface* is stored in. This is a bit hacky, but it does the trick. */ - wt = container_of(iface, struct writer_target, interface); - print_json_pkt_sent(wt); - netaddr_to_ipv6_addr_t(&wt->target_addr, &addr_send); - - /* When originating a RREQ, add it to our RREQ table/update its predecessor */ - // TOOD: shouldn't this be moved to the fib thread?! - if (wt->type == RFC5444_MSGTYPE_RREQ - && netaddr_cmp(&wt->packet_data.origNode.addr, &na_local) == 0) { - DEBUG("originating RREQ with SeqNum %d towards %s via %s; updating RREQ table...\n", - wt->packet_data.origNode.seqnum, - netaddr_to_string(&nbuf, &wt->packet_data.targNode.addr), - ipv6_addr_to_str(addr_str, &addr_send, IPV6_MAX_ADDR_STR_LEN)); - rreqtable_is_redundant(&wt->packet_data); - } - - _aodv_send(addr_send, (uint16_t) MANET_PORT, buffer, length); -} - -/* Print the json representation of a sent packet to stdout for debugging */ +/* Print the json representation of a sent packet to stdout for automated + * testing and debugging */ static void print_json_pkt_sent(struct writer_target *wt) { #if TEST_SETUP @@ -539,26 +329,3 @@ static void print_json_pkt_sent(struct writer_target *wt) (void) wt; /* silence compiler */ #endif } - -/* free the matryoshka doll of cobbled-together structs that the sender_thread receives */ -/* TODO deleteme -static void _deep_free_msg_container(struct msg_container *mc) -{ - int type = mc->type; - if ((type == RFC5444_MSGTYPE_RREQ) || (type == RFC5444_MSGTYPE_RREP)) { - struct rreq_rrep_data *rreq_rrep_data = (struct rreq_rrep_data *) mc->data; - free(rreq_rrep_data->packet_data); - if (netaddr_cmp(rreq_rrep_data->next_hop, &na_mcast) != 0) { - free(rreq_rrep_data->next_hop); - } - } - else if (type == RFC5444_MSGTYPE_RERR) { - struct rerr_data *rerr_data = (struct rerr_data *) mc->data; - if (netaddr_cmp(rerr_data->next_hop, &na_mcast) != 0) { - free(rerr_data->next_hop); - } - } - free(mc->data); - free(mc); -} -*/ \ No newline at end of file diff --git a/sys/net/gnrc/routing/aodvv2/constants.h b/sys/net/gnrc/routing/aodvv2/constants.h index ea44c4b9a443..8f81114619a5 100644 --- a/sys/net/gnrc/routing/aodvv2/constants.h +++ b/sys/net/gnrc/routing/aodvv2/constants.h @@ -51,11 +51,8 @@ enum tlv_index TLV_METRIC, }; -/* my multicast address */ -extern struct netaddr na_mcast; - -// TODO DELETEME (for debugging only) -extern ipv6_addr_t _v6_addr_local; +/* the multicast address for this router */ +extern struct netaddr aodvv2_netaddr_mcast; /* the interface this protocol operates on */ extern kernel_pid_t aodvv2_if_id; diff --git a/sys/net/gnrc/routing/aodvv2/reader.c b/sys/net/gnrc/routing/aodvv2/reader.c index a51bb4ffc7ae..629e8b99c2f2 100644 --- a/sys/net/gnrc/routing/aodvv2/reader.c +++ b/sys/net/gnrc/routing/aodvv2/reader.c @@ -353,11 +353,11 @@ static enum rfc5444_result _cb_rreq_end_callback( /* make sure to start with a clean metric value */ packet_data.targNode.metric = 0; - aodv_send_rrep(&packet_data, &packet_data.sender); + aodv_packet_writer_send_rrep(&packet_data, &packet_data.sender); } else { AODV_DEBUG("I am not TargNode, forwarding RREQ\n"); - aodv_send_rreq(&packet_data); + aodv_packet_writer_send_rreq(&packet_data, &aodvv2_netaddr_mcast); } return RFC5444_OKAY; } @@ -370,6 +370,7 @@ static enum rfc5444_result _cb_rreq_end_callback( */ static enum rfc5444_result _cb_rrep_blocktlv_messagetlvs_okay(struct rfc5444_reader_tlvblock_context *cont) { + if (!cont->has_hoplimit) { AODV_DEBUG("\tERROR: missing hop limit\n"); return RFC5444_DROP_PACKET; @@ -538,8 +539,15 @@ static enum rfc5444_result _cb_rrep_end_callback( /* If HandlingRtr is not RREQ_Gen then the outgoing RREP is sent to the * Route.NextHopAddress for the RREP.AddrBlk[OrigNodeNdx]. */ AODV_DEBUG("Not my RREP, passing it on to the next hop\n"); - aodv_send_rrep(&packet_data, - routingtable_get_next_hop(&packet_data.origNode.addr,packet_data.metricType)); + + // TODO DELETEME (for debugging only) + print_routingtable(); + struct netaddr_str nbuf; + printf("%s\n", netaddr_to_string(&nbuf, routingtable_get_next_hop(&packet_data.origNode.addr,packet_data.metricType))); + + aodv_packet_writer_send_rrep(&packet_data, routingtable_get_next_hop( + &packet_data.origNode.addr, + packet_data.metricType)); } return RFC5444_OKAY; } @@ -567,7 +575,8 @@ static enum rfc5444_result _cb_rerr_blocktlv_messagetlvs_okay(struct rfc5444_rea return RFC5444_OKAY; } -static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_reader_tlvblock_context *cont) +static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay( + struct rfc5444_reader_tlvblock_context *cont) { #if AODV_DEBUG /* cppcheck-suppress unusedVariable as nbuf is needed by AODV_DEBUG. */ @@ -599,13 +608,15 @@ static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_rea } /* Check if there is an entry for unreachable node in our routing table */ - unreachable_entry = routingtable_get_entry(&packet_data.origNode.addr, packet_data.metricType); + unreachable_entry = routingtable_get_entry(&packet_data.origNode.addr, + packet_data.metricType); if (unreachable_entry) { AODV_DEBUG("\t found possibly unreachable entry.\n"); /* check if route to unreachable node has to be marked as broken and RERR has to be forwarded */ if (netaddr_cmp(&unreachable_entry->nextHopAddr, &packet_data.sender) == 0 - && (!tlv || seqnum_cmp(unreachable_entry->seqnum, packet_data.origNode.seqnum) == 0)) { + && (!tlv || seqnum_cmp(unreachable_entry->seqnum, + packet_data.origNode.seqnum) == 0)) { unreachable_entry->state = ROUTE_STATE_INVALID; unreachable_nodes[num_unreachable_nodes].addr = packet_data.origNode.addr; unreachable_nodes[num_unreachable_nodes].seqnum = packet_data.origNode.seqnum; @@ -613,7 +624,8 @@ static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_rea } /* remove entry from FIB */ - fib_remove_entry(&gnrc_ipv6_fib_table, packet_data.origNode.addr._addr, sizeof(ipv6_addr_t)); + fib_remove_entry(&gnrc_ipv6_fib_table, packet_data.origNode.addr._addr, + sizeof(ipv6_addr_t)); } /* TODO: run routingtable_break_and_get_all_hopping_over() in addr, remove @@ -622,7 +634,9 @@ static enum rfc5444_result _cb_rerr_blocktlv_addresstlvs_okay(struct rfc5444_rea return RFC5444_OKAY; } -static enum rfc5444_result _cb_rerr_end_callback(struct rfc5444_reader_tlvblock_context *cont, bool dropped) +static enum rfc5444_result _cb_rerr_end_callback( + struct rfc5444_reader_tlvblock_context *cont, + bool dropped) { (void) cont; @@ -636,7 +650,8 @@ static enum rfc5444_result _cb_rerr_end_callback(struct rfc5444_reader_tlvblock_ return RFC5444_DROP_PACKET; } /* gather all unreachable nodes and put them into a RERR */ - aodv_send_rerr(unreachable_nodes, num_unreachable_nodes, &na_mcast); + aodv_packet_writer_send_rerr(unreachable_nodes, num_unreachable_nodes, + AODVV2_MAX_HOPCOUNT, &aodvv2_netaddr_mcast); return RFC5444_OKAY; } diff --git a/sys/net/gnrc/routing/aodvv2/utils.h b/sys/net/gnrc/routing/aodvv2/utils.h index 3af0832bc4ff..684944af34b0 100644 --- a/sys/net/gnrc/routing/aodvv2/utils.h +++ b/sys/net/gnrc/routing/aodvv2/utils.h @@ -88,7 +88,9 @@ void rreqtable_init(void); /** * Check if a RREQ is redundant, i.e. was received from another node already. - * Behaves as described in Sections 5.7. and 7.6. + * If it is not redundant, add it to the RREQ table. (TODO split this up into 2 + * functions) + * * @param packet_data data of the RREQ in question * @return true if packet_data is redundant, false otherwise. */ diff --git a/sys/net/gnrc/routing/aodvv2/writer.c b/sys/net/gnrc/routing/aodvv2/writer.c index fa774ee17a8b..b10990c9652e 100644 --- a/sys/net/gnrc/routing/aodvv2/writer.c +++ b/sys/net/gnrc/routing/aodvv2/writer.c @@ -322,6 +322,7 @@ void aodv_packet_writer_send_rerr(struct unreachable_node unreachable_nodes[], s { AODV_DEBUG("%s()\n", __func__); + // TODO: shouldn't hoplimit be always 1 because a RERR is always regenerated? if ((unreachable_nodes == NULL) || (next_hop == NULL)) { return; }