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 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;