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"
|
|
|
|
#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
|
|
|
|
2016-07-24 01:18:19 +02:00
|
|
|
static void on_trace(const char *label, struct interface *ifp,
|
|
|
|
struct in_addr src)
|
2015-02-04 07:01:14 +01:00
|
|
|
{
|
|
|
|
if (PIM_DEBUG_PIM_TRACE) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
|
|
|
|
zlog_debug("%s: from %s on %s", label, src_str, ifp->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
|
|
|
|
uint16_t holdtime, struct in_addr upstream,
|
2022-01-04 17:54:44 +01:00
|
|
|
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
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char up_str[INET_ADDRSTRLEN];
|
|
|
|
char neigh_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
|
|
|
|
pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str,
|
|
|
|
sizeof(neigh_str));
|
2022-01-04 21:24:48 +01:00
|
|
|
zlog_debug("%s: join (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
|
|
|
|
__func__, sg,
|
|
|
|
!!(source_flags & PIM_RPT_BIT_MASK),
|
|
|
|
!!(source_flags & PIM_WILDCARD_BIT_MASK), up_str,
|
|
|
|
holdtime, neigh_str, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
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);
|
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
|
|
|
|
*/
|
2017-06-05 19:44:15 +02:00
|
|
|
if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) {
|
|
|
|
char local_rp[INET_ADDRSTRLEN];
|
|
|
|
pim_inet4_dump("<local?>", rp->rpf_addr.u.prefix4,
|
|
|
|
local_rp, sizeof(local_rp));
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn(
|
2022-01-05 19:12:12 +01:00
|
|
|
"%s: Specified RP(%pPAs) in join is different than our configured RP(%s)",
|
|
|
|
__func__, &sg->src, local_rp);
|
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,
|
|
|
|
uint16_t holdtime, struct in_addr upstream,
|
2022-01-04 17:54:44 +01:00
|
|
|
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
|
|
|
|
2015-02-04 07:01:14 +01:00
|
|
|
if (PIM_DEBUG_PIM_TRACE) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char up_str[INET_ADDRSTRLEN];
|
|
|
|
char neigh_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<upstream?>", upstream, up_str, sizeof(up_str));
|
|
|
|
pim_inet4_dump("<neigh?>", neigh->source_addr, neigh_str,
|
|
|
|
sizeof(neigh_str));
|
2022-01-04 21:24:48 +01:00
|
|
|
zlog_debug("%s: prune (S,G)=%pSG rpt=%d wc=%d upstream=%s holdtime=%d from %s on %s",
|
|
|
|
__func__, sg,
|
|
|
|
source_flags & PIM_RPT_BIT_MASK,
|
|
|
|
source_flags & PIM_WILDCARD_BIT_MASK, up_str,
|
|
|
|
holdtime,
|
|
|
|
neigh_str, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
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,
|
|
|
|
struct in_addr src_addr, uint8_t *tlv_buf,
|
|
|
|
int tlv_buf_size)
|
|
|
|
{
|
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) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
|
|
|
|
zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, src_str, 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) {
|
2019-10-08 16:36:02 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
|
2020-03-05 19:17:54 +01:00
|
|
|
zlog_warn(
|
2022-01-14 16:38:41 +01:00
|
|
|
"%s: ignoring join/prune directed to unexpected addr family from %s on %s",
|
|
|
|
__func__, src_str, 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) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
|
|
|
|
zlog_warn(
|
|
|
|
"%s: short join/prune message buffer for group list: size=%d minimum=%d from %s on %s",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, remain, 4, src_str, 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
|
|
|
|
2016-07-24 01:18:19 +02:00
|
|
|
if (PIM_DEBUG_PIM_J_P) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
|
2016-07-24 01:18:19 +02:00
|
|
|
zlog_debug(
|
2022-01-14 16:38:41 +01:00
|
|
|
"%s: join/prune upstream=%pPAs groups=%d holdtime=%d from %s on %s",
|
|
|
|
__func__, &msg_upstream_addr, msg_num_groups,
|
|
|
|
msg_holdtime, src_str, ifp->name);
|
2015-02-04 07:01:14 +01:00
|
|
|
}
|
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) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str,
|
|
|
|
sizeof(src_str));
|
|
|
|
zlog_warn(
|
|
|
|
"%s: short join/prune buffer for source list: size=%d minimum=%d from %s on %s",
|
2020-03-05 19:17:54 +01:00
|
|
|
__func__, remain, 4, src_str, 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
|
|
|
|
2016-07-24 01:18:19 +02:00
|
|
|
if (PIM_DEBUG_PIM_J_P) {
|
2016-10-20 16:09:30 +02:00
|
|
|
char src_str[INET_ADDRSTRLEN];
|
2015-02-04 07:01:14 +01:00
|
|
|
pim_inet4_dump("<src?>", src_addr, src_str,
|
|
|
|
sizeof(src_str));
|
2019-10-08 16:36:02 +02:00
|
|
|
zlog_debug(
|
2022-01-14 16:38:41 +01:00
|
|
|
"%s: join/prune upstream=%pPAs group=%pPA/32 join_src=%d prune_src=%d from %s on %s",
|
|
|
|
__func__, &msg_upstream_addr, &sg.grp,
|
2015-02-04 07:01:14 +01:00
|
|
|
msg_num_joined_sources, msg_num_pruned_sources,
|
|
|
|
src_str, 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;
|
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
|
|
|
|
2020-03-06 15:23:22 +01:00
|
|
|
on_trace(__func__, rpf->source_nexthop.interface,
|
|
|
|
rpf->rpf_addr.u.prefix4);
|
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-01-13 14:37:42 +01:00
|
|
|
if (rpf->rpf_addr.u.prefix4.s_addr == INADDR_ANY) {
|
2017-02-15 03:32:16 +01:00
|
|
|
if (PIM_DEBUG_PIM_J_P) {
|
|
|
|
char dst_str[INET_ADDRSTRLEN];
|
|
|
|
pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4,
|
|
|
|
dst_str, sizeof(dst_str));
|
|
|
|
zlog_debug("%s: upstream=%s is myself on interface %s",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__, dst_str,
|
2017-02-15 03:32:16 +01:00
|
|
|
rpf->source_nexthop.interface->name);
|
|
|
|
}
|
|
|
|
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
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr,
|
|
|
|
rpf->rpf_addr.u.prefix4);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
if (PIM_DEBUG_PIM_J_P) {
|
|
|
|
char dst_str[INET_ADDRSTRLEN];
|
|
|
|
char grp_str[INET_ADDRSTRLEN];
|
|
|
|
pim_inet4_dump("<dst?>", rpf->rpf_addr.u.prefix4,
|
|
|
|
dst_str, sizeof(dst_str));
|
|
|
|
pim_inet4_dump("<grp?>", group->group, grp_str,
|
|
|
|
sizeof(grp_str));
|
|
|
|
zlog_debug(
|
|
|
|
"%s: sending (G)=%s to upstream=%s on interface %s",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__, grp_str, dst_str,
|
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) {
|
|
|
|
pim_msg_build_header(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
|
|
|
|
2017-02-15 03:32:16 +01:00
|
|
|
pim_msg_addr_encode_ipv4_ucast((uint8_t *)&msg->addr,
|
|
|
|
rpf->rpf_addr.u.prefix4);
|
|
|
|
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) {
|
|
|
|
pim_msg_build_header(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);
|
|
|
|
pim_msg_build_header(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__, rpf->source_nexthop.interface->name);
|
2017-02-15 03:32:16 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 07:01:14 +01:00
|
|
|
return 0;
|
|
|
|
}
|