if (child)
child->parent = NULL;
}
- list_delete(up->sources);
- up->sources = NULL;
+ list_delete_and_null(&up->sources);
}
/*
/* Detaching from channel_oil, channel_oil may exist post del,
but upstream would not keep reference of it
*/
+ up->channel_oil->up = NULL;
pim_channel_oil_del(up->channel_oil);
up->channel_oil = NULL;
}
if (PIM_DEBUG_TRACE)
zlog_debug(
- "%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
- __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count,
+ "%s(%s): Delete %s[%s] ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
+ __PRETTY_FUNCTION__, name, up->sg_str,
+ pim->vrf->name, up->ref_count,
up->flags, up->channel_oil->oil_ref_count);
--up->ref_count;
pim_upstream_remove_children(pim, up);
if (up->sources)
- list_delete(up->sources);
- up->sources = NULL;
+ list_delete_and_null(&up->sources);
+
pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
upstream_channel_oil_detach(up);
- list_delete(up->ifchannels);
- up->ifchannels = NULL;
+ list_delete_and_null(&up->ifchannels);
/*
notice that listnode_delete() can't be moved
hash_release(pim->upstream_hash, up);
if (notify_msdp) {
- pim_msdp_up_del(&up->sg);
+ pim_msdp_up_del(pim, &up->sg);
}
/* Deregister addr with Zebra NHT */
/* scan per-interface (S,G) state */
for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
- pim_forward_stop(ch);
+ pim_forward_stop(ch, false);
} /* scan iface channel list */
}
if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer)
continue;
- if (pim_is_grp_ssm(up->sg.grp)) {
+ if (pim_is_grp_ssm(pim, up->sg.grp)) {
/* clear the register state for SSM groups */
if (up->reg_state != PIM_REG_NOINFO) {
if (PIM_DEBUG_PIM_EVENTS)
}
}
-void pim_upstream_switch(struct pim_upstream *up,
+void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
enum pim_upstream_state new_state)
{
enum pim_upstream_state old_state = up->join_state;
if (old_state != PIM_UPSTREAM_JOINED) {
int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags);
forward_on(up);
- pim_msdp_up_join_state_changed(up);
+ pim_msdp_up_join_state_changed(pim, up);
if (pim_upstream_could_register(up)) {
PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
if (!old_fhr
&& PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(
up->flags)) {
pim_upstream_keep_alive_timer_start(
- up, qpim_keep_alive_time);
+ up, pim->keep_alive_time);
pim_register_join(up);
}
} else {
forward_off(up);
if (old_state == PIM_UPSTREAM_JOINED)
- pim_msdp_up_join_state_changed(up);
+ pim_msdp_up_join_state_changed(pim, up);
/* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
RP.
If I am RP for G then send S,G prune to its IIF. */
if (pim_upstream_is_sg_rpt(up) && up->parent
- && !I_am_RP(up->channel_oil->pim, up->sg.grp)) {
+ && !I_am_RP(pim, up->sg.grp)) {
if (PIM_DEBUG_PIM_TRACE_DETAIL)
zlog_debug(
"%s: *,G IIF %s S,G IIF %s ",
return 0;
}
-static struct pim_upstream *
-pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
+static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
+ struct prefix_sg *sg,
+ struct interface *incoming,
+ int flags,
+ struct pim_ifchannel *ch)
{
enum pim_rpf_result rpf_result;
struct pim_interface *pim_ifp;
- struct pim_instance *pim;
struct pim_upstream *up;
up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
return NULL;
}
- pim_ifp = incoming->info;
- pim = pim_ifp->pim;
up->sg = *sg;
pim_str_sg_set(sg, up->sg_str);
+ if (ch)
+ ch->upstream = up;
+
up = hash_get(pim->upstream_hash, up, hash_alloc_intern);
if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
sg->grp)) {
if (up->sg.src.s_addr != INADDR_ANY)
wheel_add_item(pim->upstream_sg_wheel, up);
- rpf_result = pim_rpf_update(up, NULL, 1);
+ rpf_result = pim_rpf_update(pim, up, NULL, 1);
if (rpf_result == PIM_RPF_FAILURE) {
struct prefix nht_p;
nht_p.family = AF_INET;
nht_p.prefixlen = IPV4_MAX_BITLEN;
nht_p.u.prefix4 = up->upstream_addr;
- pim_delete_tracked_nexthop(pim_ifp->pim, &nht_p, up, NULL);
+ pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
if (up->parent) {
listnode_delete(up->parent->sources, up);
pim_upstream_remove_children(pim, up);
if (up->sources)
- list_delete(up->sources);
+ list_delete_and_null(&up->sources);
+
+ list_delete_and_null(&up->ifchannels);
hash_release(pim->upstream_hash, up);
XFREE(MTYPE_PIM_UPSTREAM, up);
up->ref_count);
}
} else
- up = pim_upstream_add(sg, incoming, flags, name);
+ up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
+ NULL);
return up;
}
up->ref_count);
}
-struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
+struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
+ struct prefix_sg *sg,
struct interface *incoming, int flags,
- const char *name)
+ const char *name,
+ struct pim_ifchannel *ch)
{
struct pim_upstream *up = NULL;
- struct pim_interface *pim_ifp;
int found = 0;
- pim_ifp = incoming->info;
- up = pim_upstream_find(pim_ifp->pim, sg);
+ up = pim_upstream_find(pim, sg);
if (up) {
pim_upstream_ref(up, flags, name);
found = 1;
} else {
- up = pim_upstream_new(sg, incoming, flags);
+ up = pim_upstream_new(pim, sg, incoming, flags, ch);
}
if (PIM_DEBUG_TRACE) {
struct pim_upstream *up)
{
struct interface *ifp;
- struct listnode *node;
struct pim_ifchannel *ch, *starch;
struct pim_upstream *starup = up->parent;
int ret = 0;
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
if (!ifp->info)
continue;
/* switched from false to true */
if (is_join_desired && !was_join_desired) {
- pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
return;
}
/* switched from true to false */
if (!is_join_desired && was_join_desired) {
- pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
return;
}
}
pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str,
sizeof(rpf_addr_str));
zlog_debug(
- "%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s",
- __PRETTY_FUNCTION__, neigh_str, up->sg_str,
+ "%s: matching neigh=%s against upstream (S,G)=%s[%s] joined=%d rpf_addr=%s",
+ __PRETTY_FUNCTION__, neigh_str, up->sg_str, pim->vrf->name,
up->join_state == PIM_UPSTREAM_JOINED,
rpf_addr_str);
}
static int pim_upstream_keep_alive_timer(struct thread *t)
{
struct pim_upstream *up;
+ struct pim_instance *pim;
up = THREAD_ARG(t);
+ pim = up->channel_oil->pim;
- if (I_am_RP(pimg, up->sg.grp)) {
+ if (I_am_RP(pim, up->sg.grp)) {
pim_br_clear_pmbr(&up->sg);
/*
* We need to do more here :)
}
/* source is no longer active - pull the SA from MSDP's cache */
- pim_msdp_sa_local_del(&up->sg);
+ pim_msdp_sa_local_del(pim, &up->sg);
/* if entry was created because of activity we need to deref it */
if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
- pim_upstream_fhr_kat_expiry(pimg, up);
+ pim_upstream_fhr_kat_expiry(pim, up);
if (PIM_DEBUG_TRACE)
- zlog_debug("kat expired on %s; remove stream reference",
- up->sg_str);
+ zlog_debug("kat expired on %s[%s]; remove stream reference",
+ up->sg_str, pim->vrf->name);
PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
- pim_upstream_del(pimg, up, __PRETTY_FUNCTION__);
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
+ struct pim_upstream *parent = up->parent;
+
PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
- pim_upstream_del(pimg, up, __PRETTY_FUNCTION__);
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+
+ if (parent) {
+ pim_jp_agg_single_upstream_send(&parent->rpf,
+ parent, true);
+ }
}
return 0;
/* MSDP on RP needs to know if a source is registerable to this RP */
static int pim_upstream_msdp_reg_timer(struct thread *t)
{
- struct pim_upstream *up;
-
- up = THREAD_ARG(t);
+ struct pim_upstream *up = THREAD_ARG(t);
+ struct pim_instance *pim = up->channel_oil->pim;
/* source is no longer active - pull the SA from MSDP's cache */
- pim_msdp_sa_local_del(&up->sg);
+ pim_msdp_sa_local_del(pim, &up->sg);
return 1;
}
void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
* SwitchToSptDesired(S,G) return true once a single packet has been
* received for the source and group.
*/
-int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg)
+int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
+ struct prefix_sg *sg)
{
- if (I_am_RP(pimg, sg->grp))
+ if (I_am_RP(pim, sg->grp))
return 1;
return 0;
static int pim_upstream_register_stop_timer(struct thread *t)
{
struct pim_interface *pim_ifp;
+ struct pim_instance *pim;
struct pim_upstream *up;
struct pim_rpf *rpg;
struct ip ip_hdr;
up = THREAD_ARG(t);
+ pim = up->channel_oil->pim;
if (PIM_DEBUG_TRACE) {
char state_str[PIM_REG_STATE_STR_LEN];
- zlog_debug("%s: (S,G)=%s upstream register stop timer %s",
- __PRETTY_FUNCTION__, up->sg_str,
+ zlog_debug("%s: (S,G)=%s[%s] upstream register stop timer %s",
+ __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
pim_reg_state2str(up->reg_state, state_str));
}
switch (up->reg_state) {
case PIM_REG_JOIN_PENDING:
up->reg_state = PIM_REG_JOIN;
- pim_channel_add_oif(up->channel_oil, pimg->regiface,
+ pim_channel_add_oif(up->channel_oil, pim->regiface,
PIM_OIF_FLAG_PROTO_PIM);
break;
case PIM_REG_JOIN:
pim_upstream_start_register_stop_timer(up, 1);
if (((up->channel_oil->cc.lastused / 100)
- > PIM_KEEPALIVE_PERIOD)
+ > pim->keep_alive_time)
&& (I_am_RP(pim_ifp->pim, up->sg.grp))) {
if (PIM_DEBUG_TRACE)
zlog_debug(
return 0;
}
rpg = RP(pim_ifp->pim, up->sg.grp);
+ if (!rpg) {
+ if (PIM_DEBUG_TRACE)
+ zlog_debug(
+ "%s: Cannot send register for %s no RPF to the RP",
+ __PRETTY_FUNCTION__, up->sg_str);
+ return 0;
+ }
memset(&ip_hdr, 0, sizeof(struct ip));
ip_hdr.ip_p = PIM_IP_PROTO_PIM;
ip_hdr.ip_hl = 5;
struct interface *ifp;
struct pim_interface *pim_ifp = NULL;
struct pim_ifchannel *ch, *starch;
- struct listnode *node;
struct pim_upstream *starup = up->parent;
int output_intf = 0;
up->channel_oil = pim_channel_oil_add(
pim, &up->sg, pim_ifp->mroute_vif_index);
- for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
if (!ifp->info)
continue;
* incoming packets so we don't bother the other stuff!
*/
if (output_intf)
- pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+ pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
else
forward_on(up);
zlog_debug(
"Upstream %s without a path to send join, checking",
up->sg_str);
- pim_rpf_update(up, NULL, 1);
+ pim_rpf_update(pim, up, NULL, 1);
}
}
}
-static unsigned int pim_upstream_hash_key(void *arg)
+unsigned int pim_upstream_hash_key(void *arg)
{
struct pim_upstream *up = (struct pim_upstream *)arg;
void pim_upstream_terminate(struct pim_instance *pim)
{
if (pim->upstream_list)
- list_delete(pim->upstream_list);
- pim->upstream_list = NULL;
+ list_delete_and_null(&pim->upstream_list);
if (pim->upstream_hash)
hash_free(pim->upstream_hash);
pim->upstream_hash = NULL;
}
-static int pim_upstream_equal(const void *arg1, const void *arg2)
+int pim_upstream_equal(const void *arg1, const void *arg2)
{
const struct pim_upstream *up1 = (const struct pim_upstream *)arg1;
const struct pim_upstream *up2 = (const struct pim_upstream *)arg2;
*/
static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
{
+ struct pim_instance *pim = up->channel_oil->pim;
+
/* "iif == RPF_interface(S)" check has to be done by the kernel or hw
* so we will skip that here */
if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
* MUST be
* removed to handle spt turn-arounds correctly in a 3-tier clos
*/
- if (I_am_RP(pimg, up->sg.grp))
+ if (I_am_RP(pim, up->sg.grp))
return true;
}
static void pim_upstream_sg_running(void *arg)
{
struct pim_upstream *up = (struct pim_upstream *)arg;
+ struct pim_instance *pim = up->channel_oil->pim;
// No packet can have arrived here if this is the case
- if (!up->channel_oil || !up->channel_oil->installed) {
+ if (!up->channel_oil->installed) {
if (PIM_DEBUG_TRACE)
- zlog_debug("%s: %s is not installed in mroute",
- __PRETTY_FUNCTION__, up->sg_str);
+ zlog_debug("%s: %s[%s] is not installed in mroute",
+ __PRETTY_FUNCTION__,
+ up->sg_str, pim->vrf->name);
return;
}
if (up->channel_oil->oil_inherited_rescan) {
if (PIM_DEBUG_TRACE)
zlog_debug(
- "%s: Handling unscanned inherited_olist for %s",
- __PRETTY_FUNCTION__, up->sg_str);
- pim_upstream_inherited_olist_decide(pimg, up);
+ "%s: Handling unscanned inherited_olist for %s[%s]",
+ __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name);
+ pim_upstream_inherited_olist_decide(pim, up);
up->channel_oil->oil_inherited_rescan = 0;
}
pim_mroute_update_counters(up->channel_oil);
&& (up->channel_oil->cc.lastused / 100 > 30)) {
if (PIM_DEBUG_TRACE) {
zlog_debug(
- "%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",
- __PRETTY_FUNCTION__, up->sg_str,
+ "%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",
+ __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
up->channel_oil->cc.oldpktcnt,
up->channel_oil->cc.pktcnt,
up->channel_oil->cc.lastused / 100);
if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
if (PIM_DEBUG_TRACE)
zlog_debug(
- "source reference created on kat restart %s",
- up->sg_str);
+ "source reference created on kat restart %s[%s]",
+ up->sg_str, pim->vrf->name);
pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
__PRETTY_FUNCTION__);
PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
pim_upstream_fhr_kat_start(up);
}
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
} else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
- pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+ pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
void pim_upstream_init(struct pim_instance *pim)
{
+ char hash_name[64];
+
pim->upstream_sg_wheel =
wheel_init(master, 31000, 100, pim_upstream_hash_key,
pim_upstream_sg_running);
+
+ snprintf(hash_name, 64, "PIM %s Upstream Hash",
+ pim->vrf->name);
pim->upstream_hash = hash_create_size(8192, pim_upstream_hash_key,
- pim_upstream_equal, NULL);
+ pim_upstream_equal, hash_name);
pim->upstream_list = list_new();
pim->upstream_list->del = (void (*)(void *))pim_upstream_free;