pimd: Refactor pim NHT

Refactor the next hop tracking in PIM to fully support the configured RPF lookup mode.
Moved many NHT related functions to pim_nht.h/c
NHT now tracks both MRIB and URIB tables and makes nexthop decisions based on the configured lookup mode.

Signed-off-by: Nathan Bahr <nbahr@atcorp.com>
This commit is contained in:
Nathan Bahr 2024-10-23 19:00:31 +00:00
parent cc865c0192
commit 6d30c8f6b5
20 changed files with 974 additions and 867 deletions

View file

@ -727,7 +727,7 @@ void pim_bsm_clear(struct pim_instance *pim)
__func__, &nht_p); __func__, &nht_p);
} }
pim_delete_tracked_nexthop(pim, nht_p, NULL, rp_info); pim_nht_delete_tracked(pim, nht_p, NULL, rp_info);
if (!pim_get_all_mcast_group(&g_all)) if (!pim_get_all_mcast_group(&g_all))
return; return;

View file

@ -413,11 +413,11 @@ void pim_crp_nht_update(struct pim_instance *pim, struct pim_nexthop_cache *pnc)
struct bsr_crp_rp *rp, ref; struct bsr_crp_rp *rp, ref;
bool ok; bool ok;
ref.addr = pnc->rpf.rpf_addr; ref.addr = pnc->addr;
rp = bsr_crp_rps_find(scope->ebsr_rps, &ref); rp = bsr_crp_rps_find(scope->ebsr_rps, &ref);
assertf(rp, "addr=%pPA", &ref.addr); assertf(rp, "addr=%pPA", &ref.addr);
ok = CHECK_FLAG(pnc->flags, PIM_NEXTHOP_VALID); ok = pim_nht_pnc_is_valid(pim, pnc);
if (ok == rp->nht_ok) if (ok == rp->nht_ok)
return; return;

View file

