pimd: Allow (*,G) joins to join a (s,g) that pre-exists

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2016-07-23 06:01:55 -04:00 committed by Donald Sharp
parent 219e00134c
commit 6c62910301
3 changed files with 59 additions and 0 deletions

View File

@ -34,6 +34,8 @@
#include "pim_iface.h"
#include "pim_hello.h"
#include "pim_ifchannel.h"
#include "pim_rpf.h"
#include "pim_rp.h"
static void on_trace(const char *label,
struct interface *ifp, struct in_addr src)
@ -76,6 +78,25 @@ static void recv_join(struct interface *ifp,
/* Restart join expiry timer */
pim_ifchannel_join_add(ifp, neigh->source_addr, upstream,
&sg, source_flags, holdtime);
if (I_am_RP (group) && source.s_addr == INADDR_ANY)
{
struct pim_upstream *up;
up = pim_upstream_find_non_any (&sg);
if (up)
{
zlog_debug("%s %s: Join(S,G)=%s from %s",
__FILE__, __PRETTY_FUNCTION__,
pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg));
pim_rp_set_upstream_addr (&up->upstream_addr, up->sg.u.sg.src);
pim_nexthop_lookup (&up->rpf.source_nexthop, up->upstream_addr, NULL);
pim_ifchannel_join_add (ifp, neigh->source_addr, upstream, &up->sg, source_flags, holdtime);
}
}
}
static void recv_prune(struct interface *ifp,
@ -106,6 +127,22 @@ static void recv_prune(struct interface *ifp,
}
pim_ifchannel_prune(ifp, upstream, &sg, source_flags, holdtime);
if (I_am_RP (group) && source.s_addr == INADDR_ANY)
{
struct pim_upstream *up;
up = pim_upstream_find_non_any (&sg);
if (up)
{
zlog_debug("%s %s: Prune(S,G)=%s from %s",
__FILE__, __PRETTY_FUNCTION__,
pim_str_sg_dump (&up->sg), pim_str_sg_dump (&sg));
pim_ifchannel_prune (ifp, upstream, &up->sg, source_flags, holdtime);
}
}
}
int pim_joinprune_recv(struct interface *ifp,

View File

@ -374,6 +374,27 @@ static struct pim_upstream *pim_upstream_new(struct prefix *sg,
return up;
}
/*
* For a given sg, find any non * source
*/
struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg)
{
struct listnode *up_node;
struct prefix any = *sg;
struct pim_upstream *up;
any.u.sg.src.s_addr = INADDR_ANY;
for (ALL_LIST_ELEMENTS_RO (qpim_upstream_list, up_node, up))
{
if ((any.u.sg.grp.s_addr == up->sg.u.sg.grp.s_addr) &&
(up->sg.u.sg.src.s_addr != any.u.sg.src.s_addr))
return up;
}
return NULL;
}
struct pim_upstream *pim_upstream_find(struct prefix *sg)
{
struct listnode *up_node;

View File

@ -122,6 +122,7 @@ struct pim_upstream {
void pim_upstream_free(struct pim_upstream *up);
void pim_upstream_delete(struct pim_upstream *up);
struct pim_upstream *pim_upstream_find (struct prefix *sg);
struct pim_upstream *pim_upstream_find_non_any (struct prefix *sg);
struct pim_upstream *pim_upstream_add (struct prefix *sg,
struct interface *ifp);
void pim_upstream_del(struct pim_upstream *up);