mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 15:17:15 +00:00
commit
97610b589f
@ -2566,30 +2566,30 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_rpf_refresh_stats(struct vty *vty, time_t now,
|
static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
|
||||||
json_object *json)
|
time_t now, json_object *json)
|
||||||
{
|
{
|
||||||
char refresh_uptime[10];
|
char refresh_uptime[10];
|
||||||
|
|
||||||
pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
|
pim_time_uptime_begin(refresh_uptime, sizeof(refresh_uptime), now,
|
||||||
qpim_rpf_cache_refresh_last);
|
pim->rpf_cache_refresh_last);
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
|
json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
|
||||||
qpim_rpf_cache_refresh_delay_msec);
|
qpim_rpf_cache_refresh_delay_msec);
|
||||||
json_object_int_add(
|
json_object_int_add(
|
||||||
json, "rpfCacheRefreshTimer",
|
json, "rpfCacheRefreshTimer",
|
||||||
pim_time_timer_remain_msec(qpim_rpf_cache_refresher));
|
pim_time_timer_remain_msec(pim->rpf_cache_refresher));
|
||||||
json_object_int_add(json, "rpfCacheRefreshRequests",
|
json_object_int_add(json, "rpfCacheRefreshRequests",
|
||||||
qpim_rpf_cache_refresh_requests);
|
pim->rpf_cache_refresh_requests);
|
||||||
json_object_int_add(json, "rpfCacheRefreshEvents",
|
json_object_int_add(json, "rpfCacheRefreshEvents",
|
||||||
qpim_rpf_cache_refresh_events);
|
pim->rpf_cache_refresh_events);
|
||||||
json_object_string_add(json, "rpfCacheRefreshLast",
|
json_object_string_add(json, "rpfCacheRefreshLast",
|
||||||
refresh_uptime);
|
refresh_uptime);
|
||||||
json_object_int_add(json, "nexthopLookups",
|
json_object_int_add(json, "nexthopLookups",
|
||||||
qpim_nexthop_lookups);
|
pim->nexthop_lookups);
|
||||||
json_object_int_add(json, "nexthopLookupsAvoided",
|
json_object_int_add(json, "nexthopLookupsAvoided",
|
||||||
nexthop_lookups_avoided);
|
pim->nexthop_lookups_avoided);
|
||||||
} else {
|
} else {
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"RPF Cache Refresh Delay: %ld msecs\n"
|
"RPF Cache Refresh Delay: %ld msecs\n"
|
||||||
@ -2600,11 +2600,11 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,
|
|||||||
"Nexthop Lookups: %lld\n"
|
"Nexthop Lookups: %lld\n"
|
||||||
"Nexthop Lookups Avoided: %lld\n",
|
"Nexthop Lookups Avoided: %lld\n",
|
||||||
qpim_rpf_cache_refresh_delay_msec,
|
qpim_rpf_cache_refresh_delay_msec,
|
||||||
pim_time_timer_remain_msec(qpim_rpf_cache_refresher),
|
pim_time_timer_remain_msec(pim->rpf_cache_refresher),
|
||||||
(long long)qpim_rpf_cache_refresh_requests,
|
(long long)pim->rpf_cache_refresh_requests,
|
||||||
(long long)qpim_rpf_cache_refresh_events,
|
(long long)pim->rpf_cache_refresh_events,
|
||||||
refresh_uptime, (long long)qpim_nexthop_lookups,
|
refresh_uptime, (long long)pim->nexthop_lookups,
|
||||||
(long long)nexthop_lookups_avoided);
|
(long long)pim->nexthop_lookups_avoided);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2616,7 +2616,7 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
|
|||||||
char uptime_mroute_del[10];
|
char uptime_mroute_del[10];
|
||||||
|
|
||||||
pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
|
pim_time_uptime_begin(uptime_scan_oil, sizeof(uptime_scan_oil), now,
|
||||||
qpim_scan_oil_last);
|
pim->scan_oil_last);
|
||||||
pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
|
pim_time_uptime_begin(uptime_mroute_add, sizeof(uptime_mroute_add), now,
|
||||||
pim->mroute_add_last);
|
pim->mroute_add_last);
|
||||||
pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
|
pim_time_uptime_begin(uptime_mroute_del, sizeof(uptime_mroute_del), now,
|
||||||
@ -2626,7 +2626,7 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty,
|
|||||||
"Scan OIL - Last: %s Events: %lld\n"
|
"Scan OIL - Last: %s Events: %lld\n"
|
||||||
"MFC Add - Last: %s Events: %lld\n"
|
"MFC Add - Last: %s Events: %lld\n"
|
||||||
"MFC Del - Last: %s Events: %lld\n",
|
"MFC Del - Last: %s Events: %lld\n",
|
||||||
uptime_scan_oil, (long long)qpim_scan_oil_events,
|
uptime_scan_oil, (long long)pim->scan_oil_events,
|
||||||
uptime_mroute_add, (long long)pim->mroute_add_events,
|
uptime_mroute_add, (long long)pim->mroute_add_events,
|
||||||
uptime_mroute_del, (long long)pim->mroute_del_events);
|
uptime_mroute_del, (long long)pim->mroute_del_events);
|
||||||
}
|
}
|
||||||
@ -2642,9 +2642,9 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, uint8_t uj)
|
|||||||
|
|
||||||
if (uj) {
|
if (uj) {
|
||||||
json = json_object_new_object();
|
json = json_object_new_object();
|
||||||
show_rpf_refresh_stats(vty, now, json);
|
show_rpf_refresh_stats(vty, pim, now, json);
|
||||||
} else {
|
} else {
|
||||||
show_rpf_refresh_stats(vty, now, json);
|
show_rpf_refresh_stats(vty, pim, now, json);
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
vty_out(vty,
|
vty_out(vty,
|
||||||
"Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
|
"Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
|
||||||
@ -4337,7 +4337,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
|
|||||||
|
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
|
|
||||||
show_rpf_refresh_stats(vty, now, NULL);
|
show_rpf_refresh_stats(vty, pim, now, NULL);
|
||||||
|
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
|
|||||||
|
|
||||||
pim_upstream_init(pim);
|
pim_upstream_init(pim);
|
||||||
|
|
||||||
|
pim->last_route_change_time = -1;
|
||||||
return pim;
|
return pim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +94,18 @@ struct pim_instance {
|
|||||||
|
|
||||||
unsigned int keep_alive_time;
|
unsigned int keep_alive_time;
|
||||||
unsigned int rp_keep_alive_time;
|
unsigned int rp_keep_alive_time;
|
||||||
|
|
||||||
|
/* If we need to rescan all our upstreams */
|
||||||
|
struct thread *rpf_cache_refresher;
|
||||||
|
int64_t rpf_cache_refresh_requests;
|
||||||
|
int64_t rpf_cache_refresh_events;
|
||||||
|
int64_t rpf_cache_refresh_last;
|
||||||
|
int64_t scan_oil_events;
|
||||||
|
int64_t scan_oil_last;
|
||||||
|
|
||||||
|
int64_t nexthop_lookups;
|
||||||
|
int64_t nexthop_lookups_avoided;
|
||||||
|
int64_t last_route_change_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
void pim_vrf_init(void);
|
void pim_vrf_init(void);
|
||||||
|
@ -477,17 +477,6 @@ struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp)
|
|||||||
return listnode_head(pim_ifp->pim_neighbor_list);
|
return listnode_head(pim_ifp->pim_neighbor_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rpf info associated with an upstream entry needs to be re-evaluated
|
|
||||||
* when an RPF neighbor comes or goes */
|
|
||||||
static void pim_neighbor_rpf_update(void)
|
|
||||||
{
|
|
||||||
/* XXX: for the time being piggyback on the timer used on rib changes
|
|
||||||
* to scan and update the rpf nexthop. This is expensive processing
|
|
||||||
* and we should be able to optimize neighbor changes differently than
|
|
||||||
* nexthop changes. */
|
|
||||||
sched_rpf_cache_refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pim_neighbor *
|
struct pim_neighbor *
|
||||||
pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
|
pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
|
||||||
pim_hello_options hello_options, uint16_t holdtime,
|
pim_hello_options hello_options, uint16_t holdtime,
|
||||||
@ -556,7 +545,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
|
|||||||
|
|
||||||
pim_rp_setup(pim_ifp->pim);
|
pim_rp_setup(pim_ifp->pim);
|
||||||
|
|
||||||
pim_neighbor_rpf_update();
|
sched_rpf_cache_refresh(pim_ifp->pim);
|
||||||
return neigh;
|
return neigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +667,7 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
|
|||||||
|
|
||||||
pim_neighbor_free(neigh);
|
pim_neighbor_free(neigh);
|
||||||
|
|
||||||
pim_neighbor_rpf_update();
|
sched_rpf_cache_refresh(pim_ifp->pim);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)
|
void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)
|
||||||
|
@ -759,7 +759,7 @@ int pim_parse_nexthop_update(int command, struct zclient *zclient,
|
|||||||
pnc->upstream_hash->count, listcount(pnc->rp_list));
|
pnc->upstream_hash->count, listcount(pnc->rp_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
pim_rpf_set_refresh_time();
|
pim_rpf_set_refresh_time(pim);
|
||||||
|
|
||||||
if (listcount(pnc->rp_list))
|
if (listcount(pnc->rp_list))
|
||||||
pim_update_rp_nh(pim, pnc);
|
pim_update_rp_nh(pim, pnc);
|
||||||
|
@ -868,7 +868,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group)
|
|||||||
"%s: Nexthop cache not found for RP %s grp %s register with Zebra",
|
"%s: Nexthop cache not found for RP %s grp %s register with Zebra",
|
||||||
__PRETTY_FUNCTION__, buf, buf1);
|
__PRETTY_FUNCTION__, buf, buf1);
|
||||||
}
|
}
|
||||||
pim_rpf_set_refresh_time();
|
pim_rpf_set_refresh_time(pim);
|
||||||
pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
|
pim_nexthop_lookup(pim, &rp_info->rp.source_nexthop,
|
||||||
rp_info->rp.rpf_addr.u.prefix4, 1);
|
rp_info->rp.rpf_addr.u.prefix4, 1);
|
||||||
}
|
}
|
||||||
|
@ -37,17 +37,15 @@
|
|||||||
#include "pim_nht.h"
|
#include "pim_nht.h"
|
||||||
#include "pim_oil.h"
|
#include "pim_oil.h"
|
||||||
|
|
||||||
static long long last_route_change_time = -1;
|
|
||||||
long long nexthop_lookups_avoided = 0;
|
|
||||||
|
|
||||||
static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up);
|
static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up);
|
||||||
|
|
||||||
void pim_rpf_set_refresh_time(void)
|
void pim_rpf_set_refresh_time(struct pim_instance *pim)
|
||||||
{
|
{
|
||||||
last_route_change_time = pim_time_monotonic_usec();
|
pim->last_route_change_time = pim_time_monotonic_usec();
|
||||||
if (PIM_DEBUG_TRACE)
|
if (PIM_DEBUG_TRACE)
|
||||||
zlog_debug("%s: New last route change time: %lld",
|
zlog_debug("%s: vrf(%s) New last route change time: %" PRId64,
|
||||||
__PRETTY_FUNCTION__, last_route_change_time);
|
__PRETTY_FUNCTION__, pim->vrf->name,
|
||||||
|
pim->last_route_change_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
|
int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
|
||||||
@ -70,7 +68,7 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((nexthop->last_lookup.s_addr == addr.s_addr)
|
if ((nexthop->last_lookup.s_addr == addr.s_addr)
|
||||||
&& (nexthop->last_lookup_time > last_route_change_time)) {
|
&& (nexthop->last_lookup_time > pim->last_route_change_time)) {
|
||||||
if (PIM_DEBUG_TRACE) {
|
if (PIM_DEBUG_TRACE) {
|
||||||
char addr_str[INET_ADDRSTRLEN];
|
char addr_str[INET_ADDRSTRLEN];
|
||||||
pim_inet4_dump("<addr?>", addr, addr_str,
|
pim_inet4_dump("<addr?>", addr, addr_str,
|
||||||
@ -79,12 +77,12 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
|
|||||||
pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr,
|
pim_addr_dump("<nexthop?>", &nexthop->mrib_nexthop_addr,
|
||||||
nexthop_str, sizeof(nexthop_str));
|
nexthop_str, sizeof(nexthop_str));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s: Using last lookup for %s at %lld, %lld addr%s",
|
"%s: Using last lookup for %s at %lld, %" PRId64 " addr%s",
|
||||||
__PRETTY_FUNCTION__, addr_str,
|
__PRETTY_FUNCTION__, addr_str,
|
||||||
nexthop->last_lookup_time,
|
nexthop->last_lookup_time,
|
||||||
last_route_change_time, nexthop_str);
|
pim->last_route_change_time, nexthop_str);
|
||||||
}
|
}
|
||||||
nexthop_lookups_avoided++;
|
pim->nexthop_lookups_avoided++;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (PIM_DEBUG_TRACE) {
|
if (PIM_DEBUG_TRACE) {
|
||||||
@ -92,10 +90,10 @@ int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
|
|||||||
pim_inet4_dump("<addr?>", addr, addr_str,
|
pim_inet4_dump("<addr?>", addr, addr_str,
|
||||||
sizeof(addr_str));
|
sizeof(addr_str));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s: Looking up: %s, last lookup time: %lld, %lld",
|
"%s: Looking up: %s, last lookup time: %lld, %" PRId64,
|
||||||
__PRETTY_FUNCTION__, addr_str,
|
__PRETTY_FUNCTION__, addr_str,
|
||||||
nexthop->last_lookup_time,
|
nexthop->last_lookup_time,
|
||||||
last_route_change_time);
|
pim->last_route_change_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,6 @@ enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE };
|
|||||||
|
|
||||||
struct pim_upstream;
|
struct pim_upstream;
|
||||||
|
|
||||||
extern long long nexthop_lookups_avoided;
|
|
||||||
|
|
||||||
unsigned int pim_rpf_hash_key(void *arg);
|
unsigned int pim_rpf_hash_key(void *arg);
|
||||||
int pim_rpf_equal(const void *arg1, const void *arg2);
|
int pim_rpf_equal(const void *arg1, const void *arg2);
|
||||||
|
|
||||||
@ -71,5 +69,5 @@ int pim_rpf_addr_is_inaddr_none(struct pim_rpf *rpf);
|
|||||||
int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf);
|
int pim_rpf_addr_is_inaddr_any(struct pim_rpf *rpf);
|
||||||
|
|
||||||
int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2);
|
int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2);
|
||||||
void pim_rpf_set_refresh_time(void);
|
void pim_rpf_set_refresh_time(struct pim_instance *pim);
|
||||||
#endif /* PIM_RPF_H */
|
#endif /* PIM_RPF_H */
|
||||||
|
@ -48,7 +48,7 @@ static void pim_ssm_range_reevaluate(struct pim_instance *pim)
|
|||||||
* disappear in time for SSM groups.
|
* disappear in time for SSM groups.
|
||||||
*/
|
*/
|
||||||
pim_upstream_register_reevaluate(pim);
|
pim_upstream_register_reevaluate(pim);
|
||||||
igmp_source_forward_reevaluate_all();
|
igmp_source_forward_reevaluate_all(pim);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_ssm_prefix_list_update(struct pim_instance *pim,
|
void pim_ssm_prefix_list_update(struct pim_instance *pim,
|
||||||
|
308
pimd/pim_zebra.c
308
pimd/pim_zebra.c
@ -394,133 +394,105 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_upstream_rpf_cache()
|
static void scan_upstream_rpf_cache(struct pim_instance *pim)
|
||||||
{
|
{
|
||||||
struct listnode *up_node;
|
struct listnode *up_node;
|
||||||
struct listnode *up_nextnode;
|
struct listnode *up_nextnode;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct pim_upstream *up;
|
struct pim_upstream *up;
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct vrf *vrf;
|
|
||||||
struct pim_instance *pim;
|
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
|
||||||
pim = vrf->info;
|
enum pim_rpf_result rpf_result;
|
||||||
if (!pim)
|
struct pim_rpf old;
|
||||||
|
struct prefix nht_p;
|
||||||
|
|
||||||
|
nht_p.family = AF_INET;
|
||||||
|
nht_p.prefixlen = IPV4_MAX_BITLEN;
|
||||||
|
nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
|
||||||
|
pim_resolve_upstream_nh(pim, &nht_p);
|
||||||
|
|
||||||
|
old.source_nexthop.interface = up->rpf.source_nexthop.interface;
|
||||||
|
old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
|
||||||
|
rpf_result = pim_rpf_update(pim, up, &old, 0);
|
||||||
|
|
||||||
|
if (rpf_result == PIM_RPF_FAILURE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode,
|
if (rpf_result == PIM_RPF_CHANGED) {
|
||||||
up)) {
|
struct pim_neighbor *nbr;
|
||||||
enum pim_rpf_result rpf_result;
|
|
||||||
struct pim_rpf old;
|
|
||||||
struct prefix nht_p;
|
|
||||||
|
|
||||||
nht_p.family = AF_INET;
|
nbr = pim_neighbor_find(old.source_nexthop.interface,
|
||||||
nht_p.prefixlen = IPV4_MAX_BITLEN;
|
old.rpf_addr.u.prefix4);
|
||||||
nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;
|
if (nbr)
|
||||||
pim_resolve_upstream_nh(pim, &nht_p);
|
pim_jp_agg_remove_group(nbr->upstream_jp_agg,
|
||||||
|
up);
|
||||||
|
|
||||||
old.source_nexthop.interface =
|
/*
|
||||||
up->rpf.source_nexthop.interface;
|
* We have detected a case where we might need
|
||||||
old.source_nexthop.nbr = up->rpf.source_nexthop.nbr;
|
* to rescan
|
||||||
rpf_result = pim_rpf_update(pim, up, &old, 0);
|
* the inherited o_list so do it.
|
||||||
|
*/
|
||||||
|
if (up->channel_oil->oil_inherited_rescan) {
|
||||||
|
pim_upstream_inherited_olist_decide(pim, up);
|
||||||
|
up->channel_oil->oil_inherited_rescan = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (rpf_result == PIM_RPF_FAILURE)
|
if (up->join_state == PIM_UPSTREAM_JOINED) {
|
||||||
continue;
|
/*
|
||||||
|
* If we come up real fast we can be here
|
||||||
if (rpf_result == PIM_RPF_CHANGED) {
|
* where the mroute has not been installed
|
||||||
struct pim_neighbor *nbr;
|
* so install it.
|
||||||
|
*/
|
||||||
nbr = pim_neighbor_find(
|
if (!up->channel_oil->installed)
|
||||||
old.source_nexthop.interface,
|
pim_mroute_add(up->channel_oil,
|
||||||
old.rpf_addr.u.prefix4);
|
__PRETTY_FUNCTION__);
|
||||||
if (nbr)
|
|
||||||
pim_jp_agg_remove_group(
|
|
||||||
nbr->upstream_jp_agg, up);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have detected a case where we might need
|
* RFC 4601: 4.5.7. Sending (S,G)
|
||||||
* to rescan
|
* Join/Prune Messages
|
||||||
* the inherited o_list so do it.
|
*
|
||||||
|
* Transitions from Joined State
|
||||||
|
*
|
||||||
|
* RPF'(S,G) changes not due to an Assert
|
||||||
|
*
|
||||||
|
* The upstream (S,G) state machine remains
|
||||||
|
* in Joined state. Send Join(S,G) to the new
|
||||||
|
* upstream neighbor, which is the new value
|
||||||
|
* of RPF'(S,G). Send Prune(S,G) to the old
|
||||||
|
* upstream neighbor, which is the old value
|
||||||
|
* of RPF'(S,G). Set the Join Timer (JT) to
|
||||||
|
* expire after t_periodic seconds.
|
||||||
*/
|
*/
|
||||||
if (up->channel_oil->oil_inherited_rescan) {
|
pim_jp_agg_switch_interface(&old, &up->rpf, up);
|
||||||
pim_upstream_inherited_olist_decide(pim,
|
|
||||||
up);
|
|
||||||
up->channel_oil->oil_inherited_rescan =
|
|
||||||
0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (up->join_state == PIM_UPSTREAM_JOINED) {
|
pim_upstream_join_timer_restart(up, &old);
|
||||||
/*
|
} /* up->join_state == PIM_UPSTREAM_JOINED */
|
||||||
* If we come up real fast we can be
|
|
||||||
* here
|
|
||||||
* where the mroute has not been
|
|
||||||
* installed
|
|
||||||
* so install it.
|
|
||||||
*/
|
|
||||||
if (!up->channel_oil->installed)
|
|
||||||
pim_mroute_add(
|
|
||||||
up->channel_oil,
|
|
||||||
__PRETTY_FUNCTION__);
|
|
||||||
|
|
||||||
/*
|
/* FIXME can join_desired actually be changed by
|
||||||
* RFC 4601: 4.5.7. Sending (S,G)
|
pim_rpf_update()
|
||||||
* Join/Prune Messages
|
returning PIM_RPF_CHANGED ? */
|
||||||
*
|
pim_upstream_update_join_desired(pim, up);
|
||||||
* Transitions from Joined State
|
|
||||||
*
|
|
||||||
* RPF'(S,G) changes not due to an
|
|
||||||
* Assert
|
|
||||||
*
|
|
||||||
* The upstream (S,G) state machine
|
|
||||||
* remains in Joined
|
|
||||||
* state. Send Join(S,G) to the new
|
|
||||||
* upstream neighbor, which is
|
|
||||||
* the new value of RPF'(S,G). Send
|
|
||||||
* Prune(S,G) to the old
|
|
||||||
* upstream neighbor, which is the old
|
|
||||||
* value of RPF'(S,G). Set
|
|
||||||
* the Join Timer (JT) to expire after
|
|
||||||
* t_periodic seconds.
|
|
||||||
*/
|
|
||||||
pim_jp_agg_switch_interface(
|
|
||||||
&old, &up->rpf, up);
|
|
||||||
|
|
||||||
pim_upstream_join_timer_restart(up,
|
} /* PIM_RPF_CHANGED */
|
||||||
&old);
|
|
||||||
} /* up->join_state == PIM_UPSTREAM_JOINED */
|
|
||||||
|
|
||||||
/* FIXME can join_desired actually be changed by
|
} /* for (qpim_upstream_list) */
|
||||||
pim_rpf_update()
|
|
||||||
returning PIM_RPF_CHANGED ? */
|
|
||||||
pim_upstream_update_join_desired(pim, up);
|
|
||||||
|
|
||||||
} /* PIM_RPF_CHANGED */
|
FOR_ALL_INTERFACES (pim->vrf, ifp)
|
||||||
|
if (ifp->info) {
|
||||||
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
|
struct pim_iface_upstream_switch *us;
|
||||||
|
|
||||||
} /* for (qpim_upstream_list) */
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list,
|
||||||
}
|
node, us)) {
|
||||||
|
struct pim_rpf rpf;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
rpf.source_nexthop.interface = ifp;
|
||||||
pim = vrf->info;
|
rpf.rpf_addr.u.prefix4 = us->address;
|
||||||
if (!pim)
|
pim_joinprune_send(&rpf, us->us);
|
||||||
continue;
|
pim_jp_agg_clear_group(us->us);
|
||||||
|
|
||||||
FOR_ALL_INTERFACES (pim->vrf, ifp)
|
|
||||||
if (ifp->info) {
|
|
||||||
struct pim_interface *pim_ifp = ifp->info;
|
|
||||||
struct pim_iface_upstream_switch *us;
|
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(
|
|
||||||
pim_ifp->upstream_switch_list,
|
|
||||||
node, us)) {
|
|
||||||
struct pim_rpf rpf;
|
|
||||||
rpf.source_nexthop.interface = ifp;
|
|
||||||
rpf.rpf_addr.u.prefix4 = us->address;
|
|
||||||
pim_joinprune_send(&rpf, us->us);
|
|
||||||
pim_jp_agg_clear_group(us->us);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
|
void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
|
||||||
@ -657,69 +629,57 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pim_scan_oil(struct pim_instance *pim_matcher)
|
void pim_scan_oil(struct pim_instance *pim)
|
||||||
{
|
{
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct listnode *nextnode;
|
struct listnode *nextnode;
|
||||||
struct channel_oil *c_oil;
|
struct channel_oil *c_oil;
|
||||||
ifindex_t ifindex;
|
ifindex_t ifindex;
|
||||||
int vif_index = 0;
|
int vif_index = 0;
|
||||||
struct vrf *vrf;
|
|
||||||
struct pim_instance *pim;
|
|
||||||
|
|
||||||
qpim_scan_oil_last = pim_time_monotonic_sec();
|
pim->scan_oil_last = pim_time_monotonic_sec();
|
||||||
++qpim_scan_oil_events;
|
++pim->scan_oil_events;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
|
||||||
pim = vrf->info;
|
if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) {
|
||||||
if (!pim)
|
ifindex = c_oil->up->rpf.source_nexthop
|
||||||
continue;
|
.interface->ifindex;
|
||||||
|
vif_index =
|
||||||
if (pim_matcher && pim != pim_matcher)
|
pim_if_find_vifindex_by_ifindex(pim, ifindex);
|
||||||
continue;
|
/* Pass Current selected NH vif index to mroute
|
||||||
|
* download */
|
||||||
for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode,
|
if (vif_index)
|
||||||
c_oil)) {
|
pim_scan_individual_oil(c_oil, vif_index);
|
||||||
if (c_oil->up
|
} else
|
||||||
&& c_oil->up->rpf.source_nexthop.interface) {
|
pim_scan_individual_oil(c_oil, 0);
|
||||||
ifindex = c_oil->up->rpf.source_nexthop
|
|
||||||
.interface->ifindex;
|
|
||||||
vif_index = pim_if_find_vifindex_by_ifindex(
|
|
||||||
pim, ifindex);
|
|
||||||
/* Pass Current selected NH vif index to mroute
|
|
||||||
* download */
|
|
||||||
if (vif_index)
|
|
||||||
pim_scan_individual_oil(c_oil,
|
|
||||||
vif_index);
|
|
||||||
} else
|
|
||||||
pim_scan_individual_oil(c_oil, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int on_rpf_cache_refresh(struct thread *t)
|
static int on_rpf_cache_refresh(struct thread *t)
|
||||||
{
|
{
|
||||||
|
struct pim_instance *pim = THREAD_ARG(t);
|
||||||
|
|
||||||
/* update PIM protocol state */
|
/* update PIM protocol state */
|
||||||
scan_upstream_rpf_cache();
|
scan_upstream_rpf_cache(pim);
|
||||||
|
|
||||||
/* update kernel multicast forwarding cache (MFC) */
|
/* update kernel multicast forwarding cache (MFC) */
|
||||||
pim_scan_oil(NULL);
|
pim_scan_oil(pim);
|
||||||
|
|
||||||
qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();
|
pim->rpf_cache_refresh_last = pim_time_monotonic_sec();
|
||||||
++qpim_rpf_cache_refresh_events;
|
++pim->rpf_cache_refresh_events;
|
||||||
|
|
||||||
// It is called as part of pim_neighbor_add
|
// It is called as part of pim_neighbor_add
|
||||||
// pim_rp_setup ();
|
// pim_rp_setup ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_rpf_cache_refresh(void)
|
void sched_rpf_cache_refresh(struct pim_instance *pim)
|
||||||
{
|
{
|
||||||
++qpim_rpf_cache_refresh_requests;
|
++pim->rpf_cache_refresh_requests;
|
||||||
|
|
||||||
pim_rpf_set_refresh_time();
|
pim_rpf_set_refresh_time(pim);
|
||||||
|
|
||||||
if (qpim_rpf_cache_refresher) {
|
if (pim->rpf_cache_refresher) {
|
||||||
/* Refresh timer is already running */
|
/* Refresh timer is already running */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -731,9 +691,9 @@ void sched_rpf_cache_refresh(void)
|
|||||||
qpim_rpf_cache_refresh_delay_msec);
|
qpim_rpf_cache_refresh_delay_msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_add_timer_msec(master, on_rpf_cache_refresh, 0,
|
thread_add_timer_msec(master, on_rpf_cache_refresh, pim,
|
||||||
qpim_rpf_cache_refresh_delay_msec,
|
qpim_rpf_cache_refresh_delay_msec,
|
||||||
&qpim_rpf_cache_refresher);
|
&pim->rpf_cache_refresher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pim_zebra_connected(struct zclient *zclient)
|
static void pim_zebra_connected(struct zclient *zclient)
|
||||||
@ -864,48 +824,40 @@ static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void igmp_source_forward_reevaluate_all(void)
|
void igmp_source_forward_reevaluate_all(struct pim_instance *pim)
|
||||||
{
|
{
|
||||||
struct interface *ifp;
|
struct interface *ifp;
|
||||||
struct vrf *vrf;
|
|
||||||
struct pim_instance *pim;
|
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
||||||
pim = vrf->info;
|
struct pim_interface *pim_ifp = ifp->info;
|
||||||
if (!pim)
|
struct listnode *sock_node;
|
||||||
|
struct igmp_sock *igmp;
|
||||||
|
|
||||||
|
if (!pim_ifp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FOR_ALL_INTERFACES (pim->vrf, ifp) {
|
/* scan igmp sockets */
|
||||||
struct pim_interface *pim_ifp = ifp->info;
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
|
||||||
struct listnode *sock_node;
|
igmp)) {
|
||||||
struct igmp_sock *igmp;
|
struct listnode *grpnode;
|
||||||
|
struct igmp_group *grp;
|
||||||
|
|
||||||
if (!pim_ifp)
|
/* scan igmp groups */
|
||||||
continue;
|
for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
|
||||||
|
grpnode, grp)) {
|
||||||
|
struct listnode *srcnode;
|
||||||
|
struct igmp_source *src;
|
||||||
|
|
||||||
/* scan igmp sockets */
|
/* scan group sources */
|
||||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list,
|
for (ALL_LIST_ELEMENTS_RO(
|
||||||
sock_node, igmp)) {
|
grp->group_source_list, srcnode,
|
||||||
struct listnode *grpnode;
|
src)) {
|
||||||
struct igmp_group *grp;
|
igmp_source_forward_reevaluate_one(pim,
|
||||||
|
src);
|
||||||
/* scan igmp groups */
|
} /* scan group sources */
|
||||||
for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list,
|
} /* scan igmp groups */
|
||||||
grpnode, grp)) {
|
} /* scan igmp sockets */
|
||||||
struct listnode *srcnode;
|
} /* scan interfaces */
|
||||||
struct igmp_source *src;
|
|
||||||
|
|
||||||
/* scan group sources */
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(
|
|
||||||
grp->group_source_list,
|
|
||||||
srcnode, src)) {
|
|
||||||
igmp_source_forward_reevaluate_one(
|
|
||||||
pim, src);
|
|
||||||
} /* scan group sources */
|
|
||||||
} /* scan igmp groups */
|
|
||||||
} /* scan igmp sockets */
|
|
||||||
} /* scan interfaces */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void igmp_source_forward_start(struct pim_instance *pim,
|
void igmp_source_forward_start(struct pim_instance *pim,
|
||||||
|
@ -39,11 +39,11 @@ void igmp_anysource_forward_stop(struct igmp_group *group);
|
|||||||
void igmp_source_forward_start(struct pim_instance *pim,
|
void igmp_source_forward_start(struct pim_instance *pim,
|
||||||
struct igmp_source *source);
|
struct igmp_source *source);
|
||||||
void igmp_source_forward_stop(struct igmp_source *source);
|
void igmp_source_forward_stop(struct igmp_source *source);
|
||||||
void igmp_source_forward_reevaluate_all(void);
|
void igmp_source_forward_reevaluate_all(struct pim_instance *pim);
|
||||||
|
|
||||||
void pim_forward_start(struct pim_ifchannel *ch);
|
void pim_forward_start(struct pim_ifchannel *ch);
|
||||||
void pim_forward_stop(struct pim_ifchannel *ch, bool install_it);
|
void pim_forward_stop(struct pim_ifchannel *ch, bool install_it);
|
||||||
|
|
||||||
void sched_rpf_cache_refresh(void);
|
void sched_rpf_cache_refresh(struct pim_instance *pim);
|
||||||
struct zclient *pim_zebra_zclient_get(void);
|
struct zclient *pim_zebra_zclient_get(void);
|
||||||
#endif /* PIM_ZEBRA_H */
|
#endif /* PIM_ZEBRA_H */
|
||||||
|
@ -352,7 +352,7 @@ int zclient_lookup_nexthop(struct pim_instance *pim,
|
|||||||
uint32_t route_metric = 0xFFFFFFFF;
|
uint32_t route_metric = 0xFFFFFFFF;
|
||||||
uint8_t protocol_distance = 0xFF;
|
uint8_t protocol_distance = 0xFF;
|
||||||
|
|
||||||
qpim_nexthop_lookups++;
|
pim->nexthop_lookups++;
|
||||||
|
|
||||||
for (lookup = 0; lookup < max_lookup; ++lookup) {
|
for (lookup = 0; lookup < max_lookup; ++lookup) {
|
||||||
int num_ifindex;
|
int num_ifindex;
|
||||||
|
@ -52,13 +52,6 @@ int qpim_t_periodic =
|
|||||||
PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
|
PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
|
||||||
struct pim_assert_metric qpim_infinite_assert_metric;
|
struct pim_assert_metric qpim_infinite_assert_metric;
|
||||||
long qpim_rpf_cache_refresh_delay_msec = 50;
|
long qpim_rpf_cache_refresh_delay_msec = 50;
|
||||||
struct thread *qpim_rpf_cache_refresher = NULL;
|
|
||||||
int64_t qpim_rpf_cache_refresh_requests = 0;
|
|
||||||
int64_t qpim_rpf_cache_refresh_events = 0;
|
|
||||||
int64_t qpim_rpf_cache_refresh_last = 0;
|
|
||||||
int64_t qpim_scan_oil_events = 0;
|
|
||||||
int64_t qpim_scan_oil_last = 0;
|
|
||||||
int64_t qpim_nexthop_lookups = 0;
|
|
||||||
int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
|
int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
|
||||||
uint8_t qpim_ecmp_enable = 0;
|
uint8_t qpim_ecmp_enable = 0;
|
||||||
uint8_t qpim_ecmp_rebalance_enable = 0;
|
uint8_t qpim_ecmp_rebalance_enable = 0;
|
||||||
|
@ -140,13 +140,6 @@ struct in_addr qpim_all_pim_routers_addr;
|
|||||||
int qpim_t_periodic; /* Period between Join/Prune Messages */
|
int qpim_t_periodic; /* Period between Join/Prune Messages */
|
||||||
struct pim_assert_metric qpim_infinite_assert_metric;
|
struct pim_assert_metric qpim_infinite_assert_metric;
|
||||||
long qpim_rpf_cache_refresh_delay_msec;
|
long qpim_rpf_cache_refresh_delay_msec;
|
||||||
struct thread *qpim_rpf_cache_refresher;
|
|
||||||
int64_t qpim_rpf_cache_refresh_requests;
|
|
||||||
int64_t qpim_rpf_cache_refresh_events;
|
|
||||||
int64_t qpim_rpf_cache_refresh_last;
|
|
||||||
int64_t qpim_scan_oil_events;
|
|
||||||
int64_t qpim_scan_oil_last;
|
|
||||||
int64_t qpim_nexthop_lookups;
|
|
||||||
extern int qpim_packet_process;
|
extern int qpim_packet_process;
|
||||||
extern uint8_t qpim_ecmp_enable;
|
extern uint8_t qpim_ecmp_enable;
|
||||||
extern uint8_t qpim_ecmp_rebalance_enable;
|
extern uint8_t qpim_ecmp_rebalance_enable;
|
||||||
|
Loading…
Reference in New Issue
Block a user