Skip to content

Commit

Permalink
pimd: re-eval c_oil mute flags on upstream attach/detach
Browse files Browse the repository at this point in the history
Theoretically there should be no case where the channel-oil hangs
around after the upstream entry is removed. But currently there are
cases where it does. This is a precautionary fixup till we are
rid off all of those cases.

Signed-off-by: Anuradha Karuppiah <[email protected]>
  • Loading branch information
AnuradhaKaruppiah committed Nov 15, 2019
1 parent 5a5f404 commit a155fed
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
52 changes: 49 additions & 3 deletions pimd/pim_oil.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
// struct list *pim_channel_oil_list = NULL;
// struct hash *pim_channel_oil_hash = NULL;

static void pim_channel_update_mute(struct channel_oil *c_oil);

char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
{
char *out;
Expand Down Expand Up @@ -205,8 +207,17 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
pim_channel_oil_change_iif(pim, c_oil, input_vif_index,
name);
++c_oil->oil_ref_count;
/* channel might be present prior to upstream */
c_oil->up = pim_upstream_find(pim, sg);

if (!c_oil->up) {
/* channel might be present prior to upstream */
c_oil->up = pim_upstream_find(
pim, sg);
/* if the upstream entry is being anchored to an
* already existing channel OIL we need to re-evaluate
* the "Mute" state on AA OIFs
*/
pim_channel_update_mute(c_oil);
}

if (PIM_DEBUG_MROUTE)
zlog_debug(
Expand Down Expand Up @@ -247,7 +258,8 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
return c_oil;
}

void pim_channel_oil_del(struct channel_oil *c_oil, const char *name)
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
const char *name)
{
if (PIM_DEBUG_MROUTE) {
struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
Expand All @@ -270,6 +282,24 @@ void pim_channel_oil_del(struct channel_oil *c_oil, const char *name)
hash_release(c_oil->pim->channel_oil_hash, c_oil);

pim_channel_oil_free(c_oil);
return NULL;
}

return c_oil;
}

void pim_channel_oil_upstream_deref(struct channel_oil *c_oil)
{
/* The upstream entry associated with a channel_oil is abt to be
* deleted. If the channel_oil is kept around because of other
* references we need to remove upstream based states out of it.
*/
c_oil = pim_channel_oil_del(c_oil, __func__);
if (c_oil) {
/* note: here we assume that c_oil->up has already been
* cleared
*/
pim_channel_update_mute(c_oil);
}
}

Expand Down Expand Up @@ -448,6 +478,22 @@ void pim_channel_update_oif_mute(struct channel_oil *c_oil,
pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
}

/* pim_upstream has been set or cleared on the c_oil. re-eval mute state
* on all existing OIFs
*/
static void pim_channel_update_mute(struct channel_oil *c_oil)
{
struct pim_interface *pim_reg_ifp;
struct pim_interface *vxlan_ifp;

pim_reg_ifp = c_oil->pim->regiface->info;
if (pim_reg_ifp)
pim_channel_update_oif_mute(c_oil, pim_reg_ifp);
vxlan_ifp = pim_vxlan_get_term_ifp(c_oil->pim);
if (vxlan_ifp)
pim_channel_update_oif_mute(c_oil, vxlan_ifp);
}

int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
uint32_t proto_mask, const char *caller)
{
Expand Down
5 changes: 4 additions & 1 deletion pimd/pim_oil.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
void pim_channel_oil_change_iif(struct pim_instance *pim,
struct channel_oil *c_oil, int input_vif_index,
const char *name);
void pim_channel_oil_del(struct channel_oil *c_oil, const char *name);
struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
const char *name);

int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
uint32_t proto_mask, const char *caller);
Expand All @@ -133,4 +134,6 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size);

void pim_channel_update_oif_mute(struct channel_oil *c_oil,
struct pim_interface *pim_ifp);

void pim_channel_oil_upstream_deref(struct channel_oil *c_oil);
#endif /* PIM_OIL_H */
14 changes: 11 additions & 3 deletions pimd/pim_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,22 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,

static void upstream_channel_oil_detach(struct pim_upstream *up)
{
if (up->channel_oil) {
struct channel_oil *channel_oil = up->channel_oil;

if (channel_oil) {
/* 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, __PRETTY_FUNCTION__);
channel_oil->up = NULL;
up->channel_oil = NULL;

/* attempt to delete channel_oil; if channel_oil is being held
* because of other references cleanup info such as "Mute"
* inferred from the parent upstream
*/
pim_channel_oil_upstream_deref(channel_oil);
}

}

struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
Expand Down
7 changes: 7 additions & 0 deletions pimd/pim_vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ static inline bool pim_vxlan_is_orig_mroute(struct pim_vxlan_sg *vxlan_sg)
return (vxlan_sg->sg.src.s_addr != 0);
}

static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)
{
return (up->sg.src.s_addr != INADDR_ANY) &&
up->rpf.source_nexthop.interface &&
if_is_loopback_or_vrf(up->rpf.source_nexthop.interface);
}

extern struct pim_vxlan *pim_vxlan_p;
extern struct pim_vxlan_sg *pim_vxlan_sg_find(struct pim_instance *pim,
struct prefix_sg *sg);
Expand Down

0 comments on commit a155fed

Please sign in to comment.