forked from Mirror/frr
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:
parent
cc865c0192
commit
6d30c8f6b5
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
1404
pimd/pim_nht.c
1404
pimd/pim_nht.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
142
pimd/pim_rpf.c
142
pimd/pim_rpf.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__);
|
||||
|
|
Loading…
Reference in a new issue