diff --git a/sys/include/net/ng_ipv6/nc.h b/sys/include/net/ng_ipv6/nc.h index 46d09af88..c5d26730f 100644 --- a/sys/include/net/ng_ipv6/nc.h +++ b/sys/include/net/ng_ipv6/nc.h @@ -21,13 +21,14 @@ #ifndef NG_IPV6_NC_H_ #define NG_IPV6_NC_H_ +#include #include #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 diff --git a/sys/net/network_layer/ng_ipv6/nc/ng_ipv6_nc.c b/sys/net/network_layer/ng_ipv6/nc/ng_ipv6_nc.c index 39ce430a7..fe4f4c42d 100644 --- a/sys/net/network_layer/ng_ipv6/nc/ng_ipv6_nc.c +++ b/sys/net/network_layer/ng_ipv6/nc/ng_ipv6_nc.c @@ -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);