summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_connection.c34
-rw-r--r--bgpd/bgp_connection.h10
-rw-r--r--bgpd/bgp_session.c116
-rw-r--r--bgpd/bgp_session.h6
-rw-r--r--lib/mqueue.c15
-rw-r--r--lib/mqueue.h3
6 files changed, 91 insertions, 93 deletions
diff --git a/bgpd/bgp_connection.c b/bgpd/bgp_connection.c
index ba75a509..665d5557 100644
--- a/bgpd/bgp_connection.c
+++ b/bgpd/bgp_connection.c
@@ -461,7 +461,7 @@ bgp_connection_queue_process(void)
} ;
/* Process next item on connection's pending queue */
- mqb = mqueue_local_head(&connection->pending_queue) ;
+ mqb = mqueue_local_dequeue(&connection->pending_queue) ;
if (mqb != NULL)
/* The action will either remove the mqb from the pending queue,
* or remove the connection from the connection queue.
@@ -472,12 +472,40 @@ bgp_connection_queue_process(void)
&& (connection
== session->connections[bgp_connection_primary]) ) ;
mqb_dispatch_action(mqb) ;
- }
- else
+ } ;
+
+ /* If head is unchanged, then no more to do now. */
+ if (mqb == mqueue_local_head(&connection->pending_queue))
bgp_connection_queue_del(connection) ;
} ;
} ;
+/*------------------------------------------------------------------------------
+ * Add given message block to the given connection's pending queue
+ *
+ * If mqb is not already pending, add it at the tail and mark it pending.
+ *
+ * If is already pending, then is being put back onto the queue, so put it
+ * at the head, and remove the connection from the connection queue -- there
+ * is nothing more to be done for the connection for the time being.
+ */
+extern void
+bgp_connection_add_pending(bgp_connection connection, mqueue_block mqb,
+ bgp_connection* is_pending)
+{
+ if (*is_pending == NULL)
+ {
+ mqueue_local_enqueue(&connection->pending_queue, mqb) ;
+ *is_pending = connection ;
+ }
+ else
+ {
+ dassert(*is_pending == connection) ;
+ mqueue_local_enqueue_head(&connection->pending_queue, mqb) ;
+ bgp_connection_queue_del(connection) ;
+ } ;
+} ;
+
/*==============================================================================
* Opening and closing Connections
*/
diff --git a/bgpd/bgp_connection.h b/bgpd/bgp_connection.h
index e4c183b8..c620de55 100644
--- a/bgpd/bgp_connection.h
+++ b/bgpd/bgp_connection.h
@@ -234,6 +234,16 @@ bgp_connection_queue_del(bgp_connection connection) ;
extern void
bgp_connection_queue_process(void) ;
+Inline int
+bgp_connection_no_pending(bgp_connection connection, bgp_connection* is_pending)
+{
+ return ( (mqueue_local_head(&connection->pending_queue) == NULL)
+ || (*is_pending != NULL) ) ;
+} ;
+
+extern void
+bgp_connection_add_pending(bgp_connection connection, mqueue_block mqb,
+ bgp_connection* is_pending) ;
/*------------------------------------------------------------------------------
* See if have enough room for what want to write PLUS 1.
diff --git a/bgpd/bgp_session.c b/bgpd/bgp_session.c
index 56d6c7f8..e0c3972e 100644
--- a/bgpd/bgp_session.c
+++ b/bgpd/bgp_session.c
@@ -323,6 +323,7 @@ bgp_session_enable(bgp_peer peer)
confirm(sizeof(struct bgp_session_enable_args) == 0) ;
+ session->state = bgp_session_sEnabled;
bgp_to_bgp_engine(mqb) ;
} ;
@@ -340,7 +341,6 @@ bgp_session_do_enable(mqueue_block mqb, mqb_flag_t flag)
session->active = 1 ;
bgp_fsm_enable_session(session) ;
- session->state = bgp_session_sEnabled;
BGP_SESSION_UNLOCK(session) ; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
} ;
@@ -487,8 +487,8 @@ bgp_session_update_send(bgp_session session, struct stream* upd)
mqb = mqb_init_new(NULL, bgp_session_do_update_send, session) ;
args = mqb_get_args(mqb) ;
- args->buf = stream_dup(upd) ;
- args->pending = NULL ;
+ args->buf = stream_dup(upd) ;
+ args->is_pending = NULL ;
BGP_SESSION_LOCK(session) ; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
session->flow_control++; /* count them in ... */
@@ -544,33 +544,22 @@ bgp_session_do_update_send(mqueue_block mqb, mqb_flag_t flag)
bgp_connection connection = session->connections[bgp_connection_primary] ;
assert(connection != NULL) ;
- mqueue_block head = mqueue_local_head(&connection->pending_queue) ;
-
- int is_pending = (args->pending != NULL) ;
- if (is_pending)
- assert( (args->pending == connection) && (mqb == head) ) ;
-
/* If established, try and send. */
if (connection->state == bgp_fsm_sEstablished)
{
- int ret = 0 ;
+ int ret = bgp_connection_no_pending(connection, &args->is_pending) ;
- if ((head == NULL) || is_pending)
+ if (ret != 0)
ret = bgp_msg_send_update(connection, args->buf) ;
if (ret == 0)
{
- /* Did not fail, but could not write the message. */
- if (!is_pending)
- {
- mqueue_local_enqueue(&connection->pending_queue, mqb) ;
- args->pending = connection ;
- }
- else
- bgp_connection_queue_del(connection) ;
-
- return ; /* **** Quit now, with message intact. */
-
+ /* Either there is already a pending queue, or the message
+ * could not be sent (and has not failed) -- so add to the
+ * pending queue.
+ */
+ bgp_connection_add_pending(connection, mqb, &args->is_pending) ;
+ return ; /* Quit now, with message intact. */
}
else if (ret > 0)
{
@@ -584,10 +573,6 @@ bgp_session_do_update_send(mqueue_block mqb, mqb_flag_t flag)
bgp_session_XON(session);
} ;
} ;
-
- /* Have dealt with the message -- if was pending, it's done. */
- if (is_pending)
- mqueue_local_dequeue(&connection->pending_queue) ;
} ;
stream_free(args->buf) ;
@@ -641,8 +626,8 @@ bgp_session_route_refresh_send(bgp_session session, bgp_route_refresh rr)
mqb = mqb_init_new(NULL, bgp_session_do_route_refresh_send, session) ;
args = mqb_get_args(mqb) ;
- args->rr = rr ;
- args->pending = NULL ;
+ args->rr = rr ;
+ args->is_pending = NULL ;
bgp_to_bgp_engine(mqb) ;
} ;
@@ -664,45 +649,24 @@ bgp_session_do_route_refresh_send(mqueue_block mqb, mqb_flag_t flag)
bgp_connection connection = session->connections[bgp_connection_primary] ;
assert(connection != NULL) ;
- mqueue_block head = mqueue_local_head(&connection->pending_queue) ;
-
- int is_pending = (args->pending != NULL) ;
- if (is_pending)
- assert( (args->pending == connection) && (mqb == head) ) ;
-
/* If established, try and send. */
if (connection->state == bgp_fsm_sEstablished)
{
- int ret = 0 ;
+ int ret = bgp_connection_no_pending(connection, &args->is_pending) ;
- if ((head == NULL) || is_pending)
+ if (ret != 0)
ret = bgp_msg_send_route_refresh(connection, args->rr) ;
if (ret == 0)
{
- /* Did not fail, but could not write everything.
- *
- * If this is not on the connection's pending queue, put it there.
- *
- * Otherwise leave it there, and take the connection off the
- * connection queue -- nothing further can be done for this
- * connection.
+ /* Either there is already a pending queue, or the message
+ * could not be sent (and has not failed) -- so add to the
+ * pending queue.
*/
- if (!is_pending)
- {
- mqueue_local_enqueue(&connection->pending_queue, mqb) ;
- args->pending = connection ;
- }
- else
- bgp_connection_queue_del(connection) ;
-
+ bgp_connection_add_pending(connection, mqb, &args->is_pending) ;
return ; /* Quit now, with message intact. */
} ;
} ;
-
- /* Have dealt with the message -- if was pending, it's done. */
- if (is_pending)
- mqueue_local_dequeue(&connection->pending_queue) ;
} ;
bgp_route_refresh_free(args->rr) ;
@@ -724,9 +688,9 @@ bgp_session_end_of_rib_send(bgp_session session, qAFI_t afi, qSAFI_t safi)
mqb = mqb_init_new(NULL, bgp_session_do_end_of_rib_send, session) ;
args = mqb_get_args(mqb) ;
- args->afi = get_iAFI(qafx) ;
- args->safi = get_iSAFI(qafx) ;
- args->pending = NULL ;
+ args->afi = get_iAFI(qafx) ;
+ args->safi = get_iSAFI(qafx) ;
+ args->is_pending = NULL ;
bgp_to_bgp_engine(mqb) ;
} ;
@@ -748,45 +712,25 @@ bgp_session_do_end_of_rib_send(mqueue_block mqb, mqb_flag_t flag)
bgp_connection connection = session->connections[bgp_connection_primary] ;
assert(connection != NULL) ;
- mqueue_block head = mqueue_local_head(&connection->pending_queue) ;
-
- int is_pending = (args->pending != NULL) ;
- if (is_pending)
- assert( (args->pending == connection) && (mqb == head) ) ;
-
/* If established, try and send. */
if (connection->state == bgp_fsm_sEstablished)
{
- int ret = 0 ;
+ int ret = bgp_connection_no_pending(connection, &args->is_pending) ;
- if ((head == NULL) || is_pending)
+ if (ret != 0)
ret = bgp_msg_send_end_of_rib(connection, args->afi, args->safi) ;
if (ret == 0)
{
- /* Did not fail, but could not write everything.
- *
- * If this is not on the connection's pending queue, put it there.
- *
- * Otherwise leave it there, and take the connection off the
- * connection queue -- nothing further can be done for this
- * connection.
+ /* Either there is already a pending queue, or the message
+ * could not be sent (and has not failed) -- so add to the
+ * pending queue.
*/
- if (!is_pending)
- {
- mqueue_local_enqueue(&connection->pending_queue, mqb) ;
- args->pending = connection ;
- }
- else
- bgp_connection_queue_del(connection) ;
+ bgp_connection_add_pending(connection, mqb, &args->is_pending) ;
return ; /* Quit now, with message intact. */
} ;
} ;
-
- /* Have dealt with the message -- if was pending, it's done. */
- if (is_pending)
- mqueue_local_dequeue(&connection->pending_queue) ;
} ;
mqb_free(mqb) ;
@@ -853,8 +797,8 @@ bgp_session_route_refresh_recv(bgp_session session, bgp_route_refresh rr)
mqb = mqb_init_new(NULL, bgp_session_do_route_refresh_recv, session) ;
args = mqb_get_args(mqb) ;
- args->rr = rr ;
- args->pending = NULL ;
+ args->rr = rr ;
+ args->is_pending = NULL ;
bgp_to_peering_engine(mqb) ;
} ;
diff --git a/bgpd/bgp_session.h b/bgpd/bgp_session.h
index 06d2846d..967286ef 100644
--- a/bgpd/bgp_session.h
+++ b/bgpd/bgp_session.h
@@ -244,7 +244,7 @@ struct bgp_session_update_args /* to and from BGP Engine */
struct stream* buf ;
bgp_size_t size ;
- bgp_connection pending ; /* used inside the BGP Engine */
+ bgp_connection is_pending ; /* used inside the BGP Engine */
/* set NULL on message creation */
} ;
MQB_ARGS_SIZE_OK(bgp_session_update_args) ;
@@ -253,7 +253,7 @@ struct bgp_session_route_refresh_args /* to and from BGP Engine */
{
bgp_route_refresh rr ;
- bgp_connection pending ; /* used inside the BGP Engine */
+ bgp_connection is_pending ; /* used inside the BGP Engine */
/* set NULL on message creation */
} ;
MQB_ARGS_SIZE_OK(bgp_session_route_refresh_args) ;
@@ -263,7 +263,7 @@ struct bgp_session_end_of_rib_args /* to and from BGP Engine */
iAFI_t afi ;
iSAFI_t safi ;
- bgp_connection pending ; /* used inside the BGP Engine */
+ bgp_connection is_pending ; /* used inside the BGP Engine */
/* set NULL on message creation */
} ;
MQB_ARGS_SIZE_OK(bgp_session_end_of_rib_args) ;
diff --git a/lib/mqueue.c b/lib/mqueue.c
index 7156e31e..de1d654c 100644
--- a/lib/mqueue.c
+++ b/lib/mqueue.c
@@ -708,7 +708,7 @@ mqueue_done_waiting(mqueue_queue mq, mqueue_thread_signal mtsig)
} ;
/*------------------------------------------------------------------------------
- * Enqueue message on local queue
+ * Enqueue message on local queue -- at tail
*/
extern void
mqueue_local_enqueue(mqueue_local_queue lmq, mqueue_block mqb)
@@ -722,6 +722,19 @@ mqueue_local_enqueue(mqueue_local_queue lmq, mqueue_block mqb)
} ;
/*------------------------------------------------------------------------------
+ * Enqueue message on local queue -- at head
+ */
+extern void
+mqueue_local_enqueue_head(mqueue_local_queue lmq, mqueue_block mqb)
+{
+ if (lmq->head == NULL)
+ lmq->tail = mqb ;
+
+ mqb->next = lmq->head ;
+ lmq->head = mqb ;
+} ;
+
+/*------------------------------------------------------------------------------
* Dequeue message from local queue -- returns NULL if empty
*/
extern mqueue_block
diff --git a/lib/mqueue.h b/lib/mqueue.h
index a6edb4d7..2bd96896 100644
--- a/lib/mqueue.h
+++ b/lib/mqueue.h
@@ -234,6 +234,9 @@ mqueue_done_waiting(mqueue_queue mq, mqueue_thread_signal mtsig) ;
extern void
mqueue_local_enqueue(mqueue_local_queue lmq, mqueue_block mqb) ;
+extern void
+mqueue_local_enqueue_head(mqueue_local_queue lmq, mqueue_block mqb) ;
+
Inline mqueue_block
mqueue_local_head(mqueue_local_queue lmq) ;