mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 18:52:04 +00:00
pimd: re-eval c_oil mute flags on upstream attach/detach
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 <anuradhak@cumulusnetworks.com>
This commit is contained in:
parent
5a5f404e1b
commit
a155fed53c
@ -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;
|
||||
@ -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(
|
||||
@ -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,
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user