@ -3288,7 +3288,7 @@ DEFUN (show_ip_rib,
return CMD_WARNING; return CMD_WARNING;
} }
if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) { if (!pim_nht_lookup(vrf->info, &nexthop, addr, 0)) {
vty_out(vty, vty_out(vty,
"Failure querying RIB nexthop for unicast address %s\n", "Failure querying RIB nexthop for unicast address %s\n",
addr_str); addr_str);

View file

@ -2947,10 +2947,7 @@ int pim_show_nexthop_lookup_cmd_helper(const char *vrf, struct vty *vty,
pim_addr_to_prefix(&grp, group); pim_addr_to_prefix(&grp, group);
memset(&nexthop, 0, sizeof(nexthop)); memset(&nexthop, 0, sizeof(nexthop));
result = if (!pim_nht_lookup_ecmp(v->info, &nexthop, vif_source, &grp, false)) {
pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
if (!result) {
vty_out(vty, vty_out(vty,
"Nexthop Lookup failed, no usable routes returned.\n"); "Nexthop Lookup failed, no usable routes returned.\n");
return CMD_SUCCESS; return CMD_SUCCESS;

View file

@ -601,26 +601,13 @@ void pim_if_addr_add(struct connected *ifc)
ifp->name); ifp->name);
} }
} }
struct pim_nexthop_cache *pnc = NULL;
struct pim_rpf rpf;
struct zclient *zclient = NULL;
zclient = pim_zebra_zclient_get(); /* RP config might come prior to local RP's interface IF UP event.
/* RP config might come prior to (local RP's interface) * In this case, pnc would not have pim enabled nexthops. Once
IF UP event. * Interface is UP and pim info is available, reregister with RNH
In this case, pnc would not have pim enabled * address to receive update and add the interface as nexthop.
nexthops. */
Once Interface is UP and pim info is available, pim_nht_get(pim_ifp->pim, pim_addr_from_prefix(ifc->address));
reregister
with RNH address to receive update and add the
interface as nexthop. */
memset(&rpf, 0, sizeof(struct pim_rpf));
rpf.rpf_addr = pim_addr_from_prefix(ifc->address);
pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
if (pnc)
pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
pnc,
ZEBRA_NEXTHOP_REGISTER);
} }
} /* pim */ } /* pim */
@ -2043,7 +2030,7 @@ void pim_pim_interface_delete(struct interface *ifp)
* pim_ifp->pim_neighbor_list. * pim_ifp->pim_neighbor_list.
*/ */
pim_sock_delete(ifp, "pim unconfigured on interface"); pim_sock_delete(ifp, "pim unconfigured on interface");
pim_upstream_nh_if_update(pim_ifp->pim, ifp); pim_nht_upstream_if_update(pim_ifp->pim, ifp);
if (!pim_ifp->gm_enable) { if (!pim_ifp->gm_enable) {
pim_if_addr_del_all(ifp); pim_if_addr_del_all(ifp);

View file

@ -16,6 +16,7 @@
#include "pim_oil.h" #include "pim_oil.h"
#include "pim_ifchannel.h" #include "pim_ifchannel.h"
#include "pim_macro.h" #include "pim_macro.h"
#include "pim_nht.h"
#include "pim_igmp_mtrace.h" #include "pim_igmp_mtrace.h"
static struct in_addr mtrace_primary_address(struct interface *ifp) static struct in_addr mtrace_primary_address(struct interface *ifp)
@ -58,14 +59,14 @@ static bool mtrace_fwd_info_weak(struct pim_instance *pim,
memset(&nexthop, 0, sizeof(nexthop)); memset(&nexthop, 0, sizeof(nexthop));
if (!pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1)) { if (!pim_nht_lookup(pim, &nexthop, mtracep->src_addr, 1)) {
if (PIM_DEBUG_MTRACE) if (PIM_DEBUG_MTRACE)
zlog_debug("mtrace not found neighbor"); zlog_debug("mtrace not found neighbor");
return false; return false;
} }
if (PIM_DEBUG_MTRACE) if (PIM_DEBUG_MTRACE)
zlog_debug("mtrace pim_nexthop_lookup OK"); zlog_debug("mtrace pim_nht_lookup OK");
if (PIM_DEBUG_MTRACE) if (PIM_DEBUG_MTRACE)
zlog_debug("mtrace next_hop=%pPAs", &nexthop.mrib_nexthop_addr); zlog_debug("mtrace next_hop=%pPAs", &nexthop.mrib_nexthop_addr);
@ -353,7 +354,7 @@ static int mtrace_un_forward_packet(struct pim_instance *pim, struct ip *ip_hdr,
if (interface == NULL) { if (interface == NULL) {
memset(&nexthop, 0, sizeof(nexthop)); memset(&nexthop, 0, sizeof(nexthop));
if (!pim_nexthop_lookup(pim, &nexthop, ip_hdr->ip_dst, 0)) { if (!pim_nht_lookup(pim, &nexthop, ip_hdr->ip_dst, 0)) {
if (PIM_DEBUG_MTRACE) if (PIM_DEBUG_MTRACE)
zlog_debug( zlog_debug(
"Dropping mtrace packet, no route to destination"); "Dropping mtrace packet, no route to destination");
@ -535,7 +536,7 @@ static int mtrace_send_response(struct pim_instance *pim,
} else { } else {
memset(&nexthop, 0, sizeof(nexthop)); memset(&nexthop, 0, sizeof(nexthop));
/* TODO: should use unicast rib lookup */ /* TODO: should use unicast rib lookup */
if (!pim_nexthop_lookup(pim, &nexthop, mtracep->rsp_addr, 1)) { if (!pim_nht_lookup(pim, &nexthop, mtracep->rsp_addr, 1)) {
if (PIM_DEBUG_MTRACE) if (PIM_DEBUG_MTRACE)
zlog_debug( zlog_debug(
"Dropped response qid=%ud, no route to response address", "Dropped response qid=%ud, no route to response address",

View file

@ -15,6 +15,7 @@
#include "pim_ssm.h" #include "pim_ssm.h"
#include "pim_rpf.h" #include "pim_rpf.h"
#include "pim_rp.h" #include "pim_rp.h"
#include "pim_nht.h"
#include "pim_mroute.h" #include "pim_mroute.h"
#include "pim_oil.h" #include "pim_oil.h"
#include "pim_static.h" #include "pim_static.h"
@ -46,8 +47,7 @@ static void pim_instance_terminate(struct pim_instance *pim)
pim_bsm_proc_free(pim); pim_bsm_proc_free(pim);
/* Traverse and cleanup rpf_hash */ pim_nht_terminate(pim);
hash_clean_and_free(&pim->rpf_hash, (void *)pim_rp_list_hash_clean);
pim_if_terminate(pim); pim_if_terminate(pim);
@ -75,7 +75,6 @@ static void pim_instance_terminate(struct pim_instance *pim)
static struct pim_instance *pim_instance_init(struct vrf *vrf) static struct pim_instance *pim_instance_init(struct vrf *vrf)
{ {
struct pim_instance *pim; struct pim_instance *pim;
char hash_name[64];
pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance)); pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance));
@ -98,12 +97,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
#endif /* PIM_IPV == 4 */ #endif /* PIM_IPV == 4 */
pim_vxlan_init(pim); pim_vxlan_init(pim);
snprintf(hash_name, sizeof(hash_name), "PIM %s RPF Hash", vrf->name); pim_nht_init(pim);
pim->rpf_hash = hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal,
hash_name);
if (PIM_DEBUG_ZEBRA)
zlog_debug("%s: NHT rpf hash init ", __func__);
pim->ssm_info = pim_ssm_init(); pim->ssm_info = pim_ssm_init();

View file

@ -115,7 +115,7 @@ struct pim_instance {
/* The name of the register-accept prefix-list */ /* The name of the register-accept prefix-list */
char *register_plist; char *register_plist;
struct hash *rpf_hash; struct hash *nht_hash;
enum pim_rpf_lookup_mode rpf_mode; enum pim_rpf_lookup_mode rpf_mode;
void *ssm_info; /* per-vrf SSM configuration */ void *ssm_info; /* per-vrf SSM configuration */

View file

@ -36,6 +36,7 @@
#include "pim_vxlan.h" #include "pim_vxlan.h"
#include "pim_msg.h" #include "pim_msg.h"
#include "pim_util.h" #include "pim_util.h"
#include "pim_nht.h"
static void mroute_read_on(struct pim_instance *pim); static void mroute_read_on(struct pim_instance *pim);
static int pim_upstream_mroute_update(struct channel_oil *c_oil, static int pim_upstream_mroute_update(struct channel_oil *c_oil,
@ -566,8 +567,7 @@ int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf,
* setting the SPTBIT to true * setting the SPTBIT to true
*/ */
if (!(pim_addr_is_any(up->upstream_register)) && if (!(pim_addr_is_any(up->upstream_register)) &&
pim_nexthop_lookup(pim_ifp->pim, &source, pim_nht_lookup(pim_ifp->pim, &source, up->upstream_register, 0)) {
up->upstream_register, 0)) {
pim_register_stop_send(source.interface, &sg, pim_register_stop_send(source.interface, &sg,
pim_ifp->primary_address, pim_ifp->primary_address,
up->upstream_register); up->upstream_register);
@ -580,9 +580,7 @@ int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf,
__func__); __func__);
} else { } else {
if (I_am_RP(pim_ifp->pim, up->sg.grp)) { if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
if (pim_nexthop_lookup(pim_ifp->pim, &source, if (pim_nht_lookup(pim_ifp->pim, &source, up->upstream_register, 0))
up->upstream_register,
0))
pim_register_stop_send( pim_register_stop_send(
source.interface, &sg, source.interface, &sg,
pim_ifp->primary_address, pim_ifp->primary_address,

View file

@ -26,6 +26,7 @@
#include "pim_time.h" #include "pim_time.h"
#include "pim_upstream.h" #include "pim_upstream.h"
#include "pim_oil.h" #include "pim_oil.h"
#include "pim_nht.h"
#include "pim_msdp.h" #include "pim_msdp.h"
#include "pim_msdp_packet.h" #include "pim_msdp_packet.h"
@ -691,7 +692,7 @@ bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp)
} }
/* check if the MSDP peer is the nexthop for the RP */ /* check if the MSDP peer is the nexthop for the RP */
if (pim_nexthop_lookup(mp->pim, &nexthop, rp, 0) && if (pim_nht_lookup(mp->pim, &nexthop, rp, 0) &&
nexthop.mrib_nexthop_addr.s_addr == mp->peer.s_addr) { nexthop.mrib_nexthop_addr.s_addr == mp->peer.s_addr) {
return true; return true;
} }

View file

@ -157,7 +157,7 @@ static int pim_cmd_interface_add(struct interface *ifp)
pim_ifp->pim_enable = true; pim_ifp->pim_enable = true;
pim_if_addr_add_all(ifp); pim_if_addr_add_all(ifp);
pim_upstream_nh_if_update(pim_ifp->pim, ifp); pim_nht_upstream_if_update(pim_ifp->pim, ifp);
pim_if_membership_refresh(ifp); pim_if_membership_refresh(ifp);
pim_if_create_pimreg(pim_ifp->pim); pim_if_create_pimreg(pim_ifp->pim);

File diff suppressed because it is too large Load diff

View file

@ -17,11 +17,12 @@
#include "pim_rpf.h" #include "pim_rpf.h"
/* PIM nexthop cache value structure. */ /* PIM nexthop cache value structure. */
struct pim_nexthop_cache { struct pim_nexthop_cache_rib {
struct pim_rpf rpf;
/* IGP route's metric. */ /* IGP route's metric. */
uint32_t metric; uint32_t metric;
uint32_t distance; uint32_t distance;
uint16_t prefix_len;
/* Nexthop number and nexthop linked list. */ /* Nexthop number and nexthop linked list. */
uint16_t nexthop_num; uint16_t nexthop_num;
struct nexthop *nexthop; struct nexthop *nexthop;
@ -29,6 +30,13 @@ struct pim_nexthop_cache {
uint16_t flags; uint16_t flags;
#define PIM_NEXTHOP_VALID (1 << 0) #define PIM_NEXTHOP_VALID (1 << 0)
#define PIM_NEXTHOP_ANSWER_RECEIVED (1 << 1) #define PIM_NEXTHOP_ANSWER_RECEIVED (1 << 1)
};
struct pim_nexthop_cache {
pim_addr addr;
struct pim_nexthop_cache_rib mrib;
struct pim_nexthop_cache_rib urib;
struct list *rp_list; struct list *rp_list;
struct hash *upstream_hash; struct hash *upstream_hash;
@ -46,36 +54,71 @@ struct pnc_hash_walk_data {
struct interface *ifp; struct interface *ifp;
}; };
void pim_nexthop_update(struct vrf *vrf, struct prefix *match, /* Verify that we have nexthop information in the cache entry */
struct zapi_route *nhr); bool pim_nht_pnc_is_valid(struct pim_instance *pim, struct pim_nexthop_cache *pnc);
int pim_find_or_track_nexthop(struct pim_instance *pim, pim_addr addr,
struct pim_upstream *up, struct rp_info *rp,
struct pim_nexthop_cache *out_pnc);
void pim_delete_tracked_nexthop(struct pim_instance *pim, pim_addr addr,
struct pim_upstream *up, struct rp_info *rp);
struct pim_nexthop_cache *pim_nexthop_cache_find(struct pim_instance *pim,
struct pim_rpf *rpf);
uint32_t pim_compute_ecmp_hash(struct prefix *src, struct prefix *grp);
int pim_ecmp_nexthop_lookup(struct pim_instance *pim,
struct pim_nexthop *nexthop, pim_addr src,
struct prefix *grp, int neighbor_needed);
void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
struct pim_nexthop_cache *pnc, int command);
int pim_ecmp_fib_lookup_if_vif_index(struct pim_instance *pim, pim_addr src,
struct prefix *grp);
void pim_rp_nexthop_del(struct rp_info *rp_info);
/* for RPF check on BSM message receipt */ /* Get (or add) the NH cache entry for the given address */
struct pim_nexthop_cache *pim_nht_get(struct pim_instance *pim, pim_addr addr);
/* Set the gateway address for all nexthops in the given cache entry to the given address
* unless the gateway is already set, and only if the nexthop is through the given interface.
*/
void pim_nht_set_gateway(struct pim_instance *pim, struct pim_nexthop_cache *pnc, pim_addr addr,
struct interface *ifp);
/* Track a new addr, registers an upstream or RP for updates */
bool pim_nht_find_or_track(struct pim_instance *pim, pim_addr addr, struct pim_upstream *up,
struct rp_info *rp, struct pim_nexthop_cache *out_pnc);
/* Track a new addr, increments BSR count */
void pim_nht_bsr_add(struct pim_instance *pim, pim_addr bsr_addr); void pim_nht_bsr_add(struct pim_instance *pim, pim_addr bsr_addr);
void pim_nht_bsr_del(struct pim_instance *pim, pim_addr bsr_addr);
/* RPF(bsr_addr) == src_ip%src_ifp? */
bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr,
struct interface *src_ifp, pim_addr src_ip);
void pim_upstream_nh_if_update(struct pim_instance *pim, struct interface *ifp);
/* wrappers for usage with Candidate RPs in BSMs */ /* Track a new addr, increments Cand RP count */
bool pim_nht_candrp_add(struct pim_instance *pim, pim_addr addr); bool pim_nht_candrp_add(struct pim_instance *pim, pim_addr addr);
/* Delete a tracked addr with registered upstream or RP, if no-one else is interested, stop tracking */
void pim_nht_delete_tracked(struct pim_instance *pim, pim_addr addr, struct pim_upstream *up,
struct rp_info *rp);
/* Delete a tracked addr and decrement BSR count, if no-one else is interested, stop tracking */
void pim_nht_bsr_del(struct pim_instance *pim, pim_addr bsr_addr);
/* Delete a tracked addr and decrement Cand RP count, if no-one else is interested, stop tracking */
void pim_nht_candrp_del(struct pim_instance *pim, pim_addr addr); void pim_nht_candrp_del(struct pim_instance *pim, pim_addr addr);
void pim_crp_nht_update(struct pim_instance *pim, struct pim_nexthop_cache *pnc);
/* RPF(bsr_addr) == src_ip%src_ifp? */
bool pim_nht_bsr_rpf_check(struct pim_instance *pim, pim_addr bsr_addr, struct interface *src_ifp,
pim_addr src_ip);
/* Reset the rp.source_nexthop of the given RP */
void pim_nht_rp_del(struct rp_info *rp_info);
/* Walk the NH cache and update every nexthop that uses the given interface */
void pim_nht_upstream_if_update(struct pim_instance *pim, struct interface *ifp);
/* Lookup nexthop information for src, returned in nexthop when function returns true.
* Tries to find in cache first and does a synchronous lookup if not found in the cache.
* If neighbor_needed is true, then nexthop is only considered valid if it's to a pim
* neighbor.
* Providing the group only effects the ECMP decision, if enabled
*/
bool pim_nht_lookup_ecmp(struct pim_instance *pim, struct pim_nexthop *nexthop, pim_addr src,
struct prefix *grp, bool neighbor_needed);
/* Very similar to pim_nht_lookup_ecmp, but does not check the nht cache and only does
* a synchronous lookup. No ECMP decision is made.
*/
bool pim_nht_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, pim_addr addr,
int neighbor_needed);
/* Performs a pim_nht_lookup_ecmp and returns the mroute VIF index of the nexthop interface */
int pim_nht_lookup_ecmp_if_vif_index(struct pim_instance *pim, pim_addr src, struct prefix *grp);
/* Tracked nexthop update from zebra */
void pim_nexthop_update(struct vrf *vrf, struct prefix *match, struct zapi_route *nhr);
/* NHT init and finish funcitons */
void pim_nht_init(struct pim_instance *pim);
void pim_nht_terminate(struct pim_instance *pim);
#endif #endif

View file

@ -40,20 +40,6 @@
#include "pim_ssm.h" #include "pim_ssm.h"
#include "termtable.h" #include "termtable.h"
/* Cleanup pim->rpf_hash each node data */
void pim_rp_list_hash_clean(void *data)
{
struct pim_nexthop_cache *pnc = (struct pim_nexthop_cache *)data;
list_delete(&pnc->rp_list);
hash_clean_and_free(&pnc->upstream_hash, NULL);
if (pnc->nexthop)
nexthops_free(pnc->nexthop);
XFREE(MTYPE_PIM_NEXTHOP_CACHE, pnc);
}
static void pim_rp_info_free(struct rp_info *rp_info) static void pim_rp_info_free(struct rp_info *rp_info)
{ {
XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist); XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
@ -439,7 +425,7 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
zlog_debug( zlog_debug(
"%s: Deregister upstream %s addr %pPA with Zebra NHT", "%s: Deregister upstream %s addr %pPA with Zebra NHT",
__func__, up->sg_str, &old_upstream_addr); __func__, up->sg_str, &old_upstream_addr);
pim_delete_tracked_nexthop(pim, old_upstream_addr, up, NULL); pim_nht_delete_tracked(pim, old_upstream_addr, up, NULL);
} }
/* Update the upstream address */ /* Update the upstream address */
@ -594,12 +580,10 @@ int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
zlog_debug("new RP %pPA for %pFX is ourselves", zlog_debug("new RP %pPA for %pFX is ourselves",
&rp_all->rp.rpf_addr, &rp_all->group); &rp_all->rp.rpf_addr, &rp_all->group);
pim_rp_refresh_group_to_rp_mapping(pim); pim_rp_refresh_group_to_rp_mapping(pim);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_all, pim_nht_find_or_track(pim, nht_p, NULL, rp_all, NULL);
NULL);
if (!pim_ecmp_nexthop_lookup(pim, if (!pim_nht_lookup_ecmp(pim, &rp_all->rp.source_nexthop, nht_p,
&rp_all->rp.source_nexthop, &rp_all->group, true))
nht_p, &rp_all->group, 1))
return PIM_RP_NO_PATH; return PIM_RP_NO_PATH;
return PIM_SUCCESS; return PIM_SUCCESS;
} }
@ -694,9 +678,8 @@ int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
if (PIM_DEBUG_PIM_NHT_RP) if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra ", zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra ",
__func__, &nht_p, &rp_info->group); __func__, &nht_p, &rp_info->group);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL); pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, nht_p, if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true))
&rp_info->group, 1))
return PIM_RP_NO_PATH; return PIM_RP_NO_PATH;
return PIM_SUCCESS; return PIM_SUCCESS;
@ -787,7 +770,7 @@ int pim_rp_del(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
if (PIM_DEBUG_PIM_NHT_RP) if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: Deregister RP addr %pPA with Zebra ", __func__, zlog_debug("%s: Deregister RP addr %pPA with Zebra ", __func__,
&nht_p); &nht_p);
pim_delete_tracked_nexthop(pim, nht_p, NULL, rp_info); pim_nht_delete_tracked(pim, nht_p, NULL, rp_info);
if (!pim_get_all_mcast_group(&g_all)) if (!pim_get_all_mcast_group(&g_all))
return PIM_RP_BAD_ADDRESS; return PIM_RP_BAD_ADDRESS;
@ -921,10 +904,10 @@ int pim_rp_change(struct pim_instance *pim, pim_addr new_rp_addr,
if (PIM_DEBUG_PIM_NHT_RP) if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: Deregister RP addr %pPA with Zebra ", zlog_debug("%s: Deregister RP addr %pPA with Zebra ",
__func__, &nht_p); __func__, &nht_p);
pim_delete_tracked_nexthop(pim, nht_p, NULL, rp_info); pim_nht_delete_tracked(pim, nht_p, NULL, rp_info);
} }
pim_rp_nexthop_del(rp_info); pim_nht_rp_del(rp_info);
listnode_delete(pim->rp_list, rp_info); listnode_delete(pim->rp_list, rp_info);
/* Update the new RP address*/ /* Update the new RP address*/
@ -958,9 +941,8 @@ int pim_rp_change(struct pim_instance *pim, pim_addr new_rp_addr,
zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra ", zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra ",
__func__, &nht_p, &rp_info->group); __func__, &nht_p, &rp_info->group);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL); pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, nht_p, if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true)) {
&rp_info->group, 1)) {
route_unlock_node(rn); route_unlock_node(rn);
return PIM_RP_NO_PATH; return PIM_RP_NO_PATH;
} }
@ -986,13 +968,13 @@ void pim_rp_setup(struct pim_instance *pim)
nht_p = rp_info->rp.rpf_addr; nht_p = rp_info->rp.rpf_addr;
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL); pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group,
nht_p, &rp_info->group, 1)) { true)) {
if (PIM_DEBUG_PIM_NHT_RP) if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug( zlog_debug(
"Unable to lookup nexthop for rp specified"); "Unable to lookup nexthop for rp specified");
pim_rp_nexthop_del(rp_info); pim_nht_rp_del(rp_info);
} }
} }
} }
@ -1135,10 +1117,9 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, pim_addr group)
zlog_debug( zlog_debug(
"%s: NHT Register RP addr %pPA grp %pFX with Zebra", "%s: NHT Register RP addr %pPA grp %pFX with Zebra",
__func__, &nht_p, &rp_info->group); __func__, &nht_p, &rp_info->group);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL); pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
pim_rpf_set_refresh_time(pim); pim_rpf_set_refresh_time(pim);
(void)pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true);
nht_p, &rp_info->group, 1);
return (&rp_info->rp); return (&rp_info->rp);
} }
@ -1343,7 +1324,6 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
{ {
struct listnode *node = NULL; struct listnode *node = NULL;
struct rp_info *rp_info = NULL; struct rp_info *rp_info = NULL;
struct nexthop *nh_node = NULL;
pim_addr nht_p; pim_addr nht_p;
struct pim_nexthop_cache pnc; struct pim_nexthop_cache pnc;
@ -1353,35 +1333,11 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
nht_p = rp_info->rp.rpf_addr; nht_p = rp_info->rp.rpf_addr;
memset(&pnc, 0, sizeof(struct pim_nexthop_cache)); memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
if (!pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, &pnc))
if (!pim_nht_find_or_track(pim, nht_p, NULL, rp_info, &pnc))
continue; continue;
for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) { pim_nht_set_gateway(pim, &pnc, nbr->source_addr, nbr->interface);
#if PIM_IPV == 4
if (!pim_addr_is_any(nh_node->gate.ipv4))
continue;
#else
if (!pim_addr_is_any(nh_node->gate.ipv6))
continue;
#endif
struct interface *ifp1 = if_lookup_by_index(
nh_node->ifindex, pim->vrf->vrf_id);
if (nbr->interface != ifp1)
continue;
#if PIM_IPV == 4
nh_node->gate.ipv4 = nbr->source_addr;
#else
nh_node->gate.ipv6 = nbr->source_addr;
#endif
if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug(
"%s: addr %pPA new nexthop addr %pPAs interface %s",
__func__, &nht_p, &nbr->source_addr,
ifp1->name);
}
} }
} }
@ -1546,9 +1502,9 @@ void pim_embedded_rp_new(struct pim_instance *pim, const pim_addr *group, const
zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra", __func__, zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra", __func__,
&rp_info->rp.rpf_addr, &rp_info->group); &rp_info->rp.rpf_addr, &rp_info->group);
pim_find_or_track_nexthop(pim, rp_info->rp.rpf_addr, NULL, rp_info, NULL); pim_nht_find_or_track(pim, rp_info->rp.rpf_addr, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, rp_info->rp.rpf_addr, if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, rp_info->rp.rpf_addr,
&rp_info->group, 1)) { &rp_info->group, 1)) {
if (PIM_DEBUG_PIM_NHT_RP) if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: Embedded RP %pPA learned but no next hop", __func__, zlog_debug("%s: Embedded RP %pPA learned but no next hop", __func__,
&rp_info->rp.rpf_addr); &rp_info->rp.rpf_addr);
@ -1588,7 +1544,7 @@ void pim_embedded_rp_free(struct pim_instance *pim, struct rp_info *rp_info)
if (PIM_DEBUG_TRACE) if (PIM_DEBUG_TRACE)
zlog_debug("delete embedded RP %pPA", &rp_info->rp.rpf_addr); zlog_debug("delete embedded RP %pPA", &rp_info->rp.rpf_addr);
pim_delete_tracked_nexthop(pim, rp_info->rp.rpf_addr, NULL, rp_info); pim_nht_delete_tracked(pim, rp_info->rp.rpf_addr, NULL, rp_info);
listnode_delete(pim->rp_list, rp_info); listnode_delete(pim->rp_list, rp_info);
XFREE(MTYPE_PIM_EMBEDDED_RP_ENTRY, rp_info); XFREE(MTYPE_PIM_EMBEDDED_RP_ENTRY, rp_info);
} }

