]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: Capabality and stale route handling for GR client.
authorSantosh P K <sapk@vmware.com>
Thu, 9 Jan 2020 17:53:27 +0000 (09:53 -0800)
committerSantosh P K <sapk@vmware.com>
Fri, 31 Jan 2020 11:36:37 +0000 (03:36 -0800)
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>
doc/developer/zebra.rst
zebra/main.c
zebra/zapi_msg.c
zebra/zebra_gr.c
zebra/zserv.h

index 74a8605bf2cd14cf9fb2e783afbda1465310a13b..e3526d184371a47ed91df0538d3f2d1232e3af19 100644 (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   |
 +------------------------------------+-------+
index 75f825e5077e7179f22daee23e84b66e30f162a3..f23702d8789d6d050068e8906ea76ab21c984117 100644 (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);
 
index 72629318e21844ba7918bf59c04077c54d5b0189..3f52a9def357464d09991b372dc64bd9f1a3b27e 100644 (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)
index 86669df51a2f5771fad350f90569857de1b4571f..e8c7304f44b1f1bed706bf2c10ebca32e4caad50 100644 (file)
  * 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
+ */
+
+/*
+ * 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);
+       }
+}
 
-static int zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
+/*
+ * 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);
+       }
+}
index 877f3a8e307d5203eb9ce8d934774390669bfa99..77ea19202f334ba43e6fa6fcdee7a18768c42932 100644 (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
 }