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 "net/uip-nd6.h"
|
||||
#include "net/uip-ds6.h"
|
||||
#include "net/uip-packetqueue.h"
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
|
@ -268,6 +269,7 @@ uip_ds6_list_loop(uip_ds6_element_t * list, uint8_t size,
|
|||
element <
|
||||
(uip_ds6_element_t *) ((uint8_t *) list + (size * elementsize));
|
||||
element = (uip_ds6_element_t *) ((uint8_t *) element + elementsize)) {
|
||||
// printf("+ %p %d\n", &element->isused, element->isused);
|
||||
if(element->isused) {
|
||||
if(uip_ipaddr_prefixcmp(&(element->ipaddr), ipaddr, ipaddrlen)) {
|
||||
*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;
|
||||
} else {
|
||||
return NOSPACE;
|
||||
|
@ -290,10 +292,15 @@ uip_ds6_nbr_t *
|
|||
uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
||||
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,
|
||||
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;
|
||||
uip_ipaddr_copy(&(locnbr->ipaddr), ipaddr);
|
||||
if(lladdr != NULL) {
|
||||
|
@ -303,6 +310,9 @@ uip_ds6_nbr_add(uip_ipaddr_t * ipaddr, uip_lladdr_t * lladdr,
|
|||
}
|
||||
locnbr->isrouter = isrouter;
|
||||
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 */
|
||||
stimer_set(&(locnbr->reachable), 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);
|
||||
|
||||
locnbr->last_lookup = clock_time();
|
||||
// printf("add %p\n", locnbr);
|
||||
return locnbr;
|
||||
} else {
|
||||
} else if(r == NOSPACE) {
|
||||
/* We did not find any empty slot on the neighbor list, so we need
|
||||
to remove one old entry to make room. */
|
||||
{
|
||||
uip_ds6_nbr_t *n, *oldest;
|
||||
clock_time_t oldest_time;
|
||||
uip_ds6_nbr_t *n, *oldest;
|
||||
clock_time_t oldest_time;
|
||||
|
||||
oldest = NULL;
|
||||
oldest_time = 0 - 1UL;
|
||||
oldest = NULL;
|
||||
oldest_time = clock_time();
|
||||
|
||||
for(n = uip_ds6_nbr_cache;
|
||||
n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
|
||||
n++) {
|
||||
if(n->isused) {
|
||||
if(n->last_lookup < oldest_time) {
|
||||
oldest = n;
|
||||
oldest_time = n->last_lookup;
|
||||
}
|
||||
for(n = uip_ds6_nbr_cache;
|
||||
n < &uip_ds6_nbr_cache[UIP_DS6_NBR_NB];
|
||||
n++) {
|
||||
if(n->isused) {
|
||||
if(n->last_lookup < oldest_time) {
|
||||
oldest = n;
|
||||
oldest_time = n->last_lookup;
|
||||
}
|
||||
}
|
||||
if(oldest != NULL) {
|
||||
uip_ds6_nbr_rm(oldest);
|
||||
return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state);
|
||||
}
|
||||
}
|
||||
if(oldest != NULL) {
|
||||
// printf("rm3\n");
|
||||
uip_ds6_nbr_rm(oldest);
|
||||
return uip_ds6_nbr_add(ipaddr, lladdr, isrouter, state);
|
||||
}
|
||||
}
|
||||
PRINTF("uip_ds6_nbr_add drop\n");
|
||||
|
@ -352,7 +362,11 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
|
|||
{
|
||||
if(nbr != NULL) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
typedef struct uip_ds6_nbr {
|
||||
uint8_t isused;
|
||||
uip_ipaddr_t ipaddr;
|
||||
uip_lladdr_t lladdr;
|
||||
uint8_t isrouter;
|
||||
uint8_t state;
|
||||
struct stimer reachable;
|
||||
struct stimer sendns;
|
||||
uint8_t nscount;
|
||||
clock_time_t last_lookup;
|
||||
uint8_t nscount;
|
||||
uint8_t isrouter;
|
||||
uint8_t state;
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
|
||||
uint8_t queue_buf_len;
|
||||
struct uip_packetqueue_handle packethandle;
|
||||
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
|
||||
#endif /*UIP_CONF_QUEUE_PKT */
|
||||
} 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_addr_t *addr; /** Pointer to an interface address */
|
||||
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* create a llao */
|
||||
static void
|
||||
|
@ -507,12 +508,19 @@ uip_nd6_na_input(void)
|
|||
}
|
||||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
/* 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;
|
||||
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
||||
nbr->queue_buf_len = 0;
|
||||
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 */
|
||||
|
||||
discard:
|
||||
|
@ -918,12 +926,19 @@ uip_nd6_ra_input(void)
|
|||
#if UIP_CONF_IPV6_QUEUE_PKT
|
||||
/* 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 */
|
||||
if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
|
||||
/* if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
|
||||
uip_len = nbr->queue_buf_len;
|
||||
memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
|
||||
nbr->queue_buf_len = 0;
|
||||
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 */
|
||||
|
||||
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