From 6c62910301f0d03e88c4c30286f95383ef8eb195 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 23 Jul 2016 06:01:55 -0400 Subject: [PATCH] pimd: Allow (*,G) joins to join a (s,g) that pre-exists Signed-off-by: Donald Sharp --- pimd/pim_join.c | 37 +++++++++++++++++++++++++++++++++++++ pimd/pim_upstream.c | 21 +++++++++++++++++++++ pimd/pim_upstream.h | 1 + 3 files changed, 59 insertions(+) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index b5ebfb5d9a..c496b988ee 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -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, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index fc83acf7ea..34e7d9a759 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -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; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 18f302183a..2fb193d42d 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -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); -- 2.39.5