summaryrefslogtreecommitdiff
path: root/pimd/pim_bsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'pimd/pim_bsm.c')
-rw-r--r--pimd/pim_bsm.c269
1 files changed, 172 insertions, 97 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index a3a3426f39..238c19d2cc 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -35,6 +35,7 @@
#include "pim_nht.h"
#include "pim_bsm.h"
#include "pim_time.h"
+#include "pim_zebra.h"
/* Functions forward declaration */
static void pim_bs_timer_start(struct bsm_scope *scope, int bs_timeout);
@@ -70,7 +71,7 @@ static void pim_bsm_rpinfo_free(struct bsm_rpinfo *bsrp_info)
XFREE(MTYPE_PIM_BSRP_INFO, bsrp_info);
}
-void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
+static void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
{
struct bsm_rpinfo *bsrp_info;
@@ -78,14 +79,14 @@ void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
pim_bsm_rpinfo_free(bsrp_info);
}
-void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
+static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
{
pim_bsm_rpinfos_free(bsgrp_node->bsrp_list);
pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
}
-void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
+static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
{
struct route_node *rn;
@@ -102,7 +103,7 @@ static void pim_bsm_frag_free(struct bsm_frag *bsfrag)
XFREE(MTYPE_PIM_BSM_FRAG, bsfrag);
}
-void pim_bsm_frags_free(struct bsm_scope *scope)
+static void pim_bsm_frags_free(struct bsm_scope *scope)
{
struct bsm_frag *bsfrag;
@@ -162,8 +163,6 @@ static int pim_on_bs_timer(struct thread *t)
struct bsm_scope *scope;
struct bsgrp_node *bsgrp_node;
struct bsm_rpinfo *bsrp;
- struct prefix nht_p;
- bool is_bsr_tracking = true;
scope = THREAD_ARG(t);
THREAD_OFF(scope->bs_timer);
@@ -172,15 +171,7 @@ static int pim_on_bs_timer(struct thread *t)
zlog_debug("%s: Bootstrap Timer expired for scope: %d",
__func__, scope->sz_id);
- /* Remove next hop tracking for the bsr */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
- nht_p.u.prefix4 = scope->current_bsr;
- if (PIM_DEBUG_BSM)
- zlog_debug("%s: Deregister BSR addr %pFX with Zebra NHT",
- __func__, &nht_p);
- pim_delete_tracked_nexthop(scope->pim, &nht_p, NULL, NULL,
- is_bsr_tracking);
+ pim_nht_bsr_del(scope->pim, scope->current_bsr);
/* Reset scope zone data */
scope->accept_nofwd_bsm = false;
@@ -212,7 +203,7 @@ static int pim_on_bs_timer(struct thread *t)
return 0;
}
-void pim_bs_timer_stop(struct bsm_scope *scope)
+static void pim_bs_timer_stop(struct bsm_scope *scope)
{
if (PIM_DEBUG_BSM)
zlog_debug("%s : BS timer being stopped of sz: %d", __func__,
@@ -543,35 +534,6 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
}
-static bool pim_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr,
- struct in_addr ip_src_addr)
-{
- struct pim_nexthop nexthop;
- int result;
-
- memset(&nexthop, 0, sizeof(nexthop));
-
- /* New BSR recived */
- if (bsr.s_addr != pim->global_scope.current_bsr.s_addr) {
- result = pim_nexthop_match(pim, bsr, ip_src_addr);
-
- /* Nexthop lookup pass for the new BSR address */
- if (result)
- return true;
-
- if (PIM_DEBUG_BSM) {
- char bsr_str[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<bsr?>", bsr, bsr_str, sizeof(bsr_str));
- zlog_debug("%s : No route to BSR address %s", __func__,
- bsr_str);
- }
- return false;
- }
-
- return pim_nexthop_match_nht_cache(pim, bsr, ip_src_addr);
-}
-
static bool is_preferred_bsr(struct pim_instance *pim, struct in_addr bsr,
uint32_t bsr_prio)
{
@@ -594,35 +556,11 @@ static bool is_preferred_bsr(struct pim_instance *pim, struct in_addr bsr,
static void pim_bsm_update(struct pim_instance *pim, struct in_addr bsr,
uint32_t bsr_prio)
{
- struct pim_nexthop_cache pnc;
-
if (bsr.s_addr != pim->global_scope.current_bsr.s_addr) {
- struct prefix nht_p;
- bool is_bsr_tracking = true;
-
- /* De-register old BSR and register new BSR with Zebra NHT */
- nht_p.family = AF_INET;
- nht_p.prefixlen = IPV4_MAX_BITLEN;
+ if (pim->global_scope.current_bsr.s_addr)
+ pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
+ pim_nht_bsr_add(pim, bsr);
- if (pim->global_scope.current_bsr.s_addr != INADDR_ANY) {
- nht_p.u.prefix4 = pim->global_scope.current_bsr;
- if (PIM_DEBUG_BSM)
- zlog_debug(
- "%s: Deregister BSR addr %pFX with Zebra NHT",
- __func__, &nht_p);
- pim_delete_tracked_nexthop(pim, &nht_p, NULL, NULL,
- is_bsr_tracking);
- }
-
- nht_p.u.prefix4 = bsr;
- if (PIM_DEBUG_BSM)
- zlog_debug(
- "%s: NHT Register BSR addr %pFX with Zebra NHT",
- __func__, &nht_p);
-
- memset(&pnc, 0, sizeof(struct pim_nexthop_cache));
- pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL,
- is_bsr_tracking, &pnc);
pim->global_scope.current_bsr = bsr;
pim->global_scope.current_bsr_first_ts =
pim_time_monotonic_sec();
@@ -632,6 +570,127 @@ static void pim_bsm_update(struct pim_instance *pim, struct in_addr bsr,
pim->global_scope.current_bsr_last_ts = pim_time_monotonic_sec();
}
+void pim_bsm_clear(struct pim_instance *pim)
+{
+ struct route_node *rn;
+ struct route_node *rpnode;
+ struct bsgrp_node *bsgrp;
+ struct prefix nht_p;
+ struct prefix g_all;
+ struct rp_info *rp_all;
+ struct pim_upstream *up;
+ struct rp_info *rp_info;
+ bool upstream_updated = false;
+
+ if (pim->global_scope.current_bsr.s_addr)
+ pim_nht_bsr_del(pim, pim->global_scope.current_bsr);
+
+ /* Reset scope zone data */
+ pim->global_scope.accept_nofwd_bsm = false;
+ pim->global_scope.state = ACCEPT_ANY;
+ pim->global_scope.current_bsr.s_addr = INADDR_ANY;
+ pim->global_scope.current_bsr_prio = 0;
+ pim->global_scope.current_bsr_first_ts = 0;
+ pim->global_scope.current_bsr_last_ts = 0;
+ pim->global_scope.bsm_frag_tag = 0;
+ pim_bsm_frags_free(&pim->global_scope);
+
+ pim_bs_timer_stop(&pim->global_scope);
+
+ for (rn = route_top(pim->global_scope.bsrp_table); rn;
+ rn = route_next(rn)) {
+ bsgrp = rn->info;
+ if (!bsgrp)
+ continue;
+
+ rpnode = route_node_lookup(pim->rp_table, &bsgrp->group);
+
+ if (!rpnode) {
+ pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
+ &bsgrp->group);
+ pim_free_bsgrp_data(bsgrp);
+ continue;
+ }
+
+ rp_info = (struct rp_info *)rpnode->info;
+
+ if ((!rp_info) || (rp_info->rp_src != RP_SRC_BSR)) {
+ pim_free_bsgrp_node(bsgrp->scope->bsrp_table,
+ &bsgrp->group);
+ pim_free_bsgrp_data(bsgrp);
+ continue;
+ }
+
+ /* Deregister addr with Zebra NHT */
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4;
+
+ if (PIM_DEBUG_PIM_NHT_RP) {
+ zlog_debug("%s: Deregister RP addr %pFX with Zebra ",
+ __func__, &nht_p);
+ }
+
+ pim_delete_tracked_nexthop(pim, &nht_p, NULL, rp_info);
+
+ if (!str2prefix("224.0.0.0/4", &g_all))
+ return;
+
+ rp_all = pim_rp_find_match_group(pim, &g_all);
+
+ if (rp_all == rp_info) {
+ rp_all->rp.rpf_addr.family = AF_INET;
+ rp_all->rp.rpf_addr.u.prefix4.s_addr = INADDR_NONE;
+ rp_all->i_am_rp = 0;
+ } else {
+ /* Delete the rp_info from rp-list */
+ listnode_delete(pim->rp_list, rp_info);
+
+ /* Delete the rp node from rp_table */
+ rpnode->info = NULL;
+ route_unlock_node(rpnode);
+ route_unlock_node(rpnode);
+ XFREE(MTYPE_PIM_RP, rp_info);
+ }
+
+ pim_free_bsgrp_node(bsgrp->scope->bsrp_table, &bsgrp->group);
+ pim_free_bsgrp_data(bsgrp);
+ }
+ pim_rp_refresh_group_to_rp_mapping(pim);
+
+
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ /* Find the upstream (*, G) whose upstream address is same as
+ * the RP
+ */
+ if (up->sg.src.s_addr != INADDR_ANY)
+ continue;
+
+ struct prefix grp;
+ struct rp_info *trp_info;
+
+ grp.family = AF_INET;
+ grp.prefixlen = IPV4_MAX_BITLEN;
+ grp.u.prefix4 = up->sg.grp;
+
+ trp_info = pim_rp_find_match_group(pim, &grp);
+
+ /* RP not found for the group grp */
+ if (pim_rpf_addr_is_inaddr_none(&trp_info->rp)) {
+ pim_upstream_rpf_clear(pim, up);
+ pim_rp_set_upstream_addr(pim, &up->upstream_addr,
+ up->sg.src, up->sg.grp);
+ } else {
+ /* RP found for the group grp */
+ pim_upstream_update(pim, up);
+ upstream_updated = true;
+ }
+ }
+
+ if (upstream_updated)
+ pim_zebra_update_all_interfaces(pim);
+}
+
static bool pim_bsm_send_intf(uint8_t *buf, int len, struct interface *ifp,
struct in_addr dst_addr)
{
@@ -1115,18 +1174,6 @@ static bool pim_bsm_parse_install_g2rp(struct bsm_scope *scope, uint8_t *buf,
buf += sizeof(struct bsmmsg_grpinfo);
offset += sizeof(struct bsmmsg_grpinfo);
- if (grpinfo.rp_count == 0) {
- if (PIM_DEBUG_BSM) {
- char grp_str[INET_ADDRSTRLEN];
-
- pim_inet4_dump("<Group?>", grpinfo.group.addr,
- grp_str, sizeof(grp_str));
- zlog_debug("%s, Rp count is zero for group: %s",
- __func__, grp_str);
- }
- return false;
- }
-
group.family = AF_INET;
if (grpinfo.group.mask > IPV4_MAX_BITLEN) {
if (PIM_DEBUG_BSM)
@@ -1141,6 +1188,32 @@ static bool pim_bsm_parse_install_g2rp(struct bsm_scope *scope, uint8_t *buf,
/* Get the Group node for the BSM rp table */
bsgrp = pim_bsm_get_bsgrp_node(scope, &group);
+ if (grpinfo.rp_count == 0) {
+ struct bsm_rpinfo *old_rpinfo;
+
+ /* BSR explicitly no longer has RPs for this group */
+ if (!bsgrp)
+ continue;
+
+ if (PIM_DEBUG_BSM) {
+ char grp_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<Group?>", grpinfo.group.addr,
+ grp_str, sizeof(grp_str));
+ zlog_debug("%s, Rp count is zero for group: %s",
+ __func__, grp_str);
+ }
+
+ old_rpinfo = bsm_rpinfos_first(bsgrp->bsrp_list);
+ if (old_rpinfo)
+ pim_rp_del(scope->pim, old_rpinfo->rp_address,
+ group, NULL, RP_SRC_BSR);
+
+ pim_free_bsgrp_node(scope->bsrp_table, &bsgrp->group);
+ pim_free_bsgrp_data(bsgrp);
+ continue;
+ }
+
if (!bsgrp) {
if (PIM_DEBUG_BSM)
zlog_debug("%s, Create new BSM Group node.",
@@ -1310,21 +1383,23 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf,
}
}
- /* Mulicast BSM received */
if (ip_hdr->ip_dst.s_addr == qpim_all_pim_routers_addr.s_addr) {
- if (!no_fwd) {
- if (!pim_bsr_rpf_check(pim, bshdr->bsr_addr.addr,
- ip_hdr->ip_src)) {
- if (PIM_DEBUG_BSM)
- zlog_debug(
- "%s : RPF check fail for BSR address %s",
- __func__, bsr_str);
- pim->bsm_dropped++;
- return -1;
- }
+ /* Multicast BSMs are only accepted if source interface & IP
+ * match RPF towards the BSR's IP address, or they have
+ * no-forward set
+ */
+ if (!no_fwd
+ && !pim_nht_bsr_rpf_check(pim, bshdr->bsr_addr.addr, ifp,
+ ip_hdr->ip_src)) {
+ if (PIM_DEBUG_BSM)
+ zlog_debug(
+ "BSM check: RPF to BSR %s is not %pI4%%%s",
+ bsr_str, &ip_hdr->ip_src, ifp->name);
+ pim->bsm_dropped++;
+ return -1;
}
- } else if (if_lookup_exact_address(&ip_hdr->ip_dst, AF_INET,
- pim->vrf->vrf_id)) {
+ } else if (if_address_is_local(&ip_hdr->ip_dst, AF_INET,
+ pim->vrf->vrf_id)) {
/* Unicast BSM received - if ucast bsm not enabled on
* the interface, drop it
*/