View file

@ -42,8 +42,6 @@ struct rp_info {
void pim_rp_init(struct pim_instance *pim); void pim_rp_init(struct pim_instance *pim);
void pim_rp_free(struct pim_instance *pim); void pim_rp_free(struct pim_instance *pim);
void pim_rp_list_hash_clean(void *data);
int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group, int pim_rp_new(struct pim_instance *pim, pim_addr rp_addr, struct prefix group,
const char *plist, enum rp_source rp_src_flag); const char *plist, enum rp_source rp_src_flag);
void pim_rp_del_config(struct pim_instance *pim, pim_addr rp_addr, void pim_rp_del_config(struct pim_instance *pim, pim_addr rp_addr,

View file

@ -38,120 +38,6 @@ void pim_rpf_set_refresh_time(struct pim_instance *pim)
pim->last_route_change_time); pim->last_route_change_time);
} }
bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
pim_addr addr, int neighbor_needed)
{
struct pim_zlookup_nexthop nexthop_tab[router->multipath];
struct pim_neighbor *nbr = NULL;
int num_ifindex;
struct interface *ifp = NULL;
ifindex_t first_ifindex = 0;
int found = 0;
int i = 0;
struct pim_interface *pim_ifp;
#if PIM_IPV == 4
/*
* We should not attempt to lookup a
* 255.255.255.255 address, since
* it will never work
*/
if (pim_addr_is_any(addr))
return false;
#endif
if ((!pim_addr_cmp(nexthop->last_lookup, addr)) &&
(nexthop->last_lookup_time > pim->last_route_change_time)) {
if (PIM_DEBUG_PIM_NHT)
zlog_debug(
"%s: Using last lookup for %pPAs at %lld, %" PRId64
" addr %pPAs",
__func__, &addr, nexthop->last_lookup_time,
pim->last_route_change_time,
&nexthop->mrib_nexthop_addr);
pim->nexthop_lookups_avoided++;
return true;
} else {
if (PIM_DEBUG_PIM_NHT)
zlog_debug(
"%s: Looking up: %pPAs, last lookup time: %lld, %" PRId64,
__func__, &addr, nexthop->last_lookup_time,
pim->last_route_change_time);
}
memset(nexthop_tab, 0,
sizeof(struct pim_zlookup_nexthop) * router->multipath);
num_ifindex =
zclient_lookup_nexthop(pim, nexthop_tab, router->multipath,
addr, PIM_NEXTHOP_LOOKUP_MAX);
if (num_ifindex < 1) {
if (PIM_DEBUG_PIM_NHT)
zlog_debug(
"%s %s: could not find nexthop ifindex for address %pPAs",
__FILE__, __func__, &addr);
return false;
}
while (!found && (i < num_ifindex)) {
first_ifindex = nexthop_tab[i].ifindex;
ifp = if_lookup_by_index(first_ifindex, pim->vrf->vrf_id);
if (!ifp) {
if (PIM_DEBUG_ZEBRA)
zlog_debug(
"%s %s: could not find interface for ifindex %d (address %pPAs)",
__FILE__, __func__, first_ifindex,
&addr);
i++;
continue;
}
pim_ifp = ifp->info;
if (!pim_ifp || !pim_ifp->pim_enable) {
if (PIM_DEBUG_ZEBRA)
zlog_debug(
"%s: pim not enabled on input interface %s (ifindex=%d, RPF for source %pPAs)",
__func__, ifp->name, first_ifindex,
&addr);
i++;
} else if (neighbor_needed &&
!pim_if_connected_to_source(ifp, addr)) {
nbr = pim_neighbor_find(
ifp, nexthop_tab[i].nexthop_addr, true);
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug("ifp name: %s, pim nbr: %p",
ifp->name, nbr);
if (!nbr && !if_is_loopback(ifp))
i++;
else
found = 1;
} else
found = 1;
}
if (found) {
if (PIM_DEBUG_ZEBRA)
zlog_debug(
"%s %s: found nexthop %pPAs for address %pPAs: interface %s ifindex=%d metric=%d pref=%d",
__FILE__, __func__,
&nexthop_tab[i].nexthop_addr, &addr, ifp->name,
first_ifindex, nexthop_tab[i].route_metric,
nexthop_tab[i].protocol_distance);
/* update nexthop data */
nexthop->interface = ifp;
nexthop->mrib_nexthop_addr = nexthop_tab[i].nexthop_addr;
nexthop->mrib_metric_preference =
nexthop_tab[i].protocol_distance;
nexthop->mrib_route_metric = nexthop_tab[i].route_metric;
nexthop->last_lookup = addr;
nexthop->last_lookup_time = pim_time_monotonic_usec();
nexthop->nbr = nbr;
return true;
} else
return false;
}
static int nexthop_mismatch(const struct pim_nexthop *nh1, static int nexthop_mismatch(const struct pim_nexthop *nh1,
const struct pim_nexthop *nh2) const struct pim_nexthop *nh2)
{ {
@ -221,9 +107,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
if ((pim_addr_is_any(up->sg.src) && I_am_RP(pim, up->sg.grp)) || if ((pim_addr_is_any(up->sg.src) && I_am_RP(pim, up->sg.grp)) ||
PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)) PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
neigh_needed = false; neigh_needed = false;
pim_find_or_track_nexthop(pim, up->upstream_addr, up, NULL, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rpf->source_nexthop, src, &grp, pim_nht_find_or_track(pim, up->upstream_addr, up, NULL, NULL);
neigh_needed)) { if (!pim_nht_lookup_ecmp(pim, &rpf->source_nexthop, src, &grp, neigh_needed)) {
/* Route is Deleted in Zebra, reset the stored NH data */ /* Route is Deleted in Zebra, reset the stored NH data */
pim_upstream_rpf_clear(pim, up); pim_upstream_rpf_clear(pim, up);
pim_rpf_cost_change(pim, up, saved_mrib_route_metric); pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
@ -371,25 +257,3 @@ int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2)
return 0; return 0;
} }
unsigned int pim_rpf_hash_key(const void *arg)
{
const struct pim_nexthop_cache *r = arg;
#if PIM_IPV == 4
return jhash_1word(r->rpf.rpf_addr.s_addr, 0);
#else
return jhash2(r->rpf.rpf_addr.s6_addr32,
array_size(r->rpf.rpf_addr.s6_addr32), 0);
#endif
}
bool 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 (!pim_addr_cmp(r1->rpf.rpf_addr, r2->rpf.rpf_addr));
}

