mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-15 09:33:50 +01:00
sys: net: remove AODVv2
(will be upgraded to gnrc soon)
This commit is contained in:
parent
9db612cd53
commit
00a44c9147
@ -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
|
||||
|
||||
@ -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_ */
|
||||
/** @} */
|
||||
@ -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 +0,0 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
@ -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);
|
||||
}
|
||||
@ -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_ */
|
||||
@ -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_*/
|
||||
/** @} */
|
||||
@ -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_ */
|
||||
@ -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)
|
||||
|| !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
|
||||
*/
|
||||
|
||||
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_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(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.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(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
|
||||
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;
|
||||
}
|
||||
@ -1,62 +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>
|
||||
*/
|
||||
|
||||
#ifndef AODVV2_READER_H_
|
||||
#define AODVV2_READER_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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_ */
|
||||
@ -1,299 +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 Cobbled-together routing table.
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@ -1,160 +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 Cobbled-together routing table.
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef AODVV2_ROUTINGTABLE_H_
|
||||
#define AODVV2_ROUTINGTABLE_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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_*/
|
||||
@ -1,49 +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 sequence number
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
@ -1,63 +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 sequence number
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef AODVV2_SEQNUM_H_
|
||||
#define AODVV2_SEQNUM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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_ */
|
||||
@ -1,241 +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 client- and RREQ-table, ipv6 address representation converters
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#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(ipv6_addr_t *src, struct netaddr *dst)
|
||||
{
|
||||
dst->_type = AF_INET6;
|
||||
dst->_prefix_len = AODVV2_RIOT_PREFIXLEN;
|
||||
memcpy(dst->_addr, src, sizeof(dst->_addr));
|
||||
}
|
||||
|
||||
void netaddr_to_ipv6_addr_t(struct netaddr *src, ipv6_addr_t *dst)
|
||||
{
|
||||
memcpy(dst, src->_addr, sizeof(uint8_t) * NETADDR_MAX_LENGTH);
|
||||
}
|
||||
@ -1,116 +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 client- and RREQ-table, ipv6 address representation converters
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef AODVV2_UTILS_H_
|
||||
#define AODVV2_UTILS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "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 ipv6_addr_t to convert
|
||||
* @param dst (empty) netaddr to convert into
|
||||
*/
|
||||
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 ipv6_addr_t to convert
|
||||
*/
|
||||
void netaddr_to_ipv6_addr_t(struct netaddr *src, ipv6_addr_t *dst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AODVV2_UTILS_H_ */
|
||||
@ -1,348 +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 writer to create RFC5444 aodvv2 messages
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
@ -1,101 +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 writer to create RFC5444 aodvv2 messages
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#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_ */
|
||||
@ -1,31 +0,0 @@
|
||||
# name of your application
|
||||
APPLICATION = aodvv2_tests
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# If no BOARD is found in the environment, use this default:
|
||||
BOARD ?= native
|
||||
|
||||
# This test has not been verified to work on any other boards-- proceed with caution.
|
||||
BOARD_WHITELIST := native
|
||||
|
||||
# This has to be the absolute path to the RIOT base directory:
|
||||
RIOTBASE ?= $(CURDIR)/../..
|
||||
|
||||
# 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
|
||||
CFLAGS += -DRIOT
|
||||
CFLAGS += -DFIB_DEVEL_HELPER
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
# Modules to include
|
||||
USEMODULE += defaulttransceiver
|
||||
USEMODULE += aodvv2
|
||||
USEMODULE += udp
|
||||
|
||||
export INCLUDES += -I$(RIOTBASE)/sys/net/routing/aodvv2/
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
@ -1,190 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tests for the interaction between AODVv2 and the FIB
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "aodv_fib_tests.h"
|
||||
#include "aodv_tests.h"
|
||||
|
||||
#include "common/autobuf.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
#include "rfc5444/rfc5444_print.h"
|
||||
#include "ng_fib.h"
|
||||
|
||||
#include "reader.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/* make sure packet is not rejected because "sender" is not in the neighbor cache */
|
||||
static void _aodv_test_add_to_nc(struct netaddr *sender_na){
|
||||
ipv6_addr_t sender;
|
||||
|
||||
netaddr_to_ipv6_addr_t(sender_na, &sender);
|
||||
/* TODO: isrouter = 1 correct? */
|
||||
ndp_neighbor_cache_add(aodvv2_iface_id, &sender, &sender.uint16[7], 2, 1,
|
||||
NDP_NCE_STATUS_REACHABLE, NDP_NCE_TYPE_TENTATIVE, 0xffff);
|
||||
}
|
||||
|
||||
/* Handle RREQ with no anomalies */
|
||||
static void aodv_test_add_to_fib_regular_rreq(void)
|
||||
{
|
||||
printf("\n============= Handling regular RREQ ================================\n");
|
||||
ipv6_addr_t next_hop;
|
||||
kernel_pid_t iface_id;
|
||||
size_t next_hop_size = sizeof(ipv6_addr_t);
|
||||
uint32_t next_hop_flags = 0;
|
||||
|
||||
_aodv_test_add_to_nc(aodv_test_plain_rreq.sender);
|
||||
aodv_packet_reader_handle_packet((void *) aodv_test_plain_rreq.buffer,
|
||||
aodv_test_plain_rreq.length,
|
||||
aodv_test_plain_rreq.sender);
|
||||
|
||||
printf("Checking FIB ...\n");
|
||||
|
||||
/* Check if route back to origaddr was created */
|
||||
int fib_success = fib_get_next_hop(&iface_id, &next_hop.uint8[0], &next_hop_size,
|
||||
&next_hop_flags, aodvv2_test_origaddr._addr,
|
||||
sizeof(ipv6_addr_t), 0);
|
||||
assert(0 == fib_success);
|
||||
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
/* Handle RREQ with no anomalies */
|
||||
static void aodv_test_add_to_fib_regular_rrep(void)
|
||||
{
|
||||
printf("\n============= Handling regular RREP ================================\n");
|
||||
ipv6_addr_t next_hop;
|
||||
kernel_pid_t iface_id;
|
||||
size_t next_hop_size = sizeof(ipv6_addr_t);
|
||||
uint32_t next_hop_flags = 0;
|
||||
timex_t now;
|
||||
|
||||
_aodv_test_add_to_nc(aodv_test_plain_rrep.sender);
|
||||
|
||||
/* Make sure route back is known TODO make this global too?!*/
|
||||
vtimer_now(&now);
|
||||
struct aodvv2_routing_entry_t tmp_rt_entry = {
|
||||
.addr = aodvv2_test_origaddr,
|
||||
.seqnum = 1,
|
||||
.nextHopAddr = aodvv2_test_sender_oa,
|
||||
.lastUsed = now,
|
||||
.expirationTime = timex_add(now,
|
||||
timex_set(AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME, 0)),
|
||||
.metricType = AODVV2_DEFAULT_METRIC_TYPE,
|
||||
.metric = 2,
|
||||
.state = ROUTE_STATE_ACTIVE,
|
||||
};
|
||||
routingtable_add_entry(&tmp_rt_entry);
|
||||
|
||||
aodv_packet_reader_handle_packet((void *) aodv_test_plain_rrep.buffer,
|
||||
aodv_test_plain_rrep.length,
|
||||
aodv_test_plain_rrep.sender);
|
||||
printf("Checking FIB ...\n");
|
||||
|
||||
/* Check if route back to origaddr was created */
|
||||
int fib_success = fib_get_next_hop(&iface_id, &next_hop.uint8[0], &next_hop_size,
|
||||
&next_hop_flags, aodvv2_test_targaddr._addr,
|
||||
sizeof(ipv6_addr_t), 0);
|
||||
assert(0 == fib_success);
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
static void aodv_test_update_fib_regular_rreq(void)
|
||||
{
|
||||
printf("\n============= Handling more recent RREQ ============================\n");
|
||||
timex_t lifetime, now;
|
||||
|
||||
printf("Checking FIB ...\n");
|
||||
aodv_packet_reader_handle_packet((void *) aodv_test_more_recent_rreq.buffer,
|
||||
aodv_test_more_recent_rreq.length,
|
||||
aodv_test_more_recent_rreq.sender);
|
||||
|
||||
assert(0 == fib_devel_get_lifetime(&lifetime, aodvv2_test_origaddr._addr, sizeof(ipv6_addr_t)));
|
||||
|
||||
/* assuming some ms passed during these operations... */
|
||||
vtimer_now(&now);
|
||||
timex_t cmp_lifetime = timex_add(now, timex_set(0, 900000));
|
||||
assert(1 == timex_cmp(lifetime, cmp_lifetime));
|
||||
|
||||
printf("Done. \n");
|
||||
}
|
||||
|
||||
static void aodv_test_update_fib_regular_rrep(void)
|
||||
{
|
||||
printf("\n============= Handling more recent RREP ============================\n");
|
||||
timex_t lifetime, now;
|
||||
|
||||
printf("Checking FIB ...\n");
|
||||
aodv_packet_reader_handle_packet((void *) aodv_test_more_recent_rrep.buffer,
|
||||
aodv_test_more_recent_rrep.length,
|
||||
aodv_test_more_recent_rrep.sender);
|
||||
|
||||
assert(0 == fib_devel_get_lifetime(&lifetime, aodvv2_test_targaddr._addr, sizeof(ipv6_addr_t)));
|
||||
|
||||
/* assuming some ms passed during these operations... */
|
||||
vtimer_now(&now);
|
||||
timex_t cmp_lifetime = timex_add(now, timex_set(0, 900000));
|
||||
assert(1 == timex_cmp(lifetime, cmp_lifetime));
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
static void aodv_test_route_expired(void)
|
||||
{
|
||||
printf("\n============= testing if route vanishes after expiring ===========\n");
|
||||
kernel_pid_t iface_id;
|
||||
uint32_t next_hop_flags = 0;
|
||||
size_t next_hop_size = sizeof(ipv6_addr_t);
|
||||
ipv6_addr_t next_hop;
|
||||
|
||||
printf("waiting until route expires... (about 4.5 minutes)\n");
|
||||
/* TODO: use MAXTIME */
|
||||
sleep(AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME);
|
||||
printf("Checking FIB ...\n");
|
||||
|
||||
/* Check if route back to origaddr was created */
|
||||
int fib_success = fib_get_next_hop(&iface_id, &next_hop.uint8[0], &next_hop_size,
|
||||
&next_hop_flags, aodvv2_test_origaddr._addr,
|
||||
sizeof(ipv6_addr_t), 0);
|
||||
assert( 0 != fib_success);
|
||||
|
||||
printf("Done.\n");
|
||||
|
||||
}
|
||||
|
||||
void aodv_test_add_to_fib(void)
|
||||
{
|
||||
/* overwrite the aodvv2 packet writer so that messages aren't actually swnt */
|
||||
aodv_packet_writer_init(aodv_test_drop_packet);
|
||||
|
||||
printf("Starting tests...\n");
|
||||
aodv_test_add_to_fib_regular_rreq();
|
||||
sleep(5);
|
||||
aodv_test_update_fib_regular_rreq();
|
||||
sleep(5);
|
||||
aodv_test_add_to_fib_regular_rrep();
|
||||
sleep(5);
|
||||
aodv_test_update_fib_regular_rrep();
|
||||
sleep(5);
|
||||
aodv_test_route_expired();
|
||||
printf("All done!\n");
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tests for the interaction between AODVv2 and the FIB
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef AODV_FIB_TESTS_H_
|
||||
#define AODV_FIB_TESTS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void aodv_test_add_to_fib(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AODV_FIB_TESTS_H_ */
|
||||
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief constants and global variables for AODVv2 tests
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef AODV_TESTS_H_
|
||||
#define AODV_TESTS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "udp.h"
|
||||
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#define AODV_TEST_MSGBUF_MAX (500)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char buffer[AODV_TEST_MSGBUF_MAX];
|
||||
uint8_t length;
|
||||
struct netaddr* sender;
|
||||
} aodvv2_test_msg;
|
||||
|
||||
|
||||
extern radio_address_t aodvv2_iface_id;
|
||||
|
||||
extern aodvv2_test_msg aodv_test_plain_rreq;
|
||||
extern aodvv2_test_msg aodv_test_more_recent_rreq;
|
||||
extern aodvv2_test_msg aodv_test_plain_rrep;
|
||||
extern aodvv2_test_msg aodv_test_more_recent_rrep;
|
||||
|
||||
/*
|
||||
Messages will always be sent/stored along the following path:
|
||||
OrigAddr -> sender_oa -> TESTNODE -> sender_ta -> TargAddr
|
||||
OrigAddr <- sender_oa <- TESTNODE <- sender_ta <- TargAddr */
|
||||
extern struct netaddr aodvv2_test_origaddr;
|
||||
extern struct netaddr aodvv2_test_sender_oa;
|
||||
extern struct netaddr aodvv2_test_sender_ta;
|
||||
extern struct netaddr aodvv2_test_targaddr;
|
||||
|
||||
/* callback for the rfc5444 packet writer. can be set with aodv_packet_writer_init()
|
||||
* To enforce the dropping of all control packets (and reduce overhead) */
|
||||
void aodv_test_drop_packet(struct rfc5444_writer *wr __attribute__ ((unused)),
|
||||
struct rfc5444_writer_target *iface __attribute__((unused)),
|
||||
void *buffer, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AODV_FIB_TESTS_H_ */
|
||||
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tests for the AODVv2 writer
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "aodv_writer_tests.h"
|
||||
#include "aodv_tests.h"
|
||||
|
||||
#include "aodv.h"
|
||||
#include "aodvv2/aodvv2.h"
|
||||
|
||||
#include "common/autobuf.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
#include "rfc5444/rfc5444_print.h"
|
||||
#include "writer.h"
|
||||
#include "thread.h"
|
||||
|
||||
aodvv2_test_msg aodv_test_plain_rreq;
|
||||
aodvv2_test_msg aodv_test_more_recent_rreq;
|
||||
aodvv2_test_msg aodv_test_plain_rrep;
|
||||
aodvv2_test_msg aodv_test_more_recent_rrep;
|
||||
|
||||
static aodvv2_test_msg* current_msg; /* Point to the buffer the current message should be written to.
|
||||
* Yes, this is awful, but I fear the oonf_apis
|
||||
* callback infrastructure leaves me no other choice...
|
||||
* Sorry. :( */
|
||||
|
||||
/* All the test data */
|
||||
static timex_t now, validity_t;
|
||||
|
||||
static struct aodvv2_packet_data plain_rreq_msg, plain_rrep_msg;
|
||||
|
||||
static int aodv_test_writer_init_data(void)
|
||||
{
|
||||
vtimer_now(&now);
|
||||
validity_t = timex_set(AODVV2_ACTIVE_INTERVAL + AODVV2_MAX_IDLETIME, 0);
|
||||
|
||||
plain_rreq_msg = (struct aodvv2_packet_data) {
|
||||
.hoplimit = AODVV2_MAX_HOPCOUNT,
|
||||
.sender = aodvv2_test_sender_oa,
|
||||
.metricType = AODVV2_DEFAULT_METRIC_TYPE,
|
||||
.origNode = {
|
||||
.addr = aodvv2_test_origaddr,
|
||||
.metric = 2,
|
||||
.seqnum = 1,
|
||||
},
|
||||
.targNode = {
|
||||
.addr = aodvv2_test_targaddr,
|
||||
.metric = 12,
|
||||
.seqnum = 1,
|
||||
},
|
||||
.timestamp = now,
|
||||
};
|
||||
|
||||
vtimer_now(&now);
|
||||
plain_rrep_msg = (struct aodvv2_packet_data) {
|
||||
.hoplimit = AODVV2_MAX_HOPCOUNT,
|
||||
.sender = aodvv2_test_sender_ta,
|
||||
.metricType = AODVV2_DEFAULT_METRIC_TYPE,
|
||||
.origNode = {
|
||||
.addr = aodvv2_test_origaddr,
|
||||
.metric = 4,
|
||||
.seqnum = 1,
|
||||
},
|
||||
.targNode = {
|
||||
.addr = aodvv2_test_targaddr,
|
||||
.metric = 2,
|
||||
.seqnum = 2,
|
||||
},
|
||||
.timestamp = now,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aodv_test_write_packet(struct rfc5444_writer *wr __attribute__ ((unused)),
|
||||
struct rfc5444_writer_target *iface __attribute__((unused)),
|
||||
void *buffer, size_t length)
|
||||
{
|
||||
printf("Writing message to buffer\n");
|
||||
/* make sure buffer is clear */
|
||||
memcpy(current_msg->buffer, buffer, length);
|
||||
current_msg->length = length;
|
||||
printf("Done.\n");
|
||||
}
|
||||
|
||||
static void aodv_test_writer_write_new_rreq(void)
|
||||
{
|
||||
current_msg = &aodv_test_plain_rreq;
|
||||
current_msg->sender = &aodvv2_test_sender_oa;
|
||||
aodv_send_rreq(&plain_rreq_msg);
|
||||
}
|
||||
|
||||
static void aodv_test_writer_write_more_recent_rreq(void)
|
||||
{
|
||||
plain_rreq_msg.origNode.seqnum += 1;
|
||||
current_msg = &aodv_test_more_recent_rreq;
|
||||
current_msg->sender = &aodvv2_test_sender_oa;
|
||||
aodv_send_rreq(&plain_rreq_msg);
|
||||
}
|
||||
|
||||
static void aodv_test_writer_write_new_rrep(void)
|
||||
{
|
||||
current_msg = &aodv_test_plain_rrep;
|
||||
current_msg->sender = &aodvv2_test_sender_ta;
|
||||
aodv_send_rrep(&plain_rrep_msg, &aodvv2_test_sender_ta);
|
||||
}
|
||||
|
||||
static void aodv_test_writer_write_more_recent_rrep(void)
|
||||
{
|
||||
plain_rrep_msg.targNode.seqnum += 1;
|
||||
current_msg = &aodv_test_more_recent_rrep;
|
||||
current_msg->sender = &aodvv2_test_sender_ta;
|
||||
aodv_send_rrep(&plain_rrep_msg, &aodvv2_test_sender_ta);
|
||||
}
|
||||
|
||||
/* Store packets in buffers that we can use them for testing */
|
||||
void write_packets_to_buf(void)
|
||||
{
|
||||
printf("============= Preparing to write packets to buffers ==================\n");
|
||||
|
||||
/* Make sure the threads are up and running */
|
||||
sleep(2);
|
||||
|
||||
if (0 != aodv_test_writer_init_data()){
|
||||
printf ("FAILED: unable to init data!\n");
|
||||
return;
|
||||
}
|
||||
/* overwrite the aodvv2 packet writer */
|
||||
aodv_packet_writer_init(aodv_test_write_packet);
|
||||
|
||||
aodv_test_writer_write_new_rreq();
|
||||
|
||||
/* make sure sender_thread is done */
|
||||
sleep(2);
|
||||
aodv_test_writer_write_more_recent_rreq();
|
||||
|
||||
/* make sure sender_thread is done */
|
||||
sleep(2);
|
||||
aodv_test_writer_write_new_rrep();
|
||||
|
||||
/* make sure sender_thread is done */
|
||||
sleep(2);
|
||||
aodv_test_writer_write_more_recent_rrep();
|
||||
|
||||
/* give current writer time to finish and init aodvv2 again cleanly
|
||||
* to undo the change to the aodv_packet_writer callback */
|
||||
sleep(2);
|
||||
aodv_init();
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tests for the AODVv2 writer
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef AODV_WRITER_TESTS_H_
|
||||
#define AODV_WRITER_TESTS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void write_packets_to_buf(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AODV_WRITER_TESTS_H_ */
|
||||
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hochschule für Angewandte Wissenschaften Hamburg (HAW)
|
||||
* Copyright (C) 2015 Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
* Copyright (C) 2014 Martin Landsmann <Martin.Landsmann@HAW-Hamburg.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 tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief tests for the interaction between AODVv2 and the FIB
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
* @author Martin Landsmann <Martin.Landsmann@HAW-Hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "udp.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "aodvv2/aodvv2.h"
|
||||
|
||||
#include "aodv_writer_tests.h"
|
||||
#include "aodv_fib_tests.h"
|
||||
#include "aodv_tests.h"
|
||||
|
||||
#define AODVV2_IFACE (0) /**< The used Trasmssion device */
|
||||
|
||||
/** The node IPv6 address */
|
||||
ipv6_addr_t myaddr;
|
||||
|
||||
radio_address_t aodvv2_iface_id;
|
||||
struct netaddr aodvv2_test_sender_oa, aodvv2_test_sender_ta, aodvv2_test_origaddr, aodvv2_test_targaddr;
|
||||
|
||||
/**
|
||||
* @brief prepares this node
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int aodvv2_setup_node(void)
|
||||
{
|
||||
/* setup the radio interface */
|
||||
if( net_if_set_src_address_mode(AODVV2_IFACE, NET_IF_TRANS_ADDR_M_SHORT) != 1 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
aodvv2_iface_id = net_if_get_hardware_address(AODVV2_IFACE);
|
||||
if( aodvv2_iface_id == 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* choose addresses */
|
||||
ipv6_addr_init(&myaddr, 0x2015, 0x3, 0x18, 0x1111, 0x0, 0x0, 0x0, aodvv2_iface_id);
|
||||
|
||||
/* and set it */
|
||||
if( ipv6_net_if_add_addr(AODVV2_IFACE, &myaddr, NDP_ADDR_STATE_PREFERRED, 0, 0, 0) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief init data that needs to be globally known
|
||||
*/
|
||||
static int aodvv2_init_testdata(void)
|
||||
{
|
||||
if( netaddr_from_string(&aodvv2_test_origaddr, "::10") == -1 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( netaddr_from_string(&aodvv2_test_sender_oa, "::11") == -1 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( netaddr_from_string(&aodvv2_test_sender_ta, "::12") == -1 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( netaddr_from_string(&aodvv2_test_targaddr, "::13") == -1 ) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void aodv_test_drop_packet(struct rfc5444_writer *wr __attribute__ ((unused)),
|
||||
struct rfc5444_writer_target *iface __attribute__((unused)),
|
||||
void *buffer, size_t length)
|
||||
{
|
||||
(void) buffer;
|
||||
(void) length;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if( aodvv2_init_testdata() != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( aodvv2_setup_node() != 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
aodv_init();
|
||||
|
||||
write_packets_to_buf();
|
||||
|
||||
sleep(5);
|
||||
|
||||
/* TODO:
|
||||
- use route and see if it updates the lifetime
|
||||
*/
|
||||
aodv_test_add_to_fib();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user