summaryrefslogtreecommitdiff
path: root/pimd
diff options
context:
space:
mode:
Diffstat (limited to 'pimd')
-rw-r--r--pimd/pim_bfd.c6
-rw-r--r--pimd/pim_bsm.c6
-rw-r--r--pimd/pim_bsm.h3
-rw-r--r--pimd/pim_cmd.c151
-rw-r--r--pimd/pim_hello.c16
-rw-r--r--pimd/pim_ifchannel.c61
-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_instance.c8
-rw-r--r--pimd/pim_jp_agg.c26
-rw-r--r--pimd/pim_mroute.c9
-rw-r--r--pimd/pim_msdp_socket.c4
-rw-r--r--pimd/pim_nb_config.c3
-rw-r--r--pimd/pim_rp.c4
-rw-r--r--pimd/pim_rp.h1
-rw-r--r--pimd/pim_upstream.c7
-rw-r--r--pimd/pim_vxlan.c22
-rw-r--r--pimd/test_igmpv3_join.c5
19 files changed, 298 insertions, 71 deletions
diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c
index 1d653cdc3f..5e1b9a69e1 100644
--- a/pimd/pim_bfd.c
+++ b/pimd/pim_bfd.c
@@ -217,7 +217,7 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
{
struct interface *ifp = NULL;
struct pim_interface *pim_ifp = NULL;
- struct prefix p;
+ struct prefix p, src_p;
int status;
char msg[100];
int old_status;
@@ -227,8 +227,8 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
struct listnode *neigh_nextnode = NULL;
struct pim_neighbor *neigh = NULL;
- ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status,
- NULL, vrf_id);
+ ifp = bfd_get_peer_info(zclient->ibuf, &p, &src_p, &status, NULL,
+ vrf_id);
if ((ifp == NULL) || (p.family != AF_INET))
return 0;
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 8e08dc724b..714d6e8e1d 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -4049,6 +4049,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]",
@@ -10927,9 +11073,9 @@ static void pim_show_vxlan_sg_entry(struct pim_vxlan_sg *vxlan_sg,
}
}
-static void pim_show_vxlan_sg_hash_entry(struct hash_bucket *backet, void *arg)
+static void pim_show_vxlan_sg_hash_entry(struct hash_bucket *bucket, void *arg)
{
- pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)backet->data,
+ pim_show_vxlan_sg_entry((struct pim_vxlan_sg *)bucket->data,
(struct pim_sg_cache_walk_data *)arg);
}
@@ -11447,6 +11593,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_hello.c b/pimd/pim_hello.c
index e50504ec10..6f5c4174e2 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -95,22 +95,6 @@ static void tlv_trace_uint32_hex(const char *label, const char *tlv_name,
}
}
-#if 0
-static void tlv_trace(const char *label, const char *tlv_name,
- const char *ifname, struct in_addr src_addr,
- int isset)
-{
- if (isset) {
- char src_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
- zlog_debug("%s: PIM hello option from %s on interface %s: %s",
- label,
- src_str, ifname,
- tlv_name);
- }
-}
-#endif
-
static void tlv_trace_list(const char *label, const char *tlv_name,
const char *ifname, struct in_addr src_addr,
int isset, struct list *addr_list)
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index e7ff434f4b..cdaf7bcdd4 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);
}
@@ -710,6 +729,21 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
pim_jp_agg_single_upstream_send(&parent->rpf,
parent, true);
+ /*
+ * SGRpt prune pending expiry has to install
+ * SG entry with empty olist to drop the SG
+ * traffic incase no other intf exists.
+ * On that scenario, SG entry wouldn't have
+ * got installed until Prune pending timer
+ * expired. So install now.
+ */
+ pim_channel_del_oif(
+ ch->upstream->channel_oil, ifp,
+ PIM_OIF_FLAG_PROTO_STAR, __func__);
+ if (!ch->upstream->channel_oil->installed)
+ pim_upstream_mroute_add(
+ ch->upstream->channel_oil,
+ __PRETTY_FUNCTION__);
}
}
/* from here ch may have been deleted */
@@ -1094,6 +1128,24 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
case PIM_IFJOIN_PRUNE:
if (source_flags & PIM_ENCODE_RPT_BIT) {
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
+ /*
+ * While in Prune State, Receive SGRpt Prune.
+ * RFC 7761 Sec 4.5.3:
+ * The (S,G,rpt) downstream state machine on interface I
+ * remains in Prune state. The Expiry Timer (ET) is
+ * restarted and is then set to the maximum of its
+ * current value and the HoldTime from the triggering
+ * Join/Prune message.
+ */
+ if (ch->t_ifjoin_expiry_timer) {
+ unsigned long rem = thread_timer_remain_second(
+ ch->t_ifjoin_expiry_timer);
+
+ if (rem > holdtime)
+ return;
+ THREAD_OFF(ch->t_ifjoin_expiry_timer);
+ }
+
thread_add_timer(router->master, on_ifjoin_expiry_timer,
ch, holdtime,
&ch->t_ifjoin_expiry_timer);
@@ -1272,6 +1324,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_instance.c b/pimd/pim_instance.c
index b7e49078ef..019048abf1 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -71,6 +71,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
+
+ pim->vrf = NULL;
XFREE(MTYPE_PIM_PIM_INSTANCE, pim);
}
@@ -153,10 +155,16 @@ static int pim_vrf_delete(struct vrf *vrf)
{
struct pim_instance *pim = vrf->info;
+ if (!pim)
+ return 0;
+
zlog_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
pim_ssmpingd_destroy(pim);
pim_instance_terminate(pim);
+
+ vrf->info = NULL;
+
return 0;
}
diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c
index 5279a00855..d95d9dd25d 100644
--- a/pimd/pim_jp_agg.c
+++ b/pimd/pim_jp_agg.c
@@ -360,11 +360,9 @@ void pim_jp_agg_switch_interface(struct pim_rpf *orpf, struct pim_rpf *nrpf,
void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf,
struct pim_upstream *up, bool is_join)
{
- static struct list *groups = NULL;
- static struct pim_jp_agg_group jag;
- static struct pim_jp_sources js;
-
- static bool first = true;
+ struct list groups, sources;
+ struct pim_jp_agg_group jag;
+ struct pim_jp_sources js;
/* skip JP upstream messages if source is directly connected */
if (!up || !rpf->source_nexthop.interface ||
@@ -373,19 +371,19 @@ void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf,
if_is_loopback_or_vrf(rpf->source_nexthop.interface))
return;
- if (first) {
- groups = list_new();
- jag.sources = list_new();
-
- listnode_add(groups, &jag);
- listnode_add(jag.sources, &js);
+ memset(&groups, 0, sizeof(groups));
+ memset(&sources, 0, sizeof(sources));
+ jag.sources = &sources;
- first = false;
- }
+ listnode_add(&groups, &jag);
+ listnode_add(jag.sources, &js);
jag.group.s_addr = up->sg.grp.s_addr;
js.up = up;
js.is_join = is_join;
- pim_joinprune_send(rpf, groups);
+ pim_joinprune_send(rpf, &groups);
+
+ list_delete_all_node(jag.sources);
+ list_delete_all_node(&groups);
}
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 0bccba397b..afd38face3 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,
@@ -1221,10 +1221,9 @@ void pim_mroute_update_counters(struct channel_oil *c_oil)
sg.src = c_oil->oil.mfcc_origin;
sg.grp = c_oil->oil.mfcc_mcastgrp;
- if (PIM_DEBUG_MROUTE)
- zlog_debug(
- "Channel%s is not installed no need to collect data from kernel",
- pim_str_sg_dump(&sg));
+ zlog_debug(
+ "Channel%s is not installed no need to collect data from kernel",
+ pim_str_sg_dump(&sg));
}
return;
}
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index 7620cd5792..ddd8dc6bf9 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -44,7 +44,7 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) {
flog_err_sys(EC_LIB_SOCKET,
- "getsockopt of SO_SNDBUF failed %s\n",
+ "getsockopt of SO_SNDBUF failed %s",
safe_strerror(errno));
return;
}
@@ -53,7 +53,7 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size))
< 0) {
flog_err_sys(EC_LIB_SOCKET,
- "Couldn't increase send buffer: %s\n",
+ "Couldn't increase send buffer: %s",
safe_strerror(errno));
}
}
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index ba044de2f8..4bc78529a8 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -545,7 +545,7 @@ static int pim_cmd_igmp_start(struct interface *ifp)
pim_ifp = ifp->info;
if (!pim_ifp) {
- (void)pim_if_new(ifp, true, false, false, false);
+ pim_ifp = pim_if_new(ifp, true, false, false, false);
need_startup = 1;
} else {
if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
@@ -553,6 +553,7 @@ static int pim_cmd_igmp_start(struct interface *ifp)
need_startup = 1;
}
}
+ pim_if_create_pimreg(pim_ifp->pim);
/* 'ip igmp' executed multiple times, with need_startup
* avoid multiple if add all and membership refresh
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index fa5d6f37bf..dbba6b66d8 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -242,7 +242,7 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim,
if (!rn) {
flog_err(
EC_LIB_DEVELOPMENT,
- "%s: BUG We should have found default group information\n",
+ "%s: BUG We should have found default group information",
__func__);
return best;
}
@@ -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);
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_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_vxlan.c b/pimd/pim_vxlan.c
index 380c97a97c..6a12c7fb13 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -497,10 +497,10 @@ static void pim_vxlan_orig_mr_del(struct pim_vxlan_sg *vxlan_sg)
pim_vxlan_orig_mr_up_del(vxlan_sg);
}
-static void pim_vxlan_orig_mr_iif_update(struct hash_bucket *backet, void *arg)
+static void pim_vxlan_orig_mr_iif_update(struct hash_bucket *bucket, void *arg)
{
struct interface *ifp;
- struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)bucket->data;
struct interface *old_iif = vxlan_sg->iif;
if (!pim_vxlan_is_orig_mroute(vxlan_sg))
@@ -812,11 +812,11 @@ bool pim_vxlan_do_mlag_reg(void)
* to the MLAG peer which may mroute it over the underlay if there are any
* interested receivers.
*/
-static void pim_vxlan_sg_peerlink_oif_update(struct hash_bucket *backet,
+static void pim_vxlan_sg_peerlink_oif_update(struct hash_bucket *bucket,
void *arg)
{
struct interface *new_oif = (struct interface *)arg;
- struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)bucket->data;
if (!pim_vxlan_is_orig_mroute(vxlan_sg))
return;
@@ -950,10 +950,10 @@ static void pim_vxlan_up_cost_update(struct pim_instance *pim,
}
}
-static void pim_vxlan_term_mr_cost_update(struct hash_bucket *backet, void *arg)
+static void pim_vxlan_term_mr_cost_update(struct hash_bucket *bucket, void *arg)
{
struct interface *old_peerlink_rif = (struct interface *)arg;
- struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)bucket->data;
struct pim_upstream *up;
struct listnode *listnode;
struct pim_upstream *child;
@@ -975,11 +975,11 @@ static void pim_vxlan_term_mr_cost_update(struct hash_bucket *backet, void *arg)
old_peerlink_rif);
}
-static void pim_vxlan_sg_peerlink_rif_update(struct hash_bucket *backet,
+static void pim_vxlan_sg_peerlink_rif_update(struct hash_bucket *bucket,
void *arg)
{
- pim_vxlan_orig_mr_iif_update(backet, NULL);
- pim_vxlan_term_mr_cost_update(backet, arg);
+ pim_vxlan_orig_mr_iif_update(bucket, NULL);
+ pim_vxlan_term_mr_cost_update(bucket, arg);
}
static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
@@ -1032,10 +1032,10 @@ static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
}
}
-static void pim_vxlan_term_mr_oif_update(struct hash_bucket *backet, void *arg)
+static void pim_vxlan_term_mr_oif_update(struct hash_bucket *bucket, void *arg)
{
struct interface *ifp = (struct interface *)arg;
- struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)bucket->data;
if (pim_vxlan_is_orig_mroute(vxlan_sg))
return;
diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c
index bf44f3c94a..3c26517e88 100644
--- a/pimd/test_igmpv3_join.c
+++ b/pimd/test_igmpv3_join.c
@@ -54,11 +54,6 @@ static int iface_solve_index(const char *ifname)
}
for (i = 0; ini[i].if_index; ++i) {
-#if 0
- fprintf(stderr,
- "%s: interface=%s matching against local ifname=%s ifindex=%d\n",
- prog_name, ifname, ini[i].if_name, ini[i].if_index);
-#endif
if (!strcmp(ini[i].if_name, ifname)) {
ifindex = ini[i].if_index;
break;