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);
}
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))
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;
bool ok;
ref.addr = pnc->rpf.rpf_addr;
ref.addr = pnc->addr;
rp = bsr_crp_rps_find(scope->ebsr_rps, &ref);
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)
return;

View file

@ -3288,7 +3288,7 @@ DEFUN (show_ip_rib,
return CMD_WARNING;
}
if (!pim_nexthop_lookup(vrf->info, &nexthop, addr, 0)) {
if (!pim_nht_lookup(vrf->info, &nexthop, addr, 0)) {
vty_out(vty,
"Failure querying RIB nexthop for unicast address %s\n",
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);
memset(&nexthop, 0, sizeof(nexthop));
result =
pim_ecmp_nexthop_lookup(v->info, &nexthop, vif_source, &grp, 0);
if (!result) {
if (!pim_nht_lookup_ecmp(v->info, &nexthop, vif_source, &grp, false)) {
vty_out(vty,
"Nexthop Lookup failed, no usable routes returned.\n");
return CMD_SUCCESS;

View file

@ -601,26 +601,13 @@ void pim_if_addr_add(struct connected *ifc)
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.
In this case, pnc would not have pim enabled
nexthops.
Once Interface is UP and pim info is available,
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);
/* RP config might come prior to local RP's interface IF UP event.
* In this case, pnc would not have pim enabled nexthops. Once
* Interface is UP and pim info is available, reregister with RNH
* address to receive update and add the interface as nexthop.
*/
pim_nht_get(pim_ifp->pim, pim_addr_from_prefix(ifc->address));
}
} /* pim */
@ -2043,7 +2030,7 @@ void pim_pim_interface_delete(struct interface *ifp)
* pim_ifp->pim_neighbor_list.
*/
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) {
pim_if_addr_del_all(ifp);

View file

@ -16,6 +16,7 @@
#include "pim_oil.h"
#include "pim_ifchannel.h"
#include "pim_macro.h"
#include "pim_nht.h"
#include "pim_igmp_mtrace.h"
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));
if (!pim_nexthop_lookup(pim, &nexthop, mtracep->src_addr, 1)) {
if (!pim_nht_lookup(pim, &nexthop, mtracep->src_addr, 1)) {
if (PIM_DEBUG_MTRACE)
zlog_debug("mtrace not found neighbor");
return false;
}
if (PIM_DEBUG_MTRACE)
zlog_debug("mtrace pim_nexthop_lookup OK");
zlog_debug("mtrace pim_nht_lookup OK");
if (PIM_DEBUG_MTRACE)
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) {
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)
zlog_debug(
"Dropping mtrace packet, no route to destination");
@ -535,7 +536,7 @@ static int mtrace_send_response(struct pim_instance *pim,
} else {
memset(&nexthop, 0, sizeof(nexthop));
/* 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)
zlog_debug(
"Dropped response qid=%ud, no route to response address",

View file

@ -15,6 +15,7 @@
#include "pim_ssm.h"
#include "pim_rpf.h"
#include "pim_rp.h"
#include "pim_nht.h"
#include "pim_mroute.h"
#include "pim_oil.h"
#include "pim_static.h"
@ -46,8 +47,7 @@ static void pim_instance_terminate(struct pim_instance *pim)
pim_bsm_proc_free(pim);
/* Traverse and cleanup rpf_hash */
hash_clean_and_free(&pim->rpf_hash, (void *)pim_rp_list_hash_clean);
pim_nht_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)
{
struct pim_instance *pim;
char hash_name[64];
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 */
pim_vxlan_init(pim);
snprintf(hash_name, sizeof(hash_name), "PIM %s RPF Hash", vrf->name);
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_nht_init(pim);
pim->ssm_info = pim_ssm_init();

View file

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

View file

@ -36,6 +36,7 @@
#include "pim_vxlan.h"
#include "pim_msg.h"
#include "pim_util.h"
#include "pim_nht.h"
static void mroute_read_on(struct pim_instance *pim);
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
*/
if (!(pim_addr_is_any(up->upstream_register)) &&
pim_nexthop_lookup(pim_ifp->pim, &source,
up->upstream_register, 0)) {
pim_nht_lookup(pim_ifp->pim, &source, up->upstream_register, 0)) {
pim_register_stop_send(source.interface, &sg,
pim_ifp->primary_address,
up->upstream_register);
@ -580,9 +580,7 @@ int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp, const char *buf,
__func__);
} else {
if (I_am_RP(pim_ifp->pim, up->sg.grp)) {
if (pim_nexthop_lookup(pim_ifp->pim, &source,
up->upstream_register,
0))
if (pim_nht_lookup(pim_ifp->pim, &source, up->upstream_register, 0))
pim_register_stop_send(
source.interface, &sg,
pim_ifp->primary_address,

View file

@ -26,6 +26,7 @@
#include "pim_time.h"
#include "pim_upstream.h"
#include "pim_oil.h"
#include "pim_nht.h"
#include "pim_msdp.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 */
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) {
return true;
}

View file

@ -157,7 +157,7 @@ static int pim_cmd_interface_add(struct interface *ifp)
pim_ifp->pim_enable = true;
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_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"
/* PIM nexthop cache value structure. */
struct pim_nexthop_cache {
struct pim_rpf rpf;
struct pim_nexthop_cache_rib {
/* IGP route's metric. */
uint32_t metric;
uint32_t distance;
uint16_t prefix_len;
/* Nexthop number and nexthop linked list. */
uint16_t nexthop_num;
struct nexthop *nexthop;
@ -29,6 +30,13 @@ struct pim_nexthop_cache {
uint16_t flags;
#define PIM_NEXTHOP_VALID (1 << 0)
#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 hash *upstream_hash;
@ -46,36 +54,71 @@ struct pnc_hash_walk_data {
struct interface *ifp;
};
void pim_nexthop_update(struct vrf *vrf, struct prefix *match,
struct zapi_route *nhr);
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);
/* Verify that we have nexthop information in the cache entry */
bool pim_nht_pnc_is_valid(struct pim_instance *pim, struct pim_nexthop_cache *pnc);
/* 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_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);
/* 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_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

View file

@ -40,20 +40,6 @@
#include "pim_ssm.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)
{
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(
"%s: Deregister upstream %s addr %pPA with Zebra NHT",
__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 */
@ -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",
&rp_all->rp.rpf_addr, &rp_all->group);
pim_rp_refresh_group_to_rp_mapping(pim);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_all,
NULL);
pim_nht_find_or_track(pim, nht_p, NULL, rp_all, NULL);
if (!pim_ecmp_nexthop_lookup(pim,
&rp_all->rp.source_nexthop,
nht_p, &rp_all->group, 1))
if (!pim_nht_lookup_ecmp(pim, &rp_all->rp.source_nexthop, nht_p,
&rp_all->group, true))
return PIM_RP_NO_PATH;
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)
zlog_debug("%s: NHT Register RP addr %pPA grp %pFX with Zebra ",
__func__, &nht_p, &rp_info->group);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, nht_p,
&rp_info->group, 1))
pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true))
return PIM_RP_NO_PATH;
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)
zlog_debug("%s: Deregister RP addr %pPA with Zebra ", __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))
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)
zlog_debug("%s: Deregister RP addr %pPA with Zebra ",
__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);
/* 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 ",
__func__, &nht_p, &rp_info->group);
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop, nht_p,
&rp_info->group, 1)) {
pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true)) {
route_unlock_node(rn);
return PIM_RP_NO_PATH;
}
@ -986,13 +968,13 @@ void pim_rp_setup(struct pim_instance *pim)
nht_p = rp_info->rp.rpf_addr;
pim_find_or_track_nexthop(pim, nht_p, NULL, rp_info, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
nht_p, &rp_info->group, 1)) {
pim_nht_find_or_track(pim, nht_p, NULL, rp_info, NULL);
if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group,
true)) {
if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug(
"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(
"%s: NHT Register RP addr %pPA grp %pFX with Zebra",
__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);
(void)pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
nht_p, &rp_info->group, 1);
pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, nht_p, &rp_info->group, true);
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 rp_info *rp_info = NULL;
struct nexthop *nh_node = NULL;
pim_addr nht_p;
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;
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;
for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
#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);
}
pim_nht_set_gateway(pim, &pnc, nbr->source_addr, nbr->interface);
}
}
@ -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__,
&rp_info->rp.rpf_addr, &rp_info->group);
pim_find_or_track_nexthop(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,
&rp_info->group, 1)) {
pim_nht_find_or_track(pim, rp_info->rp.rpf_addr, NULL, rp_info, NULL);
if (!pim_nht_lookup_ecmp(pim, &rp_info->rp.source_nexthop, rp_info->rp.rpf_addr,
&rp_info->group, 1)) {
if (PIM_DEBUG_PIM_NHT_RP)
zlog_debug("%s: Embedded RP %pPA learned but no next hop", __func__,
&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)
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);
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_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,
const char *plist, enum rp_source rp_src_flag);
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);
}
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,
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)) ||
PIM_UPSTREAM_FLAG_TEST_FHR(up->flags))
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,
neigh_needed)) {
pim_nht_find_or_track(pim, up->upstream_addr, up, NULL, NULL);
if (!pim_nht_lookup_ecmp(pim, &rpf->source_nexthop, src, &grp, neigh_needed)) {
/* Route is Deleted in Zebra, reset the stored NH data */
pim_upstream_rpf_clear(pim, up);
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;
}
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"
struct pim_instance;
struct pim_upstream;
/*
RFC 4601:
@ -52,13 +53,6 @@ enum pim_rpf_lookup_mode {
/* 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,
struct pim_upstream *up,
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);
if (up) {
memcpy(&nexthop, &up->rpf.source_nexthop,
sizeof(struct pim_nexthop));
(void)pim_ecmp_nexthop_lookup(pim, &nexthop, vif_source, &grp,
0);
memcpy(&nexthop, &up->rpf.source_nexthop, sizeof(struct pim_nexthop));
pim_nht_lookup_ecmp(pim, &nexthop, vif_source, &grp, false);
if (nexthop.interface)
input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
pim, nexthop.interface->ifindex);
} else
input_iface_vif_index =
pim_ecmp_fib_lookup_if_vif_index(pim, vif_source, &grp);
input_iface_vif_index = pim_nht_lookup_ecmp_if_vif_index(pim, vif_source, &grp);
if (PIM_DEBUG_ZEBRA)
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(
"%s: Deregister upstream %s addr %pPA with Zebra NHT",
__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);

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"
* iif
*/
if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)) {
pim_delete_tracked_nexthop(vxlan_sg->pim,
up->upstream_addr, up, NULL);
}
if (!PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags))
pim_nht_delete_tracked(vxlan_sg->pim, up->upstream_addr, up, NULL);
/* We are acting FHR; clear out use_rpt setting if any */
pim_upstream_update_use_rpt(up, false /*update_mroute*/);
pim_upstream_ref(up, flags, __func__);