Browse Source

sys: net: remove AODVv2

(will be upgraded to gnrc soon)
dev/timer
Kaspar Schleiser 8 years ago
parent
commit
00a44c9147
  1. 3
      sys/Makefile
  2. 52
      sys/net/include/aodvv2/aodvv2.h
  3. 102
      sys/net/include/aodvv2/types.h
  4. 1
      sys/net/routing/aodvv2/Makefile
  5. 478
      sys/net/routing/aodvv2/aodv.c
  6. 131
      sys/net/routing/aodvv2/aodv.h
  7. 53
      sys/net/routing/aodvv2/aodv_debug.h
  8. 64
      sys/net/routing/aodvv2/constants.h
  9. 792
      sys/net/routing/aodvv2/reader.c
  10. 62
      sys/net/routing/aodvv2/reader.h
  11. 299
      sys/net/routing/aodvv2/routingtable.c
  12. 160
      sys/net/routing/aodvv2/routingtable.h
  13. 49
      sys/net/routing/aodvv2/seqnum.c
  14. 63
      sys/net/routing/aodvv2/seqnum.h
  15. 241
      sys/net/routing/aodvv2/utils.c
  16. 116
      sys/net/routing/aodvv2/utils.h
  17. 348
      sys/net/routing/aodvv2/writer.c
  18. 101
      sys/net/routing/aodvv2/writer.h
  19. 31
      tests/aodvv2/Makefile
  20. 190
      tests/aodvv2/aodv_fib_tests.c
  21. 35
      tests/aodvv2/aodv_fib_tests.h
  22. 69
      tests/aodvv2/aodv_tests.h
  23. 171
      tests/aodvv2/aodv_writer_tests.c
  24. 35
      tests/aodvv2/aodv_writer_tests.h
  25. 124
      tests/aodvv2/main.c

3
sys/Makefile

@ -40,9 +40,6 @@ endif
ifneq (,$(filter routing,$(USEMODULE)))
DIRS += net/routing
endif
ifneq (,$(filter aodvv2,$(USEMODULE)))
DIRS += net/routing/aodvv2
endif
ifneq (,$(filter ieee802154,$(USEMODULE)))
DIRS += net/link_layer/ieee802154
endif

52
sys/net/include/aodvv2/aodvv2.h

@ -1,52 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#ifndef AODVV2_H_
#define AODVV2_H_
#include "common/netaddr.h"
#include "rfc5444/rfc5444_print.h"
#include "aodvv2/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize the AODVv2 routing protocol.
*/
void aodv_init(void);
/**
* @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_ */
/** @} */

102
sys/net/include/aodvv2/types.h

@ -1,102 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#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 */

1
sys/net/routing/aodvv2/Makefile

@ -1 +0,0 @@
include $(RIOTBASE)/Makefile.base

478
sys/net/routing/aodvv2/aodv.c

