ipv6_nc: simplify API usage for NDP

* Bonus: simplify DEBUG output.
dev/timer
Martine Lenders 8 years ago
parent 0a81c9c9a8
commit 3e3f7bdf3c

@ -21,13 +21,14 @@
#ifndef NG_IPV6_NC_H_
#define NG_IPV6_NC_H_
#include <stdbool.h>
#include <stdint.h>
#include "kernel_types.h"
#include "net/ng_ipv6/addr.h"
#include "net/ng_netif.h"
#include "net/ng_pktqueue.h"
#include "timex.h"
#include "vtimer.h"
#ifdef __cplusplus
extern "C" {
@ -123,6 +124,23 @@ typedef struct {
uint8_t l2_addr_len; /**< Length of ng_ipv6_nc_t::l2_addr */
uint8_t flags; /**< Flags as defined above */
kernel_pid_t iface; /**< PID to the interface where the neighbor is */
vtimer_t rtr_timeout; /**< timeout timer for router flag */
/**
* @brief (Re)Transmission timer for neighbor solicitations of this entry and
* timeout for states.
*/
vtimer_t nbr_sol_timer;
/**
* @brief Delay timer for neighbor advertisements of this entry.
*/
vtimer_t nbr_adv_timer;
uint8_t unanswered_probes; /**< number of unanswered probes */
/**
* @}
*/
} ng_ipv6_nc_t;
/**
@ -141,16 +159,11 @@ void ng_ipv6_nc_init(void);
* to NG_IPV6_L2_ADDR_MAX. 0 if unknown.
* @param[in] flags Flags for the entry
*
* @return 0 on success
* @return -EADDRINUSE, if @p ipv6_addr is already registered to the neighbor
* cache.
* @return -EFAULT, if @p ipv6_addr was NULL.
* @return -EINVAL, if @p l2_addr_len is greater then @ref NG_IPV6_NC_L2_ADDR_MAX,
* @p ipv6_addr is unspecified or @p iface is KERNEL_PID_UNDEF.
* @return -ENOMEM, if no space is left to store entry.
* @return Pointer to new neighbor cache entry on success
* @return NULL, on failure
*/
int ng_ipv6_nc_add(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr,
const void *l2_addr, size_t l2_addr_len, uint8_t flags);
ng_ipv6_nc_t *ng_ipv6_nc_add(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr,
const void *l2_addr, size_t l2_addr_len, uint8_t flags);
/**
* @brief Removes a neighbor from the neighbor cache
@ -194,20 +207,49 @@ ng_ipv6_nc_t *ng_ipv6_nc_get_next(ng_ipv6_nc_t *prev);
ng_ipv6_nc_t *ng_ipv6_nc_get_next_router(ng_ipv6_nc_t *prev);
/**
* @brief Searches for any neighbor cache entry fitting the @p ipv6_addr,
* where you currently can send a packet to (do not confuse with
* NG_IPV6_NC_STATE_REACHABLE).
* @brief Returns the state of a neigbor cache entry.
*
* @param[in] iface PID to the interface where the neighbor is. If it
* is KERNEL_PID_UNDEF it will be searched on all
* interfaces.
* @param[in] ipv6_addr An IPv6 address
* @param[in] entry A neighbor cache entry
*
* @return The neighbor cache entry, if one is found.
* @return NULL, if none is found.
* @return The state of the neighbor cache entry as defined by its flags.
*/
ng_ipv6_nc_t *ng_ipv6_nc_get_reachable(kernel_pid_t iface,
const ng_ipv6_addr_t *ipv6_addr);
static inline uint8_t ng_ipv6_nc_get_state(const ng_ipv6_nc_t *entry)
{
return (entry->flags & NG_IPV6_NC_STATE_MASK);
}
/**
* @brief Returns the type of a neigbor cache entry.
*
* @param[in] entry A neighbor cache entry
*
* @return The type of the neighbor cache entry as defined by its flags.
*/
static inline uint8_t ng_ipv6_nc_get_type(const ng_ipv6_nc_t *entry)
{
return (entry->flags & NG_IPV6_NC_TYPE_MASK);
}
/**
* @brief Checks if an entry is reachable (do not confuse with
* @ref NG_IPV6_NC_STATE_REACHABLE).
*
* @param[in] entry A neighbor cache entry
*
* @return true, if you can send packets to @p entry
* @return false, if you can't send packets to @p entry
*/
static inline bool ng_ipv6_nc_is_reachable(const ng_ipv6_nc_t *entry)
{
switch (ng_ipv6_nc_get_state(entry)) {
case NG_IPV6_NC_STATE_UNREACHABLE:
case NG_IPV6_NC_STATE_INCOMPLETE:
return false;
default:
return true;
}
}
/**
* @brief Marks an entry as still reachable, if one with a fitting @p ipv6_addr

@ -43,27 +43,40 @@ ng_ipv6_nc_t *_find_free_entry(void)
return NULL;
}
int ng_ipv6_nc_add(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr,
const void *l2_addr, size_t l2_addr_len, uint8_t flags)
ng_ipv6_nc_t *ng_ipv6_nc_add(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr,
const void *l2_addr, size_t l2_addr_len, uint8_t flags)
{
if (ipv6_addr == NULL) {
DEBUG("ipv6_nc: address was NULL\n");
return -EFAULT;
return NULL;
}
if ((l2_addr_len > NG_IPV6_NC_L2_ADDR_MAX) || (iface == KERNEL_PID_UNDEF) ||
ng_ipv6_addr_is_unspecified(ipv6_addr)) {
return -EINVAL;
DEBUG("ipv6_nc: invalid parameters\n");
return NULL;
}
for (int i = 0; i < NG_IPV6_NC_SIZE; i++) {
if (ng_ipv6_addr_equal(&(ncache[i].ipv6_addr), ipv6_addr)) {
DEBUG("ipv6_nc: Address %s already registered\n",
DEBUG("ipv6_nc: Address %s already registered.\n",
ng_ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)));
return -EADDRINUSE;
if ((l2_addr != NULL) && (l2_addr_len > 0)) {
DEBUG("ipv6_nc: Update to L2 address %s",
ng_netif_addr_to_str(addr_str, sizeof(addr_str),
l2_addr, l2_addr_len));
memcpy(&(ncache[i].l2_addr), l2_addr, l2_addr_len);
ncache[i].l2_addr_len = l2_addr_len;
ncache[i].flags = flags;
DEBUG(" with flags = 0x%0x\n", flags);
}
return &ncache[i];
}
if (ncache[i].iface == KERNEL_PID_UNDEF) {
if (ng_ipv6_addr_is_unspecified(&(ncache[i].ipv6_addr))) {
ncache[i].iface = iface;
ng_pktqueue_init(&(ncache[i].pkts));
@ -73,30 +86,24 @@ int ng_ipv6_nc_add(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr,
iface);
if ((l2_addr != NULL) && (l2_addr_len > 0)) {
#if ENABLE_DEBUG
DEBUG(" to L2 address ");
for (size_t i = 0; i < l2_addr_len; i++) {
if (i > 0) {
putchar(':');
}
DEBUG("%02x", ((uint8_t *)l2_addr)[i]);
}
#endif
DEBUG(" to L2 address %s",
ng_netif_addr_to_str(addr_str, sizeof(addr_str),
l2_addr, l2_addr_len));
memcpy(&(ncache[i].l2_addr), l2_addr, l2_addr_len);
ncache[i].l2_addr_len = l2_addr_len;
}
ncache[i].flags = flags;
DEBUG(" with flags = 0x%0x\n", flags);
return 0;
return &ncache[i];
}
}
return -ENOMEM;
DEBUG("ipv6_nc: neighbor cache full.\n");
return NULL;
}
void ng_ipv6_nc_remove(kernel_pid_t iface, const ng_ipv6_addr_t *ipv6_addr)
@ -156,18 +163,6 @@ ng_ipv6_nc_t *ng_ipv6_nc_get_next(ng_ipv6_nc_t *prev)
return NULL;
}
static inline bool _is_reachable(ng_ipv6_nc_t *entry)
{
switch ((entry->flags & NG_IPV6_NC_STATE_MASK) >> NG_IPV6_NC_STATE_POS) {
case NG_IPV6_NC_STATE_UNREACHABLE:
case NG_IPV6_NC_STATE_INCOMPLETE:
return false;
default:
return true;
}
}
ng_ipv6_nc_t *ng_ipv6_nc_get_next_router(ng_ipv6_nc_t *prev)
{
for (ng_ipv6_nc_t *router = ng_ipv6_nc_get_next(prev); router != NULL;
@ -180,25 +175,6 @@ ng_ipv6_nc_t *ng_ipv6_nc_get_next_router(ng_ipv6_nc_t *prev)
return NULL;
}
ng_ipv6_nc_t *ng_ipv6_nc_get_reachable(kernel_pid_t iface,
const ng_ipv6_addr_t *ipv6_addr)
{
ng_ipv6_nc_t *entry = ng_ipv6_nc_get(iface, ipv6_addr);
if (entry == NULL) {
DEBUG("ipv6_nc: No entry found for %s on interface %" PRIkernel_pid "\n",
ng_ipv6_addr_to_str(addr_str, ipv6_addr, sizeof(addr_str)),
iface);
return NULL;
}
if (_is_reachable(entry)) {
return entry;
}
return NULL;
}
ng_ipv6_nc_t *ng_ipv6_nc_still_reachable(const ng_ipv6_addr_t *ipv6_addr)
{
ng_ipv6_nc_t *entry = ng_ipv6_nc_get(KERNEL_PID_UNDEF, ipv6_addr);

Loading…
Cancel
Save