mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 01:15:12 +00:00
Merge pull request #5207 from Spantik/ZERBA_GR
Zebra: Adding GR infrastructure for clients.
This commit is contained in:
commit
a6bb6a1fe9
@ -3102,43 +3102,6 @@ int bgp_zebra_update(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int zclient_capabilities_send(uint32_t cmd, struct zclient *zclient,
|
|
||||||
struct zapi_cap *api)
|
|
||||||
{
|
|
||||||
struct stream *s;
|
|
||||||
|
|
||||||
if (zclient == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
s = zclient->obuf;
|
|
||||||
stream_reset(s);
|
|
||||||
zclient_create_header(s, cmd, 0);
|
|
||||||
stream_putl(s, api->cap);
|
|
||||||
switch (api->cap) {
|
|
||||||
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
|
||||||
case ZEBRA_CLIENT_RIB_STALE_TIME:
|
|
||||||
stream_putl(s, api->stale_removal_time);
|
|
||||||
stream_putl(s, api->vrf_id);
|
|
||||||
break;
|
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
|
||||||
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
|
||||||
stream_putl(s, api->afi);
|
|
||||||
stream_putl(s, api->safi);
|
|
||||||
stream_putl(s, api->vrf_id);
|
|
||||||
break;
|
|
||||||
case ZEBRA_CLIENT_GR_DISABLE:
|
|
||||||
stream_putl(s, api->vrf_id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put length at the first point of the stream */
|
|
||||||
stream_putw_at(s, 0, stream_get_endp(s));
|
|
||||||
|
|
||||||
return zclient_send_message(zclient);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send RIB stale timer update */
|
/* Send RIB stale timer update */
|
||||||
int bgp_zebra_stale_timer_update(struct bgp *bgp)
|
int bgp_zebra_stale_timer_update(struct bgp *bgp)
|
||||||
{
|
{
|
||||||
|
@ -169,175 +169,201 @@ Zebra Protocol Commands
|
|||||||
+------------------------------------+-------+
|
+------------------------------------+-------+
|
||||||
| ZEBRA_INTERFACE_SET_MASTER | 6 |
|
| 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 |
|
||||||
+------------------------------------+-------+
|
+------------------------------------+-------+
|
||||||
|
@ -1094,7 +1094,7 @@ static const struct zebra_desc_table command_types[] = {
|
|||||||
DESC_ENTRY(ZEBRA_VXLAN_SG_DEL),
|
DESC_ENTRY(ZEBRA_VXLAN_SG_DEL),
|
||||||
DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY),
|
DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY),
|
||||||
DESC_ENTRY(ZEBRA_ERROR),
|
DESC_ENTRY(ZEBRA_ERROR),
|
||||||
};
|
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES)};
|
||||||
#undef DESC_ENTRY
|
#undef DESC_ENTRY
|
||||||
|
|
||||||
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
|
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
|
||||||
|
@ -3300,9 +3300,52 @@ void zclient_interface_set_master(struct zclient *client,
|
|||||||
zclient_send_message(client);
|
zclient_send_message(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process capabilities message from zebra */
|
/*
|
||||||
int zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
|
* Send capabilities message to zebra
|
||||||
|
*/
|
||||||
|
int32_t zclient_capabilities_send(uint32_t cmd, struct zclient *zclient,
|
||||||
|
struct zapi_cap *api)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct stream *s;
|
||||||
|
|
||||||
|
if (zclient == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
s = zclient->obuf;
|
||||||
|
stream_reset(s);
|
||||||
|
zclient_create_header(s, cmd, 0);
|
||||||
|
stream_putl(s, api->cap);
|
||||||
|
|
||||||
|
switch (api->cap) {
|
||||||
|
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
||||||
|
case ZEBRA_CLIENT_RIB_STALE_TIME:
|
||||||
|
stream_putl(s, api->stale_removal_time);
|
||||||
|
stream_putl(s, api->vrf_id);
|
||||||
|
break;
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
||||||
|
stream_putl(s, api->afi);
|
||||||
|
stream_putl(s, api->safi);
|
||||||
|
stream_putl(s, api->vrf_id);
|
||||||
|
break;
|
||||||
|
case ZEBRA_CLIENT_GR_DISABLE:
|
||||||
|
stream_putl(s, api->vrf_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put length at the first point of the stream */
|
||||||
|
stream_putw_at(s, 0, stream_get_endp(s));
|
||||||
|
|
||||||
|
return zclient_send_message(zclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process capabilities message from zebra
|
||||||
|
*/
|
||||||
|
int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
|
||||||
|
{
|
||||||
|
|
||||||
memset(api, 0, sizeof(*api));
|
memset(api, 0, sizeof(*api));
|
||||||
|
|
||||||
STREAM_GETL(s, api->cap);
|
STREAM_GETL(s, api->cap);
|
||||||
@ -3321,10 +3364,7 @@ int zapi_capabilities_decode(struct stream *s, struct zapi_cap *api)
|
|||||||
case ZEBRA_CLIENT_GR_DISABLE:
|
case ZEBRA_CLIENT_GR_DISABLE:
|
||||||
STREAM_GETL(s, api->vrf_id);
|
STREAM_GETL(s, api->vrf_id);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_failure:
|
stream_failure:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,17 @@ typedef uint16_t zebra_size_t;
|
|||||||
#define ZEBRA_FEC_REGISTER_LABEL 0x1
|
#define ZEBRA_FEC_REGISTER_LABEL 0x1
|
||||||
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x2
|
#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x2
|
||||||
|
|
||||||
/* Client Graceful Restart */
|
/* Client capabilities */
|
||||||
#define ZEBRA_CLIENT_GR_CAPABILITIES 0x1
|
enum zserv_client_capabilities {
|
||||||
#define ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE 0x2
|
ZEBRA_CLIENT_GR_CAPABILITIES = 1,
|
||||||
#define ZEBRA_CLIENT_ROUTE_UPDATE_PENDING 0x3
|
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE = 2,
|
||||||
#define ZEBRA_CLIENT_GR_DISABLE 0x4
|
ZEBRA_CLIENT_ROUTE_UPDATE_PENDING = 3,
|
||||||
#define ZEBRA_CLIENT_RIB_STALE_TIME 0x5
|
ZEBRA_CLIENT_GR_DISABLE = 4,
|
||||||
#define ZEBRA_CLIENT_GR_ENABLED(X) (X & ZEBRA_CLIENT_GR_CAPABILITIES)
|
ZEBRA_CLIENT_RIB_STALE_TIME
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Macro to check if there GR enabled. */
|
||||||
|
#define ZEBRA_CLIENT_GR_ENABLED(X) (X == ZEBRA_CLIENT_GR_CAPABILITIES)
|
||||||
|
|
||||||
extern struct sockaddr_storage zclient_addr;
|
extern struct sockaddr_storage zclient_addr;
|
||||||
extern socklen_t zclient_addr_len;
|
extern socklen_t zclient_addr_len;
|
||||||
@ -233,7 +237,7 @@ struct zclient_capabilities {
|
|||||||
|
|
||||||
/* Graceful Restart Capabilities message */
|
/* Graceful Restart Capabilities message */
|
||||||
struct zapi_cap {
|
struct zapi_cap {
|
||||||
uint32_t cap;
|
enum zserv_client_capabilities cap;
|
||||||
uint32_t stale_removal_time;
|
uint32_t stale_removal_time;
|
||||||
afi_t afi;
|
afi_t afi;
|
||||||
safi_t safi;
|
safi_t safi;
|
||||||
@ -777,6 +781,11 @@ extern bool zapi_nexthop_update_decode(struct stream *s,
|
|||||||
/* Decode the zebra error message */
|
/* Decode the zebra error message */
|
||||||
extern bool zapi_error_decode(struct stream *s, enum zebra_error_types *error);
|
extern bool zapi_error_decode(struct stream *s, enum zebra_error_types *error);
|
||||||
|
|
||||||
|
/* Encode and decode restart capabilities */
|
||||||
|
extern int32_t zclient_capabilities_send(uint32_t cmd, struct zclient *zclient,
|
||||||
|
struct zapi_cap *api);
|
||||||
|
extern int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api);
|
||||||
|
|
||||||
static inline void zapi_route_set_blackhole(struct zapi_route *api,
|
static inline void zapi_route_set_blackhole(struct zapi_route *api,
|
||||||
enum blackhole_type bh_type)
|
enum blackhole_type bh_type)
|
||||||
{
|
{
|
||||||
@ -794,7 +803,4 @@ extern void zclient_send_mlag_deregister(struct zclient *client);
|
|||||||
extern void zclient_send_mlag_data(struct zclient *client,
|
extern void zclient_send_mlag_data(struct zclient *client,
|
||||||
struct stream *client_s);
|
struct stream *client_s);
|
||||||
|
|
||||||
extern int zclient_capabilities_send(uint32_t cmd, struct zclient *zclient,
|
|
||||||
struct zapi_cap *api);
|
|
||||||
extern int zapi_capabilities_decode(struct stream *s, struct zapi_cap *api);
|
|
||||||
#endif /* _ZEBRA_ZCLIENT_H */
|
#endif /* _ZEBRA_ZCLIENT_H */
|
||||||
|
@ -151,6 +151,10 @@ static void sigint(void)
|
|||||||
|
|
||||||
zebra_dplane_pre_finish();
|
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))
|
for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client))
|
||||||
zserv_close_client(client);
|
zserv_close_client(client);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ vtysh_scan += \
|
|||||||
$(top_srcdir)/zebra/zebra_routemap.c \
|
$(top_srcdir)/zebra/zebra_routemap.c \
|
||||||
$(top_srcdir)/zebra/zebra_vty.c \
|
$(top_srcdir)/zebra/zebra_vty.c \
|
||||||
$(top_srcdir)/zebra/zserv.c \
|
$(top_srcdir)/zebra/zserv.c \
|
||||||
|
$(top_srcdir)/zebra/zebra_gr.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# can be loaded as DSO - always include for vtysh
|
# can be loaded as DSO - always include for vtysh
|
||||||
@ -101,6 +102,7 @@ zebra_zebra_SOURCES = \
|
|||||||
zebra/table_manager.c \
|
zebra/table_manager.c \
|
||||||
zebra/zapi_msg.c \
|
zebra/zapi_msg.c \
|
||||||
zebra/zebra_errors.c \
|
zebra/zebra_errors.c \
|
||||||
|
zebra/zebra_gr.c \
|
||||||
# end
|
# end
|
||||||
|
|
||||||
zebra/debug_clippy.c: $(CLIPPY_DEPS)
|
zebra/debug_clippy.c: $(CLIPPY_DEPS)
|
||||||
|
@ -1775,6 +1775,8 @@ static void zread_hello(ZAPI_HANDLER_ARGS)
|
|||||||
client->instance = instance;
|
client->instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Graceful restart processing for client connect */
|
||||||
|
zebra_gr_client_reconnect(client);
|
||||||
zsend_capabilities(client, zvrf);
|
zsend_capabilities(client, zvrf);
|
||||||
zebra_vrf_update_all(client);
|
zebra_vrf_update_all(client);
|
||||||
stream_failure:
|
stream_failure:
|
||||||
@ -2668,6 +2670,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
|||||||
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
|
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
|
||||||
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
|
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
|
||||||
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
|
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
|
||||||
|
[ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HANDLE_ZAPI_FUZZING)
|
#if defined(HANDLE_ZAPI_FUZZING)
|
||||||
|
684
zebra/zebra_gr.c
Normal file
684
zebra/zebra_gr.c
Normal file
@ -0,0 +1,684 @@
|
|||||||
|
/*
|
||||||
|
* Zebra GR related helper functions.
|
||||||
|
*
|
||||||
|
* Portions:
|
||||||
|
* Copyright (C) 2019 VMware, Inc.
|
||||||
|
* et al.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; see the file COPYING; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zebra.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include "lib/prefix.h"
|
||||||
|
#include "lib/command.h"
|
||||||
|
#include "lib/if.h"
|
||||||
|
#include "lib/thread.h"
|
||||||
|
#include "lib/stream.h"
|
||||||
|
#include "lib/memory.h"
|
||||||
|
#include "lib/table.h"
|
||||||
|
#include "lib/network.h"
|
||||||
|
#include "lib/sockunion.h"
|
||||||
|
#include "lib/log.h"
|
||||||
|
#include "lib/zclient.h"
|
||||||
|
#include "lib/privs.h"
|
||||||
|
#include "lib/network.h"
|
||||||
|
#include "lib/buffer.h"
|
||||||
|
#include "lib/nexthop.h"
|
||||||
|
#include "lib/vrf.h"
|
||||||
|
#include "lib/libfrr.h"
|
||||||
|
#include "lib/sockopt.h"
|
||||||
|
|
||||||
|
#include "zebra/zebra_router.h"
|
||||||
|
#include "zebra/debug.h"
|
||||||
|
#include "zebra/zapi_msg.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forward declaration.
|
||||||
|
*/
|
||||||
|
static struct zserv *zebra_gr_find_stale_client(struct zserv *client);
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
#define LOG_GR(msg, ...) \
|
||||||
|
do { \
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT) \
|
||||||
|
zlog_debug(msg, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
int32_t zebra_gr_client_disconnect(struct zserv *client)
|
||||||
|
{
|
||||||
|
struct zserv *stale_client;
|
||||||
|
struct timeval tv;
|
||||||
|
struct client_gr_info *info = NULL;
|
||||||
|
|
||||||
|
/* Find the stale client */
|
||||||
|
stale_client = zebra_gr_find_stale_client(client);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should never be here.
|
||||||
|
*/
|
||||||
|
if (stale_client) {
|
||||||
|
LOG_GR("%s: Stale client %s exist, we should not be here!",
|
||||||
|
__func__, zebra_route_string(client->proto));
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
client->restart_time = monotime(&tv);
|
||||||
|
|
||||||
|
/* For all the GR instance start the starle removal timer. */
|
||||||
|
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
|
||||||
|
if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)
|
||||||
|
&& (info->t_stale_removal == NULL)) {
|
||||||
|
thread_add_timer(
|
||||||
|
zrouter.master,
|
||||||
|
zebra_gr_route_stale_delete_timer_expiry, info,
|
||||||
|
info->stale_removal_time,
|
||||||
|
&info->t_stale_removal);
|
||||||
|
info->current_afi = AFI_IP;
|
||||||
|
info->stale_client_ptr = client;
|
||||||
|
info->stale_client = true;
|
||||||
|
LOG_GR("%s: Client %s Stale timer update to %d",
|
||||||
|
__func__, zebra_route_string(client->proto),
|
||||||
|
info->stale_removal_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listnode_add(zrouter.stale_client_list, 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.
|
||||||
|
*/
|
||||||
|
static struct zserv *zebra_gr_find_stale_client(struct zserv *client)
|
||||||
|
{
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct zserv *stale_client;
|
||||||
|
|
||||||
|
/* Find the stale client */
|
||||||
|
for (ALL_LIST_ELEMENTS(zrouter.stale_client_list, node, nnode,
|
||||||
|
stale_client)) {
|
||||||
|
if (client->proto == stale_client->proto
|
||||||
|
&& client->instance == stale_client->instance) {
|
||||||
|
return stale_client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to handle reconnect of client post restart.
|
||||||
|
*/
|
||||||
|
void zebra_gr_client_reconnect(struct zserv *client)
|
||||||
|
{
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
struct zserv *old_client = NULL;
|
||||||
|
struct client_gr_info *info = NULL;
|
||||||
|
|
||||||
|
/* Find the stale client */
|
||||||
|
for (ALL_LIST_ELEMENTS(zrouter.stale_client_list, node, nnode,
|
||||||
|
old_client)) {
|
||||||
|
if (client->proto == old_client->proto
|
||||||
|
&& client->instance == old_client->instance)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the timers */
|
||||||
|
if (old_client) {
|
||||||
|
client->gr_instance_count = old_client->gr_instance_count;
|
||||||
|
client->restart_time = old_client->restart_time;
|
||||||
|
|
||||||
|
LOG_GR("%s : old client %s, gr_instance_count %d", __func__,
|
||||||
|
zebra_route_string(old_client->proto),
|
||||||
|
old_client->gr_instance_count);
|
||||||
|
|
||||||
|
if (TAILQ_FIRST(&old_client->gr_info_queue)) {
|
||||||
|
TAILQ_CONCAT(&client->gr_info_queue,
|
||||||
|
&old_client->gr_info_queue, gr_info);
|
||||||
|
TAILQ_INIT(&old_client->gr_info_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
|
||||||
|
info->stale_client_ptr = client;
|
||||||
|
info->stale_client = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the stale client */
|
||||||
|
listnode_delete(zrouter.stale_client_list, old_client);
|
||||||
|
/* Delete old client */
|
||||||
|
XFREE(MTYPE_TMP, old_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
@ -117,6 +117,9 @@ struct zebra_router {
|
|||||||
/* Lists of clients who have connected to us */
|
/* Lists of clients who have connected to us */
|
||||||
struct list *client_list;
|
struct list *client_list;
|
||||||
|
|
||||||
|
/* List of clients in GR */
|
||||||
|
struct list *stale_client_list;
|
||||||
|
|
||||||
struct zebra_router_table_head tables;
|
struct zebra_router_table_head tables;
|
||||||
|
|
||||||
/* L3-VNI hash table (for EVPN). Only in default instance */
|
/* L3-VNI hash table (for EVPN). Only in default instance */
|
||||||
|
126
zebra/zserv.c
126
zebra/zserv.c
@ -557,6 +557,9 @@ DEFINE_KOOH(zserv_client_close, (struct zserv *client), (client));
|
|||||||
*/
|
*/
|
||||||
static void zserv_client_free(struct zserv *client)
|
static void zserv_client_free(struct zserv *client)
|
||||||
{
|
{
|
||||||
|
if (client == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
hook_call(zserv_client_close, client);
|
hook_call(zserv_client_close, client);
|
||||||
|
|
||||||
/* Close file descriptor. */
|
/* Close file descriptor. */
|
||||||
@ -565,11 +568,14 @@ static void zserv_client_free(struct zserv *client)
|
|||||||
|
|
||||||
close(client->sock);
|
close(client->sock);
|
||||||
|
|
||||||
nroutes = rib_score_proto(client->proto, client->instance);
|
if (!client->gr_instance_count) {
|
||||||
|
nroutes = rib_score_proto(client->proto,
|
||||||
|
client->instance);
|
||||||
zlog_notice(
|
zlog_notice(
|
||||||
"client %d disconnected. %lu %s routes removed from the rib",
|
"client %d disconnected %lu %s routes removed from the rib",
|
||||||
client->sock, nroutes,
|
client->sock, nroutes,
|
||||||
zebra_route_string(client->proto));
|
zebra_route_string(client->proto));
|
||||||
|
}
|
||||||
client->sock = -1;
|
client->sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,7 +606,25 @@ static void zserv_client_free(struct zserv *client)
|
|||||||
}
|
}
|
||||||
vrf_bitmap_free(client->ridinfo);
|
vrf_bitmap_free(client->ridinfo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any instance are graceful restart enabled,
|
||||||
|
* client is not deleted
|
||||||
|
*/
|
||||||
|
if (!client->gr_instance_count) {
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
|
zlog_debug("%s: Deleting client %s", __func__,
|
||||||
|
zebra_route_string(client->proto));
|
||||||
XFREE(MTYPE_TMP, client);
|
XFREE(MTYPE_TMP, client);
|
||||||
|
} else {
|
||||||
|
/* Handle cases where client has GR instance. */
|
||||||
|
if (IS_ZEBRA_DEBUG_EVENT)
|
||||||
|
zlog_debug("%s: client %s restart enabled", __func__,
|
||||||
|
zebra_route_string(client->proto));
|
||||||
|
if (zebra_gr_client_disconnect(client) < 0)
|
||||||
|
zlog_err(
|
||||||
|
"%s: GR enabled but could not handle disconnect event",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zserv_close_client(struct zserv *client)
|
void zserv_close_client(struct zserv *client)
|
||||||
@ -670,6 +694,7 @@ static struct zserv *zserv_client_create(int sock)
|
|||||||
pthread_mutex_init(&client->ibuf_mtx, NULL);
|
pthread_mutex_init(&client->ibuf_mtx, NULL);
|
||||||
pthread_mutex_init(&client->obuf_mtx, NULL);
|
pthread_mutex_init(&client->obuf_mtx, NULL);
|
||||||
client->wb = buffer_new(0);
|
client->wb = buffer_new(0);
|
||||||
|
TAILQ_INIT(&(client->gr_info_queue));
|
||||||
|
|
||||||
atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
|
atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
|
||||||
memory_order_relaxed);
|
memory_order_relaxed);
|
||||||
@ -861,12 +886,14 @@ static char *zserv_time_buf(time_t *time1, char *buf, int buflen)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Display client info details */
|
||||||
static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
||||||
{
|
{
|
||||||
char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
|
char cbuf[ZEBRA_TIME_BUF], rbuf[ZEBRA_TIME_BUF];
|
||||||
char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
|
char wbuf[ZEBRA_TIME_BUF], nhbuf[ZEBRA_TIME_BUF], mbuf[ZEBRA_TIME_BUF];
|
||||||
time_t connect_time, last_read_time, last_write_time;
|
time_t connect_time, last_read_time, last_write_time;
|
||||||
uint32_t last_read_cmd, last_write_cmd;
|
uint32_t last_read_cmd, last_write_cmd;
|
||||||
|
struct client_gr_info *info = NULL;
|
||||||
|
|
||||||
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
|
vty_out(vty, "Client: %s", zebra_route_string(client->proto));
|
||||||
if (client->instance)
|
if (client->instance)
|
||||||
@ -945,12 +972,100 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
|
|||||||
vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
|
vty_out(vty, "MAC-IP add notifications: %d\n", client->macipadd_cnt);
|
||||||
vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
|
vty_out(vty, "MAC-IP delete notifications: %d\n", client->macipdel_cnt);
|
||||||
|
|
||||||
|
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
|
||||||
|
vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
|
||||||
|
vty_out(vty, "Capabilities : ");
|
||||||
|
switch (info->capabilities) {
|
||||||
|
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
||||||
|
vty_out(vty, "Graceful Restart\n");
|
||||||
|
break;
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
||||||
|
case ZEBRA_CLIENT_GR_DISABLE:
|
||||||
|
case ZEBRA_CLIENT_RIB_STALE_TIME:
|
||||||
|
vty_out(vty, "None\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined DEV_BUILD
|
#if defined DEV_BUILD
|
||||||
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
|
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
|
||||||
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
|
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
|
||||||
client->obuf_fifo->count, client->obuf_fifo->max_count);
|
client->obuf_fifo->count, client->obuf_fifo->max_count);
|
||||||
#endif
|
#endif
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display stale client information */
|
||||||
|
static void zebra_show_stale_client_detail(struct vty *vty,
|
||||||
|
struct zserv *client)
|
||||||
|
{
|
||||||
|
char buf[PREFIX2STR_BUFFER];
|
||||||
|
struct tm *tm;
|
||||||
|
struct timeval tv;
|
||||||
|
time_t uptime;
|
||||||
|
struct client_gr_info *info = NULL;
|
||||||
|
struct zserv *s = NULL;
|
||||||
|
|
||||||
|
if (client->instance)
|
||||||
|
vty_out(vty, " Instance: %d", client->instance);
|
||||||
|
|
||||||
|
TAILQ_FOREACH (info, &client->gr_info_queue, gr_info) {
|
||||||
|
vty_out(vty, "VRF : %s\n", vrf_id_to_name(info->vrf_id));
|
||||||
|
vty_out(vty, "Capabilities : ");
|
||||||
|
switch (info->capabilities) {
|
||||||
|
case ZEBRA_CLIENT_GR_CAPABILITIES:
|
||||||
|
vty_out(vty, "Graceful Restart\n");
|
||||||
|
break;
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE:
|
||||||
|
case ZEBRA_CLIENT_ROUTE_UPDATE_PENDING:
|
||||||
|
case ZEBRA_CLIENT_GR_DISABLE:
|
||||||
|
case ZEBRA_CLIENT_RIB_STALE_TIME:
|
||||||
|
vty_out(vty, "None\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)) {
|
||||||
|
if (info->stale_client_ptr) {
|
||||||
|
s = (struct zserv *)(info->stale_client_ptr);
|
||||||
|
uptime = monotime(&tv);
|
||||||
|
uptime -= s->restart_time;
|
||||||
|
tm = gmtime(&uptime);
|
||||||
|
vty_out(vty, "Last restart time : ");
|
||||||
|
if (uptime < ONE_DAY_SECOND)
|
||||||
|
vty_out(vty, "%02d:%02d:%02d",
|
||||||
|
tm->tm_hour, tm->tm_min,
|
||||||
|
tm->tm_sec);
|
||||||
|
else if (uptime < ONE_WEEK_SECOND)
|
||||||
|
vty_out(vty, "%dd%02dh%02dm",
|
||||||
|
tm->tm_yday, tm->tm_hour,
|
||||||
|
tm->tm_min);
|
||||||
|
else
|
||||||
|
vty_out(vty, "%02dw%dd%02dh",
|
||||||
|
tm->tm_yday / 7,
|
||||||
|
tm->tm_yday - ((tm->tm_yday / 7)
|
||||||
|
* 7),
|
||||||
|
tm->tm_hour);
|
||||||
|
vty_out(vty, " ago\n");
|
||||||
|
|
||||||
|
vty_out(vty, "Stalepath removal time: %d sec\n",
|
||||||
|
info->stale_removal_time);
|
||||||
|
if (info->t_stale_removal) {
|
||||||
|
vty_out(vty,
|
||||||
|
"Stale delete timer: %ld sec\n",
|
||||||
|
thread_timer_remain_second(
|
||||||
|
info->t_stale_removal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vty_out(vty, "Current AFI : %d\n", info->current_afi);
|
||||||
|
if (info->current_prefix) {
|
||||||
|
prefix2str(info->current_prefix, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
vty_out(vty, "Current prefix : %s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vty_out(vty, "\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,8 +1117,12 @@ DEFUN (show_zebra_client,
|
|||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct zserv *client;
|
struct zserv *client;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client))
|
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
|
||||||
zebra_show_client_detail(vty, client);
|
zebra_show_client_detail(vty, client);
|
||||||
|
vty_out(vty, "Stale Client Information\n");
|
||||||
|
vty_out(vty, "------------------------\n");
|
||||||
|
zebra_show_stale_client_detail(vty, client);
|
||||||
|
}
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -1047,6 +1166,7 @@ void zserv_init(void)
|
|||||||
{
|
{
|
||||||
/* Client list init. */
|
/* Client list init. */
|
||||||
zrouter.client_list = list_new();
|
zrouter.client_list = list_new();
|
||||||
|
zrouter.stale_client_list = list_new();
|
||||||
|
|
||||||
/* Misc init. */
|
/* Misc init. */
|
||||||
zsock = -1;
|
zsock = -1;
|
||||||
|
@ -52,6 +52,42 @@ extern "C" {
|
|||||||
|
|
||||||
#define ZEBRA_RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
|
#define ZEBRA_RMAP_DEFAULT_UPDATE_TIMER 5 /* disabled by default */
|
||||||
|
|
||||||
|
|
||||||
|
/* Stale route marker timer */
|
||||||
|
#define ZEBRA_DEFAULT_STALE_UPDATE_DELAY 1
|
||||||
|
|
||||||
|
/* Count of stale routes processed in timer context */
|
||||||
|
#define ZEBRA_MAX_STALE_ROUTE_COUNT 50000
|
||||||
|
|
||||||
|
/* Graceful Restart information */
|
||||||
|
struct client_gr_info {
|
||||||
|
/* VRF for which GR enabled */
|
||||||
|
vrf_id_t vrf_id;
|
||||||
|
|
||||||
|
/* AFI */
|
||||||
|
afi_t current_afi;
|
||||||
|
|
||||||
|
/* Stale time and GR cap */
|
||||||
|
uint32_t stale_removal_time;
|
||||||
|
enum zserv_client_capabilities capabilities;
|
||||||
|
|
||||||
|
/* GR commands */
|
||||||
|
bool delete;
|
||||||
|
bool gr_enable;
|
||||||
|
bool stale_client;
|
||||||
|
|
||||||
|
/* Route sync and enable flags for AFI/SAFI */
|
||||||
|
bool af_enabled[AFI_MAX][SAFI_MAX];
|
||||||
|
bool route_sync[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
|
/* Book keeping */
|
||||||
|
struct prefix *current_prefix;
|
||||||
|
void *stale_client_ptr;
|
||||||
|
struct thread *t_stale_removal;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(client_gr_info) gr_info;
|
||||||
|
};
|
||||||
|
|
||||||
/* Client structure. */
|
/* Client structure. */
|
||||||
struct zserv {
|
struct zserv {
|
||||||
/* Client pthread */
|
/* Client pthread */
|
||||||
@ -170,6 +206,19 @@ struct zserv {
|
|||||||
_Atomic uint32_t last_read_cmd;
|
_Atomic uint32_t last_read_cmd;
|
||||||
/* command code of last message written */
|
/* command code of last message written */
|
||||||
_Atomic uint32_t last_write_cmd;
|
_Atomic uint32_t last_write_cmd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of instances configured with
|
||||||
|
* graceful restart
|
||||||
|
*/
|
||||||
|
uint32_t gr_instance_count;
|
||||||
|
time_t restart_time;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Graceful restart information for
|
||||||
|
* each instance
|
||||||
|
*/
|
||||||
|
TAILQ_HEAD(info_list, client_gr_info) gr_info_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZAPI_HANDLER_ARGS \
|
#define ZAPI_HANDLER_ARGS \
|
||||||
@ -230,7 +279,6 @@ extern int zserv_send_message(struct zserv *client, struct stream *msg);
|
|||||||
*/
|
*/
|
||||||
extern struct zserv *zserv_find_client(uint8_t proto, unsigned short instance);
|
extern struct zserv *zserv_find_client(uint8_t proto, unsigned short instance);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close a client.
|
* Close a client.
|
||||||
*
|
*
|
||||||
@ -242,7 +290,6 @@ extern struct zserv *zserv_find_client(uint8_t proto, unsigned short instance);
|
|||||||
*/
|
*/
|
||||||
extern void zserv_close_client(struct zserv *client);
|
extern void zserv_close_client(struct zserv *client);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log a ZAPI message hexdump.
|
* Log a ZAPI message hexdump.
|
||||||
*
|
*
|
||||||
@ -265,6 +312,16 @@ extern void zserv_read_file(char *input);
|
|||||||
/* TODO */
|
/* TODO */
|
||||||
int zebra_finalize(struct thread *event);
|
int zebra_finalize(struct thread *event);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Graceful restart functions.
|
||||||
|
*/
|
||||||
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user