zebra: Capabality and stale route handling for GR client.

Handling capability received from client. It may contain
GR enable/disable, Stale time changes, RIB update complete
for given AFi, ASAFI and instance. It also has changes for
stale route handling.

Signed-off-by: Santosh P K <sapk@vmware.com>
This commit is contained in:
Santosh P K 2020-01-09 09:53:27 -08:00
parent 851140a7bb
commit b9e6727acd
5 changed files with 624 additions and 89 deletions

View File

@ -169,175 +169,201 @@ Zebra Protocol Commands
+------------------------------------+-------+
| ZEBRA_INTERFACE_SET_MASTER | 6 |
+------------------------------------+-------+
| ZEBRA_ROUTE_ADD | 7 |
| ZEBRA_INTERFACE_SET_PROTODOWN | 7 |
+------------------------------------+-------+
| ZEBRA_ROUTE_DELETE | 8 |
| ZEBRA_ROUTE_ADD | 8 |
+------------------------------------+-------+
| ZEBRA_ROUTE_NOTIFY_OWNER | 9 |
| ZEBRA_ROUTE_DELETE | 9 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ADD | 10 |
| ZEBRA_ROUTE_NOTIFY_OWNER | 10 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DELETE | 11 |
| ZEBRA_REDISTRIBUTE_ADD | 11 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DEFAULT_ADD | 12 |
| ZEBRA_REDISTRIBUTE_DELETE | 12 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_DEFAULT_DELETE | 13 |
| ZEBRA_REDISTRIBUTE_DEFAULT_ADD | 13 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_ADD | 14 |
| ZEBRA_REDISTRIBUTE_DEFAULT_DELETE | 14 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_DELETE | 15 |
| ZEBRA_ROUTER_ID_ADD | 15 |
+------------------------------------+-------+
| ZEBRA_ROUTER_ID_UPDATE | 16 |
| ZEBRA_ROUTER_ID_DELETE | 16 |
+------------------------------------+-------+
| ZEBRA_HELLO | 17 |
| ZEBRA_ROUTER_ID_UPDATE | 17 |
+------------------------------------+-------+
| ZEBRA_CAPABILITIES | 18 |
| ZEBRA_HELLO | 18 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_REGISTER | 19 |
| ZEBRA_CAPABILITIES | 19 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_UNREGISTER | 20 |
| ZEBRA_NEXTHOP_REGISTER | 20 |
+------------------------------------+-------+
| ZEBRA_NEXTHOP_UPDATE | 21 |
| ZEBRA_NEXTHOP_UNREGISTER | 21 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_NBR_ADDRESS_ADD | 22 |
| ZEBRA_NEXTHOP_UPDATE | 22 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_NBR_ADDRESS_DELETE | 23 |
| ZEBRA_INTERFACE_NBR_ADDRESS_ADD | 23 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_BFD_DEST_UPDATE | 24 |
| ZEBRA_INTERFACE_NBR_ADDRESS_DELETE | 24 |
+------------------------------------+-------+
| ZEBRA_IMPORT_ROUTE_REGISTER | 25 |
| ZEBRA_INTERFACE_BFD_DEST_UPDATE | 25 |
+------------------------------------+-------+
| ZEBRA_IMPORT_ROUTE_UNREGISTER | 26 |
| ZEBRA_IMPORT_ROUTE_REGISTER | 26 |
+------------------------------------+-------+
| ZEBRA_IMPORT_CHECK_UPDATE | 27 |
| ZEBRA_IMPORT_ROUTE_UNREGISTER | 27 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_REGISTER | 28 |
| ZEBRA_IMPORT_CHECK_UPDATE | 28 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_DEREGISTER | 29 |
| ZEBRA_BFD_DEST_REGISTER | 29 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_UPDATE | 30 |
| ZEBRA_BFD_DEST_DEREGISTER | 30 |
+------------------------------------+-------+
| ZEBRA_BFD_DEST_REPLAY | 31 |
| ZEBRA_BFD_DEST_UPDATE | 31 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ROUTE_ADD | 32 |
| ZEBRA_BFD_DEST_REPLAY | 32 |
+------------------------------------+-------+
| ZEBRA_REDISTRIBUTE_ROUTE_DEL | 33 |
| ZEBRA_REDISTRIBUTE_ROUTE_ADD | 33 |
+------------------------------------+-------+
| ZEBRA_VRF_UNREGISTER | 34 |
| ZEBRA_REDISTRIBUTE_ROUTE_DEL | 34 |
+------------------------------------+-------+
| ZEBRA_VRF_ADD | 35 |
| ZEBRA_VRF_UNREGISTER | 35 |
+------------------------------------+-------+
| ZEBRA_VRF_DELETE | 36 |
| ZEBRA_VRF_ADD | 36 |
+------------------------------------+-------+
| ZEBRA_VRF_LABEL | 37 |
| ZEBRA_VRF_DELETE | 37 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_VRF_UPDATE | 38 |
| ZEBRA_VRF_LABEL | 38 |
+------------------------------------+-------+
| ZEBRA_BFD_CLIENT_REGISTER | 39 |
| ZEBRA_INTERFACE_VRF_UPDATE | 39 |
+------------------------------------+-------+
| ZEBRA_BFD_CLIENT_DEREGISTER | 40 |
| ZEBRA_BFD_CLIENT_REGISTER | 40 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_ENABLE_RADV | 41 |
| ZEBRA_BFD_CLIENT_DEREGISTER | 41 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_DISABLE_RADV | 42 |
| ZEBRA_INTERFACE_ENABLE_RADV | 42 |
+------------------------------------+-------+
| ZEBRA_IPV3_NEXTHOP_LOOKUP_MRIB | 43 |
| ZEBRA_INTERFACE_DISABLE_RADV | 43 |
+------------------------------------+-------+
| ZEBRA_INTERFACE_LINK_PARAMS | 44 |
| ZEBRA_IPV3_NEXTHOP_LOOKUP_MRIB | 44 |
+------------------------------------+-------+
| ZEBRA_MPLS_LABELS_ADD | 45 |
| ZEBRA_INTERFACE_LINK_PARAMS | 45 |
+------------------------------------+-------+
| ZEBRA_MPLS_LABELS_DELETE | 46 |
| ZEBRA_MPLS_LABELS_ADD | 46 |
+------------------------------------+-------+
| ZEBRA_IPMR_ROUTE_STATS | 47 |
| ZEBRA_MPLS_LABELS_DELETE | 47 |
+------------------------------------+-------+
| ZEBRA_LABEL_MANAGER_CONNECT | 48 |
| ZEBRA_MPLS_LABELS_REPLACE | 48 |
+------------------------------------+-------+
| ZEBRA_LABEL_MANAGER_CONNECT_ASYNC | 49 |
| ZEBRA_IPMR_ROUTE_STATS | 49 |
+------------------------------------+-------+
| ZEBRA_GET_LABEL_CHUNK | 50 |
| ZEBRA_LABEL_MANAGER_CONNECT | 50 |
+------------------------------------+-------+
| ZEBRA_RELEASE_LABEL_CHUNK | 51 |
| ZEBRA_LABEL_MANAGER_CONNECT_ASYNC | 51 |
+------------------------------------+-------+
| ZEBRA_FEC_REGISTER | 52 |
| ZEBRA_GET_LABEL_CHUNK | 52 |
+------------------------------------+-------+
| ZEBRA_FEC_UNREGISTER | 53 |
| ZEBRA_RELEASE_LABEL_CHUNK | 53 |
+------------------------------------+-------+
| ZEBRA_FEC_UPDATE | 54 |
| ZEBRA_FEC_REGISTER | 54 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_DEFAULT_GW | 55 |
| ZEBRA_FEC_UNREGISTER | 55 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_SUBNET | 56 |
| ZEBRA_FEC_UPDATE | 56 |
+------------------------------------+-------+
| ZEBRA_ADVERTISE_ALL_VNI | 57 |
| ZEBRA_ADVERTISE_DEFAULT_GW | 57 |
+------------------------------------+-------+
| ZEBRA_LOCAL_ES_ADD | 58 |
| ZEBRA_ADVERTISE_SVI_MACIP | 58 |
+------------------------------------+-------+
| ZEBRA_LOCAL_ES_DEL | 59 |
| ZEBRA_ADVERTISE_SUBNET | 59 |
+------------------------------------+-------+
| ZEBRA_VNI_ADD | 60 |
| ZEBRA_ADVERTISE_ALL_VNI | 60 |
+------------------------------------+-------+
| ZEBRA_VNI_DEL | 61 |
| ZEBRA_LOCAL_ES_ADD | 61 |
+------------------------------------+-------+
| ZEBRA_L3VNI_ADD | 62 |
| ZEBRA_LOCAL_ES_DEL | 62 |
+------------------------------------+-------+
| ZEBRA_L3VNI_DEL | 63 |
| ZEBRA_VNI_ADD | 63 |
+------------------------------------+-------+
| ZEBRA_REMOTE_VTEP_ADD | 64 |
| ZEBRA_VNI_DEL | 64 |
+------------------------------------+-------+
| ZEBRA_REMOTE_VTEP_DEL | 65 |
| ZEBRA_L3VNI_ADD | 65 |
+------------------------------------+-------+
| ZEBRA_MACIP_ADD | 66 |
| ZEBRA_L3VNI_DEL | 66 |
+------------------------------------+-------+
| ZEBRA_MACIP_DEL | 67 |
| ZEBRA_REMOTE_VTEP_ADD | 67 |
+------------------------------------+-------+
| ZEBRA_IP_PREFIX_ROUTE_ADD | 68 |
| ZEBRA_REMOTE_VTEP_DEL | 68 |
+------------------------------------+-------+
| ZEBRA_IP_PREFIX_ROUTE_DEL | 69 |
| ZEBRA_MACIP_ADD | 69 |
+------------------------------------+-------+
| ZEBRA_REMOTE_MACIP_ADD | 70 |
| ZEBRA_MACIP_DEL | 70 |
+------------------------------------+-------+
| ZEBRA_REMOTE_MACIP_DEL | 71 |
| ZEBRA_IP_PREFIX_ROUTE_ADD | 71 |
+------------------------------------+-------+
| ZEBRA_PW_ADD | 72 |
| ZEBRA_IP_PREFIX_ROUTE_DEL | 72 |
+------------------------------------+-------+
| ZEBRA_PW_DELETE | 73 |
| ZEBRA_REMOTE_MACIP_ADD | 73 |
+------------------------------------+-------+
| ZEBRA_PW_SET | 74 |
| ZEBRA_REMOTE_MACIP_DEL | 74 |
+------------------------------------+-------+
| ZEBRA_PW_UNSET | 75 |
| ZEBRA_DUPLICATE_ADDR_DETECTION | 75 |
+------------------------------------+-------+
| ZEBRA_PW_STATUS_UPDATE | 76 |
| ZEBRA_PW_ADD | 76 |
+------------------------------------+-------+
| ZEBRA_RULE_ADD | 77 |
| ZEBRA_PW_DELETE | 77 |
+------------------------------------+-------+
| ZEBRA_RULE_DELETE | 78 |
| ZEBRA_PW_SET | 78 |
+------------------------------------+-------+
| ZEBRA_RULE_NOTIFY_OWNER | 79 |
| ZEBRA_PW_UNSET | 79 |
+------------------------------------+-------+
| ZEBRA_TABLE_MANAGER_CONNECT | 80 |
| ZEBRA_PW_STATUS_UPDATE | 80 |
+------------------------------------+-------+
| ZEBRA_GET_TABLE_CHUNK | 81 |
| ZEBRA_RULE_ADD | 81 |
+------------------------------------+-------+
| ZEBRA_RELEASE_TABLE_CHUNK | 82 |
| ZEBRA_RULE_DELETE | 82 |
+------------------------------------+-------+
| ZEBRA_IPSET_CREATE | 83 |
| ZEBRA_RULE_NOTIFY_OWNER | 83 |
+------------------------------------+-------+
| ZEBRA_IPSET_DESTROY | 84 |
| ZEBRA_TABLE_MANAGER_CONNECT | 84 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_ADD | 85 |
| ZEBRA_GET_TABLE_CHUNK | 85 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_DELETE | 86 |
| ZEBRA_RELEASE_TABLE_CHUNK | 86 |
+------------------------------------+-------+
| ZEBRA_IPSET_NOTIFY_OWNER | 87 |
| ZEBRA_IPSET_CREATE | 87 |
+------------------------------------+-------+
| ZEBRA_IPSET_ENTRY_NOTIFY_OWNER | 88 |
| ZEBRA_IPSET_DESTROY | 88 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_ADD | 89 |
| ZEBRA_IPSET_ENTRY_ADD | 89 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_DELETE | 90 |
| ZEBRA_IPSET_ENTRY_DELETE | 90 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_NOTIFY_OWNER | 91 |
| ZEBRA_IPSET_NOTIFY_OWNER | 91 |
+------------------------------------+-------+
| ZEBRA_VXLAN_FLOOD_CONTROL | 92 |
| ZEBRA_IPSET_ENTRY_NOTIFY_OWNER | 92 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_ADD | 93 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_DELETE | 94 |
+------------------------------------+-------+
| ZEBRA_IPTABLE_NOTIFY_OWNER | 95 |
+------------------------------------+-------+
| ZEBRA_VXLAN_FLOOD_CONTROL | 96 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_ADD | 97 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_DEL | 98 |
+------------------------------------+-------+
| ZEBRA_VXLAN_SG_REPLAY | 99 |
+------------------------------------+-------+
| ZEBRA_MLAG_PROCESS_UP | 100 |
+------------------------------------+-------+
| ZEBRA_MLAG_PROCESS_DOWN | 101 |
+------------------------------------+-------+
| ZEBRA_MLAG_CLIENT_REGISTER | 102 |
+------------------------------------+-------+
| ZEBRA_MLAG_CLIENT_UNREGISTER | 103 |
+------------------------------------+-------+
| ZEBRA_MLAG_FORWARD_MSG | 104 |
+------------------------------------+-------+
| ZEBRA_CLIENT_CAPABILITIES | 105 |
+------------------------------------+-------+

