When IPv6 ND kicks in, the packet that caused the ND can either be dropped or saved in a buffer to be send when the NS reply returns. This commit reimplements the buffer management to avoid having one buffer per neighbor, but instead use a buffer pool from which buffers can be allocated for different neighbors.
This commit is contained in:
parent
677575fc8c
commit
f5031861ac
|
@ -45,6 +45,7 @@
|
||||||
#include "lib/random.h"
|
#include "lib/random.h"
|
||||||
#include "net/uip-nd6.h"
|
#include "net/uip-nd6.h"
|
||||||
#include "net/uip-ds6.h"
|
#include "net/uip-ds6.h"
|
||||||
|
#include "net/uip-packetqueue.h"
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -268,6 +269,7 @@ uip_ds6_list_loop(uip_ds6_element_t * list, uint8_t size,
|
||||||
element <
|
element <
|
||||||
(uip_ds6_element_t *) ((uint8_t *) list + (size * elementsize));
|
(uip_ds6_element_t *) ((uint8_t *) list + (size * elementsize));
|
||||||
element = (uip_ds6_element_t *) ((uint8_t *) element + elementsize)) {
|
element = (uip_ds6_element_t *) ((uint8_t *) element + elementsize)) {
|
||||||
|
// printf("+ %p %d\n", &element->isused, element->isused);
|
||||||
if(element->isused) {
|
if(element->isused) {
|
||||||
if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) {
|
if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) {
|
||||||
*out_element = element;
|
*out_element = element;
|
||||||
|
@ -278,7 +280,7 @@ uip_ds6_list_loop(uip_ds6_element_t * list, uint8_t size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*out_element) {
|
if(*out_element != NULL) {
|
||||||
return FREESPACE;
|
return FREESPACE;
|
||||||
} else {
|
} else {
|
||||||
return NOSPACE;
|
return NOSPACE;
|
||||||
|
@ -290,10 +292,15 @@ uip_ds6_nbr_t *
|
||||||
uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
||||||
uint8_t isrouter, uint8_t state)
|
uint8_t isrouter, uint8_t state)
|
||||||
{
|
{
|
||||||
if(uip_ds6_list_loop
|
int r;
|
||||||
|
|
||||||
|
r = uip_ds6_list_loop
|
||||||
((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
|
((uip_ds6_element_t *) uip_ds6_nbr_cache, UIP_DS6_NBR_NB,
|
||||||
sizeof(uip_ds6_nbr_t), ipaddr, 128,
|
sizeof(uip_ds6_nbr_t), ipaddr, 128,
|
||||||
(uip_ds6_element_t **) & locnbr) == FREESPACE) {
|
(uip_ds6_element_t **) &locnbr);
|
||||||
|
// printf("r %d\n", r);
|
||||||
|
|
||||||
|
if(r == FREESPACE) {
|
||||||
locnbr->isused = 1;
|
locnbr->isused = 1;
|
||||||
uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr);
|
uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr);
|
||||||
if(lladdr != NULL) {
|
if(lladdr != NULL) {
|
||||||
|
@ -303,6 +310,9 @@ uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
||||||
}
|
}
|
||||||
locnbr->isrouter = isrouter;
|
locnbr->isrouter = isrouter;
|
||||||
locnbr->state = state;
|
locnbr->state = state;
|
||||||
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
|
uip_packetqueue_new(&locnbr->packethandle);
|
||||||
|
#endif /* UIP_CONF_IPV6_QUEUE_PKT */
|
||||||
/* timers are set separately, for now we put them in expired state */
|
/* timers are set separately, for now we put them in expired state */
|
||||||
stimer_set(&(locnbr->reachable), 0);
|
stimer_set(&(locnbr->reachable), 0);
|
||||||
stimer_set(&(locnbr->sendns), 0);
|
stimer_set(&(locnbr->sendns), 0);
|
||||||
|
@ -315,31 +325,31 @@ uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
||||||
NEIGHBOR_STATE_CHANGED(locnbr);
|
NEIGHBOR_STATE_CHANGED(locnbr);
|
||||||
|
|
||||||
locnbr->last_lookup = clock_time();
|
locnbr->last_lookup = clock_time();
|
||||||
|
// printf("add %p\n", locnbr);
|
||||||
return locnbr;
|
return locnbr;
|
||||||
} else {
|
} else if(r == NOSPACE) {
|
||||||
/* We did not find any empty slot on the neighbor list, so we need
|
/* We did not find any empty slot on the neighbor list, so we need
|
||||||
to remove one old entry to make room. */
|
to remove one old entry to make room. */
|
||||||
{
|
uip_ds6_nbr_t *n, *oldest;
|
||||||
uip_ds6_nbr_t *n, *oldest;
|
clock_time_t oldest_time;
|
||||||
clock_time_t oldest_time;
|
|
||||||
|
|
||||||
oldest = NULL;
|
oldest = NULL;
|
||||||
oldest_time = 0 - 1UL;
|
oldest_time = clock_time();
|
||||||
|
|
||||||
for(n = uip_ds6_nbr_cache;
|
for(n = uip_ds6_nbr_cache;
|
||||||
n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
|
n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
|
||||||
n++) {
|
n++) {
|
||||||
if(n->isused) {
|
if(n->isused) {
|
||||||
if(n->last_lookup < oldest_time) {
|
if(n->last_lookup < oldest_time) {
|
||||||
oldest = n;
|
oldest = n;
|
||||||
oldest_time = n->last_lookup;
|
oldest_time = n->last_lookup;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(oldest != NULL) {
|
}
|
||||||
uip_ds6_nbr_rm(oldest);
|
if(oldest != NULL) {
|
||||||
return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state);
|
// printf("rm3\n");
|
||||||
}
|
uip_ds6_nbr_rm(oldest);
|
||||||
|
return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PRINTF("uip_ds6_nbr_add drop\n");
|
PRINTF("uip_ds6_nbr_add drop\n");
|
||||||
|
@ -352,7 +362,11 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
|
||||||
{
|
{
|
||||||
if(nbr != NULL) {
|
if(nbr != NULL) {
|
||||||
nbr->isused = 0;
|
nbr->isused = 0;
|
||||||
NEIGHBOR_STATE_CHANGED(nbr);
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
|
// printf("rm %p\n", &nbr->isused);
|
||||||
|
uip_packetqueue_free(&nbr->packethandle);
|
||||||
|
#endif /* UIP_CONF_IPV6_QUEUE_PKT */
|
||||||
|
// NEIGHBOR_STATE_CHANGED(nbr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,20 +152,23 @@
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------*/
|
/*--------------------------------------------------*/
|
||||||
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
|
#include "net/uip-packetqueue.h"
|
||||||
|
#endif /*UIP_CONF_QUEUE_PKT */
|
||||||
/** \brief An entry in the nbr cache */
|
/** \brief An entry in the nbr cache */
|
||||||
typedef struct uip_ds6_nbr {
|
typedef struct uip_ds6_nbr {
|
||||||
uint8_t isused;
|
uint8_t isused;
|
||||||
uip_ipaddr_t ipaddr;
|
uip_ipaddr_t ipaddr;
|
||||||
uip_lladdr_t lladdr;
|
uip_lladdr_t lladdr;
|
||||||
uint8_t isrouter;
|
|
||||||
uint8_t state;
|
|
||||||
struct stimer reachable;
|
struct stimer reachable;
|
||||||
struct stimer sendns;
|
struct stimer sendns;
|
||||||
uint8_t nscount;
|
|
||||||
clock_time_t last_lookup;
|
clock_time_t last_lookup;
|
||||||
|
uint8_t nscount;
|
||||||
|
uint8_t isrouter;
|
||||||
|
uint8_t state;
|
||||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
|
struct uip_packetqueue_handle packethandle;
|
||||||
uint8_t queue_buf_len;
|
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
|
||||||
#endif /*UIP_CONF_QUEUE_PKT */
|
#endif /*UIP_CONF_QUEUE_PKT */
|
||||||
} uip_ds6_nbr_t;
|
} uip_ds6_nbr_t;
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
|
||||||
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
|
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
|
||||||
static uip_ds6_addr_t *addr; /** Pointer to an interface address */
|
static uip_ds6_addr_t *addr; /** Pointer to an interface address */
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
/* create a llao */
|
/* create a llao */
|
||||||
static void
|
static void
|
||||||
|
@ -507,12 +508,19 @@ uip_nd6_na_input(void)
|
||||||
}
|
}
|
||||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
/* The nbr is now reachable, check if we had buffered a pkt for it */
|
/* The nbr is now reachable, check if we had buffered a pkt for it */
|
||||||
if(nbr->queue_buf_len != 0) {
|
/*if(nbr->queue_buf_len != 0) {
|
||||||
uip_len = nbr->queue_buf_len;
|
uip_len = nbr->queue_buf_len;
|
||||||
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
||||||
nbr->queue_buf_len = 0;
|
nbr->queue_buf_len = 0;
|
||||||
return;
|
return;
|
||||||
|
}*/
|
||||||
|
if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
|
||||||
|
uip_len = uip_packetqueue_buflen(&nbr->packethandle);
|
||||||
|
memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
|
||||||
|
uip_packetqueue_free(&nbr->packethandle);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
||||||
|
|
||||||
discard:
|
discard:
|
||||||
|
@ -918,12 +926,19 @@ uip_nd6_ra_input(void)
|
||||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||||
/* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
|
/* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
|
||||||
* and we got a SLLAO), check if we had buffered a pkt for it */
|
* and we got a SLLAO), check if we had buffered a pkt for it */
|
||||||
if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
|
/* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
|
||||||
uip_len = nbr->queue_buf_len;
|
uip_len = nbr->queue_buf_len;
|
||||||
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
||||||
nbr->queue_buf_len = 0;
|
nbr->queue_buf_len = 0;
|
||||||
return;
|
return;
|
||||||
|
}*/
|
||||||
|
if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
|
||||||
|
uip_len = uip_packetqueue_buflen(&nbr->packethandle);
|
||||||
|
memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
|
||||||
|
uip_packetqueue_free(&nbr->packethandle);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
#endif /*UIP_CONF_IPV6_QUEUE_PKT */
|
||||||
|
|
||||||
discard:
|
discard:
|
||||||
|
|
86
core/net/uip-packetqueue.c
Normal file
86
core/net/uip-packetqueue.c
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "net/uip.h"
|
||||||
|
|
||||||
|
#include "lib/memb.h"
|
||||||
|
|
||||||
|
#include "net/uip-packetqueue.h"
|
||||||
|
|
||||||
|
#define MAX_NUM_QUEUED_PACKETS 2
|
||||||
|
MEMB(packets_memb, struct uip_packetqueue_packet, MAX_NUM_QUEUED_PACKETS);
|
||||||
|
|
||||||
|
#define DEBUG 0
|
||||||
|
#if DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#define PRINTF(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define PRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
packet_timedout(void *ptr)
|
||||||
|
{
|
||||||
|
struct uip_packetqueue_handle *h = ptr;
|
||||||
|
|
||||||
|
PRINTF("uip_packetqueue_free timed out %p\n", h);
|
||||||
|
memb_free(&packets_memb, h->packet);
|
||||||
|
h->packet = NULL;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
uip_packetqueue_new(struct uip_packetqueue_handle *handle)
|
||||||
|
{
|
||||||
|
PRINTF("uip_packetqueue_new %p\n", handle);
|
||||||
|
handle->packet = NULL;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
struct uip_packetqueue_packet *
|
||||||
|
uip_packetqueue_alloc(struct uip_packetqueue_handle *handle, clock_time_t lifetime)
|
||||||
|
{
|
||||||
|
PRINTF("uip_packetqueue_alloc %p\n", handle);
|
||||||
|
if(handle->packet != NULL) {
|
||||||
|
PRINTF("alloced\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
handle->packet = memb_alloc(&packets_memb);
|
||||||
|
if(handle->packet != NULL) {
|
||||||
|
ctimer_set(&handle->packet->lifetimer, lifetime,
|
||||||
|
packet_timedout, handle);
|
||||||
|
} else {
|
||||||
|
PRINTF("uip_packetqueue_alloc failed\n");
|
||||||
|
}
|
||||||
|
return handle->packet;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
uip_packetqueue_free(struct uip_packetqueue_handle *handle)
|
||||||
|
{
|
||||||
|
PRINTF("uip_packetqueue_free %p\n", handle);
|
||||||
|
if(handle->packet != NULL) {
|
||||||
|
ctimer_stop(&handle->packet->lifetimer);
|
||||||
|
memb_free(&packets_memb, handle->packet);
|
||||||
|
handle->packet = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint8_t *
|
||||||
|
uip_packetqueue_buf(struct uip_packetqueue_handle *h)
|
||||||
|
{
|
||||||
|
return h->packet != NULL? h->packet->queue_buf: NULL;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint16_t
|
||||||
|
uip_packetqueue_buflen(struct uip_packetqueue_handle *h)
|
||||||
|
{
|
||||||
|
return h->packet != NULL? h->packet->queue_buf_len: 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
uip_packetqueue_set_buflen(struct uip_packetqueue_handle *h, uint16_t len)
|
||||||
|
{
|
||||||
|
if(h->packet != NULL) {
|
||||||
|
h->packet->queue_buf_len = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
35
core/net/uip-packetqueue.h
Normal file
35
core/net/uip-packetqueue.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef UIP_PACKETQUEUE_H
|
||||||
|
#define UIP_PACKETQUEUE_H
|
||||||
|
|
||||||
|
#include "sys/ctimer.h"
|
||||||
|
|
||||||
|
struct uip_packetqueue_handle;
|
||||||
|
|
||||||
|
struct uip_packetqueue_packet {
|
||||||
|
struct uip_ds6_queued_packet *next;
|
||||||
|
uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
|
||||||
|
uint16_t queue_buf_len;
|
||||||
|
struct ctimer lifetimer;
|
||||||
|
struct uip_packetqueue_handle *handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uip_packetqueue_handle {
|
||||||
|
struct uip_packetqueue_packet *packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
void uip_packetqueue_new(struct uip_packetqueue_handle *handle);
|
||||||
|
|
||||||
|
|
||||||
|
struct uip_packetqueue_packet *
|
||||||
|
uip_packetqueue_alloc(struct uip_packetqueue_handle *handle, clock_time_t lifetime);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
uip_packetqueue_free(struct uip_packetqueue_handle *handle);
|
||||||
|
|
||||||
|
uint8_t *uip_packetqueue_buf(struct uip_packetqueue_handle *h);
|
||||||
|
uint16_t uip_packetqueue_buflen(struct uip_packetqueue_handle *h);
|
||||||
|
void uip_packetqueue_set_buflen(struct uip_packetqueue_handle *h, uint16_t len);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* UIP_PACKETQUEUE_H */
|
Loading…
Reference in a new issue