View file

@ -11,6 +11,7 @@
#include "pim_str.h" #include "pim_str.h"
struct pim_instance; struct pim_instance;
struct pim_upstream;
/* /*
RFC 4601: RFC 4601:
@ -52,13 +53,6 @@ enum pim_rpf_lookup_mode {
/* on equal value, MRIB wins for last 2 */ /* on equal value, MRIB wins for last 2 */
}; };
struct pim_upstream;
unsigned int pim_rpf_hash_key(const void *arg);
bool pim_rpf_equal(const void *arg1, const void *arg2);
bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
pim_addr addr, int neighbor_needed);
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim, enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct pim_upstream *up, struct pim_upstream *up,
struct pim_rpf *old, const char *caller); struct pim_rpf *old, const char *caller);

View file

@ -34,16 +34,13 @@ tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif)
up = pim_upstream_find(pim, &sg); up = pim_upstream_find(pim, &sg);
if (up) { if (up) {
memcpy(&nexthop, &up->rpf.source_nexthop, memcpy(&nexthop, &up->rpf.source_nexthop, sizeof(struct pim_nexthop));
sizeof(struct pim_nexthop)); pim_nht_lookup_ecmp(pim, &nexthop, vif_source, &grp, false);
(void)pim_ecmp_nexthop_lookup(pim, &nexthop, vif_source, &grp,
0);
if (nexthop.interface) if (nexthop.interface)
input_iface_vif_index = pim_if_find_vifindex_by_ifindex( input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
pim, nexthop.interface->ifindex); pim, nexthop.interface->ifindex);
} else } else
input_iface_vif_index = input_iface_vif_index = pim_nht_lookup_ecmp_if_vif_index(pim, vif_source, &grp);
pim_ecmp_fib_lookup_if_vif_index(pim, vif_source, &grp);
if (PIM_DEBUG_ZEBRA) if (PIM_DEBUG_ZEBRA)
zlog_debug("%s: NHT %pSG vif_source %pPAs vif_index:%d", zlog_debug("%s: NHT %pSG vif_source %pPAs vif_index:%d",

View file

@ -265,7 +265,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
zlog_debug( zlog_debug(
"%s: Deregister upstream %s addr %pPA with Zebra NHT", "%s: Deregister upstream %s addr %pPA with Zebra NHT",
__func__, up->sg_str, &up->upstream_addr); __func__, up->sg_str, &up->upstream_addr);
pim_delete_tracked_nexthop(pim, up->upstream_addr, up, NULL); pim_nht_delete_tracked(pim, up->upstream_addr, up, NULL);
} }
XFREE(MTYPE_PIM_UPSTREAM, up); XFREE(MTYPE_PIM_UPSTREAM, up);

View file

@ -411,10 +411,9 @@ static void pim_vxlan_orig_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
* we must dereg the old nexthop and force to new "static" * we must dereg the old nexthop and force to new "static"
* iif * iif
*/ */
if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) { if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags))
pim_delete_tracked_nexthop(vxlan_sg->pim, pim_nht_delete_tracked(vxlan_sg->pim, up->upstream_addr, up, NULL);
up->upstream_addr, up, NULL);
}
/* We are acting FHR; clear out use_rpt setting if any */ /* We are acting FHR; clear out use_rpt setting if any */
pim_upstream_update_use_rpt(up, false /*update_mroute*/); pim_upstream_update_use_rpt(up, false /*update_mroute*/);
pim_upstream_ref(up, flags, __func__); pim_upstream_ref(up, flags, __func__);