#include "pim_upstream.h"
#include "pim_ssm.h"
#include "pim_rp.h"
+#include "pim_mlag.h"
RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb, pim_ifchannel_compare);
void pim_ifchannel_delete(struct pim_ifchannel *ch)
{
struct pim_interface *pim_ifp;
+ struct pim_upstream *up;
pim_ifp = ch->interface->info;
+ if (PIM_DEBUG_PIM_TRACE)
+ zlog_debug("%s: ifchannel entry %s(%s) del start", __func__,
+ ch->sg_str, ch->interface->name);
+
+ if (PIM_I_am_DualActive(pim_ifp)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: if-chnanel-%s is deleted from a Dual "
+ "active Interface",
+ __func__, ch->sg_str);
+ /* Post Delete only if it is the last Dual-active Interface */
+ if (ch->upstream->dualactive_ifchannel_count == 1) {
+ pim_mlag_up_local_del(pim_ifp->pim, ch->upstream);
+ PIM_UPSTREAM_FLAG_UNSET_MLAG_INTERFACE(
+ ch->upstream->flags);
+ }
+ ch->upstream->dualactive_ifchannel_count--;
+ }
+
if (ch->upstream->channel_oil) {
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
listnode_delete(ch->upstream->ifchannels, ch);
- pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
+ up = ch->upstream;
/* upstream is common across ifchannels, check if upstream's
ifchannel list is empty before deleting upstream_del
ref count will take care of it.
*/
if (ch->upstream->ref_count > 0)
- pim_upstream_del(pim_ifp->pim, ch->upstream,
- __PRETTY_FUNCTION__);
+ up = pim_upstream_del(pim_ifp->pim, ch->upstream, __func__);
else {
if (PIM_DEBUG_PIM_TRACE)
- zlog_debug("%s: Avoiding deletion of upstream with ref_count %d "
- "from ifchannel(%s): %s", __PRETTY_FUNCTION__,
- ch->upstream->ref_count, ch->interface->name,
- ch->sg_str);
+ zlog_debug(
+ "%s: Avoiding deletion of upstream with ref_count %d "
+ "from ifchannel(%s): %s",
+ __func__, ch->upstream->ref_count,
+ ch->interface->name, ch->sg_str);
}
ch->upstream = NULL;
RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
if (PIM_DEBUG_PIM_TRACE)
- zlog_debug("%s: ifchannel entry %s is deleted ",
- __PRETTY_FUNCTION__, ch->sg_str);
+ zlog_debug("%s: ifchannel entry %s(%s) is deleted ", __func__,
+ ch->sg_str, ch->interface->name);
XFREE(MTYPE_PIM_IFCHANNEL, ch);
+
+ if (up)
+ pim_upstream_update_join_desired(pim_ifp->pim, up);
}
void pim_ifchannel_delete_all(struct interface *ifp)
while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__,
- ch, PIM_IFJOIN_NOINFO);
+ pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
pim_ifchannel_delete(ch);
}
}
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug(
"%s calledby %s: non-transition on state %d (%s)",
- __PRETTY_FUNCTION__, caller, new_state,
+ __func__, caller, new_state,
pim_ifchannel_ifjoin_name(new_state, 0));
}
return;
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s %s: Prune(S,G)=%s from %s",
- __FILE__,
- __PRETTY_FUNCTION__,
+ __FILE__, __func__,
child->sg_str,
up->sg_str);
if (!c_oil)
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s %s: Join(S,G)=%s from %s",
- __FILE__,
- __PRETTY_FUNCTION__,
+ __FILE__, __func__,
child->sg_str,
up->sg_str);
if (!pim_ifp) {
zlog_warn("%s: (S,G)=%s: multicast not enabled on interface %s",
- __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
+ __func__, pim_str_sg_dump(sg), ifp->name);
return NULL;
}
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug("%s: (S,G)=%s membership now is %s on interface %s",
- __PRETTY_FUNCTION__, ch->sg_str,
+ __func__, ch->sg_str,
membership == PIM_IFMEMBERSHIP_INCLUDE ? "INCLUDE"
: "NOINFO",
ch->interface->name);
RB_INSERT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
- up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags,
- __PRETTY_FUNCTION__, ch);
+ up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags, __func__, ch);
ch->upstream = up;
else
PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags);
+ /*
+ * advertise MLAG Data to MLAG peer
+ */
+ if (PIM_I_am_DualActive(pim_ifp)) {
+ up->dualactive_ifchannel_count++;
+ /* Sync once for upstream */
+ if (up->dualactive_ifchannel_count == 1) {
+ PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(up->flags);
+ pim_mlag_up_local_add(pim_ifp->pim, up);
+ }
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: New Dual active if-chnanel is added to upstream:%s "
+ "count:%d, flags:0x%x",
+ __func__, up->sg_str,
+ up->dualactive_ifchannel_count, up->flags);
+ }
+
+ 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 (PIM_DEBUG_PIM_TRACE)
- zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__,
- ch->sg_str);
+ zlog_debug("%s: ifchannel %s(%s) is created ", __func__,
+ ch->sg_str, ch->interface->name);
return ch;
}
static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del)
{
pim_forward_stop(ch, !ch_del);
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO);
+ pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
if (ch_del)
delete_on_noinfo(ch);
}
ch = THREAD_ARG(t);
if (PIM_DEBUG_PIM_TRACE)
- zlog_debug("%s: ifchannel %s expiry timer", __PRETTY_FUNCTION__,
+ zlog_debug("%s: ifchannel %s expiry timer", __func__,
ch->sg_str);
ifjoin_to_noinfo(ch, true);
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s: IFCHANNEL%s %s Prune Pending Timer Popped",
- __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg),
+ __func__, pim_str_sg_dump(&ch->sg),
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags));
if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) {
if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
/* RPF'(S,G) not found */
- zlog_warn("%s %s: RPF'%s not found", __FILE__,
- __PRETTY_FUNCTION__, up->sg_str);
+ zlog_warn("%s %s: RPF'%s not found", __FILE__, __func__,
+ up->sg_str);
return;
}
sizeof(rpf_str));
zlog_warn(
"%s %s: (S,G)=%s upstream=%s not directed to RPF'(S,G)=%s on interface %s",
- __FILE__, __PRETTY_FUNCTION__, up->sg_str, up_str,
- rpf_str, recv_ifp->name);
+ __FILE__, __func__, up->sg_str, up_str, rpf_str,
+ recv_ifp->name);
return;
}
/* upstream directed to RPF'(S,G) */
char up_str[INET_ADDRSTRLEN];
pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
zlog_warn("%s: recv %s (S,G)=%s to non-local upstream=%s on %s",
- __PRETTY_FUNCTION__, is_join ? "join" : "prune",
+ __func__, is_join ? "join" : "prune",
pim_str_sg_dump(sg), up_str, recv_ifp->name);
}
static void pim_ifchannel_ifjoin_handler(struct pim_ifchannel *ch,
struct pim_interface *pim_ifp)
{
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
- PIM_IFJOIN_JOIN);
+ pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_JOIN);
PIM_IF_FLAG_UNSET_S_G_RPT(ch->flags);
/* check if the interface qualifies as an immediate
* OIF
pim_inet4_dump("<neigh?>", neigh_addr, neigh_str,
sizeof(neigh_str));
zlog_warn("%s: Assert Loser recv Join%s from %s on %s",
- __PRETTY_FUNCTION__, ch->sg_str, neigh_str,
- ifp->name);
+ __func__, ch->sg_str, neigh_str, ifp->name);
assert_action_a5(ch);
}
switch (ch->ifjoin_state) {
case PIM_IFJOIN_NOINFO:
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
- PIM_IFJOIN_JOIN);
+ pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_JOIN);
if (pim_macro_chisin_oiflist(ch)) {
pim_upstream_inherited_olist(pim_ifp->pim,
ch->upstream);
/*
* If we are going to be a LHR, we need to note it
*/
- if (ch->upstream->parent && (ch->upstream->parent->flags
- & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ if (ch->upstream->parent &&
+ (PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(
+ ch->upstream->parent->flags))
&& !(ch->upstream->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) {
pim_upstream_ref(ch->upstream,
PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
- __PRETTY_FUNCTION__);
+ __func__);
pim_upstream_keep_alive_timer_start(
ch->upstream, pim_ifp->pim->keep_alive_time);
}
break;
case PIM_IFJOIN_PRUNE:
if (source_flags & PIM_ENCODE_RPT_BIT)
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
+ pim_ifchannel_ifjoin_switch(__func__, ch,
PIM_IFJOIN_NOINFO);
else
pim_ifchannel_ifjoin_handler(ch, pim_ifp);
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
if (source_flags & PIM_ENCODE_RPT_BIT) {
THREAD_OFF(ch->t_ifjoin_expiry_timer);
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
+ pim_ifchannel_ifjoin_switch(__func__, ch,
PIM_IFJOIN_NOINFO);
} else {
pim_ifchannel_ifjoin_handler(ch, pim_ifp);
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
"%s: Received prune with no relevant ifchannel %s%s state: %d",
- __PRETTY_FUNCTION__, ifp->name,
- pim_str_sg_dump(sg), source_flags);
+ __func__, ifp->name, pim_str_sg_dump(sg),
+ source_flags);
return;
}
case PIM_IFJOIN_JOIN:
THREAD_OFF(ch->t_ifjoin_expiry_timer);
- pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
+ pim_ifchannel_ifjoin_switch(__func__, ch,
PIM_IFJOIN_PRUNE_PENDING);
if (listcount(pim_ifp->pim_neighbor_list) > 1)
}
int pim_ifchannel_local_membership_add(struct interface *ifp,
- struct prefix_sg *sg)
+ struct prefix_sg *sg, bool is_vxlan)
{
struct pim_ifchannel *ch, *starch;
struct pim_interface *pim_ifp;
struct pim_instance *pim;
+ int up_flags;
/* PIM enabled on interface? */
pim_ifp = ifp->info;
if (!pim_ifp) {
if (PIM_DEBUG_EVENTS)
zlog_debug("%s:%s Expected pim interface setup for %s",
- __PRETTY_FUNCTION__,
- pim_str_sg_dump(sg), ifp->name);
+ __func__, pim_str_sg_dump(sg), ifp->name);
return 0;
}
if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
if (PIM_DEBUG_EVENTS)
- zlog_debug("%s:%s PIM is not configured on this interface %s",
- __PRETTY_FUNCTION__,
- pim_str_sg_dump(sg), ifp->name);
+ zlog_debug(
+ "%s:%s PIM is not configured on this interface %s",
+ __func__, pim_str_sg_dump(sg), ifp->name);
return 0;
}
if (PIM_DEBUG_PIM_EVENTS)
zlog_debug(
"%s: local membership (S,G)=%s ignored as group is SSM",
- __PRETTY_FUNCTION__,
- pim_str_sg_dump(sg));
+ __func__, pim_str_sg_dump(sg));
return 1;
}
}
- ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
+ /* vxlan term mroutes use ipmr-lo as local member to
+ * pull down multicast vxlan tunnel traffic
+ */
+ up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
+ PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
+ ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) {
if (PIM_DEBUG_EVENTS)
zlog_debug("%s %s: IGMP (S,G)=%s(%s) from %s",
- __FILE__, __PRETTY_FUNCTION__,
- child->sg_str, ifp->name,
- up->sg_str);
+ __FILE__, __func__, child->sg_str,
+ ifp->name, up->sg_str);
ch = pim_ifchannel_find(ifp, &child->sg);
if (pim_upstream_evaluate_join_desired_interface(
if (PIM_DEBUG_EVENTS)
zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s",
- __FILE__, __PRETTY_FUNCTION__,
- up->sg_str, ifp->name,
- child->sg_str);
+ __FILE__, __func__, up->sg_str,
+ ifp->name, child->sg_str);
ch = pim_ifchannel_find(ifp, &child->sg);
/*
pim_inet4_dump("<src?>", ch->sg.src, src_str, sizeof(src_str));
pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str));
zlog_debug("%s: CouldAssert(%s,%s,%s) changed from %d to %d",
- __PRETTY_FUNCTION__, src_str, grp_str,
- ch->interface->name, old_couldassert,
- new_couldassert);
+ __func__, src_str, grp_str, ch->interface->name,
+ old_couldassert, new_couldassert);
}
if (new_couldassert) {
new_addr_str, sizeof(new_addr_str));
zlog_debug(
"%s: my_assert_metric(%s,%s,%s) changed from %u,%u,%u,%s to %u,%u,%u,%s",
- __PRETTY_FUNCTION__, src_str, grp_str,
- ch->interface->name,
+ __func__, src_str, grp_str, ch->interface->name,
ch->ifassert_my_metric.rpt_bit_flag,
ch->ifassert_my_metric.metric_preference,
ch->ifassert_my_metric.route_metric, old_addr_str,
pim_inet4_dump("<grp?>", ch->sg.grp, grp_str, sizeof(grp_str));
zlog_debug(
"%s: AssertTrackingDesired(%s,%s,%s) changed from %d to %d",
- __PRETTY_FUNCTION__, src_str, grp_str,
- ch->interface->name, old_atd, new_atd);
+ __func__, src_str, grp_str, ch->interface->name,
+ old_atd, new_atd);
}
if (new_atd) {
if (PIM_DEBUG_PIM_TRACE)
zlog_debug(
- "%s: %s %s eom: %d join %u", __PRETTY_FUNCTION__,
+ "%s: %s %s eom: %d join %u", __func__,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
ch->sg_str, eom, join);
if (!ch->sources)