diff options
author | Chirag Shah <chirag@cumulusnetworks.com> | 2017-02-22 16:28:36 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2017-03-16 23:53:28 +0100 |
commit | 1bc9827622572b24c7c47656565dc1a2601d6dc5 (patch) | |
tree | eda923517f772ca214aa507de5fc313bff1a24dd /pimd/pimd.c | |
parent | Merge pull request #270 from donaldsharp/cares (diff) | |
download | frr-1bc9827622572b24c7c47656565dc1a2601d6dc5.tar.xz frr-1bc9827622572b24c7c47656565dc1a2601d6dc5.zip |
pimd: Nexthop tracking support
Add pim Nexthop tracking feature 1st part where, specific RP or Source address (unicast address)
register with Zebra. Once nexthop update received from Zebra for a given address, scan RP or upstream
entries impacted by the change in nexthop.
Reviewed By: CCR-5761, Donald Sharp <sharpd@cumulusnetworks.com>
Testing Done: Tested with multiple RPs and multiple *,G entries at LHR.
Add new Nexthop or remove one of the link towards RP and verify RP and upstream nexthop update.
similar test done at RP with multiple S,G entries to reach source.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
Diffstat (limited to 'pimd/pimd.c')
-rw-r--r-- | pimd/pimd.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/pimd/pimd.c b/pimd/pimd.c index c8a0efc40..b67544b28 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -26,6 +26,8 @@ #include "prefix.h" #include "vty.h" #include "plist.h" +#include "hash.h" +#include "jhash.h" #include "pimd.h" #include "pim_cmd.h" @@ -40,6 +42,7 @@ #include "pim_static.h" #include "pim_rp.h" #include "pim_zlookup.h" +#include "pim_nht.h" const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; @@ -71,10 +74,127 @@ unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; signed int qpim_rp_keep_alive_time = 0; int64_t qpim_nexthop_lookups = 0; int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +struct pim_instance *pimg = NULL; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; +static struct pim_instance *pim_instance_init (vrf_id_t vrf_id, afi_t afi); +static void pim_instance_terminate (void); + +static int +pim_vrf_new (struct vrf *vrf) +{ + zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); + return 0; +} + +static int +pim_vrf_delete (struct vrf *vrf) +{ + zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); + return 0; +} + +static int +pim_vrf_enable (struct vrf *vrf) +{ + + if (!vrf) // unexpected + return -1; + + if (vrf->vrf_id == VRF_DEFAULT) + { + pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); + if (pimg == NULL) + zlog_err ("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + } + return 0; +} + +static int +pim_vrf_disable (struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return 0; + + if (vrf->vrf_id == VRF_DEFAULT) + pim_instance_terminate (); + + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; +} + +void +pim_vrf_init (void) +{ + vrf_add_hook (VRF_NEW_HOOK, pim_vrf_new); + vrf_add_hook (VRF_ENABLE_HOOK, pim_vrf_enable); + vrf_add_hook (VRF_DISABLE_HOOK, pim_vrf_disable); + vrf_add_hook (VRF_DELETE_HOOK, pim_vrf_delete); + + vrf_init (); +} + +static void +pim_vrf_terminate (void) +{ + vrf_add_hook (VRF_NEW_HOOK, NULL); + vrf_add_hook (VRF_ENABLE_HOOK, NULL); + vrf_add_hook (VRF_DISABLE_HOOK, NULL); + vrf_add_hook (VRF_DELETE_HOOK, NULL); + + vrf_terminate (); +} + +/* Key generate for pim->rpf_hash */ +static unsigned int +pim_rpf_hash_key (void *arg) +{ + struct pim_nexthop_cache *r = (struct pim_nexthop_cache *) arg; + + return jhash_1word (r->rpf.rpf_addr.u.prefix4.s_addr, 0); +} + +/* Compare pim->rpf_hash node data */ +static int +pim_rpf_equal (const void *arg1, const void *arg2) +{ + const struct pim_nexthop_cache *r1 = + (const struct pim_nexthop_cache *) arg1; + const struct pim_nexthop_cache *r2 = + (const struct pim_nexthop_cache *) arg2; + + return prefix_same (&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); +} + +/* Cleanup pim->rpf_hash each node data */ +static void +pim_rp_list_hash_clean (void *data) +{ + struct pim_nexthop_cache *pnc; + + pnc = (struct pim_nexthop_cache *) data; + if (pnc->rp_list->count) + list_delete_all_node (pnc->rp_list); + if (pnc->upstream_list->count) + list_delete_all_node (pnc->upstream_list); +} + +static void +pim_instance_terminate (void) +{ + /* Traverse and cleanup rpf_hash */ + if (pimg && pimg->rpf_hash) + { + hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); + hash_free (pimg->rpf_hash); + } + + XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); +} + static void pim_free() { pim_ssmpingd_destroy(); @@ -96,6 +216,27 @@ static void pim_free() zprivs_terminate(&pimd_privs); } +static struct pim_instance * +pim_instance_init (vrf_id_t vrf_id, afi_t afi) +{ + struct pim_instance *pim; + + pim = XCALLOC (MTYPE_PIM_PIM_INSTANCE, sizeof (struct pim_instance)); + if (!pim) + return NULL; + + pim->vrf_id = vrf_id; + pim->afi = afi; + + pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal); + + if (PIM_DEBUG_ZEBRA) + zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); + + + return pim; +} + void pim_init() { qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; @@ -147,4 +288,11 @@ void pim_init() void pim_terminate() { pim_free(); + + /* reverse prefix_list_init */ + prefix_list_add_hook (NULL); + prefix_list_delete_hook (NULL); + prefix_list_reset (); + + pim_vrf_terminate (); } |