diff --git a/src/route_bgp.c b/src/route_bgp.c index 43144e01..207cd925 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -441,14 +441,12 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) { struct ROUTE_TABLE* rt = conn->instance->rt; // Remove this connection from all nodes' path lists - bool need_withdraw = false; int nodes_removed = 0; struct ll_entry* node_entry = bgp->nodes ? bgp->nodes->head : NULL; while (node_entry) { struct ll_entry* next = node_entry->next; struct NODEINFO_Q* nq = (struct NODEINFO_Q*)node_entry; if (route_bgp_remove_path(nq, conn) == 1) { - need_withdraw = true; if (rt) route_delete(rt, nq); if (conn->instance && conn->instance->control_srv) control_server_notify_node_removed(conn->instance->control_srv, nq->node.node_id); @@ -460,6 +458,8 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) { if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); } nodes_removed++; etcp_router_conn_close_all_for_node(bgp->instance, key); + uint64_t wd_src = (key == conn->peer_node_id) ? conn->instance->node_id : conn->peer_node_id; + route_bgp_broadcast_withdraw(bgp, key, wd_src, NULL); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Removed node %016llx after link down", (unsigned long long)key); } node_entry = next; @@ -477,12 +477,8 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) { e = e->next; } - if (need_withdraw) { - route_bgp_broadcast_withdraw(bgp, conn->peer_node_id, conn->instance->node_id, NULL); - } - - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d withdraw=%d", - conn->log_name, nodes_removed, need_withdraw); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", + conn->log_name, nodes_removed); } @@ -755,7 +751,16 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co uint8_t new_ver = ni->ver; if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver-new_ver)>=0) { - DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO ignored old ver: node=%016llx ver=%d<=%d from=%s", + int new_hops = ni->hop_count + 1; + if (new_hops <= MAX_HOPS) { + uint64_t hop_list[MAX_HOPS]; + uint64_t* pkt_hops = (uint64_t*)((uint8_t*)ni + sizeof(struct NODEINFO) + dyn_size); + memcpy(hop_list, pkt_hops, ni->hop_count * 8); + hop_list[ni->hop_count] = from->peer_node_id; + route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); + route_bgp_add_path(nodeinfo1, from, hop_list, new_hops); + } + DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO old ver: node=%016llx ver=%d<=%d from=%s (paths updated)", (unsigned long long)node_id, new_ver, nodeinfo1->last_ver, from->log_name); return 0; } @@ -887,7 +892,7 @@ int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, return 0; } int ret=route_bgp_remove_path_by_hop(nq, wd_source); - if (ret>0 || !nq->paths || (nq->paths && queue_entry_count(nq->paths) == 0)) { + if (ret == 1) { if (bgp->instance && bgp->instance->rt) route_delete(bgp->instance->rt, nq); if (bgp->instance->control_srv) control_server_notify_node_removed(bgp->instance->control_srv, node_id); nq->dirty = 1;