diff options
Diffstat (limited to 'bgpd/bgp_session.c')
-rw-r--r-- | bgpd/bgp_session.c | 164 |
1 files changed, 93 insertions, 71 deletions
diff --git a/bgpd/bgp_session.c b/bgpd/bgp_session.c index a2b49da5..9d17e36c 100644 --- a/bgpd/bgp_session.c +++ b/bgpd/bgp_session.c @@ -80,10 +80,10 @@ static void bgp_session_do_route_refresh_recv(mqueue_block mqb, mqb_flag_t flag) * change any shared item in the session, except under the mutex. And * even then it may make no sense ! * - * NB: a session reaches eDisabled when the Peering Engine has sent a disable + * NB: a session reaches eDisabled when the Routing Engine has sent a disable * request to the BGP Engine, AND an eDisabled event has come back. * - * While the Peering Engine is waiting for the eDisabled event, the session + * While the Routing Engine is waiting for the eDisabled event, the session * is in sLimping state. * * The BGP Engine's primary interest is in its (private) bgp_connection @@ -212,7 +212,7 @@ bgp_session_free(bgp_session session) } /*============================================================================== - * Peering Engine: enable session for given peer -- allocate if required. + * Routing Engine: enable session for given peer -- allocate if required. * * Sets up the session given the current state of the peer. If the state * changes, then need to disable the session and re-enable it again with new @@ -226,12 +226,12 @@ bgp_session_enable(bgp_peer peer) /* Set up session if required. Check session if already exists. * - * Only the Peering Engine creates sessions, so it is safe to pick up the + * Only the Routing Engine creates sessions, so it is safe to pick up the * peer->session pointer and test it. * * If session exists, it MUST be inactive. * - * Peering Engine does not require the mutex while the session is inactive. + * Routing Engine does not require the mutex while the session is inactive. */ session = peer->session ; @@ -348,7 +348,7 @@ bgp_session_do_enable(mqueue_block mqb, mqb_flag_t flag) } ; /*============================================================================== - * Peering Engine: disable session for given peer -- if enabled (!). + * Routing Engine: disable session for given peer -- if enabled (!). * * Passes any bgp_notify to the BGP Engine, which will dispose of it in due * course. @@ -398,7 +398,7 @@ bgp_session_disable(bgp_peer peer, bgp_notify notification) * * the disable is being issued in response to a stopped event from * the BGP Engine. * - * * the session is stopped, but the message to the Peering Engine is + * * the session is stopped, but the message to the Routing Engine is * still in its message queue. * * * the session is stopped while the disable message is in the @@ -410,11 +410,11 @@ bgp_session_disable(bgp_peer peer, bgp_notify notification) * * NB: The BGP Engine will discard any outstanding work for the session. * - * The Peering Engine should discard all further messages for this + * The Routing Engine should discard all further messages for this * session up to the eDisabled, and must then discard any other * messages for the session. * - * NB: the Peering Engine MUST not issue any further messages until it sees + * NB: the Routing Engine MUST not issue any further messages until it sees * the returned eDisabled event. */ mqb = mqb_init_new(NULL, bgp_session_do_disable, session) ; @@ -433,7 +433,6 @@ bgp_session_disable(bgp_peer peer, bgp_notify notification) c = 0 ; s = 0 ; } ; - fprintf(stderr, " session disable %d/%d", c, s) ; } ; ++bgp_engine_queue_stats.event ; @@ -469,7 +468,7 @@ bgp_session_do_disable(mqueue_block mqb, mqb_flag_t flag) /*============================================================================== * BGP Engine: send session event signal to Routeing Engine * - * NB: is passing responsibility for the notification to the Peering Engine. + * NB: is passing responsibility for the notification to the Routing Engine. */ extern void bgp_session_event(bgp_session session, bgp_session_event_t event, @@ -494,21 +493,20 @@ bgp_session_event(bgp_session session, bgp_session_event_t event, args->ordinal = ordinal ; args->stopped = stopped, - ++peering_engine_queue_stats.event ; + ++routing_engine_queue_stats.event ; - bgp_to_peering_engine(mqb) ; -} + bgp_to_routing_engine(mqb) ; +} ; /*============================================================================== - * Peering Engine: dispatch update to peer -> BGP Engine + * Routing Engine: dispatch update(s) to peer -> BGP Engine * - * PRO TEM -- this is being passed the pre-packaged BGP message. + * PRO TEM -- this is being passed the pre-packaged BGP message(s). * - * The BGP Engine takes care of discarding the stream block once it's been - * dealt with. + * The BGP Engine takes care of discarding the stream block(s) once dealt with. */ extern void -bgp_session_update_send(bgp_session session, struct stream* upd) +bgp_session_update_send(bgp_session session, struct stream_fifo* fifo) { struct bgp_session_update_args* args ; mqueue_block mqb ; @@ -516,37 +514,38 @@ 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->buf = stream_fifo_head(fifo) ; args->is_pending = NULL ; - args->xon_kick = (session->flow_control == BGP_XON_KICK); - session->flow_control--; + args->xon_kick = (session->flow_control == BGP_XON_KICK); ++bgp_engine_queue_stats.update ; bgp_to_bgp_engine(mqb) ; + + stream_fifo_reset(fifo) ; } ; /*------------------------------------------------------------------------------ - * BGP Engine: write given BGP update message -- mqb action function. + * BGP Engine: write given BGP update message(s) -- mqb action function. * * Each connection has a pending queue associated with it, onto which messages * are put if the connection's write buffer is unable to absorb any further * messages. * - * This function is called both when the mqb is received from the Peering + * This function is called both when the mqb is received from the Routing * Engine, and when the BGP Engine is trying to empty the connection's pending * queue. * - * When the mqb is received from the Peering Engine, then: + * When the mqb is received from the Routing Engine, then: * - * -- if the connection's pending queue is empty, try to send the message. + * -- if the connection's pending queue is empty, try to send the message(s). * * When the mqb is from connection's pending queue, then: * - * -- try to send the message. + * -- try to send the message(s). * - * In any case, if cannot send the message (and not encountered any error), add - * it (back) to the connection's pending queue. + * In any case, if cannot send all the message(s), add it (back) to the + * connection's pending queue. * * If the mqb has been dealt with, it is freed, along with the stream buffer. * Also, update the flow control counter, and issue XON if required. @@ -557,43 +556,54 @@ bgp_session_do_update_send(mqueue_block mqb, mqb_flag_t flag) struct bgp_session_update_args* args = mqb_get_args(mqb) ; bgp_session session = mqb_get_arg0(mqb) ; - if ((flag == mqb_action) && session->active) + while (args->buf != NULL) { - bgp_connection connection = session->connections[bgp_connection_primary] ; - assert(connection != NULL) ; + struct stream* buf ; - /* If established, try and send. */ - if (connection->state == bgp_fsm_sEstablished) + if ((flag == mqb_action) && session->active) { - int ret = bgp_connection_no_pending(connection, &args->is_pending) ; + bgp_connection connection ; - if (ret != 0) - ret = bgp_msg_send_update(connection, args->buf) ; + connection = session->connections[bgp_connection_primary] ; + assert(connection != NULL) ; - if (ret == 0) - { - /* 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) + /* If established, try and send. */ + if (connection->state == bgp_fsm_sEstablished) { - /* Successfully wrote the message. XON if requested */ - if (args->xon_kick) - bgp_session_XON(session); + int ret ; + ret = bgp_connection_no_pending(connection, &args->is_pending) ; + + if (ret != 0) + ret = bgp_msg_send_update(connection, args->buf) ; + + if (ret == 0) + { + /* 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. */ + } } ; } ; + + buf = args->buf ; + args->buf = buf->next ; + + stream_free(buf) ; } ; - stream_free(args->buf) ; + /* If gets to here, then has dealt with all message(s). */ + if ((flag == mqb_action) && (args->xon_kick)) + bgp_session_XON(session) ; + mqb_free(mqb) ; } ; /*------------------------------------------------------------------------------ - * Peering Engine: are we in XON state ? + * Routing Engine: are we in XON state ? */ extern int bgp_session_is_XON(bgp_peer peer) @@ -606,8 +616,20 @@ bgp_session_is_XON(bgp_peer peer) return result; } ; +/*------------------------------------------------------------------------------ + * Count down flow control -- signal if reached XON point. + */ +extern int +bgp_session_dec_flow_count(bgp_peer peer) +{ + bgp_session session = peer->session; + + assert(session->flow_control > 0) ; + return (--session->flow_control == BGP_XON_KICK) ; +} ; + /*============================================================================== - * Peering Engine: dispatch Route Refresh to peer -> BGP Engine + * Routing Engine: dispatch Route Refresh to peer -> BGP Engine * * The BGP Engine takes care of discarding the bgp_route_refresh once it's been * dealt with. @@ -671,7 +693,7 @@ bgp_session_do_route_refresh_send(mqueue_block mqb, mqb_flag_t flag) } ; /*============================================================================== - * Peering Engine: dispatch End-of-RIB to peer -> BGP Engine + * Routing Engine: dispatch End-of-RIB to peer -> BGP Engine */ extern void bgp_session_end_of_rib_send(bgp_session session, qAFI_t afi, qSAFI_t safi) @@ -736,11 +758,11 @@ bgp_session_do_end_of_rib_send(mqueue_block mqb, mqb_flag_t flag) } ; /*============================================================================== - * BGP Engine: forward incoming update -> Peering Engine + * BGP Engine: forward incoming update -> Routing Engine * * PRO TEM -- this is being passed the raw BGP message. * - * The Peering Engine takes care of discarding the stream block once it's been + * The Routing Engine takes care of discarding the stream block once it's been * dealt with. */ extern void @@ -756,13 +778,13 @@ bgp_session_update_recv(bgp_session session, struct stream* buf, bgp_size_t size args->size = size; args->xon_kick = 0; - ++peering_engine_queue_stats.update ; + ++routing_engine_queue_stats.update ; - bgp_to_peering_engine(mqb) ; + bgp_to_routing_engine(mqb) ; } /*------------------------------------------------------------------------------ - * Peering Engine: process incoming update message -- mqb action function. + * Routing Engine: process incoming update message -- mqb action function. */ static void bgp_session_do_update_recv(mqueue_block mqb, mqb_flag_t flag) @@ -787,7 +809,7 @@ bgp_session_do_update_recv(mqueue_block mqb, mqb_flag_t flag) /*============================================================================== * BGP Engine: received Route Refresh to peer * - * The Peering Engine takes care of discarding the bgp_route_refresh once + * The Routing Engine takes care of discarding the bgp_route_refresh once * it's been dealt with. */ extern void @@ -802,11 +824,11 @@ bgp_session_route_refresh_recv(bgp_session session, bgp_route_refresh rr) args->rr = rr ; args->is_pending = NULL ; - bgp_to_peering_engine(mqb) ; + bgp_to_routing_engine(mqb) ; } ; /*------------------------------------------------------------------------------ - * Peering Engine: receive given BGP route refresh message -- mqb action + * Routing Engine: receive given BGP route refresh message -- mqb action * function. */ static void @@ -823,7 +845,7 @@ bgp_session_do_route_refresh_recv(mqueue_block mqb, mqb_flag_t flag) } /*============================================================================== - * BGP Engine: send XON message to Peering Engine + * BGP Engine: send XON message to Routing Engine * * Can be sent more packets now */ @@ -836,13 +858,13 @@ bgp_session_XON(bgp_session session) confirm(sizeof(struct bgp_session_XON_args) == 0) ; - ++peering_engine_queue_stats.xon ; + ++routing_engine_queue_stats.xon ; - bgp_to_peering_engine(mqb) ; + bgp_to_routing_engine(mqb) ; } /*------------------------------------------------------------------------------ - * Peering Engine: process incoming XON message -- mqb action function. + * Routing Engine: process incoming XON message -- mqb action function. */ static void bgp_session_do_XON(mqueue_block mqb, mqb_flag_t flag) @@ -854,14 +876,14 @@ bgp_session_do_XON(mqueue_block mqb, mqb_flag_t flag) int xoff = (session->flow_control <= 0); session->flow_control = BGP_XON_REFRESH; if (xoff) - bgp_write (session->peer) ; + bgp_write (session->peer, NULL) ; } mqb_free(mqb) ; } /*============================================================================== - * Peering Engine: send set ttl message to BGP Engine + * Routing Engine: send set ttl message to BGP Engine * */ void @@ -918,7 +940,7 @@ bgp_session_do_set_ttl(mqueue_block mqb, mqb_flag_t flag) * pointer is NULL -- this is largely paranoia, but it would be a grave * mistake for the listening socket(s) to find a session which is not active ! * - * NB: accessing Peering Engine "private" variable -- no lock required. + * NB: accessing Routing Engine "private" variable -- no lock required. * * accessing index_entry when not active -- no lock required. */ @@ -943,13 +965,13 @@ bgp_session_is_active(bgp_session session) } ; /*------------------------------------------------------------------------------ - * Peering Engine: if session is limping we defer re-enabling the session + * Routing Engine: if session is limping we defer re-enabling the session * until it is disabled. * * returns 1 if limping and defer * returns 0 if not limping * - * NB: accessing Peering Engine "private" variable -- no lock required. + * NB: accessing Routing Engine "private" variable -- no lock required. */ static int bgp_session_defer_if_limping(bgp_session session) |