@ -1,478 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#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;
#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 sockaddr6_t sa_wp;
static ipv6_addr_t _v6_addr_local, _v6_addr_mcast, _v6_addr_loopback;
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;
ipv6_addr_t aodvv2_prefix;
int aodvv2_prefix_len;
void aodv_init(void)
{
AODV_DEBUG("%s()\n", __func__);
/* init this thread's IPC msg queue (TODO: do I need to do this?) */
msg_t msgq[RCV_MSG_Q_SIZE];
msg_init_queue(msgq, sizeof msgq);
/* TODO: set & handle prefix and prefix_len properly (consider AODVV2_RIOT_PREFIXLEN!) */
aodvv2_prefix_len = 0;
/* TODO: set if_id properly (as param of aodv_init) */
aodvv2_if_id = 0;
net_if_set_src_address_mode(aodvv2_if_id, NET_IF_TRANS_ADDR_M_SHORT);
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;
ipv6_addr_t dest;
struct netaddr na_dest;
fib_register_rp((uint8_t*) &aodvv2_prefix, aodvv2_prefix_len);
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(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",
ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &dest));
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 */
ipv6_addr_set_all_nodes_addr(&_v6_addr_mcast);
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 */
ipv6_net_if_get_best_src_addr(&_v6_addr_local, &_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);
ipv6_addr_set_loopback_addr(&_v6_addr_loopback);
/* init sockaddr that write_packet will use to send data */
sa_wp.sin6_family = AF_INET6;
sa_wp.sin6_port = HTONS(MANET_PORT);
}
/* 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;
uint32_t fromlen;
char buf_rcv[UDP_BUFFER_SIZE];
msg_t msg_q[RCV_MSG_Q_SIZE];
msg_init_queue(msg_q, RCV_MSG_Q_SIZE);
sockaddr6_t sa_rcv = { .sin6_family = AF_INET6,
.sin6_port = HTONS(MANET_PORT)
};
int sock_rcv = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (-1 == socket_base_bind(sock_rcv, &sa_rcv, sizeof(sa_rcv))) {
AODV_DEBUG("Error: bind to receive socket failed!\n");
socket_base_close(sock_rcv);
return NULL;
}
while (true) {
int32_t rcv_size = socket_base_recvfrom(sock_rcv, (void *)buf_rcv, UDP_BUFFER_SIZE, 0,
&sa_rcv, &fromlen);
if (rcv_size < 0) {
AODV_DEBUG("ERROR receiving data!\n");
}
struct netaddr _sender;
ipv6_addr_t_to_netaddr(&sa_rcv.sin6_addr, &_sender);
/* We sometimes get passed our own packets. Drop them. */
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, rcv_size, &_sender);
}
}
socket_base_close(sock_rcv);
return NULL;
}
/**
* 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__);
/* 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, &sa_wp.sin6_addr);
/* 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) {
AODV_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, IPV6_MAX_ADDR_STR_LEN, &sa_wp.sin6_addr));
rreqtable_is_redundant(&wt->packet_data);
}
int bytes_sent = socket_base_sendto(_sock_snd, buffer, length,
0, &sa_wp, sizeof sa_wp);
(void) bytes_sent;
AODV_DEBUG("%d bytes sent.\n", bytes_sent);
}
/* 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);
}

131
sys/net/routing/aodvv2/aodv.h

@ -1,131 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#ifndef AODV_H_
#define AODV_H_
#include <sixlowpan/ip.h>
#include "sixlowpan.h"
#include "kernel.h"
#include "udp.h"
#include "socket_base/socket.h"
#include "net_help.h"
#include "net_if.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 When set as ipv6_iface_routing_provider, this function is called by
* ipv6_sendto() to determine the next hop towards dest. This function
* is non-blocking.
*
* @param[in] dest destination of the packet
* @return Address of the next hop towards dest if there is any,
* NULL if there is none (yet)
*/
ipv6_addr_t *aodv_get_next_hop(ipv6_addr_t *dest);
/**
* @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_ */

53
sys/net/routing/aodvv2/aodv_debug.h

@ -1,53 +0,0 @@
/*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#ifndef AODV_DEBUG_H_
#define AODV_DEBUG_H_
#include <stdio.h>
#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_*/
/** @} */

64
sys/net/routing/aodvv2/constants.h

@ -1,64 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#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_ */

792
sys/net/routing/aodvv2/reader.c

@ -1,792 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
* Copyright (C) 2014 Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
*
* 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 <lotte.steenbrink@fu-berlin.de>
*/
#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 <inttypes.h>
#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
*/
ipv6_addr_t sender_tmp;
netaddr_to_ipv6_addr_t(&packet_data.sender, &sender_tmp);
ndp_neighbor_cache_t *ndp_nc_entry = ndp_neighbor_cache_search(&sender_tmp);
if (ndp_nc_entry == NULL) {
AODV_DEBUG("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(ipv6_addr_t), 0,
tmp_rt_entry->nextHopAddr._addr, sizeof(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(ipv6_addr_t), rt_entry->nextHopAddr._addr,
sizeof(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)