2021-11-05 23:05:21 +01:00
|
|
|
|
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/*
|
2017-05-13 10:25:29 +02:00
|
|
|
* PIM for Quagga
|
|
|
|
* Copyright (C) 2008 Everton da Silva Marques
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2015-02-04 07:01:14 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
#include "prefix.h"
|
2016-06-18 02:43:21 +02:00
|
|
|
#include "if.h"
|
2016-09-13 21:41:33 +02:00
|
|
|
#include "vty.h"
|
|
|
|
#include "plist.h"
|
2015-02-04 07:01:14 +01:00
|
|
|
|
|
|
|
#include "pimd.h"
|
2022-05-06 12:36:51 +02:00
|
|
|
#include "pim_instance.h"
|
2015-02-04 07:01:14 +01:00
|
|
|
#include "pim_str.h"
|
|
|
|
#include "pim_tlv.h"
|
|
|
|
#include "pim_msg.h"
|
|
|
|
#include "pim_pim.h"
|
|
|
|
#include "pim_join.h"
|
2016-08-01 18:29:58 +02:00
|
|
|
#include "pim_oil.h"
|
2015-02-04 07:01:14 +01:00
|
|
|
#include "pim_iface.h"
|
|
|
|
#include "pim_hello.h"
|
|
|
|
#include "pim_ifchannel.h"
|
2016-07-23 12:01:55 +02:00
|
|
|
#include "pim_rpf.h"
|
|
|
|
#include "pim_rp.h"
|
2017-02-15 03:32:16 +01:00
|
|
|
#include "pim_jp_agg.h"
|
2017-09-01 20:33:00 +02:00
|
|
|
#include "pim_util.h"
|
2021-10-26 14:55:23 +02:00
|
|
|
#include "pim_ssm.h"
|
2015-02-04 07:01:14 +01:00
|
|
|
|
2022-03-12 22:33:23 +01:00
|
|
|
static void on_trace(const char *label, struct interface *ifp, pim_addr src)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
2022-03-12 22:33:23 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
|
|
|
zlog_debug("%s: from %pPA on %s", label, &src, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
|
2022-01-14 19:12:32 +01:00
|
|
|
uint16_t holdtime, pim_addr upstream, pim_sgaddr *sg,
|
|
|
|
uint8_t source_flags)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
2017-04-03 22:11:58 +02:00
|
|
|
struct pim_interface *pim_ifp = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-14 19:12:32 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
2022-01-14 17:47:14 +01:00
|
|
|
zlog_debug(
|
2022-01-14 19:12:32 +01:00
|
|
|
"%s: join (S,G)=%pSG rpt=%d wc=%d upstream=%pPAs holdtime=%d from %pPA on %s",
|
2022-01-14 17:47:14 +01:00
|
|
|
__func__, sg, !!(source_flags & PIM_RPT_BIT_MASK),
|
2022-01-14 19:12:32 +01:00
|
|
|
!!(source_flags & PIM_WILDCARD_BIT_MASK), &upstream,
|
2022-01-14 17:47:14 +01:00
|
|
|
holdtime, &neigh->source_addr, ifp->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-03 22:11:58 +02:00
|
|
|
pim_ifp = ifp->info;
|
2021-04-23 11:23:57 +02:00
|
|
|
assert(pim_ifp);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-03 22:11:58 +02:00
|
|
|
++pim_ifp->pim_ifstat_join_recv;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-07-27 22:33:41 +02:00
|
|
|
/*
|
|
|
|
* If the RPT and WC are set it's a (*,G)
|
|
|
|
* and the source is the RP
|
|
|
|
*/
|
|
|
|
if ((source_flags & PIM_RPT_BIT_MASK)
|
|
|
|
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
|
2017-05-19 22:41:25 +02:00
|
|
|
struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp);
|
2022-01-14 16:55:12 +01:00
|
|
|
pim_addr rpf_addr;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-11-20 01:36:19 +01:00
|
|
|
if (!rp) {
|
2022-01-04 17:54:44 +01:00
|
|
|
zlog_warn("%s: Lookup of RP failed for %pSG", __func__,
|
|
|
|
sg);
|
2019-11-20 01:36:19 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-07-27 22:33:41 +02:00
|
|
|
/*
|
|
|
|
* If the RP sent in the message is not
|
|
|
|
* our RP for the group, drop the message
|
|
|
|
*/
|
2022-01-14 16:55:12 +01:00
|
|
|
rpf_addr = pim_addr_from_prefix(&rp->rpf_addr);
|
|
|
|
if (pim_addr_cmp(sg->src, rpf_addr)) {
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn(
|
2022-01-14 16:55:12 +01:00
|
|
|
"%s: Specified RP(%pPAs) in join is different than our configured RP(%pPAs)",
|
|
|
|
__func__, &sg->src, &rpf_addr);
|
2016-07-27 22:33:41 +02:00
|
|
|
return;
|
2017-06-05 19:44:15 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-10-26 14:55:23 +02:00
|
|
|
if (pim_is_grp_ssm(pim_ifp->pim, sg->grp)) {
|
|
|
|
zlog_warn(
|
2022-01-05 19:29:11 +01:00
|
|
|
"%s: Specified Group(%pPA) in join is now in SSM, not allowed to create PIM state",
|
2021-11-05 23:05:21 +01:00
|
|
|
__func__, &sg->grp);
|
2021-10-26 14:55:23 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-05 16:07:17 +01:00
|
|
|
sg->src = PIMADDR_ANY;
|
2016-07-27 22:33:41 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/* Restart join expiry timer */
|
|
|
|
pim_ifchannel_join_add(ifp, neigh->source_addr, upstream, sg,
|
2016-11-07 21:51:18 +01:00
|
|
|
source_flags, holdtime);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh,
|
2022-01-14 19:12:32 +01:00
|
|
|
uint16_t holdtime, pim_addr upstream, pim_sgaddr *sg,
|
|
|
|
uint8_t source_flags)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
2017-04-03 22:11:58 +02:00
|
|
|
struct pim_interface *pim_ifp = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-14 19:12:32 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
2022-01-14 17:47:14 +01:00
|
|
|
zlog_debug(
|
2022-01-14 19:12:32 +01:00
|
|
|
"%s: prune (S,G)=%pSG rpt=%d wc=%d upstream=%pPAs holdtime=%d from %pPA on %s",
|
2022-01-14 17:47:14 +01:00
|
|
|
__func__, sg, source_flags & PIM_RPT_BIT_MASK,
|
2022-01-14 19:12:32 +01:00
|
|
|
source_flags & PIM_WILDCARD_BIT_MASK, &upstream,
|
|
|
|
holdtime, &neigh->source_addr, ifp->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-03 22:11:58 +02:00
|
|
|
pim_ifp = ifp->info;
|
2021-04-23 11:23:57 +02:00
|
|
|
assert(pim_ifp);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-03 22:11:58 +02:00
|
|
|
++pim_ifp->pim_ifstat_prune_recv;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-07-28 08:46:36 +02:00
|
|
|
if ((source_flags & PIM_RPT_BIT_MASK)
|
|
|
|
&& (source_flags & PIM_WILDCARD_BIT_MASK)) {
|
2020-03-17 10:28:18 +01:00
|
|
|
/*
|
|
|
|
* RFC 4601 Section 4.5.2:
|
|
|
|
* Received Prune(*,G) messages are processed even if the
|
|
|
|
* RP in the message does not match RP(G).
|
|
|
|
*/
|
2022-01-05 19:12:12 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
|
|
|
zlog_debug("%s: Prune received with RP(%pPAs) for %pSG",
|
|
|
|
__func__, &sg->src, sg);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-05 16:07:17 +01:00
|
|
|
sg->src = PIMADDR_ANY;
|
2016-07-28 08:46:36 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2016-11-07 21:51:18 +01:00
|
|
|
pim_ifchannel_prune(ifp, upstream, sg, source_flags, holdtime);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int pim_joinprune_recv(struct interface *ifp, struct pim_neighbor *neigh,
|
2022-01-17 11:07:39 +01:00
|
|
|
pim_addr src_addr, uint8_t *tlv_buf, int tlv_buf_size)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
2022-01-14 16:38:41 +01:00
|
|
|
pim_addr msg_upstream_addr;
|
|
|
|
bool wrong_af = false;
|
2017-09-01 20:33:00 +02:00
|
|
|
struct pim_interface *pim_ifp;
|
2015-02-04 07:01:14 +01:00
|
|
|
uint8_t msg_num_groups;
|
|
|
|
uint16_t msg_holdtime;
|
|
|
|
int addr_offset;
|
|
|
|
uint8_t *buf;
|
|
|
|
uint8_t *pastend;
|
|
|
|
int remain;
|
|
|
|
int group;
|
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
Issue: After SPT switchover, do shut and no-shut the received connected
interface, traffic stops.
R2
| |
+ +
Client-----R1--------R3----Source
R2 is RP.
Root cause:
Client is sending join for G and Source is sending traffic for G.
Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover,
traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets
created. first is (*, G) ifchannel which gets created because of (*, G)
join received from R1, second is (S, G) ifchannel which gets created
because of (s,g,rpt) prune received from R1
Shut the receiver connected interface on R1, R1 will send a (*, G) prune
towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel.
(s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer
expires. Before this timer expires, do noshut the received connected inrterface
on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G),
but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow
stops.
Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune
received, as (*,G) prune indicates that the router no longer wishes
to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G)
ifchannel, which was created because of (S,G,RPT) prune received
Signed-off-by: Sarita Patra <saritap@vmware.com>
2020-03-03 10:51:03 +01:00
|
|
|
struct pim_ifchannel *child = NULL;
|
|
|
|
struct listnode *ch_node, *nch_node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
buf = tlv_buf;
|
|
|
|
pastend = tlv_buf + tlv_buf_size;
|
2017-09-01 20:33:00 +02:00
|
|
|
pim_ifp = ifp->info;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/*
|
|
|
|
Parse ucast addr
|
|
|
|
*/
|
2022-01-14 16:38:41 +01:00
|
|
|
addr_offset = pim_parse_addr_ucast(&msg_upstream_addr, buf,
|
|
|
|
pastend - buf, &wrong_af);
|
2015-02-04 07:01:14 +01:00
|
|
|
if (addr_offset < 1) {
|
2022-01-17 11:07:39 +01:00
|
|
|
zlog_warn("%s: pim_parse_addr_ucast() failure: from %pPA on %s",
|
|
|
|
__func__, &src_addr, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
buf += addr_offset;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/*
|
|
|
|
Check upstream address family
|
|
|
|
*/
|
2022-01-14 16:38:41 +01:00
|
|
|
if (wrong_af) {
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn(
|
2022-01-17 11:07:39 +01:00
|
|
|
"%s: ignoring join/prune directed to unexpected addr family from %pPA on %s",
|
|
|
|
__func__, &src_addr, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
return -2;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
remain = pastend - buf;
|
|
|
|
if (remain < 4) {
|
|
|
|
zlog_warn(
|
2022-01-17 11:07:39 +01:00
|
|
|
"%s: short join/prune message buffer for group list: size=%d minimum=%d from %pPA on %s",
|
|
|
|
__func__, remain, 4, &src_addr, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
return -4;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
++buf; /* skip reserved byte */
|
|
|
|
msg_num_groups = *(const uint8_t *)buf;
|
|
|
|
++buf;
|
|
|
|
msg_holdtime = ntohs(*(const uint16_t *)buf);
|
2017-07-17 14:03:14 +02:00
|
|
|
++buf;
|
2015-02-04 07:01:14 +01:00
|
|
|
++buf;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-17 11:07:39 +01:00
|
|
|
if (PIM_DEBUG_PIM_J_P)
|
2016-07-24 01:18:19 +02:00
|
|
|
zlog_debug(
|
2022-01-17 11:07:39 +01:00
|
|
|
"%s: join/prune upstream=%pPAs groups=%d holdtime=%d from %pPA on %s",
|
2022-01-14 16:38:41 +01:00
|
|
|
__func__, &msg_upstream_addr, msg_num_groups,
|
2022-01-17 11:07:39 +01:00
|
|
|
msg_holdtime, &src_addr, ifp->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/* Scan groups */
|
|
|
|
for (group = 0; group < msg_num_groups; ++group) {
|
2022-01-04 17:54:44 +01:00
|
|
|
pim_sgaddr sg;
|
2015-02-04 07:01:14 +01:00
|
|
|
uint8_t msg_source_flags;
|
|
|
|
uint16_t msg_num_joined_sources;
|
|
|
|
uint16_t msg_num_pruned_sources;
|
|
|
|
int source;
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL;
|
2017-09-01 20:33:00 +02:00
|
|
|
bool filtered = false;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-04 17:54:44 +01:00
|
|
|
memset(&sg, 0, sizeof(sg));
|
2016-11-07 21:40:08 +01:00
|
|
|
addr_offset = pim_parse_addr_group(&sg, buf, pastend - buf);
|
2015-02-04 07:01:14 +01:00
|
|
|
if (addr_offset < 1) {
|
|
|
|
return -5;
|
|
|
|
}
|
|
|
|
buf += addr_offset;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
remain = pastend - buf;
|
|
|
|
if (remain < 4) {
|
|
|
|
zlog_warn(
|
2022-01-17 11:07:39 +01:00
|
|
|
"%s: short join/prune buffer for source list: size=%d minimum=%d from %pPA on %s",
|
|
|
|
__func__, remain, 4, &src_addr, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
return -6;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
msg_num_joined_sources = ntohs(*(const uint16_t *)buf);
|
|
|
|
buf += 2;
|
|
|
|
msg_num_pruned_sources = ntohs(*(const uint16_t *)buf);
|
|
|
|
buf += 2;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-17 11:07:39 +01:00
|
|
|
if (PIM_DEBUG_PIM_J_P)
|
2019-10-08 16:36:02 +02:00
|
|
|
zlog_debug(
|
2022-01-17 11:07:39 +01:00
|
|
|
"%s: join/prune upstream=%pPAs group=%pPA/32 join_src=%d prune_src=%d from %pPA on %s",
|
2022-01-14 16:38:41 +01:00
|
|
|
__func__, &msg_upstream_addr, &sg.grp,
|
2015-02-04 07:01:14 +01:00
|
|
|
msg_num_joined_sources, msg_num_pruned_sources,
|
2022-01-17 11:07:39 +01:00
|
|
|
&src_addr, ifp->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-09-01 20:33:00 +02:00
|
|
|
/* boundary check */
|
|
|
|
filtered = pim_is_group_filtered(pim_ifp, &sg.grp);
|
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/* Scan joined sources */
|
|
|
|
for (source = 0; source < msg_num_joined_sources; ++source) {
|
2016-11-07 21:45:40 +01:00
|
|
|
addr_offset = pim_parse_addr_source(
|
2016-07-13 02:13:32 +02:00
|
|
|
&sg, &msg_source_flags, buf, pastend - buf);
|
2015-02-04 07:01:14 +01:00
|
|
|
if (addr_offset < 1) {
|
|
|
|
return -7;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
buf += addr_offset;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-09-01 20:33:00 +02:00
|
|
|
/* if we are filtering this group, skip the join */
|
|
|
|
if (filtered)
|
|
|
|
continue;
|
|
|
|
|
2022-01-14 16:38:41 +01:00
|
|
|
recv_join(ifp, neigh, msg_holdtime, msg_upstream_addr,
|
|
|
|
&sg, msg_source_flags);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-01-04 21:48:13 +01:00
|
|
|
if (pim_addr_is_any(sg.src)) {
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
starg_ch = pim_ifchannel_find(ifp, &sg);
|
|
|
|
if (starg_ch)
|
|
|
|
pim_ifchannel_set_star_g_join_state(
|
2017-08-24 15:55:19 +02:00
|
|
|
starg_ch, 0, 1);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2016-11-08 21:26:48 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/* Scan pruned sources */
|
|
|
|
for (source = 0; source < msg_num_pruned_sources; ++source) {
|
2016-11-07 21:45:40 +01:00
|
|
|
addr_offset = pim_parse_addr_source(
|
2016-07-13 02:13:32 +02:00
|
|
|
&sg, &msg_source_flags, buf, pastend - buf);
|
2015-02-04 07:01:14 +01:00
|
|
|
if (addr_offset < 1) {
|
|
|
|
return -8;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
buf += addr_offset;
|
2017-09-01 20:33:00 +02:00
|
|
|
|
|
|
|
/* if we are filtering this group, skip the prune */
|
|
|
|
if (filtered)
|
|
|
|
continue;
|
|
|
|
|
2022-01-14 16:38:41 +01:00
|
|
|
recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr,
|
|
|
|
&sg, msg_source_flags);
|
2017-08-03 16:56:30 +02:00
|
|
|
/*
|
|
|
|
* So if we are receiving a S,G,RPT prune
|
|
|
|
* before we have any data for that S,G
|
|
|
|
* We need to retrieve the sg_ch after
|
|
|
|
* we parse the prune.
|
|
|
|
*/
|
|
|
|
sg_ch = pim_ifchannel_find(ifp, &sg);
|
|
|
|
|
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
Issue: After SPT switchover, do shut and no-shut the received connected
interface, traffic stops.
R2
| |
+ +
Client-----R1--------R3----Source
R2 is RP.
Root cause:
Client is sending join for G and Source is sending traffic for G.
Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover,
traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets
created. first is (*, G) ifchannel which gets created because of (*, G)
join received from R1, second is (S, G) ifchannel which gets created
because of (s,g,rpt) prune received from R1
Shut the receiver connected interface on R1, R1 will send a (*, G) prune
towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel.
(s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer
expires. Before this timer expires, do noshut the received connected inrterface
on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G),
but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow
stops.
Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune
received, as (*,G) prune indicates that the router no longer wishes
to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G)
ifchannel, which was created because of (S,G,RPT) prune received
Signed-off-by: Sarita Patra <saritap@vmware.com>
2020-03-03 10:51:03 +01:00
|
|
|
if (!sg_ch)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* (*,G) prune received */
|
|
|
|
for (ALL_LIST_ELEMENTS(sg_ch->sources, ch_node,
|
|
|
|
nch_node, child)) {
|
|
|
|
if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) {
|
|
|
|
if (child->ifjoin_state
|
|
|
|
== PIM_IFJOIN_PRUNE_PENDING_TMP)
|
|
|
|
THREAD_OFF(
|
|
|
|
child->t_ifjoin_prune_pending_timer);
|
2020-10-28 15:32:00 +01:00
|
|
|
THREAD_OFF(
|
|
|
|
child->t_ifjoin_expiry_timer);
|
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
Issue: After SPT switchover, do shut and no-shut the received connected
interface, traffic stops.
R2
| |
+ +
Client-----R1--------R3----Source
R2 is RP.
Root cause:
Client is sending join for G and Source is sending traffic for G.
Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover,
traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets
created. first is (*, G) ifchannel which gets created because of (*, G)
join received from R1, second is (S, G) ifchannel which gets created
because of (s,g,rpt) prune received from R1
Shut the receiver connected interface on R1, R1 will send a (*, G) prune
towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel.
(s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer
expires. Before this timer expires, do noshut the received connected inrterface
on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G),
but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow
stops.
Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune
received, as (*,G) prune indicates that the router no longer wishes
to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G)
ifchannel, which was created because of (S,G,RPT) prune received
Signed-off-by: Sarita Patra <saritap@vmware.com>
2020-03-03 10:51:03 +01:00
|
|
|
PIM_IF_FLAG_UNSET_S_G_RPT(child->flags);
|
|
|
|
child->ifjoin_state = PIM_IFJOIN_NOINFO;
|
2020-10-28 15:32:00 +01:00
|
|
|
delete_on_noinfo(child);
|
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
Issue: After SPT switchover, do shut and no-shut the received connected
interface, traffic stops.
R2
| |
+ +
Client-----R1--------R3----Source
R2 is RP.
Root cause:
Client is sending join for G and Source is sending traffic for G.
Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover,
traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets
created. first is (*, G) ifchannel which gets created because of (*, G)
join received from R1, second is (S, G) ifchannel which gets created
because of (s,g,rpt) prune received from R1
Shut the receiver connected interface on R1, R1 will send a (*, G) prune
towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel.
(s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer
expires. Before this timer expires, do noshut the received connected inrterface
on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G),
but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow
stops.
Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune
received, as (*,G) prune indicates that the router no longer wishes
to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G)
ifchannel, which was created because of (S,G,RPT) prune received
Signed-off-by: Sarita Patra <saritap@vmware.com>
2020-03-03 10:51:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
/* Received SG-RPT Prune delete oif from specific S,G */
|
pimd: Clear (s,g,rpt) ifchannel on (*, G) prune received
Issue: After SPT switchover, do shut and no-shut the received connected
interface, traffic stops.
R2
| |
+ +
Client-----R1--------R3----Source
R2 is RP.
Root cause:
Client is sending join for G and Source is sending traffic for G.
Before SPT switchover, traffic flows R3-R2-R1, after SPT switchover,
traffic flows R3-R1. Now Check in R2, there will be 2 ifchannel gets
created. first is (*, G) ifchannel which gets created because of (*, G)
join received from R1, second is (S, G) ifchannel which gets created
because of (s,g,rpt) prune received from R1
Shut the receiver connected interface on R1, R1 will send a (*, G) prune
towards RP (R2). On receiving (*, G) prune, R2 deletes the (*, G) ifchannel.
(s,g) ifchannel with flag (s,g,rpt) set will be timeout after the prune timer
expires. Before this timer expires, do noshut the received connected inrterface
on R1. R1 will send a (*,G) join to R2(RP), So oil will be updated in (*, G),
but wont get updated in (s,g) since the flag (s,g,rpt) is set. So traffic flow
stops.
Fix: When (*, G) ifchannel is getting deleted because of (*, G) prune
received, as (*,G) prune indicates that the router no longer wishes
to receive shared tree traffic, so clear (S,G,RPT) flag on all the child (S,G)
ifchannel, which was created because of (S,G,RPT) prune received
Signed-off-by: Sarita Patra <saritap@vmware.com>
2020-03-03 10:51:03 +01:00
|
|
|
if (starg_ch && (msg_source_flags & PIM_RPT_BIT_MASK)
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
&& !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) {
|
|
|
|
struct pim_upstream *up = sg_ch->upstream;
|
|
|
|
PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags);
|
|
|
|
if (up) {
|
2019-11-12 14:02:06 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
zlog_debug(
|
|
|
|
"%s: SGRpt flag is set, del inherit oif from up %s",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, up->sg_str);
|
2019-11-15 20:43:27 +01:00
|
|
|
pim_channel_del_inherited_oif(
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
up->channel_oil,
|
|
|
|
starg_ch->interface,
|
2019-11-15 17:47:33 +01:00
|
|
|
__func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
}
|
|
|
|
}
|
2017-09-01 20:33:00 +02:00
|
|
|
if (starg_ch && !filtered)
|
2017-08-24 15:55:19 +02:00
|
|
|
pim_ifchannel_set_star_g_join_state(starg_ch, 1, 0);
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
starg_ch = NULL;
|
2015-02-04 07:01:14 +01:00
|
|
|
} /* scan groups */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
/*
|
|
|
|
* J/P Message Format
|
|
|
|
*
|
|
|
|
* While the RFC clearly states that this is 32 bits wide, it
|
|
|
|
* is cheating. These fields:
|
|
|
|
* Encoded-Unicast format (6 bytes MIN)
|
|
|
|
* Encoded-Group format (8 bytes MIN)
|
|
|
|
* Encoded-Source format (8 bytes MIN)
|
|
|
|
* are *not* 32 bits wide.
|
|
|
|
*
|
|
|
|
* Nor does the RFC explicitly call out the size for:
|
|
|
|
* Reserved (1 byte)
|
|
|
|
* Num Groups (1 byte)
|
|
|
|
* Holdtime (2 bytes)
|
|
|
|
* Number of Joined Sources (2 bytes)
|
|
|
|
* Number of Pruned Sources (2 bytes)
|
|
|
|
*
|
|
|
|
* This leads to a missleading representation from casual
|
|
|
|
* reading and making assumptions. Be careful!
|
|
|
|
*
|
|
|
|
* 0 1 2 3
|
|
|
|
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* |PIM Ver| Type | Reserved | Checksum |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Upstream Neighbor Address (Encoded-Unicast format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Reserved | Num groups | Holdtime |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Multicast Group Address 1 (Encoded-Group format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Number of Joined Sources | Number of Pruned Sources |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Joined Source Address 1 (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | . |
|
|
|
|
* | . |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Joined Source Address n (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Pruned Source Address 1 (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | . |
|
|
|
|
* | . |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Pruned Source Address n (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Multicast Group Address m (Encoded-Group format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Number of Joined Sources | Number of Pruned Sources |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Joined Source Address 1 (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | . |
|
|
|
|
* | . |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Joined Source Address n (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Pruned Source Address 1 (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | . |
|
|
|
|
* | . |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | Pruned Source Address n (Encoded-Source format) |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
*/
|
2017-02-14 18:23:28 +01:00
|
|
|
int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
2017-02-15 03:32:16 +01:00
|
|
|
struct pim_jp_agg_group *group;
|
pimd: Fix WG/SGRpt & WG J/P processing
During processing of Join/Prune,
for a S,G entry, current state is SGRpt, when only *,G is
received, need to clear SGRpt and add/inherit the *,G OIF to S,G so
it can forward traffic to downstream where *,G is received.
Upon receiving SGRpt prune remove the inherited *,G OIF.
From, downstream router received *,G Prune along with SGRpt
prune. Avoid sending *,G and SGRpt Prune together.
Reset upstream_del reset ifchannel to NULL.
Testing Done:
Run failed smoke test of sending data packets, trigger SPT switchover,
*,G path received SGRpt later data traffic stopped S,G ages out from LHR, sends only
*,G join to upstream, verified S,G entry inherit the OIF.
Upon receiving SGRpt deletes inherited oif and retains in SGRpt state.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-04-22 00:08:03 +02:00
|
|
|
struct pim_interface *pim_ifp = NULL;
|
2017-02-15 03:32:16 +01:00
|
|
|
struct pim_jp_groups *grp = NULL;
|
2017-08-26 01:14:25 +02:00
|
|
|
struct pim_jp *msg = NULL;
|
2017-02-15 03:32:16 +01:00
|
|
|
struct listnode *node, *nnode;
|
|
|
|
uint8_t pim_msg[10000];
|
|
|
|
uint8_t *curr_ptr = pim_msg;
|
|
|
|
bool new_packet = true;
|
|
|
|
size_t packet_left = 0;
|
|
|
|
size_t packet_size = 0;
|
|
|
|
size_t group_size = 0;
|
2022-03-12 22:33:23 +01:00
|
|
|
pim_addr rpf_addr;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-25 07:32:23 +02:00
|
|
|
if (rpf->source_nexthop.interface)
|
|
|
|
pim_ifp = rpf->source_nexthop.interface->info;
|
|
|
|
else {
|
2020-03-06 15:23:22 +01:00
|
|
|
zlog_warn("%s: RPF interface is not present", __func__);
|
2017-04-25 07:32:23 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-03-12 22:33:23 +01:00
|
|
|
rpf_addr = pim_addr_from_prefix(&rpf->rpf_addr);
|
|
|
|
|
|
|
|
on_trace(__func__, rpf->source_nexthop.interface, rpf_addr);
|
2019-02-22 10:59:07 +01:00
|
|
|
|
pimd: Fix WG/SGRpt & WG J/P processing
During processing of Join/Prune,
for a S,G entry, current state is SGRpt, when only *,G is
received, need to clear SGRpt and add/inherit the *,G OIF to S,G so
it can forward traffic to downstream where *,G is received.
Upon receiving SGRpt prune remove the inherited *,G OIF.
From, downstream router received *,G Prune along with SGRpt
prune. Avoid sending *,G and SGRpt Prune together.
Reset upstream_del reset ifchannel to NULL.
Testing Done:
Run failed smoke test of sending data packets, trigger SPT switchover,
*,G path received SGRpt later data traffic stopped S,G ages out from LHR, sends only
*,G join to upstream, verified S,G entry inherit the OIF.
Upon receiving SGRpt deletes inherited oif and retains in SGRpt state.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-04-22 00:08:03 +02:00
|
|
|
if (!pim_ifp) {
|
2020-03-06 15:23:22 +01:00
|
|
|
zlog_warn("%s: multicast not enabled on interface %s", __func__,
|
2017-02-14 18:23:28 +01:00
|
|
|
rpf->source_nexthop.interface->name);
|
pimd: Fix WG/SGRpt & WG J/P processing
During processing of Join/Prune,
for a S,G entry, current state is SGRpt, when only *,G is
received, need to clear SGRpt and add/inherit the *,G OIF to S,G so
it can forward traffic to downstream where *,G is received.
Upon receiving SGRpt prune remove the inherited *,G OIF.
From, downstream router received *,G Prune along with SGRpt
prune. Avoid sending *,G and SGRpt Prune together.
Reset upstream_del reset ifchannel to NULL.
Testing Done:
Run failed smoke test of sending data packets, trigger SPT switchover,
*,G path received SGRpt later data traffic stopped S,G ages out from LHR, sends only
*,G join to upstream, verified S,G entry inherit the OIF.
Upon receiving SGRpt deletes inherited oif and retains in SGRpt state.
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-04-22 00:08:03 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-03-12 22:33:23 +01:00
|
|
|
if (pim_addr_is_any(rpf_addr)) {
|
|
|
|
if (PIM_DEBUG_PIM_J_P)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: upstream=%pPA is myself on interface %s",
|
|
|
|
__func__, &rpf_addr,
|
|
|
|
rpf->source_nexthop.interface->name);
|
2017-02-15 03:32:16 +01:00
|
|
|
return 0;
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
/*
|
|
|
|
RFC 4601: 4.3.1. Sending Hello Messages
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
Thus, if a router needs to send a Join/Prune or Assert message on
|
|
|
|
an interface on which it has not yet sent a Hello message with the
|
|
|
|
currently configured IP address, then it MUST immediately send the
|
|
|
|
relevant Hello message without waiting for the Hello Timer to
|
|
|
|
expire, followed by the Join/Prune or Assert message.
|
|
|
|
*/
|
2017-02-14 18:23:28 +01:00
|
|
|
pim_hello_require(rpf->source_nexthop.interface);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
for (ALL_LIST_ELEMENTS(groups, node, nnode, group)) {
|
|
|
|
if (new_packet) {
|
|
|
|
msg = (struct pim_jp *)pim_msg;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
memset(msg, 0, sizeof(*msg));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-03-12 22:33:23 +01:00
|
|
|
pim_msg_addr_encode_ucast((uint8_t *)&msg->addr,
|
|
|
|
rpf_addr);
|
2017-02-15 03:32:16 +01:00
|
|
|
msg->reserved = 0;
|
|
|
|
msg->holdtime = htons(PIM_JP_HOLDTIME);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
new_packet = false;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
grp = &msg->groups[0];
|
|
|
|
curr_ptr = (uint8_t *)grp;
|
|
|
|
packet_size = sizeof(struct pim_msg_header);
|
2022-01-14 14:57:21 +01:00
|
|
|
packet_size += sizeof(pim_encoded_unicast);
|
2017-02-15 03:32:16 +01:00
|
|
|
packet_size +=
|
|
|
|
4; // reserved (1) + groups (1) + holdtime (2)
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
packet_left = rpf->source_nexthop.interface->mtu - 24;
|
|
|
|
packet_left -= packet_size;
|
|
|
|
}
|
2022-03-12 22:33:23 +01:00
|
|
|
if (PIM_DEBUG_PIM_J_P)
|
2017-02-15 03:32:16 +01:00
|
|
|
zlog_debug(
|
2022-03-12 22:33:23 +01:00
|
|
|
"%s: sending (G)=%pPAs to upstream=%pPA on interface %s",
|
|
|
|
__func__, &group->group, &rpf_addr,
|
2017-02-15 03:32:16 +01:00
|
|
|
rpf->source_nexthop.interface->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
group_size = pim_msg_get_jp_group_size(group->sources);
|
|
|
|
if (group_size > packet_left) {
|
2022-03-27 11:50:40 +02:00
|
|
|
pim_msg_build_header(pim_ifp->primary_address,
|
|
|
|
qpim_all_pim_routers_addr, pim_msg,
|
|
|
|
packet_size,
|
2019-05-04 14:07:39 +02:00
|
|
|
PIM_MSG_TYPE_JOIN_PRUNE, false);
|
2017-02-15 03:32:16 +01:00
|
|
|
if (pim_msg_send(pim_ifp->pim_sock_fd,
|
|
|
|
pim_ifp->primary_address,
|
|
|
|
qpim_all_pim_routers_addr, pim_msg,
|
|
|
|
packet_size,
|
|
|
|
rpf->source_nexthop.interface->name)) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: could not send PIM message on interface %s",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__,
|
2017-02-15 03:32:16 +01:00
|
|
|
rpf->source_nexthop.interface->name);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
msg = (struct pim_jp *)pim_msg;
|
|
|
|
memset(msg, 0, sizeof(*msg));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2022-03-12 22:33:23 +01:00
|
|
|
pim_msg_addr_encode_ucast((uint8_t *)&msg->addr,
|
|
|
|
rpf_addr);
|
2017-02-15 03:32:16 +01:00
|
|
|
msg->reserved = 0;
|
|
|
|
msg->holdtime = htons(PIM_JP_HOLDTIME);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
new_packet = false;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
grp = &msg->groups[0];
|
|
|
|
curr_ptr = (uint8_t *)grp;
|
|
|
|
packet_size = sizeof(struct pim_msg_header);
|
2022-01-14 14:57:21 +01:00
|
|
|
packet_size += sizeof(pim_encoded_unicast);
|
2017-02-15 03:32:16 +01:00
|
|
|
packet_size +=
|
|
|
|
4; // reserved (1) + groups (1) + holdtime (2)
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
packet_left = rpf->source_nexthop.interface->mtu - 24;
|
|
|
|
packet_left -= packet_size;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
msg->num_groups++;
|
|
|
|
/*
|
|
|
|
Build PIM message
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
curr_ptr += group_size;
|
|
|
|
packet_left -= group_size;
|
|
|
|
packet_size += group_size;
|
2017-03-17 13:07:19 +01:00
|
|
|
pim_msg_build_jp_groups(grp, group, group_size);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-04-03 22:11:58 +02:00
|
|
|
pim_ifp->pim_ifstat_join_send += ntohs(grp->joins);
|
|
|
|
pim_ifp->pim_ifstat_prune_send += ntohs(grp->prunes);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
if (PIM_DEBUG_PIM_TRACE)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: interface %s num_joins %u num_prunes %u",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__, rpf->source_nexthop.interface->name,
|
pimd: Fix to Tx S,G Join when SGRpt->Join state
-Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join
towards FHR, unset SGRpt flag from channel,
add (*,G) oif to (S,G) entry.
-Add I am not RP check to triger SGRpt on *,G path otherwise,
send S,G Prune on SPT path from RP to FHR upon receving *,G Prune.
-Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G.
Testing Done:
pim-smoke
Ran 95 tests in 11790.552s
FAILED (SKIP=10, failures=4)
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
2017-05-12 21:05:46 +02:00
|
|
|
ntohs(grp->joins), ntohs(grp->prunes));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
grp = (struct pim_jp_groups *)curr_ptr;
|
|
|
|
if (packet_left < sizeof(struct pim_jp_groups)
|
|
|
|
|| msg->num_groups == 255) {
|
2022-03-27 11:50:40 +02:00
|
|
|
pim_msg_build_header(pim_ifp->primary_address,
|
|
|
|
qpim_all_pim_routers_addr, pim_msg,
|
|
|
|
packet_size,
|
2019-05-04 14:07:39 +02:00
|
|
|
PIM_MSG_TYPE_JOIN_PRUNE, false);
|
2017-02-15 03:32:16 +01:00
|
|
|
if (pim_msg_send(pim_ifp->pim_sock_fd,
|
|
|
|
pim_ifp->primary_address,
|
|
|
|
qpim_all_pim_routers_addr, pim_msg,
|
|
|
|
packet_size,
|
|
|
|
rpf->source_nexthop.interface->name)) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: could not send PIM message on interface %s",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__,
|
2017-02-15 03:32:16 +01:00
|
|
|
rpf->source_nexthop.interface->name);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
new_packet = true;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
if (!new_packet) {
|
|
|
|
// msg->num_groups = htons (msg->num_groups);
|
2022-03-27 11:50:40 +02:00
|
|
|
pim_msg_build_header(
|
|
|
|
pim_ifp->primary_address, qpim_all_pim_routers_addr,
|
|
|
|
pim_msg, packet_size, PIM_MSG_TYPE_JOIN_PRUNE, false);
|
2017-02-15 03:32:16 +01:00
|
|
|
if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address,
|
|
|
|
qpim_all_pim_routers_addr, pim_msg,
|
|
|
|
packet_size,
|
|
|
|
rpf->source_nexthop.interface->name)) {
|
|
|
|
zlog_warn(
|
|
|
|
"%s: could not send PIM message on interface %s",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__, rpf->source_nexthop.interface->name);
|
2017-02-15 03:32:16 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 07:01:14 +01:00
|
|
|
return 0;
|
|
|
|
}
|