summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPat Ruddy <pat@voltanet.io>2021-03-10 17:59:07 +0000
committerPat Ruddy <pat@voltanet.io>2021-06-18 09:40:42 +0100
commit4f7bf1ab052e82f16f8b965c6afe9d1c0f22f479 (patch)
tree27eebad2905df380b1b00b42f6231db2ebee92cc
parentaa6a96ba78bacb2792f2a6c26b6873b3ff4e35b8 (diff)
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>
-rw-r--r--ospf6d/ospf6_interface.c13
-rw-r--r--ospf6d/ospf6_interface.h5
-rw-r--r--ospf6d/ospf6_message.c91
-rw-r--r--ospf6d/ospf6_message.h30
-rw-r--r--ospf6d/ospf6_top.c3
-rw-r--r--ospf6d/ospf6_top.h2
6 files changed, 144 insertions, 0 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 952c7f8b27..57b7348bcc 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -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;
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index 796d75e897..bbed03539d 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -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;
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index e6d09b9a08..8f9ae7b0c4 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -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)
diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h
index 7c108bd452..4069e10486 100644
--- a/ospf6d/ospf6_message.h
+++ b/ospf6d/ospf6_message.h
@@ -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);
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index cd1b5b99f8..adfedcc49c 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -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);
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index e4dfebe1de..1386ffd379 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -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;