summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_fsm.c23
-rw-r--r--bgpd/bgp_packet.c27
-rw-r--r--bgpd/bgp_packet.h1
-rw-r--r--bgpd/bgp_route.c8
-rw-r--r--bgpd/bgp_table.c9
-rw-r--r--bgpd/bgp_vty.c21
-rw-r--r--bgpd/bgp_vty.h21
-rw-r--r--bgpd/bgpd.h9
8 files changed, 101 insertions, 18 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index a86c457b62..328e3a0eb0 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1197,15 +1197,20 @@ int bgp_stop(struct peer *peer)
!CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED)) {
gr_info = &bgp->gr_info[afi][safi];
- if (gr_info && gr_info->eor_required)
+
+ if (gr_info && (gr_info->eor_required))
gr_info->eor_required--;
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("peer %s, EOR %d",
+
+ if (gr_info && BGP_DEBUG(update,
+ UPDATE_OUT))
+ zlog_debug(
+ "peer %s, EOR %d",
peer->host,
gr_info->eor_required);
/* There is no pending EOR message */
- if (gr_info->eor_required == 0) {
+ if (gr_info && gr_info->eor_required
+ == 0) {
BGP_TIMER_OFF(
gr_info->t_select_deferral);
gr_info->eor_received = 0;
@@ -1813,7 +1818,15 @@ static int bgp_establish(struct peer *peer)
if (status < 0)
zlog_debug("Error in updating graceful restart for %s",
get_afi_safi_str(afi,
- safi, false));
+ safi, false));
+ } else {
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(
+ peer) &&
+ BGP_PEER_RESTARTING_MODE(peer)
+ && bgp_flag_check(peer->bgp,
+ BGP_FLAG_GR_PRESERVE_FWD))
+ peer->bgp->gr_info[afi][safi]
+ .eor_required++;
}
}
}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 88b95496e6..d6510dfaf2 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -449,14 +449,20 @@ int bgp_generate_updgrp_packets(struct thread *thread)
/* If EOR is disabled,
* the message is not sent
*/
- if (!bgp_flag_check(peer->bgp,
- BGP_FLAG_GR_DISABLE_EOR
- )) {
+ if (BGP_SEND_EOR(peer->bgp,
+ afi, safi)) {
SET_FLAG(
peer->af_sflags
[afi][safi],
PEER_STATUS_EOR_SEND);
+ /* Update EOR
+ * send time
+ */
+ peer->eor_stime
+ [afi][safi] =
+ monotime(NULL);
+
BGP_UPDATE_EOR_PKT(
peer, afi,
safi, s);
@@ -465,6 +471,10 @@ int bgp_generate_updgrp_packets(struct thread *thread)
}
continue;
}
+
+ /* Update packet send time */
+ peer->pkt_stime[afi][safi] = monotime(NULL);
+
/* Found a packet template to send, overwrite
* packet with appropriate attributes from peer
* and advance peer */
@@ -2422,3 +2432,14 @@ int bgp_process_packet(struct thread *thread)
return 0;
}
+
+/* Send EOR when routes are processed by selection deferral timer */
+void bgp_send_delayed_eor(struct bgp *bgp)
+{
+ struct peer *peer;
+ struct listnode *node, *nnode;
+
+ /* EOR message sent in bgp_write_proceed_actions */
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
+ bgp_write_proceed_actions(peer);
+}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index 1c2bafcb74..0242abab26 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -81,4 +81,5 @@ extern int bgp_packet_set_size(struct stream *s);
extern int bgp_generate_updgrp_packets(struct thread *);
extern int bgp_process_packet(struct thread *);
+extern void bgp_send_delayed_eor(struct bgp *bgp);
#endif /* _QUAGGA_BGP_PACKET_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 75963def86..217e73adf0 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2736,7 +2736,6 @@ int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
/* Process the route list */
node = listhead(bgp->gr_info[afi][safi].route_list);
- node = listhead(bgp->gr_info[afi][safi].route_list);
while (node) {
rn = listgetdata(node);
nnode = node->next;
@@ -2753,8 +2752,11 @@ int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
node = nnode;
}
- if (list_isempty(bgp->gr_info[afi][safi].route_list))
+ /* Send EOR message when all routes are processed */
+ if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
+ bgp_send_delayed_eor(bgp);
return 0;
+ }
thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
if (thread_info == NULL) {
@@ -3055,8 +3057,6 @@ void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
if (delete_route) {
if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
- UNSET_FLAG(rn->flags,
- BGP_NODE_PROCESS_SCHEDULED);
bgp = pi->peer->bgp;
if ((rn->rt_node) &&
(bgp->gr_info[afi][safi]
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 01efab8f2d..2ef272b571 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -141,13 +141,14 @@ void bgp_delete_listnode(struct bgp_node *node)
*/
if (CHECK_FLAG(node->flags, BGP_NODE_SELECT_DEFER)) {
table = bgp_node_table(node);
- if (table)
+
+ if (table) {
bgp = table->bgp;
+ afi = table->afi;
+ safi = table->safi;
+ }
rn = bgp_node_to_rnode(node);
- afi = table->afi;
- safi = table->safi;
-
if (bgp && rn && rn->lock == 1) {
/* Delete the route from the selection pending list */
if ((node->rt_node) &&
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 71a41cd688..c4689989c7 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9474,6 +9474,7 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
json_object *json_afi_safi = NULL;
json_object *json_timer = NULL;
json_object *json_endofrib_status = NULL;
+ bool eor_flag = false;
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
@@ -9490,6 +9491,12 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
json_object_new_object();
}
+ if (peer->eor_stime[afi][safi] >=
+ peer->pkt_stime[afi][safi])
+ eor_flag = true;
+ else
+ eor_flag = false;
+
if (!use_json) {
vty_out(vty, " %s :\n",
get_afi_safi_str(afi, safi, false));
@@ -9555,22 +9562,32 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
if (CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND)) {
-
if (use_json) {
json_object_boolean_true_add(
json_endofrib_status,
"endOfRibSend");
+
+ PRINT_EOR_JSON(eor_flag);
} else {
vty_out(vty, "Yes\n");
- }
+ vty_out(vty,
+ " EoRSentAfterUpdate : ");
+ PRINT_EOR(eor_flag);
+ }
} else {
if (use_json) {
json_object_boolean_false_add(
json_endofrib_status,
"endOfRibSend");
+ json_object_boolean_false_add(
+ json_endofrib_status,
+ "endOfRibSentAfterUpdate");
} else {
vty_out(vty, "No\n");
+ vty_out(vty,
+ " EoRSentAfterUpdate : ");
+ vty_out(vty, "No\n");
}
}
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 3f60c7719c..3dc639ea76 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -68,6 +68,27 @@ struct bgp;
vty, p, use_json, json); \
} while (0)
+
+#define PRINT_EOR(_eor_flag) \
+ do { \
+ if (eor_flag) \
+ vty_out(vty, "Yes\n"); \
+ else \
+ vty_out(vty, "No\n"); \
+ } while (0)
+
+#define PRINT_EOR_JSON(_eor_flag) \
+ do { \
+ if (eor_flag) \
+ json_object_boolean_true_add( \
+ json_endofrib_status, \
+ "endOfRibSentAfterUpdate"); \
+ else \
+ json_object_boolean_false_add( \
+ json_endofrib_status, \
+ "endOfRibSentAfterUpdate"); \
+ } while (0)
+
extern void bgp_vty_init(void);
extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 9b4f8d3eb4..3c9f9cb595 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -232,6 +232,11 @@ enum bgp_instance_type {
BGP_INSTANCE_TYPE_VIEW
};
+#define BGP_SEND_EOR(bgp, afi, safi) \
+ (!bgp_flag_check(bgp, BGP_FLAG_GR_DISABLE_EOR) && \
+ ((bgp->gr_info[afi][safi].t_select_deferral == NULL) || \
+ (bgp->gr_info[afi][safi].eor_required == \
+ bgp->gr_info[afi][safi].eor_received)))
/* BGP GR Global ds */
@@ -1061,6 +1066,10 @@ struct peer {
/* NSF mode (graceful restart) */
uint8_t nsf[AFI_MAX][SAFI_MAX];
+ /* EOR Send time */
+ time_t eor_stime[AFI_MAX][SAFI_MAX];
+ /* Last update packet sent time */
+ time_t pkt_stime[AFI_MAX][SAFI_MAX];
/* Peer Per AF flags */
/*