ospf6d: add tx fifo infrastructure

Add per interface fifo and per instance write list as a precursor
to implementing fairer sharing of the ospf6 oscket resources.

Signed-off-by: Pat Ruddy <pat@voltanet.io>
This commit is contained in:
Pat Ruddy 2021-03-10 17:59:07 +00:00
parent aa6a96ba78
commit 4f7bf1ab05
6 changed files with 144 additions and 0 deletions

View File

@ -185,6 +185,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
oi->obuf = ospf6_fifo_new();
oi->area = (struct ospf6_area *)NULL;
oi->neighbor_list = list_new();
oi->neighbor_list->cmp = ospf6_neighbor_cmp;
@ -243,6 +245,8 @@ void ospf6_interface_delete(struct ospf6_interface *oi)
QOBJ_UNREG(oi);
ospf6_fifo_free(oi->obuf);
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
ospf6_neighbor_delete(on);
@ -888,6 +892,15 @@ int interface_down(struct thread *thread)
ospf6_sso(oi->interface->ifindex, &allspfrouters6,
IPV6_LEAVE_GROUP, ospf6->fd);
/* deal with write fifo */
ospf6_fifo_flush(oi->obuf);
if (oi->on_write_q) {
listnode_delete(ospf6->oi_write_q, oi);
if (list_isempty(ospf6->oi_write_q))
thread_cancel(&ospf6->t_write);
oi->on_write_q = 0;
}
ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
return 0;

View File

@ -56,6 +56,9 @@ struct ospf6_interface {
/* I/F transmission delay */
uint32_t transdelay;
/* Packet send buffer. */
struct ospf6_fifo *obuf; /* Output queue */
/* Network Type */
uint8_t type;
bool type_cfg;
@ -130,6 +133,8 @@ struct ospf6_interface {
char *profile;
} bfd_config;
int on_write_q;
/* Statistics Fields */
uint32_t hello_in;
uint32_t hello_out;

View File

@ -50,6 +50,8 @@
#include <netinet/ip6.h>
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6 FIFO queue");
unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
static const struct message ospf6_message_type_str[] = {
@ -252,6 +254,95 @@ void ospf6_lsack_print(struct ospf6_header *oh, int action)
}
}
void ospf6_packet_free(struct ospf6_packet *op)
{
if (op->s)
stream_free(op->s);
XFREE(MTYPE_OSPF6_PACKET, op);
}
struct ospf6_fifo *ospf6_fifo_new(void)
{
struct ospf6_fifo *new;
new = XCALLOC(MTYPE_OSPF6_FIFO, sizeof(struct ospf6_fifo));
return new;
}
/* Add new packet to fifo. */
void ospf6_fifo_push(struct ospf6_fifo *fifo, struct ospf6_packet *op)
{
if (fifo->tail)
fifo->tail->next = op;
else
fifo->head = op;
fifo->tail = op;
fifo->count++;
}
/* Add new packet to head of fifo. */
void ospf6_fifo_push_head(struct ospf6_fifo *fifo, struct ospf6_packet *op)
{
op->next = fifo->head;
if (fifo->tail == NULL)
fifo->tail = op;
fifo->head = op;
fifo->count++;
}
/* Delete first packet from fifo. */
struct ospf6_packet *ospf6_fifo_pop(struct ospf6_fifo *fifo)
{
struct ospf6_packet *op;
op = fifo->head;
if (op) {
fifo->head = op->next;
if (fifo->head == NULL)
fifo->tail = NULL;
fifo->count--;
}
return op;
}
/* Return first fifo entry. */
struct ospf6_packet *ospf6_fifo_head(struct ospf6_fifo *fifo)
{
return fifo->head;
}
/* Flush ospf packet fifo. */
void ospf6_fifo_flush(struct ospf6_fifo *fifo)
{
struct ospf6_packet *op;
struct ospf6_packet *next;
for (op = fifo->head; op; op = next) {
next = op->next;
ospf6_packet_free(op);
}
fifo->head = fifo->tail = NULL;
fifo->count = 0;
}
/* Free ospf packet fifo. */
void ospf6_fifo_free(struct ospf6_fifo *fifo)
{
ospf6_fifo_flush(fifo);
XFREE(MTYPE_OSPF6_FIFO, fifo);
}
static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
struct ospf6_interface *oi,
struct ospf6_header *oh)

View File

@ -63,6 +63,27 @@ extern unsigned char conf_debug_ospf6_message[];
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
struct ospf6_packet {
struct ospf6_packet *next;
/* Pointer to data stream. */
struct stream *s;
/* IP destination address. */
struct in6_addr dst;
/* OSPF6 packet length. */
uint16_t length;
};
/* OSPF packet queue structure. */
struct ospf6_fifo {
unsigned long count;
struct ospf6_packet *head;
struct ospf6_packet *tail;
};
/* OSPFv3 packet header */
#define OSPF6_HEADER_SIZE 16U
struct ospf6_header {
@ -136,6 +157,15 @@ extern void ospf6_lsreq_print(struct ospf6_header *, int action);
extern void ospf6_lsupdate_print(struct ospf6_header *, int action);
extern void ospf6_lsack_print(struct ospf6_header *, int action);
extern void ospf6_packet_free(struct ospf6_packet *op);
extern struct ospf6_fifo *ospf6_fifo_new(void);
extern void ospf6_fifo_push(struct ospf6_fifo *fifo, struct ospf6_packet *op);
void ospf6_fifo_push_head(struct ospf6_fifo *fifo, struct ospf6_packet *op);
extern struct ospf6_packet *ospf6_fifo_pop(struct ospf6_fifo *fifo);
extern struct ospf6_packet *ospf6_fifo_head(struct ospf6_fifo *fifo);
extern void ospf6_fifo_flush(struct ospf6_fifo *fifo);
extern void ospf6_fifo_free(struct ospf6_fifo *fifo);
extern int ospf6_iobuf_size(unsigned int size);
extern void ospf6_message_terminate(void);
extern int ospf6_receive(struct thread *thread);

View File

@ -413,6 +413,8 @@ static struct ospf6 *ospf6_create(const char *name)
o->max_multipath = MULTIPATH_NUM;
o->oi_write_q = list_new();
QOBJ_REG(o, ospf6);
/* Make ospf protocol socket. */
@ -482,6 +484,7 @@ void ospf6_delete(struct ospf6 *o)
ospf6_distance_reset(o);
route_table_finish(o->distance_table);
list_delete(&o->oi_write_q);
if (o->vrf_id != VRF_UNKNOWN) {
vrf = vrf_lookup_by_id(o->vrf_id);

View File

@ -128,6 +128,7 @@ struct ospf6 {
struct thread *maxage_remover;
struct thread *t_distribute_update; /* Distirbute update timer. */
struct thread *t_ospf6_receive; /* OSPF6 receive timer */
struct thread *t_write;
uint32_t ref_bandwidth;
@ -150,6 +151,7 @@ struct ospf6 {
/* Count of NSSA areas */
uint8_t anyNSSA;
struct thread *t_abr_task; /* ABR task timer. */
struct list *oi_write_q;
uint32_t redist_count;
QOBJ_FIELDS;