View File

@ -151,6 +151,10 @@ static void sigint(void)
zebra_dplane_pre_finish();
/* Clean up GR related info. */
zebra_gr_stale_client_cleanup(zrouter.stale_client_list);
list_delete_all_node(zrouter.stale_client_list);
for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client))
zserv_close_client(client);

View File

@ -2668,6 +2668,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities
};
#if defined(HANDLE_ZAPI_FUZZING)

View File

@ -51,7 +51,10 @@
* Forward declaration.
*/
static struct zserv *zebra_gr_find_stale_client(struct zserv *client);
static int zebra_gr_route_stale_delete_timer_expiry(struct thread *thread);
static int32_t zebra_gr_route_stale_delete_timer_expiry(struct thread *thread);
static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info);
static void zebra_gr_process_client_stale_routes(struct zserv *client,
vrf_id_t vrf_id);
/*
* Debug macros.
@ -67,10 +70,80 @@ static int zebra_gr_route_stale_delete_timer_expiry(struct thread *thread);
* Client connection functions
*/
/*
* Function to clean all the stale clients,
* function will also clean up all per instance
* capabilities that are exchanged.
*/
void zebra_gr_stale_client_cleanup(struct list *client_list)
{
struct listnode *node, *nnode;
struct zserv *s_client = NULL;
struct client_gr_info *info, *ninfo;
/* Find the stale client */
for (ALL_LIST_ELEMENTS(client_list, node, nnode, s_client)) {
LOG_GR("%s: Stale client %s is being deleted", __func__,
zebra_route_string(s_client->proto));
TAILQ_FOREACH_SAFE (info, &s_client->gr_info_queue, gr_info,
ninfo) {
/* Cancel the stale timer */
if (info->t_stale_removal != NULL) {
THREAD_OFF(info->t_stale_removal);
info->t_stale_removal = NULL;
/* Process the stale routes */
thread_execute(
zrouter.master,
zebra_gr_route_stale_delete_timer_expiry,
info, 1);
}
}
}
}
/*
* A helper function to create client info.
*/
static struct client_gr_info *zebra_gr_client_info_create(struct zserv *client)
{
struct client_gr_info *info;
info = XCALLOC(MTYPE_TMP, sizeof(struct client_gr_info));
TAILQ_INSERT_TAIL(&(client->gr_info_queue), info, gr_info);
return info;
}
/*
* A helper function to delte and destory client info.
*/
static void zebra_gr_client_info_delte(struct zserv *client,
struct client_gr_info *info)
{
TAILQ_REMOVE(&(client->gr_info_queue), info, gr_info);
THREAD_OFF(info->t_stale_removal);
if (info->current_prefix)
XFREE(MTYPE_TMP, info->current_prefix);
LOG_GR("%s: Instance info is being deleted for client %s", __func__,
zebra_route_string(client->proto));
/* Delete all the stale routes. */
info->delete = true;
zebra_gr_delete_stale_routes(info);
XFREE(MTYPE_TMP, info);
}
/*
* Function to handle client when it disconnect.
*/
int zebra_gr_client_disconnect(struct zserv *client)
int32_t zebra_gr_client_disconnect(struct zserv *client)
{
struct zserv *stale_client;
struct timeval tv;
@ -113,6 +186,47 @@ int zebra_gr_client_disconnect(struct zserv *client)
return 0;
}
/*
* Function to delete stale client
*/
static void zebra_gr_delete_stale_client(struct client_gr_info *info)
{
struct client_gr_info *bgp_info;
struct zserv *s_client = NULL;
s_client = info->stale_client_ptr;
if (!s_client || !info->stale_client)
return;
/*
* If there are bgp instances with the stale delete timer pending
* then stale client is not deleted
*/
if ((s_client->gr_instance_count > 0) && info->gr_enable)
s_client->gr_instance_count--;
TAILQ_REMOVE(&(s_client->gr_info_queue), info, gr_info);
LOG_GR("%s: Client %s gr count %d", __func__,
zebra_route_string(s_client->proto),
s_client->gr_instance_count);
TAILQ_FOREACH (bgp_info, &s_client->gr_info_queue, gr_info) {
if (bgp_info->t_stale_removal != NULL)
return;
}
LOG_GR("%s: Client %s is being deleted", __func__,
zebra_route_string(s_client->proto));
TAILQ_INIT(&(s_client->gr_info_queue));
listnode_delete(zrouter.stale_client_list, s_client);
if (info->stale_client)
XFREE(MTYPE_TMP, s_client);
XFREE(MTYPE_TMP, info);
}
/*
* Function to find stale client.
*/
@ -177,8 +291,394 @@ void zebra_gr_client_reconnect(struct zserv *client)
}
}
/*
* Functions to deal with capabilities
*/
static int zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
/*
* Update the graceful restart information
* for the client instance.
* This function handles all the capabilties that are received.
*/
static void zebra_client_update_info(struct zserv *client, struct zapi_cap *api)
{
struct client_gr_info *info = NULL;
/* Find the bgp information for the specified vrf id */
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
if (info->vrf_id == api->vrf_id)
break;
}
/*
* If the command is delete, then cancel the stale timer and
* delete the bgp info
*/
switch (api->cap) {
case ZEBRA_CLIENT_GR_DISABLE:
if (!info)
return;
LOG_GR("%s: Client %s instance GR disabled count %d", __func__,
zebra_route_string(client->proto),
client->gr_instance_count);
if ((info->gr_enable) && (client->gr_instance_count > 0))
client->gr_instance_count--;
zebra_gr_client_info_delte(client, info);
break;
case ZEBRA_CLIENT_GR_CAPABILITIES:
/* Allocate bgp info */
if (!info)
info = zebra_gr_client_info_create(client);
/* Udpate other parameters */
if (!info->gr_enable) {
client->gr_instance_count++;
LOG_GR("%s: Cient %s GR enabled count %d", __func__,
zebra_route_string(client->proto),
client->gr_instance_count);
info->capabilities = api->cap;
info->stale_removal_time = api->stale_removal_time;
info->vrf_id = api->vrf_id;
info->gr_enable = true;
}
break;
case ZEBRA_CLIENT_RIB_STALE_TIME:
LOG_GR("%s: Client %s stale time update event", __func__,
zebra_route_string(client->proto));
/* Update the stale removal timer */
if (info && info->t_stale_removal == NULL) {
LOG_GR("%s: Stale time: %d is now update to: %d",
__func__, info->stale_removal_time,
api->stale_removal_time);
info->stale_removal_time = api->stale_removal_time;
}
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
LOG_GR(
"%s: Client %s route update complete for AFI %d, SAFI %d",
__func__, zebra_route_string(client->proto), api->afi,
api->safi);
if (info)
info->route_sync[api->afi][api->safi] = true;
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
LOG_GR("%s: Client %s route update pending for AFI %d, SAFI %d",
__func__, zebra_route_string(client->proto), api->afi,
api->safi);
if (info)
info->af_enabled[api->afi][api->safi] = true;
break;
}
}
/*
* Handler for capabilities that are received from client.
*/
static void zebra_client_capabilities_handler(struct zserv *client,
struct zapi_cap *api)
{
switch (api->cap) {
case ZEBRA_CLIENT_GR_CAPABILITIES:
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
case ZEBRA_CLIENT_GR_DISABLE:
case ZEBRA_CLIENT_RIB_STALE_TIME:
/*
* For all the cases we need to update the client info.
*/
zebra_client_update_info(client, api);
break;
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
/*
* After client info has been updated delete all
* stale routes
*/
zebra_client_update_info(client, api);
zebra_gr_process_client_stale_routes(client, api->vrf_id);
break;
}
}
/*
* Function to decode and call appropriate functions
* to handle client capabilities.
*/
void zread_client_capabilities(ZAPI_HANDLER_ARGS)
{
struct zapi_cap api;
struct stream *s;
s = msg;
if (zapi_capabilities_decode(s, &api)) {
LOG_GR("%s: Error in reading capabilities for client %s",
__func__, zebra_route_string(client->proto));
return;
}
/* Call the capabilities handler */
zebra_client_capabilities_handler(client, &api);
}
/*
* Stale route handling
*/
/*
* Delete all the stale routes that have not been refreshed
* post restart.
*/
static int32_t zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
{
struct client_gr_info *info;
int32_t cnt = 0;
struct zserv *client;
info = THREAD_ARG(thread);
info->t_stale_removal = NULL;
client = (struct zserv *)info->stale_client_ptr;
/* Set the flag to indicate all stale route deletion */
if (thread->u.val == 1)
info->delete = true;
cnt = zebra_gr_delete_stale_routes(info);
/* Retsart the timer */
if (cnt > 0) {
LOG_GR("%s: Client %s processed %d routes. Start timer again",
__func__, zebra_route_string(client->proto), cnt);
thread_add_timer(zrouter.master,
zebra_gr_route_stale_delete_timer_expiry, info,
ZEBRA_DEFAULT_STALE_UPDATE_DELAY,
&info->t_stale_removal);
} else {
/* No routes to delete for the VRF */
LOG_GR("%s: Client %s all starle routes processed", __func__,
zebra_route_string(client->proto));
if (info->current_prefix != NULL)
XFREE(MTYPE_TMP, info->current_prefix);
info->current_prefix = NULL;
info->current_afi = 0;
zebra_gr_delete_stale_client(info);
}
return 0;
}
/*
* Function to process to check if route entry is stale
* or has been updated.
*/
static void zebra_gr_process_route_entry(struct zserv *client,
struct route_node *rn,
struct route_entry *re)
{
char buf[PREFIX2STR_BUFFER];
if ((client == NULL) || (rn == NULL) || (re == NULL))
return;
/* If the route is not refreshed after restart, delete the entry */
if (re->uptime < client->restart_time) {
if (IS_ZEBRA_DEBUG_RIB) {
prefix2str(&rn->p, buf, sizeof(buf));
zlog_debug("%s: Client %s stale route %s is deleted",
__func__, zebra_route_string(client->proto),
buf);
}
rib_delnode(rn, re);
}
}
/*
* This function walks through the route table for all vrf and deletes
* the stale routes for the restarted client specified by the protocol
* type
*/
static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
struct zebra_vrf *zvrf)
{
struct route_node *rn, *curr;
struct route_entry *re;
struct route_entry *next;
struct route_table *table;
int32_t n = 0;
struct prefix *p;
afi_t afi, curr_afi;
uint8_t proto;
uint16_t instance;
struct zserv *s_client;
if ((info == NULL) || (zvrf == NULL))
return -1;
s_client = info->stale_client_ptr;
if (s_client == NULL) {
LOG_GR("%s: Stale client not present", __func__);
return -1;
}
proto = s_client->proto;
instance = s_client->instance;
curr_afi = info->current_afi;
LOG_GR("%s: Client %s stale routes are being deleted", __func__,
zebra_route_string(proto));
/* Process routes for all AFI */
for (afi = curr_afi; afi < AFI_MAX; afi++) {
table = zvrf->table[afi][SAFI_UNICAST];
p = info->current_prefix;
if (table) {
/*
* If the current prefix is NULL then get the first
* route entry in the table
*/
if (p == NULL) {
rn = route_top(table);
if (rn == NULL)
continue;
p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
if (p == NULL)
return -1;
curr = rn;
prefix_copy(p, &rn->p);
} else
/* Get the next route entry */
curr = route_table_get_next(table, p);
for (rn = curr; rn; rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
if (CHECK_FLAG(re->status,
ROUTE_ENTRY_REMOVED))
continue;
/* If the route refresh is received
* after restart then do not delete
* the route
*/
if (re->type == proto
&& re->instance == instance) {
zebra_gr_process_route_entry(
s_client, rn, re);
n++;
}
/* If the max route count is reached
* then timer thread will be restarted
* Store the current prefix and afi
*/
if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT)
&& (info->delete == false)) {
prefix_copy(p, &rn->p);
info->current_afi = afi;
info->current_prefix = p;
return n;
}
}
}
}
/*
* Reset the current prefix to indicate processing completion
* of the current AFI
*/
if (info->current_prefix) {
XFREE(MTYPE_TMP, info->current_prefix);
info->current_prefix = NULL;
}
continue;
}
return 0;
}
/*
* Delete the stale routes when client is restarted and routes are not
* refreshed within the stale timeout
*/
static int32_t zebra_gr_delete_stale_routes(struct client_gr_info *info)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
uint64_t cnt = 0;
if (info == NULL)
return -1;
/* Get the current VRF */
vrf = vrf_lookup_by_id(info->vrf_id);
if (vrf == NULL) {
LOG_GR("%s: Invalid VRF %d", __func__, info->vrf_id);
return -1;
}
zvrf = vrf->info;
if (zvrf == NULL) {
LOG_GR("%s: Invalid VRF entry %d", __func__, info->vrf_id);
return -1;
}
cnt = zebra_gr_delete_stale_route(info, zvrf);
return cnt;
}
/*
* This function checks if route update for all AFI, SAFI is completed
* and cancels the stale timer
*/
static void zebra_gr_process_client_stale_routes(struct zserv *client,
vrf_id_t vrf_id)
{
struct client_gr_info *info = NULL;
afi_t afi;
safi_t safi;
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
if (info->vrf_id == vrf_id)
break;
}
if (info == NULL)
return;
/* Check if route update completed for all AFI, SAFI */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi <= SAFI_MPLS_VPN; safi++) {
if (info->af_enabled[afi][safi]) {
if (!info->route_sync[afi][safi]) {
LOG_GR(
"%s: Client %s route update not completed for AFI %d, SAFI %d",
__func__, zebra_route_string(
client->proto),
afi, safi);
return;
}
}
}
/*
* Route update completed for all AFI, SAFI
* Cancel the stale timer and process the routes
*/
if (info->t_stale_removal) {
LOG_GR("%s: Client %s cancled stale delete timer vrf %d",
__func__, zebra_route_string(client->proto),
info->vrf_id);
THREAD_OFF(info->t_stale_removal);
thread_execute(zrouter.master,
zebra_gr_route_stale_delete_timer_expiry, info,
0);
}
}

View File

@ -317,6 +317,10 @@ int zebra_finalize(struct thread *event);
*/
extern int zebra_gr_client_disconnect(struct zserv *client);
extern void zebra_gr_client_reconnect(struct zserv *client);
extern void zebra_gr_stale_client_cleanup(struct list *client_list);
extern void zread_client_capabilities(struct zserv *client, struct zmsghdr *hdr,
struct stream *msg,
struct zebra_vrf *zvrf);
#ifdef __cplusplus
}