summaryrefslogtreecommitdiff
path: root/pimd
diff options
context:
space:
mode:
Diffstat (limited to 'pimd')
-rw-r--r--pimd/pim_bsm.c6
-rw-r--r--pimd/pim_bsm.h3
-rw-r--r--pimd/pim_cmd.c169
-rw-r--r--pimd/pim_ifchannel.c28
-rw-r--r--pimd/pim_igmp.c4
-rw-r--r--pimd/pim_igmpv2.c31
-rw-r--r--pimd/pim_igmpv2.h2
-rw-r--r--pimd/pim_mroute.c2
-rw-r--r--pimd/pim_rp.c4
-rw-r--r--pimd/pim_rp.h1
-rw-r--r--pimd/pim_static.c2
-rw-r--r--pimd/pim_upstream.c7
-rw-r--r--pimd/pim_vty.c7
-rw-r--r--pimd/pim_vxlan.h2
14 files changed, 242 insertions, 26 deletions
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 1acfece895..e873af5759 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -63,7 +63,7 @@ void pim_bsm_write_config(struct vty *vty, struct interface *ifp)
}
}
-static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
+void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
{
if (bsgrp_node->bsrp_list)
list_delete(&bsgrp_node->bsrp_list);
@@ -72,7 +72,7 @@ static void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
}
-static void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
+void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
{
struct route_node *rn;
@@ -222,7 +222,7 @@ static int pim_on_bs_timer(struct thread *t)
return 0;
}
-static void pim_bs_timer_stop(struct bsm_scope *scope)
+void pim_bs_timer_stop(struct bsm_scope *scope)
{
if (PIM_DEBUG_BSM)
zlog_debug("%s : BS timer being stopped of sz: %d", __func__,
diff --git a/pimd/pim_bsm.h b/pimd/pim_bsm.h
index 0758c94f19..2829c1e05a 100644
--- a/pimd/pim_bsm.h
+++ b/pimd/pim_bsm.h
@@ -195,4 +195,7 @@ int pim_bsm_process(struct interface *ifp,
bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp);
struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
struct prefix *grp);
+void pim_bs_timer_stop(struct bsm_scope *scope);
+void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node);
+void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp);
#endif
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 6d01cc73d7..ff85151839 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -4001,6 +4001,152 @@ DEFUN (clear_ip_pim_oil,
return CMD_SUCCESS;
}
+static void clear_pim_bsr_db(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 is_bsr_tracking = true;
+
+ /* Remove next hop tracking for the bsr */
+ nht_p.family = AF_INET;
+ nht_p.prefixlen = IPV4_MAX_BITLEN;
+ 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);
+
+ /* 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;
+ list_delete_all_node(pim->global_scope.bsm_list);
+
+ 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, false);
+
+ 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);
+ }
+ }
+}
+
+
+DEFUN (clear_ip_pim_bsr_db,
+ clear_ip_pim_bsr_db_cmd,
+ "clear ip pim [vrf NAME] bsr-data",
+ CLEAR_STR
+ IP_STR
+ CLEAR_IP_PIM_STR
+ VRF_CMD_HELP_STR
+ "Reset pim bsr data\n")
+{
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+
+ if (!vrf)
+ return CMD_WARNING;
+
+ clear_pim_bsr_db(vrf->info);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (show_ip_igmp_interface,
show_ip_igmp_interface_cmd,
"show ip igmp [vrf NAME] interface [detail|WORD] [json]",
@@ -4560,8 +4706,8 @@ DEFPY (show_ip_pim_join,
return CMD_WARNING;
}
- if (s_or_g.s_addr != 0) {
- if (g.s_addr != 0) {
+ if (s_or_g.s_addr != INADDR_ANY) {
+ if (g.s_addr != INADDR_ANY) {
sg.src = s_or_g;
sg.grp = g;
} else
@@ -5180,8 +5326,8 @@ DEFPY (show_ip_pim_upstream,
return CMD_WARNING;
}
- if (s_or_g.s_addr != 0) {
- if (g.s_addr != 0) {
+ if (s_or_g.s_addr != INADDR_ANY) {
+ if (g.s_addr != INADDR_ANY) {
sg.src = s_or_g;
sg.grp = g;
} else
@@ -5858,7 +6004,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
vty_out(vty, "IP Multicast Routing Table\n");
vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
vty_out(vty,
- " R - RP-bit set, F - Register flag, T - SPT-bit set\n");
+ " R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
vty_out(vty,
"\nSource Group Flags Proto Input Output TTL Uptime\n");
}
@@ -5872,11 +6018,11 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
if (!c_oil->installed)
continue;
- if (sg->grp.s_addr != 0 &&
- sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
+ if (sg->grp.s_addr != INADDR_ANY
+ && sg->grp.s_addr != c_oil->oil.mfcc_mcastgrp.s_addr)
continue;
- if (sg->src.s_addr != 0 &&
- sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr)
+ if (sg->src.s_addr != INADDR_ANY
+ && sg->src.s_addr != c_oil->oil.mfcc_origin.s_addr)
continue;
pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, grp_str,
@@ -6232,8 +6378,8 @@ DEFPY (show_ip_mroute,
return CMD_WARNING;
}
- if (s_or_g.s_addr != 0) {
- if (g.s_addr != 0) {
+ if (s_or_g.s_addr != INADDR_ANY) {
+ if (g.s_addr != INADDR_ANY) {
sg.src = s_or_g;
sg.grp = g;
} else
@@ -11396,6 +11542,7 @@ void pim_cmd_init(void)
install_element(ENABLE_NODE, &clear_ip_pim_interface_traffic_cmd);
install_element(ENABLE_NODE, &clear_ip_pim_oil_cmd);
install_element(ENABLE_NODE, &clear_ip_pim_statistics_cmd);
+ install_element(ENABLE_NODE, &clear_ip_pim_bsr_db_cmd);
install_element(ENABLE_NODE, &show_debugging_pim_cmd);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index e7ff434f4b..fc0f514a49 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -550,8 +550,21 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
struct pim_upstream *up;
ch = pim_ifchannel_find(ifp, sg);
- if (ch)
+ if (ch) {
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
+ PIM_IF_FLAG_SET_PROTO_PIM(ch->flags);
+
+ if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags);
+
+ if (ch->upstream)
+ ch->upstream->flags |= up_flags;
+ else if (PIM_DEBUG_EVENTS)
+ zlog_debug("%s:%s No Upstream found", __func__,
+ pim_str_sg_dump(sg));
+
return ch;
+ }
pim_ifp = ifp->info;
@@ -642,6 +655,12 @@ static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)
{
pim_forward_stop(ch, !ch_del);
pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
+
+ if (ch->upstream)
+ PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags);
+
+ PIM_IF_FLAG_UNSET_PROTO_PIM(ch->flags);
+
if (ch_del)
delete_on_noinfo(ch);
}
@@ -1272,6 +1291,13 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
* parent' delete_no_info */
}
}
+
+ /* Resettng the IGMP flags here */
+ if (orig->upstream)
+ PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(orig->upstream->flags);
+
+ PIM_IF_FLAG_UNSET_PROTO_IGMP(orig->flags);
+
delete_on_noinfo(orig);
}
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 9924e335b0..73e42e9d83 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -558,8 +558,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
igmp_msg, igmp_msg_len);
case PIM_IGMP_V2_LEAVE_GROUP:
- return igmp_v2_recv_leave(igmp, ip_hdr->ip_src, from_str,
- igmp_msg, igmp_msg_len);
+ return igmp_v2_recv_leave(igmp, ip_hdr, from_str, igmp_msg,
+ igmp_msg_len);
case PIM_IGMP_MTRACE_RESPONSE:
return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src,
diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c
index d836c66cbb..7f3c7a0f8c 100644
--- a/pimd/pim_igmpv2.c
+++ b/pimd/pim_igmpv2.c
@@ -158,12 +158,13 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
return 0;
}
-int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
+int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr,
const char *from_str, char *igmp_msg, int igmp_msg_len)
{
struct interface *ifp = igmp->interface;
struct in_addr group_addr;
char group_str[INET_ADDRSTRLEN];
+ struct in_addr from = ip_hdr->ip_src;
on_trace(__func__, igmp->interface, from);
@@ -184,8 +185,6 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
return -1;
}
- /* Collecting IGMP Rx stats */
- igmp->rx_stats.leave_v2++;
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
@@ -195,6 +194,32 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str,
ifp->name, group_str);
}
+ /*
+ * As per RFC 2236, section 9:
+ Message Type Destination Group
+ ------------ -----------------
+ General Query ALL-SYSTEMS (224.0.0.1)
+ Group-Specific Query The group being queried
+ Membership Report The group being reported
+ Leave Message ALL-ROUTERS (224.0.0.2)
+
+ Note: in older (i.e., non-standard and now obsolete) versions of
+ IGMPv2, hosts send Leave Messages to the group being left. A
+ router SHOULD accept Leave Messages addressed to the group being
+ left in the interests of backwards compatibility with such hosts.
+ In all cases, however, hosts MUST send to the ALL-ROUTERS address
+ to be compliant with this specification.
+ */
+ if ((ntohl(ip_hdr->ip_dst.s_addr) != INADDR_ALLRTRS_GROUP)
+ && (ip_hdr->ip_dst.s_addr != group_addr.s_addr)) {
+ if (PIM_DEBUG_IGMP_EVENTS)
+ zlog_debug(
+ "IGMPv2 Leave message is ignored since received on address other than ALL-ROUTERS or Group-address");
+ return -1;
+ }
+
+ /* Collecting IGMP Rx stats */
+ igmp->rx_stats.leave_v2++;
/*
* RFC 3376
diff --git a/pimd/pim_igmpv2.h b/pimd/pim_igmpv2.h
index f0a6fdc5fb..29591ff16c 100644
--- a/pimd/pim_igmpv2.h
+++ b/pimd/pim_igmpv2.h
@@ -29,7 +29,7 @@ void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname,
int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
const char *from_str, char *igmp_msg, int igmp_msg_len);
-int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
+int igmp_v2_recv_leave(struct igmp_sock *igmp, struct ip *ip_hdr,
const char *from_str, char *igmp_msg, int igmp_msg_len);
#endif /* PIM_IGMPV2_H */
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 0bccba397b..23259900b7 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -628,7 +628,7 @@ static int pim_mroute_msg(struct pim_instance *pim, const char *buf,
ifaddr = connected_src->u.prefix4;
igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
- if (PIM_DEBUG_MROUTE) {
+ if (PIM_DEBUG_IGMP_PACKETS) {
zlog_debug(
"%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4",
__func__, pim->vrf->name, ifp->name, igmp,
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 727daa42c1..301a27001f 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -271,7 +271,7 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
*
* This is a placeholder function for now.
*/
-static void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim)
+void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim)
{
pim_msdp_i_am_rp_changed(pim);
pim_upstream_reeval_use_rpt(pim);
@@ -1319,7 +1319,7 @@ void pim_resolve_rp_nh(struct pim_instance *pim, struct pim_neighbor *nbr)
continue;
for (nh_node = pnc.nexthop; nh_node; nh_node = nh_node->next) {
- if (nh_node->gate.ipv4.s_addr != 0)
+ if (nh_node->gate.ipv4.s_addr != INADDR_ANY)
continue;
struct interface *ifp1 = if_lookup_by_index(
diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h
index 8a12cb076c..dd7cd5d75e 100644
--- a/pimd/pim_rp.h
+++ b/pimd/pim_rp.h
@@ -86,4 +86,5 @@ int pim_rp_list_cmp(void *v1, void *v2);
struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
const struct prefix *group);
void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up);
+void pim_rp_refresh_group_to_rp_mapping(struct pim_instance *pim);
#endif
diff --git a/pimd/pim_static.c b/pimd/pim_static.c
index 91c9b5b933..63a9a00659 100644
--- a/pimd/pim_static.c
+++ b/pimd/pim_static.c
@@ -345,7 +345,7 @@ int pim_static_write_mroute(struct pim_instance *pim, struct vty *vty,
struct interface *oifp =
pim_if_find_by_vif_index(pim,
i);
- if (sroute->source.s_addr == 0)
+ if (sroute->source.s_addr == INADDR_ANY)
vty_out(vty,
" ip mroute %s %s\n",
oifp->name, gbuf);
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index d95b092d94..9899172e6c 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -749,6 +749,13 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
bool send_xg_jp = false;
forward_off(up);
+ /*
+ * RFC 4601 Sec 4.5.7:
+ * JoinDesired(S,G) -> False, set SPTbit to false.
+ */
+ if (up->sg.src.s_addr != INADDR_ANY)
+ up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE;
+
if (old_state == PIM_UPSTREAM_JOINED)
pim_msdp_up_join_state_changed(pim, up);
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 1f2ca11db3..57a0c69166 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -275,6 +275,13 @@ int pim_interface_config_write(struct vty *vty)
continue;
FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ /* pim is enabled internally/implicitly on the vxlan
+ * termination device ipmr-lo. skip displaying that
+ * config to avoid confusion
+ */
+ if (pim_vxlan_is_term_dev_cfg(pim, ifp))
+ continue;
+
/* IF name */
if (vrf->vrf_id == VRF_DEFAULT)
vty_frame(vty, "interface %s\n", ifp->name);
diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h
index 18f1b74175..ce9054cd26 100644
--- a/pimd/pim_vxlan.h
+++ b/pimd/pim_vxlan.h
@@ -109,7 +109,7 @@ struct pim_vxlan {
*/
static inline bool pim_vxlan_is_orig_mroute(struct pim_vxlan_sg *vxlan_sg)
{
- return (vxlan_sg->sg.src.s_addr != 0);
+ return (vxlan_sg->sg.src.s_addr != INADDR_ANY);
}
static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)