Bug Summary

File:home/sharpd/frr3/pimd/pim_upstream.c
Warning:line 912, column 4
Value stored to 'rpf_result' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pim_upstream.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/sharpd/frr3 -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D HAVE_CONFIG_H -D SYSCONFDIR="/etc/frr/" -D CONFDATE=20240105 -I . -I ./lib/assert -I . -I ./include -I ./lib -I . -I /usr/include/lua5.3 -I /usr/include/x86_64-linux-gnu -D PIM_IPV=4 -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Wno-microsoft-anon-tag -fconst-strings -fdebug-compilation-dir=/home/sharpd/frr3 -ferror-limit 19 -fms-extensions -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-01-05-120749-780821-1 -x c pimd/pim_upstream.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * PIM for Quagga
4 * Copyright (C) 2008 Everton da Silva Marques
5 */
6
7#include <zebra.h>
8
9#include "log.h"
10#include "zclient.h"
11#include "memory.h"
12#include "frrevent.h"
13#include "linklist.h"
14#include "vty.h"
15#include "plist.h"
16#include "hash.h"
17#include "jhash.h"
18#include "wheel.h"
19#include "network.h"
20#include "frrdistance.h"
21
22#include "pimd.h"
23#include "pim_pim.h"
24#include "pim_str.h"
25#include "pim_time.h"
26#include "pim_iface.h"
27#include "pim_join.h"
28#include "pim_zlookup.h"
29#include "pim_upstream.h"
30#include "pim_ifchannel.h"
31#include "pim_neighbor.h"
32#include "pim_rpf.h"
33#include "pim_zebra.h"
34#include "pim_oil.h"
35#include "pim_macro.h"
36#include "pim_rp.h"
37#include "pim_register.h"
38#include "pim_msdp.h"
39#include "pim_jp_agg.h"
40#include "pim_nht.h"
41#include "pim_ssm.h"
42#include "pim_vxlan.h"
43#include "pim_mlag.h"
44
45static void join_timer_stop(struct pim_upstream *up);
46static void
47pim_upstream_update_assert_tracking_desired(struct pim_upstream *up);
48static bool_Bool pim_upstream_sg_running_proc(struct pim_upstream *up);
49
50/*
51 * A (*,G) or a (*,*) is going away
52 * remove the parent pointer from
53 * those pointing at us
54 */
55static void pim_upstream_remove_children(struct pim_instance *pim,
56 struct pim_upstream *up)
57{
58 struct pim_upstream *child;
59
60 if (!up->sources)
61 return;
62
63 while (!list_isempty(up->sources)((up->sources)->head == ((void*)0) && (up->sources
)->tail == ((void*)0))
) {
64 child = listnode_head(up->sources);
65 listnode_delete(up->sources, child);
66 if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)((child->flags) & (1 << 8))) {
67 PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags)((child->flags) &= ~(1 << 8));
68 child = pim_upstream_del(pim, child, __func__);
69 }
70 if (child) {
71 child->parent = NULL((void*)0);
72 if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags)((child->flags) & (1 << 20)))
73 pim_upstream_mroute_iif_update(
74 child->channel_oil,
75 __func__);
76 }
77 }
78 list_delete(&up->sources);
79}
80
81/*
82 * A (*,G) or a (*,*) is being created
83 * Find the children that would point
84 * at us.
85 */
86static void pim_upstream_find_new_children(struct pim_instance *pim,
87 struct pim_upstream *up)
88{
89 struct pim_upstream *child;
90
91 if (!pim_addr_is_any(up->sg.src) && !pim_addr_is_any(up->sg.grp))
92 return;
93
94 if (pim_addr_is_any(up->sg.src) && pim_addr_is_any(up->sg.grp))
95 return;
96
97 frr_each (rb_pim_upstream, &pim->upstream_head, child)for (child = rb_pim_upstream_first(&pim->upstream_head
); child; child = rb_pim_upstream_next(&pim->upstream_head
, child))
{
98 if (!pim_addr_is_any(up->sg.grp) &&
99 !pim_addr_cmp(child->sg.grp, up->sg.grp) && (child != up)) {
100 child->parent = up;
101 listnode_add_sort(up->sources, child);
102 if (PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags)((child->flags) & (1 << 20)))
103 pim_upstream_mroute_iif_update(
104 child->channel_oil,
105 __func__);
106 }
107 }
108}
109
110/*
111 * If we have a (*,*) || (S,*) there is no parent
112 * If we have a (S,G), find the (*,G)
113 * If we have a (*,G), find the (*,*)
114 */
115static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,
116 struct pim_upstream *child)
117{
118 pim_sgaddr any = child->sg;
119 struct pim_upstream *up = NULL((void*)0);
120
121 // (S,G)
122 if (!pim_addr_is_any(child->sg.src) &&
123 !pim_addr_is_any(child->sg.grp)) {
124 any.src = PIMADDR_ANY(pim_addr){ };
125 up = pim_upstream_find(pim, &any);
126
127 if (up)
128 listnode_add(up->sources, child);
129
130 /*
131 * In case parent is MLAG entry copy the data to child
132 */
133 if (up && PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)((up->flags)&(1 << 21))) {
134 PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(child->flags)((child->flags) |= (1 << 21));
135 if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)((up->flags) & (1 << 17)))
136 PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags)((child->flags) |= (1 << 17));
137 else
138 PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(((child->flags) &= ~(1 << 17))
139 child->flags)((child->flags) &= ~(1 << 17));
140 }
141
142 return up;
143 }
144
145 return NULL((void*)0);
146}
147
148static void upstream_channel_oil_detach(struct pim_upstream *up)
149{
150 struct channel_oil *channel_oil = up->channel_oil;
151
152 if (channel_oil) {
153 /* Detaching from channel_oil, channel_oil may exist post del,
154 but upstream would not keep reference of it
155 */
156 channel_oil->up = NULL((void*)0);
157 up->channel_oil = NULL((void*)0);
158
159 /* attempt to delete channel_oil; if channel_oil is being held
160 * because of other references cleanup info such as "Mute"
161 * inferred from the parent upstream
162 */
163 pim_channel_oil_upstream_deref(channel_oil);
164 }
165
166}
167
168static void pim_upstream_timers_stop(struct pim_upstream *up)
169{
170 EVENT_OFF(up->t_ka_timer)do { if ((up->t_ka_timer)) event_cancel(&(up->t_ka_timer
)); } while (0)
;
171 EVENT_OFF(up->t_rs_timer)do { if ((up->t_rs_timer)) event_cancel(&(up->t_rs_timer
)); } while (0)
;
172 EVENT_OFF(up->t_msdp_reg_timer)do { if ((up->t_msdp_reg_timer)) event_cancel(&(up->
t_msdp_reg_timer)); } while (0)
;
173 EVENT_OFF(up->t_join_timer)do { if ((up->t_join_timer)) event_cancel(&(up->t_join_timer
)); } while (0)
;
174}
175
176struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
177 struct pim_upstream *up, const char *name)
178{
179 struct listnode *node, *nnode;
180 struct pim_ifchannel *ch;
181 bool_Bool notify_msdp = false0;
182
183 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
184 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 188, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count"
), }; static const struct xref * const xref_p_84 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), __func__, name, up->sg_str, pim->vrf->name, up->
ref_count, up->flags, up->channel_oil->oil_ref_count
); } while (0)
185 "%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 188, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count"
), }; static const struct xref * const xref_p_84 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), __func__, name, up->sg_str, pim->vrf->name, up->
ref_count, up->flags, up->channel_oil->oil_ref_count
); } while (0)
186 __func__, name, up->sg_str, pim->vrf->name,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 188, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count"
), }; static const struct xref * const xref_p_84 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), __func__, name, up->sg_str, pim->vrf->name, up->
ref_count, up->flags, up->channel_oil->oil_ref_count
); } while (0)
187 up->ref_count, up->flags,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 188, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count"
), }; static const struct xref * const xref_p_84 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), __func__, name, up->sg_str, pim->vrf->name, up->
ref_count, up->flags, up->channel_oil->oil_ref_count
); } while (0)
188 up->channel_oil->oil_ref_count)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 188, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, pim->vrf->name, up->ref_count, up->flags, up->channel_oil->oil_ref_count"
), }; static const struct xref * const xref_p_84 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): Delete %s[%s] ref count: %d, flags: %d c_oil ref count %d (Pre decrement)"
), __func__, name, up->sg_str, pim->vrf->name, up->
ref_count, up->flags, up->channel_oil->oil_ref_count
); } while (0)
;
189
190 assert(up->ref_count > 0)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 190, "pimd/pim_upstream.c"
, __func__, }, .expr = "up->ref_count > 0", }; static const
struct xref * const xref_p_85 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect((up->ref_count
> 0) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((
void*)0)); } while (up->ref_count > 0); })
;
191
192 --up->ref_count;
193
194 if (up->ref_count >= 1)
195 return up;
196
197 if (PIM_DEBUG_TRACE(router->debugs & ((1 << 5) | (1 << 9))))
198 zlog_debug("pim_upstream free vrf:%s %s flags 0x%x",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("pim_upstream free vrf:%s %s flags 0x%x"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 199, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("pim_upstream free vrf:%s %s flags 0x%x"), .priority
= (7), .ec = (0), .args = ("pim->vrf->name, up->sg_str, up->flags"
), }; static const struct xref * const xref_p_86 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("pim_upstream free vrf:%s %s flags 0x%x"), pim->
vrf->name, up->sg_str, up->flags); } while (0)
199 pim->vrf->name, up->sg_str, up->flags)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("pim_upstream free vrf:%s %s flags 0x%x"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 199, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("pim_upstream free vrf:%s %s flags 0x%x"), .priority
= (7), .ec = (0), .args = ("pim->vrf->name, up->sg_str, up->flags"
), }; static const struct xref * const xref_p_86 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("pim_upstream free vrf:%s %s flags 0x%x"), pim->
vrf->name, up->sg_str, up->flags); } while (0)
;
200
201 if (pim_up_mlag_is_local(up))
202 pim_mlag_up_local_del(pim, up);
203
204 pim_upstream_timers_stop(up);
205
206 if (up->join_state == PIM_UPSTREAM_JOINED) {
207 pim_jp_agg_single_upstream_send(&up->rpf, up, 0);
208
209 if (pim_addr_is_any(up->sg.src)) {
210 /* if a (*, G) entry in the joined state is being
211 * deleted we
212 * need to notify MSDP */
213 notify_msdp = true1;
214 }
215 }
216
217 join_timer_stop(up);
218 pim_jp_agg_upstream_verification(up, false0);
219 up->rpf.source_nexthop.interface = NULL((void*)0);
220
221 if (!pim_addr_is_any(up->sg.src)) {
222 if (pim->upstream_sg_wheel)
223 wheel_remove_item(pim->upstream_sg_wheel, up);
224 notify_msdp = true1;
225 }
226
227 pim_mroute_del(up->channel_oil, __func__);
228 upstream_channel_oil_detach(up);
229
230 for (ALL_LIST_ELEMENTS(up->ifchannels, node, nnode, ch)(node) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (node) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 230, "pimd/pim_upstream.c"
, __func__, }, .expr = "node", }; static const struct xref * const
xref_p_87 __attribute__((used, section("xref_array"))) = &
(_xref.xref); if (__builtin_expect((node) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while (node); }), ({ static const
struct xref_assert _xref __attribute__( (used)) = { .xref = {
(((void*)0)), (XREFT_ASSERT), 230, "pimd/pim_upstream.c", __func__
, }, .expr = "(node)->data != NULL", }; static const struct
xref * const xref_p_88 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect(((node)->data
!= ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref
, ((void*)0)); } while ((node)->data != ((void*)0)); }), (
node)->data)), (nnode) = node->next, 1); (node) = (nnode
), ((ch) = ((void*)0))
)
231 pim_ifchannel_delete(ch);
232 list_delete(&up->ifchannels);
233
234 pim_upstream_remove_children(pim, up);
235 if (up->sources)
236 list_delete(&up->sources);
237
238 if (up->parent && up->parent->sources)
239 listnode_delete(up->parent->sources, up);
240 up->parent = NULL((void*)0);
241
242 rb_pim_upstream_del(&pim->upstream_head, up);
243
244 if (notify_msdp) {
245 pim_msdp_up_del(pim, &up->sg);
246 }
247
248 /* When RP gets deleted, pim_rp_del() deregister addr with Zebra NHT
249 * and assign up->upstream_addr as INADDR_ANY.
250 * So before de-registering the upstream address, check if is not equal
251 * to INADDR_ANY. This is done in order to avoid de-registering for
252 * 255.255.255.255 which is maintained for some reason..
253 */
254 if (!pim_addr_is_any(up->upstream_addr)) {
255 /* Deregister addr with Zebra NHT */
256 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
257 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 259, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr"
), }; static const struct xref * const xref_p_89 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), __func__, up->sg_str, &up->upstream_addr); } while
(0)
258 "%s: Deregister upstream %s addr %pPA with Zebra NHT",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 259, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr"
), }; static const struct xref * const xref_p_89 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), __func__, up->sg_str, &up->upstream_addr); } while
(0)
259 __func__, up->sg_str, &up->upstream_addr)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 259, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr"
), }; static const struct xref * const xref_p_89 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Deregister upstream %s addr %pPA with Zebra NHT"
), __func__, up->sg_str, &up->upstream_addr); } while
(0)
;
260 pim_delete_tracked_nexthop(pim, up->upstream_addr, up, NULL((void*)0));
261 }
262
263 XFREE(MTYPE_PIM_UPSTREAM, up)do { qfree(MTYPE_PIM_UPSTREAM, up); up = ((void*)0); } while (
0)
;
264
265 return NULL((void*)0);
266}
267
268void pim_upstream_send_join(struct pim_upstream *up)
269{
270 if (!up->rpf.source_nexthop.interface) {
271 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
272 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 273, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_90 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
273 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 273, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_90 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
274 return;
275 }
276
277 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
278 zlog_debug("%s: RPF'%s=%pPA(%s) for Interface %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF'%s=%pPA(%s) for Interface %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 281, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF'%s=%pPA(%s) for Interface %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str(up->join_state), up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_91 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: RPF'%s=%pPA(%s) for Interface %s"), __func__
, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str
(up->join_state), up->rpf.source_nexthop.interface->
name); } while (0)
279 up->sg_str, &up->rpf.rpf_addr,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF'%s=%pPA(%s) for Interface %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 281, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF'%s=%pPA(%s) for Interface %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str(up->join_state), up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_91 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: RPF'%s=%pPA(%s) for Interface %s"), __func__
, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str
(up->join_state), up->rpf.source_nexthop.interface->
name); } while (0)
280 pim_upstream_state2str(up->join_state),do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF'%s=%pPA(%s) for Interface %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 281, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF'%s=%pPA(%s) for Interface %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str(up->join_state), up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_91 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: RPF'%s=%pPA(%s) for Interface %s"), __func__
, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str
(up->join_state), up->rpf.source_nexthop.interface->
name); } while (0)
281 up->rpf.source_nexthop.interface->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF'%s=%pPA(%s) for Interface %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 281, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF'%s=%pPA(%s) for Interface %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str(up->join_state), up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_91 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: RPF'%s=%pPA(%s) for Interface %s"), __func__
, up->sg_str, &up->rpf.rpf_addr, pim_upstream_state2str
(up->join_state), up->rpf.source_nexthop.interface->
name); } while (0)
;
282 if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
283 zlog_debug("%s: can't send join upstream: RPF'%s=%pPA",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: can't send join upstream: RPF'%s=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 284, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: can't send join upstream: RPF'%s=%pPA"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr"
), }; static const struct xref * const xref_p_92 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: can't send join upstream: RPF'%s=%pPA"), __func__
, up->sg_str, &up->rpf.rpf_addr); } while (0)
284 __func__, up->sg_str, &up->rpf.rpf_addr)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: can't send join upstream: RPF'%s=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 284, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: can't send join upstream: RPF'%s=%pPA"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, &up->rpf.rpf_addr"
), }; static const struct xref * const xref_p_92 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: can't send join upstream: RPF'%s=%pPA"), __func__
, up->sg_str, &up->rpf.rpf_addr); } while (0)
;
285 /* warning only */
286 }
287 }
288
289 /* send Join(S,G) to the current upstream neighbor */
290 pim_jp_agg_single_upstream_send(&up->rpf, up, 1 /* join */);
291}
292
293static void on_join_timer(struct event *t)
294{
295 struct pim_upstream *up;
296
297 up = EVENT_ARG(t)((t)->arg);
298
299 if (!up->rpf.source_nexthop.interface) {
300 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
301 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 302, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_93 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
302 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 302, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_93 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
303 return;
304 }
305
306 /*
307 * In the case of a HFR we will not ahve anyone to send this to.
308 */
309 if (PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2)))
310 return;
311
312 /*
313 * Don't send the join if the outgoing interface is a loopback
314 * But since this might change leave the join timer running
315 */
316 if (up->rpf.source_nexthop
317 .interface && !if_is_loopback(up->rpf.source_nexthop.interface))
318 pim_upstream_send_join(up);
319
320 join_timer_start(up);
321}
322
323static void join_timer_stop(struct pim_upstream *up)
324{
325 struct pim_neighbor *nbr = NULL((void*)0);
326
327 EVENT_OFF(up->t_join_timer)do { if ((up->t_join_timer)) event_cancel(&(up->t_join_timer
)); } while (0)
;
328
329 if (up->rpf.source_nexthop.interface)
330 nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
331 up->rpf.rpf_addr, true1);
332
333 if (nbr)
334 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
335
336 pim_jp_agg_upstream_verification(up, false0);
337}
338
339void join_timer_start(struct pim_upstream *up)
340{
341 struct pim_neighbor *nbr = NULL((void*)0);
342
343 if (up->rpf.source_nexthop.interface) {
344 nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
345 up->rpf.rpf_addr, true1);
346
347 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0))) {
348 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 350, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .priority = (7), .ec = (0), .args = ("__func__, router->t_periodic, up->sg_str"
), }; static const struct xref * const xref_p_94 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: starting %d sec timer for upstream (S,G)=%s"
), __func__, router->t_periodic, up->sg_str); } while (
0)
349 "%s: starting %d sec timer for upstream (S,G)=%s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 350, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .priority = (7), .ec = (0), .args = ("__func__, router->t_periodic, up->sg_str"
), }; static const struct xref * const xref_p_94 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: starting %d sec timer for upstream (S,G)=%s"
), __func__, router->t_periodic, up->sg_str); } while (
0)
350 __func__, router->t_periodic, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 350, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: starting %d sec timer for upstream (S,G)=%s"
), .priority = (7), .ec = (0), .args = ("__func__, router->t_periodic, up->sg_str"
), }; static const struct xref * const xref_p_94 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: starting %d sec timer for upstream (S,G)=%s"
), __func__, router->t_periodic, up->sg_str); } while (
0)
;
351 }
352 }
353
354 if (nbr)
355 pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1, nbr);
356 else {
357 EVENT_OFF(up->t_join_timer)do { if ((up->t_join_timer)) event_cancel(&(up->t_join_timer
)); } while (0)
;
358 event_add_timer(router->master, on_join_timer, up,({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 359, "pimd/pim_upstream.c"
, __func__, }, .funcname = "on_join_timer", .dest = "&up->t_join_timer"
, .event_type = EVENT_TIMER, }; static const struct xref * const
xref_p_95 __attribute__((used, section("xref_array"))) = &
(_xref.xref); _event_add_timer(&_xref, router->master,
on_join_timer, up, router->t_periodic, &up->t_join_timer
); })
359 router->t_periodic, &up->t_join_timer)({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 359, "pimd/pim_upstream.c"
, __func__, }, .funcname = "on_join_timer", .dest = "&up->t_join_timer"
, .event_type = EVENT_TIMER, }; static const struct xref * const
xref_p_95 __attribute__((used, section("xref_array"))) = &
(_xref.xref); _event_add_timer(&_xref, router->master,
on_join_timer, up, router->t_periodic, &up->t_join_timer
); })
;
360 }
361 pim_jp_agg_upstream_verification(up, true1);
362}
363
364/*
365 * This is only called when we are switching the upstream
366 * J/P from one neighbor to another
367 *
368 * As such we need to remove from the old list and
369 * add to the new list.
370 */
371void pim_upstream_join_timer_restart(struct pim_upstream *up,
372 struct pim_rpf *old)
373{
374 // EVENT_OFF(up->t_join_timer);
375 join_timer_start(up);
376}
377
378static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,
379 int interval_msec)
380{
381 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0))) {
382 zlog_debug("%s: restarting %d msec timer for upstream (S,G)=%s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: restarting %d msec timer for upstream (S,G)=%s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 383, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: restarting %d msec timer for upstream (S,G)=%s"
), .priority = (7), .ec = (0), .args = ("__func__, interval_msec, up->sg_str"
), }; static const struct xref * const xref_p_96 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: restarting %d msec timer for upstream (S,G)=%s"
), __func__, interval_msec, up->sg_str); } while (0)
383 __func__, interval_msec, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: restarting %d msec timer for upstream (S,G)=%s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 383, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: restarting %d msec timer for upstream (S,G)=%s"
), .priority = (7), .ec = (0), .args = ("__func__, interval_msec, up->sg_str"
), }; static const struct xref * const xref_p_96 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: restarting %d msec timer for upstream (S,G)=%s"
), __func__, interval_msec, up->sg_str); } while (0)
;
384 }
385
386 EVENT_OFF(up->t_join_timer)do { if ((up->t_join_timer)) event_cancel(&(up->t_join_timer
)); } while (0)
;
387 event_add_timer_msec(router->master, on_join_timer, up, interval_msec,({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 388, "pimd/pim_upstream.c"
, __func__, }, .funcname = "on_join_timer", .dest = "&up->t_join_timer"
, .event_type = EVENT_TIMER, }; static const struct xref * const
xref_p_97 __attribute__((used, section("xref_array"))) = &
(_xref.xref); _event_add_timer_msec(&_xref, router->master
, on_join_timer, up, interval_msec, &up->t_join_timer)
; })
388 &up->t_join_timer)({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 388, "pimd/pim_upstream.c"
, __func__, }, .funcname = "on_join_timer", .dest = "&up->t_join_timer"
, .event_type = EVENT_TIMER, }; static const struct xref * const
xref_p_97 __attribute__((used, section("xref_array"))) = &
(_xref.xref); _event_add_timer_msec(&_xref, router->master
, on_join_timer, up, interval_msec, &up->t_join_timer)
; })
;
389}
390
391void pim_update_suppress_timers(uint32_t suppress_time)
392{
393 struct pim_instance *pim;
394 struct vrf *vrf;
395 unsigned int old_rp_ka_time;
396
397 /* stash the old one so we know which values were manually configured */
398 old_rp_ka_time = (3 * router->register_suppress_time
399 + router->register_probe_time);
400 router->register_suppress_time = suppress_time;
401
402 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)for ((vrf) = vrf_name_head_RB_MIN((&vrfs_by_name)); (vrf)
!= ((void*)0); (vrf) = vrf_name_head_RB_NEXT((vrf)))
{
403 pim = vrf->info;
404 if (!pim)
405 continue;
406
407 /* Only adjust if not manually configured */
408 if (pim->rp_keep_alive_time == old_rp_ka_time)
409 pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD(3 * router->register_suppress_time + router->register_probe_time
)
;
410 }
411}
412
413void pim_upstream_join_suppress(struct pim_upstream *up, pim_addr rpf,
414 int holdtime)
415{
416 long t_joinsuppress_msec;
417 long join_timer_remain_msec = 0;
418 struct pim_neighbor *nbr = NULL((void*)0);
419
420 if (!up->rpf.source_nexthop.interface) {
421 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
422 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 423, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_98 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
423 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 423, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_98 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
424 return;
425 }
426
427 t_joinsuppress_msec =
428 MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface),(((pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface
))<(1000 * holdtime))?(pim_if_t_suppressed_msec(up->rpf
.source_nexthop.interface)):(1000 * holdtime))
429 1000 * holdtime)(((pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface
))<(1000 * holdtime))?(pim_if_t_suppressed_msec(up->rpf
.source_nexthop.interface)):(1000 * holdtime))
;
430
431 if (up->t_join_timer)
432 join_timer_remain_msec =
433 pim_time_timer_remain_msec(up->t_join_timer);
434 else {
435 /* Remove it from jp agg from the nbr for suppression */
436 nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
437 up->rpf.rpf_addr, true1);
438
439 if (nbr) {
440 join_timer_remain_msec =
441 pim_time_timer_remain_msec(nbr->jp_timer);
442 }
443 }
444
445 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
446 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 449, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, &rpf, join_timer_remain_msec, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_99 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), "pimd/pim_upstream.c", __func__, up->sg_str, &rpf, join_timer_remain_msec
, t_joinsuppress_msec); } while (0)
447 "%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 449, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, &rpf, join_timer_remain_msec, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_99 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), "pimd/pim_upstream.c", __func__, up->sg_str, &rpf, join_timer_remain_msec
, t_joinsuppress_msec); } while (0)
448 __FILE__, __func__, up->sg_str, &rpf,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 449, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, &rpf, join_timer_remain_msec, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_99 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), "pimd/pim_upstream.c", __func__, up->sg_str, &rpf, join_timer_remain_msec
, t_joinsuppress_msec); } while (0)
449 join_timer_remain_msec, t_joinsuppress_msec)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 449, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), .priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, &rpf, join_timer_remain_msec, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_99 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: detected Join%s to RPF'(S,G)=%pPA: join_timer=%ld msec t_joinsuppress=%ld msec"
), "pimd/pim_upstream.c", __func__, up->sg_str, &rpf, join_timer_remain_msec
, t_joinsuppress_msec); } while (0)
;
450
451 if (join_timer_remain_msec < t_joinsuppress_msec) {
452 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
453 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: suppressing Join(S,G)=%s for %ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 456, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: suppressing Join(S,G)=%s for %ld msec"),
.priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_100 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: suppressing Join(S,G)=%s for %ld msec")
, "pimd/pim_upstream.c", __func__, up->sg_str, t_joinsuppress_msec
); } while (0)
454 "%s %s: suppressing Join(S,G)=%s for %ld msec",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: suppressing Join(S,G)=%s for %ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 456, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: suppressing Join(S,G)=%s for %ld msec"),
.priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_100 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: suppressing Join(S,G)=%s for %ld msec")
, "pimd/pim_upstream.c", __func__, up->sg_str, t_joinsuppress_msec
); } while (0)
455 __FILE__, __func__, up->sg_str,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: suppressing Join(S,G)=%s for %ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 456, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: suppressing Join(S,G)=%s for %ld msec"),
.priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_100 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: suppressing Join(S,G)=%s for %ld msec")
, "pimd/pim_upstream.c", __func__, up->sg_str, t_joinsuppress_msec
); } while (0)
456 t_joinsuppress_msec)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s %s: suppressing Join(S,G)=%s for %ld msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 456, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s %s: suppressing Join(S,G)=%s for %ld msec"),
.priority = (7), .ec = (0), .args = ("\"pimd/pim_upstream.c\", __func__, up->sg_str, t_joinsuppress_msec"
), }; static const struct xref * const xref_p_100 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s %s: suppressing Join(S,G)=%s for %ld msec")
, "pimd/pim_upstream.c", __func__, up->sg_str, t_joinsuppress_msec
); } while (0)
;
457 }
458
459 if (nbr)
460 pim_jp_agg_remove_group(nbr->upstream_jp_agg, up, nbr);
461
462 pim_upstream_join_timer_restart_msec(up, t_joinsuppress_msec);
463 }
464}
465
466void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
467 struct pim_upstream *up)
468{
469 long join_timer_remain_msec;
470 int t_override_msec;
471
472 if (!up->rpf.source_nexthop.interface) {
473 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
474 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 475, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_101 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
475 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 475, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_101 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
476 return;
477 }
478
479 t_override_msec =
480 pim_if_t_override_msec(up->rpf.source_nexthop.interface);
481
482 if (up->t_join_timer) {
483 join_timer_remain_msec =
484 pim_time_timer_remain_msec(up->t_join_timer);
485 } else {
486 /* upstream join tracked with neighbor jp timer */
487 struct pim_neighbor *nbr;
488
489 nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
490 up->rpf.rpf_addr, true1);
491
492 if (nbr)
493 join_timer_remain_msec =
494 pim_time_timer_remain_msec(nbr->jp_timer);
495 else
496 /* Manipulate such that override takes place */
497 join_timer_remain_msec = t_override_msec + 1;
498 }
499
500 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
501 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 504, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec, t_override_msec"
), }; static const struct xref * const xref_p_102 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec
, t_override_msec); } while (0)
502 "%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 504, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec, t_override_msec"
), }; static const struct xref * const xref_p_102 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec
, t_override_msec); } while (0)
503 debug_label, up->sg_str, &up->rpf.rpf_addr,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 504, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec, t_override_msec"
), }; static const struct xref * const xref_p_102 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec
, t_override_msec); } while (0)
504 join_timer_remain_msec, t_override_msec)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 504, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec, t_override_msec"
), }; static const struct xref * const xref_p_102 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: to RPF'%s=%pPA: join_timer=%ld msec t_override=%d msec"
), debug_label, up->sg_str, &up->rpf.rpf_addr, join_timer_remain_msec
, t_override_msec); } while (0)
;
505
506 if (join_timer_remain_msec > t_override_msec) {
507 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
508 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 510, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, t_override_msec"
), }; static const struct xref * const xref_p_103 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), debug_label, up->sg_str, t_override_msec); } while (0)
509 "%s: decreasing (S,G)=%s join timer to t_override=%d msec",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 510, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, t_override_msec"
), }; static const struct xref * const xref_p_103 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), debug_label, up->sg_str, t_override_msec); } while (0)
510 debug_label, up->sg_str, t_override_msec)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 510, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), .priority = (7), .ec = (0), .args = ("debug_label, up->sg_str, t_override_msec"
), }; static const struct xref * const xref_p_103 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: decreasing (S,G)=%s join timer to t_override=%d msec"
), debug_label, up->sg_str, t_override_msec); } while (0)
;
511 }
512
513 pim_upstream_join_timer_restart_msec(up, t_override_msec);
514 }
515}
516
517static void forward_on(struct pim_upstream *up)
518{
519 struct listnode *chnode;
520 struct listnode *chnextnode;
521 struct pim_ifchannel *ch = NULL((void*)0);
522
523 /* scan (S,G) state */
524 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 524, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_104 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 524, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_105 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
525 if (pim_macro_chisin_oiflist(ch))
526 pim_forward_start(ch);
527
528 } /* scan iface channel list */
529}
530
531static void forward_off(struct pim_upstream *up)
532{
533 struct listnode *chnode;
534 struct listnode *chnextnode;
535 struct pim_ifchannel *ch;
536
537 /* scan per-interface (S,G) state */
538 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 538, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_106 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 538, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_107 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
539
540 pim_forward_stop(ch);
541
542 } /* scan iface channel list */
543}
544
545int pim_upstream_could_register(struct pim_upstream *up)
546{
547 struct pim_interface *pim_ifp = NULL((void*)0);
548
549 /* FORCE_PIMREG is a generic flag to let an app like VxLAN-AA register
550 * a source on an upstream entry even if the source is not directly
551 * connected on the IIF.
552 */
553 if (PIM_UPSTREAM_FLAG_TEST_FORCE_PIMREG(up->flags)((up->flags) & (1 << 13)))
554 return 1;
555
556 if (up->rpf.source_nexthop.interface)
557 pim_ifp = up->rpf.source_nexthop.interface->info;
558 else {
559 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
560 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 561, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_108 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
561 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 561, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_108 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
562 }
563
564 if (pim_ifp && PIM_I_am_DR(pim_ifp)!pim_addr_cmp((pim_ifp)->pim_dr_addr, (pim_ifp)->primary_address
)
565 && pim_if_connected_to_source(up->rpf.source_nexthop.interface,
566 up->sg.src))
567 return 1;
568
569 return 0;
570}
571
572/* Source registration is suppressed for SSM groups. When the SSM range changes
573 * we re-revaluate register setup for existing upstream entries */
574void pim_upstream_register_reevaluate(struct pim_instance *pim)
575{
576 struct pim_upstream *up;
577
578 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
579 /* If FHR is set CouldRegister is True. Also check if the flow
580 * is actually active; if it is not kat setup will trigger
581 * source
582 * registration whenever the flow becomes active. */
583 if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2)) ||
584 !pim_upstream_is_kat_running(up))
585 continue;
586
587 if (pim_is_grp_ssm(pim, up->sg.grp)) {
588 /* clear the register state for SSM groups */
589 if (up->reg_state != PIM_REG_NOINFO) {
590 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0)))
591 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Clear register for %s as G is now SSM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 593, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Clear register for %s as G is now SSM"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_109 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("Clear register for %s as G is now SSM"
), up->sg_str); } while (0)
592 "Clear register for %s as G is now SSM",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Clear register for %s as G is now SSM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 593, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Clear register for %s as G is now SSM"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_109 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("Clear register for %s as G is now SSM"
), up->sg_str); } while (0)
593 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Clear register for %s as G is now SSM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 593, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Clear register for %s as G is now SSM"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_109 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("Clear register for %s as G is now SSM"
), up->sg_str); } while (0)
;
594 /* remove regiface from the OIL if it is there*/
595 pim_channel_del_oif(up->channel_oil,
596 pim->regiface,
597 PIM_OIF_FLAG_PROTO_PIM(1 << 1),
598 __func__);
599 up->reg_state = PIM_REG_NOINFO;
600 }
601 } else {
602 /* register ASM sources with the RP */
603 if (up->reg_state == PIM_REG_NOINFO) {
604 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0)))
605 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Register %s as G is now ASM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 607, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Register %s as G is now ASM"), .priority = (7),
.ec = (0), .args = ("up->sg_str"), }; static const struct
xref * const xref_p_110 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("Register %s as G is now ASM"
), up->sg_str); } while (0)
606 "Register %s as G is now ASM",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Register %s as G is now ASM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 607, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Register %s as G is now ASM"), .priority = (7),
.ec = (0), .args = ("up->sg_str"), }; static const struct
xref * const xref_p_110 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("Register %s as G is now ASM"
), up->sg_str); } while (0)
607 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Register %s as G is now ASM"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 607, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("Register %s as G is now ASM"), .priority = (7),
.ec = (0), .args = ("up->sg_str"), }; static const struct
xref * const xref_p_110 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("Register %s as G is now ASM"
), up->sg_str); } while (0)
;
608 pim_channel_add_oif(up->channel_oil,
609 pim->regiface,
610 PIM_OIF_FLAG_PROTO_PIM(1 << 1),
611 __func__);
612 up->reg_state = PIM_REG_JOIN;
613 }
614 }
615 }
616}
617
618/* RFC7761, Section 4.2 “Data Packet Forwarding Rules” says we should
619 * forward a S -
620 * 1. along the SPT if SPTbit is set
621 * 2. and along the RPT if SPTbit is not set
622 * If forwarding is hw accelerated i.e. control and dataplane components
623 * are separate you may not be able to reliably set SPT bit on intermediate
624 * routers while still forwarding on the (S,G,rpt).
625 *
626 * This macro is a slight deviation on the RFC and uses "traffic-agnostic"
627 * criteria to decide between using the RPT vs. SPT for forwarding.
628 */
629void pim_upstream_update_use_rpt(struct pim_upstream *up,
630 bool_Bool update_mroute)
631{
632 bool_Bool old_use_rpt;
633 bool_Bool new_use_rpt;
634
635 if (pim_addr_is_any(up->sg.src))
636 return;
637
638 old_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags)((up->flags) & (1 << 20));
639
640 /* We will use the SPT (IIF=RPF_interface(S) if -
641 * 1. We have decided to join the SPT
642 * 2. We are FHR
643 * 3. Source is directly connected
644 * 4. We are RP (parent's IIF is lo or vrf-device)
645 * In all other cases the source will stay along the RPT and
646 * IIF=RPF_interface(RP).
647 */
648 if (up->join_state == PIM_UPSTREAM_JOINED ||
649 PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2)) ||
650 pim_if_connected_to_source(
651 up->rpf.source_nexthop.interface,
652 up->sg.src) ||
653 /* XXX - need to switch this to a more efficient
654 * lookup API
655 */
656 I_am_RP(up->pim, up->sg.grp)pim_rp_i_am_rp ((up->pim), (up->sg.grp)))
657 /* use SPT */
658 PIM_UPSTREAM_FLAG_UNSET_USE_RPT(up->flags)((up->flags) &= ~(1 << 20));
659 else
660 /* use RPT */
661 PIM_UPSTREAM_FLAG_SET_USE_RPT(up->flags)((up->flags) |= (1 << 20));
662
663 new_use_rpt = !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags)((up->flags) & (1 << 20));
664 if (old_use_rpt != new_use_rpt) {
665 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0)))
666 zlog_debug("%s switched from %s to %s", up->sg_str,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s switched from %s to %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 668, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s switched from %s to %s"), .priority = (7), .
ec = (0), .args = ("up->sg_str, old_use_rpt ? \"RPT\" : \"SPT\", new_use_rpt ? \"RPT\" : \"SPT\""
), }; static const struct xref * const xref_p_111 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s switched from %s to %s"), up->sg_str, old_use_rpt
? "RPT" : "SPT", new_use_rpt ? "RPT" : "SPT"); } while (0)
667 old_use_rpt ? "RPT" : "SPT",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s switched from %s to %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 668, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s switched from %s to %s"), .priority = (7), .
ec = (0), .args = ("up->sg_str, old_use_rpt ? \"RPT\" : \"SPT\", new_use_rpt ? \"RPT\" : \"SPT\""
), }; static const struct xref * const xref_p_111 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s switched from %s to %s"), up->sg_str, old_use_rpt
? "RPT" : "SPT", new_use_rpt ? "RPT" : "SPT"); } while (0)
668 new_use_rpt ? "RPT" : "SPT")do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s switched from %s to %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 668, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s switched from %s to %s"), .priority = (7), .
ec = (0), .args = ("up->sg_str, old_use_rpt ? \"RPT\" : \"SPT\", new_use_rpt ? \"RPT\" : \"SPT\""
), }; static const struct xref * const xref_p_111 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s switched from %s to %s"), up->sg_str, old_use_rpt
? "RPT" : "SPT", new_use_rpt ? "RPT" : "SPT"); } while (0)
;
669 if (update_mroute)
670 pim_upstream_mroute_add(up->channel_oil, __func__);
671 }
672}
673
674/* some events like RP change require re-evaluation of SGrpt across
675 * all groups
676 */
677void pim_upstream_reeval_use_rpt(struct pim_instance *pim)
678{
679 struct pim_upstream *up;
680
681 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
682 if (pim_addr_is_any(up->sg.src))
683 continue;
684
685 pim_upstream_update_use_rpt(up, true1 /*update_mroute*/);
686 }
687}
688
689void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
690 enum pim_upstream_state new_state)
691{
692 enum pim_upstream_state old_state = up->join_state;
693
694 if (pim_addr_is_any(up->upstream_addr)) {
695 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0)))
696 zlog_debug("%s: RPF not configured for %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF not configured for %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 697, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF not configured for %s"), .priority = (7
), .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_112 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RPF not configured for %s"
), __func__, up->sg_str); } while (0)
697 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RPF not configured for %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 697, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RPF not configured for %s"), .priority = (7
), .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_112 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RPF not configured for %s"
), __func__, up->sg_str); } while (0)
;
698 return;
699 }
700
701 if (!up->rpf.source_nexthop.interface) {
702 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0)))
703 zlog_debug("%s: RP not reachable for %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RP not reachable for %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 704, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RP not reachable for %s"), .priority = (7),
.ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_113 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RP not reachable for %s"
), __func__, up->sg_str); } while (0)
704 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RP not reachable for %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 704, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RP not reachable for %s"), .priority = (7),
.ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_113 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RP not reachable for %s"
), __func__, up->sg_str); } while (0)
;
705 return;
706 }
707
708 if (PIM_DEBUG_PIM_EVENTS(router->debugs & (1 << 0))) {
709 zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 712, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str(new_state)"
), }; static const struct xref * const xref_p_114 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), __func__
, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str
(new_state)); } while (0)
710 __func__, up->sg_str,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 712, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str(new_state)"
), }; static const struct xref * const xref_p_114 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), __func__
, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str
(new_state)); } while (0)
711 pim_upstream_state2str(up->join_state),do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 712, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str(new_state)"
), }; static const struct xref * const xref_p_114 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), __func__
, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str
(new_state)); } while (0)
712 pim_upstream_state2str(new_state))do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 712, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str(new_state)"
), }; static const struct xref * const xref_p_114 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s"), __func__
, up->sg_str, pim_upstream_state2str(up->join_state), pim_upstream_state2str
(new_state)); } while (0)
;
713 }
714
715 up->join_state = new_state;
716 if (old_state != new_state)
717 up->state_transition = pim_time_monotonic_sec();
718
719 pim_upstream_update_assert_tracking_desired(up);
720
721 if (new_state == PIM_UPSTREAM_JOINED) {
722 pim_upstream_inherited_olist_decide(pim, up);
723 if (old_state != PIM_UPSTREAM_JOINED) {
724 int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2));
725
726 pim_msdp_up_join_state_changed(pim, up);
727 if (pim_upstream_could_register(up)) {
728 PIM_UPSTREAM_FLAG_SET_FHR(up->flags)((up->flags) |= (1 << 2));
729 if (!old_fhr
730 && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(((up->flags) & (1 << 5))
731 up->flags)((up->flags) & (1 << 5))) {
732 pim_upstream_keep_alive_timer_start(
733 up, pim->keep_alive_time);
734 pim_register_join(up);
735 }
736 } else {
737 pim_upstream_send_join(up);
738 join_timer_start(up);
739 }
740 }
741 if (old_state != new_state)
742 pim_upstream_update_use_rpt(up, true1 /*update_mroute*/);
743 } else {
744 bool_Bool old_use_rpt;
745 bool_Bool new_use_rpt;
746 bool_Bool send_xg_jp = false0;
747
748 forward_off(up);
749 /*
750 * RFC 4601 Sec 4.5.7:
751 * JoinDesired(S,G) -> False, set SPTbit to false.
752 */
753 if (!pim_addr_is_any(up->sg.src))
754 up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE;
755
756 if (old_state == PIM_UPSTREAM_JOINED)
757 pim_msdp_up_join_state_changed(pim, up);
758
759 if (old_state != new_state) {
760 old_use_rpt =
761 !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags)((up->flags) & (1 << 20));
762 pim_upstream_update_use_rpt(up, true1 /*update_mroute*/);
763 new_use_rpt =
764 !!PIM_UPSTREAM_FLAG_TEST_USE_RPT(up->flags)((up->flags) & (1 << 20));
765 if (new_use_rpt &&
766 (new_use_rpt != old_use_rpt) &&
767 up->parent)
768 /* we have decided to switch from the SPT back
769 * to the RPT which means we need to cancel
770 * any previously sent SGrpt prunes immediately
771 */
772 send_xg_jp = true1;
773 }
774
775 /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
776 RP.
777 If I am RP for G then send S,G prune to its IIF. */
778 if (pim_upstream_is_sg_rpt(up) && up->parent &&
779 !I_am_RP(pim, up->sg.grp)pim_rp_i_am_rp ((pim), (up->sg.grp)))
780 send_xg_jp = true1;
781
782 pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */);
783
784 if (send_xg_jp) {
785 if (PIM_DEBUG_PIM_TRACE_DETAIL(router->debugs & (1 << 6)))
786 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
787 "re-join RPT; *,G IIF %s S,G IIF %s ",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
788 up->parent->rpf.source_nexthop.interface ?do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
789 up->parent->rpf.source_nexthop.interface->namedo { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
790 : "Unknown",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
791 up->rpf.source_nexthop.interface ?do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
792 up->rpf.source_nexthop.interface->name :do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
793 "Unknown")do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("re-join RPT; *,G IIF %s S,G IIF %s "
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 793, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("re-join RPT; *,G IIF %s S,G IIF %s "), .priority
= (7), .ec = (0), .args = ("up->parent->rpf.source_nexthop.interface ? up->parent->rpf.source_nexthop.interface->name : \"Unknown\", up->rpf.source_nexthop.interface ? up->rpf.source_nexthop.interface->name : \"Unknown\""
), }; static const struct xref * const xref_p_115 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("re-join RPT; *,G IIF %s S,G IIF %s "), up->
parent->rpf.source_nexthop.interface ? up->parent->rpf
.source_nexthop.interface->name : "Unknown", up->rpf.source_nexthop
.interface ? up->rpf.source_nexthop.interface->name : "Unknown"
); } while (0)
;
794 pim_jp_agg_single_upstream_send(&up->parent->rpf,
795 up->parent,
796 1 /* (W,G) Join */);
797 }
798 join_timer_stop(up);
799 }
800}
801
802int pim_upstream_compare(const struct pim_upstream *up1,
803 const struct pim_upstream *up2)
804{
805 return pim_sgaddr_cmp(up1->sg, up2->sg);
806}
807
808void pim_upstream_fill_static_iif(struct pim_upstream *up,
809 struct interface *incoming)
810{
811 up->rpf.source_nexthop.interface = incoming;
812
813 /* reset other parameters to matched a connected incoming interface */
814 up->rpf.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY(pim_addr){ };
815 up->rpf.source_nexthop.mrib_metric_preference =
816 ZEBRA_CONNECT_DISTANCE_DEFAULT0;
817 up->rpf.source_nexthop.mrib_route_metric = 0;
818 up->rpf.rpf_addr = PIMADDR_ANY(pim_addr){ };
819}
820
821static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
822 pim_sgaddr *sg,
823 struct interface *incoming,
824 int flags,
825 struct pim_ifchannel *ch)
826{
827 enum pim_rpf_result rpf_result;
828 struct pim_interface *pim_ifp;
829 struct pim_upstream *up;
830
831 up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up))qcalloc(MTYPE_PIM_UPSTREAM, sizeof(*up));
832
833 up->pim = pim;
834 up->sg = *sg;
835 snprintfrr(up->sg_str, sizeof(up->sg_str), "%pSG", sg);
836 if (ch)
837 ch->upstream = up;
838
839 rb_pim_upstream_add(&pim->upstream_head, up);
840 /* Set up->upstream_addr as INADDR_ANY, if RP is not
841 * configured and retain the upstream data structure
842 */
843 if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
844 sg->grp)) {
845 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
846 zlog_debug("%s: Received a (*,G) with no RP configured",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Received a (*,G) with no RP configured"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 847, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Received a (*,G) with no RP configured"), .
priority = (7), .ec = (0), .args = ("__func__"), }; static const
struct xref * const xref_p_116 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Received a (*,G) with no RP configured"
), __func__); } while (0)
847 __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Received a (*,G) with no RP configured"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 847, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Received a (*,G) with no RP configured"), .
priority = (7), .ec = (0), .args = ("__func__"), }; static const
struct xref * const xref_p_116 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Received a (*,G) with no RP configured"
), __func__); } while (0)
;
848 }
849
850 up->parent = pim_upstream_find_parent(pim, up);
851 if (pim_addr_is_any(up->sg.src)) {
852 up->sources = list_new();
853 up->sources->cmp =
854 (int (*)(void *, void *))pim_upstream_compare;
855 } else
856 up->sources = NULL((void*)0);
857
858 pim_upstream_find_new_children(pim, up);
859 up->flags = flags;
860 up->ref_count = 1;
861 up->t_join_timer = NULL((void*)0);
862 up->t_ka_timer = NULL((void*)0);
863 up->t_rs_timer = NULL((void*)0);
864 up->t_msdp_reg_timer = NULL((void*)0);
865 up->join_state = PIM_UPSTREAM_NOTJOINED;
866 up->reg_state = PIM_REG_NOINFO;
867 up->state_transition = pim_time_monotonic_sec();
868 up->channel_oil = pim_channel_oil_add(pim, &up->sg, __func__);
869 up->sptbit = PIM_UPSTREAM_SPTBIT_FALSE;
870
871 up->rpf.source_nexthop.interface = NULL((void*)0);
872 up->rpf.source_nexthop.mrib_nexthop_addr = PIMADDR_ANY(pim_addr){ };
873 up->rpf.source_nexthop.mrib_metric_preference =
874 router->infinite_assert_metric.metric_preference;
875 up->rpf.source_nexthop.mrib_route_metric =
876 router->infinite_assert_metric.route_metric;
877 up->rpf.rpf_addr = PIMADDR_ANY(pim_addr){ };
878 up->ifchannels = list_new();
879 up->ifchannels->cmp = (int (*)(void *, void *))pim_ifchannel_compare;
880
881 if (!pim_addr_is_any(up->sg.src)) {
882 wheel_add_item(pim->upstream_sg_wheel, up);
883
884 /* Inherit the DF role from the parent (*, G) entry for
885 * VxLAN BUM groups
886 */
887 if (up->parent
888 && PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->parent->flags)((up->parent->flags) & (1 << 16))
889 && PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->parent->flags)((up->parent->flags) & (1 << 17))) {
890 PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(up->flags)((up->flags) |= (1 << 17));
891 if (PIM_DEBUG_VXLAN(router->debugs & (1 << 26)))
892 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("upstream %s inherited mlag non-df flag from parent"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 894, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("upstream %s inherited mlag non-df flag from parent"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_117 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("upstream %s inherited mlag non-df flag from parent"
), up->sg_str); } while (0)
893 "upstream %s inherited mlag non-df flag from parent",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("upstream %s inherited mlag non-df flag from parent"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 894, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("upstream %s inherited mlag non-df flag from parent"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_117 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("upstream %s inherited mlag non-df flag from parent"
), up->sg_str); } while (0)
894 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("upstream %s inherited mlag non-df flag from parent"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 894, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("upstream %s inherited mlag non-df flag from parent"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_117 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("upstream %s inherited mlag non-df flag from parent"
), up->sg_str); } while (0)
;
895 }
896 }
897
898 if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags)((up->flags) & (1 << 10))
899 || PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)((up->flags) &(1 << 19))) {
900 pim_upstream_fill_static_iif(up, incoming);
901 pim_ifp = up->rpf.source_nexthop.interface->info;
902 assert(pim_ifp)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 902, "pimd/pim_upstream.c"
, __func__, }, .expr = "pim_ifp", }; static const struct xref
* const xref_p_118 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect((pim_ifp) ? 0 :
1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(pim_ifp); })
;
903 pim_upstream_update_use_rpt(up,
904 false0 /*update_mroute*/);
905 pim_upstream_mroute_iif_update(up->channel_oil, __func__);
906
907 if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)((up->flags) &(1 << 19))) {
908 /*
909 * Set the right RPF so that future changes will
910 * be right
911 */
912 rpf_result = pim_rpf_update(pim, up, NULL((void*)0), __func__);
Value stored to 'rpf_result' is never read
913 pim_upstream_keep_alive_timer_start(
914 up, pim->keep_alive_time);
915 }
916 } else if (!pim_addr_is_any(up->upstream_addr)) {
917 pim_upstream_update_use_rpt(up,
918 false0 /*update_mroute*/);
919 rpf_result = pim_rpf_update(pim, up, NULL((void*)0), __func__);
920 if (rpf_result == PIM_RPF_FAILURE) {
921 up->channel_oil->oil_inherited_rescan = 1;
922 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
923 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 925, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_119 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), __func__, up->sg_str); } while (0)
924 "%s: Attempting to create upstream(%s), Unable to RPF for source",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 925, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_119 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), __func__, up->sg_str); } while (0)
925 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 925, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_119 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Attempting to create upstream(%s), Unable to RPF for source"
), __func__, up->sg_str); } while (0)
;
926 }
927
928 /* Consider a case where (S,G,rpt) prune is received and this
929 * upstream is getting created due to that, then as per RFC
930 * until prune pending time we need to behave same as NOINFO
931 * state, therefore do not install if OIF is NULL until then
932 * This is for PIM Conformance PIM-SM 16.3 fix
933 * When the prune pending timer pop, this mroute will get
934 * installed with none as OIF */
935 if (up->rpf.source_nexthop.interface &&
936 !(pim_upstream_empty_inherited_olist(up) && (ch != NULL((void*)0)) &&
937 PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)((ch->flags) & (1 << 2)))) {
938 pim_upstream_mroute_iif_update(up->channel_oil,
939 __func__);
940 }
941 }
942
943 /* send the entry to the MLAG peer */
944 /* XXX - duplicate send is possible here if pim_rpf_update
945 * successfully resolved the nexthop
946 */
947 if (pim_up_mlag_is_local(up)
948 || PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)((up->flags)&(1 << 21)))
949 pim_mlag_up_local_add(pim, up);
950
951 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
952 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 955, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr, up->ref_count"
), }; static const struct xref * const xref_p_120 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), __func__, up->sg_str, &up->upstream_addr, up->
ref_count); } while (0)
953 "%s: Created Upstream %s upstream_addr %pPAs ref count %d increment",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 955, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr, up->ref_count"
), }; static const struct xref * const xref_p_120 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), __func__, up->sg_str, &up->upstream_addr, up->
ref_count); } while (0)
954 __func__, up->sg_str, &up->upstream_addr,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 955, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr, up->ref_count"
), }; static const struct xref * const xref_p_120 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), __func__, up->sg_str, &up->upstream_addr, up->
ref_count); } while (0)
955 up->ref_count)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 955, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, &up->upstream_addr, up->ref_count"
), }; static const struct xref * const xref_p_120 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Created Upstream %s upstream_addr %pPAs ref count %d increment"
), __func__, up->sg_str, &up->upstream_addr, up->
ref_count); } while (0)
;
956 }
957
958 return up;
959}
960
961uint32_t pim_up_mlag_local_cost(struct pim_upstream *up)
962{
963 if (!(pim_up_mlag_is_local(up))
964 && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE(1 << 21)))
965 return router->infinite_assert_metric.route_metric;
966
967 if ((up->rpf.source_nexthop.interface ==
968 up->pim->vxlan.peerlink_rif) &&
969 (up->rpf.source_nexthop.mrib_route_metric <
970 (router->infinite_assert_metric.route_metric -
971 PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC10)))
972 return up->rpf.source_nexthop.mrib_route_metric +
973 PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC10;
974
975 return up->rpf.source_nexthop.mrib_route_metric;
976}
977
978uint32_t pim_up_mlag_peer_cost(struct pim_upstream *up)
979{
980 if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER(1 << 18)))
981 return router->infinite_assert_metric.route_metric;
982
983 return up->mlag.peer_mrib_metric;
984}
985
986struct pim_upstream *pim_upstream_find(struct pim_instance *pim, pim_sgaddr *sg)
987{
988 struct pim_upstream lookup;
989 struct pim_upstream *up = NULL((void*)0);
990
991 lookup.sg = *sg;
992 up = rb_pim_upstream_find(&pim->upstream_head, &lookup);
993 return up;
994}
995
996struct pim_upstream *pim_upstream_find_or_add(pim_sgaddr *sg,
997 struct interface *incoming,
998 int flags, const char *name)
999{
1000 struct pim_interface *pim_ifp = incoming->info;
1001
1002 return (pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
1003 NULL((void*)0)));
1004}
1005
1006void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
1007{
1008 /* if a local MLAG reference is being created we need to send the mroute
1009 * to the peer
1010 */
1011 if (!PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags)((up->flags) & (1 << 16)) &&
1012 PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags)((flags) & (1 << 16))) {
1013 PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(up->flags)((up->flags) |= (1 << 16));
1014 pim_mlag_up_local_add(up->pim, up);
1015 }
1016
1017 /* when we go from non-FHR to FHR we need to re-eval traffic
1018 * forwarding path
1019 */
1020 if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2)) &&
1021 PIM_UPSTREAM_FLAG_TEST_FHR(flags)((flags) & (1 << 2))) {
1022 PIM_UPSTREAM_FLAG_SET_FHR(up->flags)((up->flags) |= (1 << 2));
1023 pim_upstream_update_use_rpt(up, true1 /*update_mroute*/);
1024 }
1025
1026 /* re-eval joinDesired; clearing peer-msdp-sa flag can
1027 * cause JD to change
1028 */
1029 if (!PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)((up->flags) & (1 << 6)) &&
1030 PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags)((flags) & (1 << 6))) {
1031 PIM_UPSTREAM_FLAG_SET_SRC_MSDP(up->flags)((up->flags) |= (1 << 6));
1032 pim_upstream_update_join_desired(up->pim, up);
1033 }
1034
1035 up->flags |= flags;
1036 ++up->ref_count;
1037 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1038 zlog_debug("%s(%s): upstream %s ref count %d increment",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): upstream %s ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1039, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): upstream %s ref count %d increment"), .
priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, up->ref_count"
), }; static const struct xref * const xref_p_121 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): upstream %s ref count %d increment"), __func__
, name, up->sg_str, up->ref_count); } while (0)
1039 __func__, name, up->sg_str, up->ref_count)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): upstream %s ref count %d increment"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1039, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): upstream %s ref count %d increment"), .
priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, up->ref_count"
), }; static const struct xref * const xref_p_121 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): upstream %s ref count %d increment"), __func__
, name, up->sg_str, up->ref_count); } while (0)
;
1040}
1041
1042struct pim_upstream *pim_upstream_add(struct pim_instance *pim, pim_sgaddr *sg,
1043 struct interface *incoming, int flags,
1044 const char *name,
1045 struct pim_ifchannel *ch)
1046{
1047 struct pim_upstream *up = NULL((void*)0);
1048 int found = 0;
1049
1050 up = pim_upstream_find(pim, sg);
1051 if (up) {
1052 pim_upstream_ref(up, flags, name);
1053 found = 1;
1054 } else {
1055 up = pim_upstream_new(pim, sg, incoming, flags, ch);
1056 }
1057
1058 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
1059 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1060 "%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1061 __func__, name, up->sg_str, &up->rpf.rpf_addr,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1062 up->rpf.source_nexthop.interface ? up->rpf.source_nexthopdo { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1063 .interface->namedo { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1064 : "Unknown",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
1065 found, up->ref_count)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1065, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), .priority = (7), .ec = (0), .args = ("__func__, name, up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ? up->rpf.source_nexthop .interface->name : \"Unknown\", found, up->ref_count"
), }; static const struct xref * const xref_p_122 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d"
), __func__, name, up->sg_str, &up->rpf.rpf_addr, up
->rpf.source_nexthop.interface ? up->rpf.source_nexthop
.interface->name : "Unknown", found, up->ref_count); }
while (0)
;
1066 }
1067
1068 return up;
1069}
1070
1071/*
1072 * Passed in up must be the upstream for ch. starch is NULL if no
1073 * information
1074 * This function is copied over from
1075 * pim_upstream_evaluate_join_desired_interface but limited to
1076 * parent (*,G)'s includes/joins.
1077 */
1078int pim_upstream_eval_inherit_if(struct pim_upstream *up,
1079 struct pim_ifchannel *ch,
1080 struct pim_ifchannel *starch)
1081{
1082 /* if there is an explicit prune for this interface we cannot
1083 * add it to the OIL
1084 */
1085 if (ch) {
1086 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)((ch->flags) & (1 << 2)))
1087 return 0;
1088 }
1089
1090 /* Check if the OIF can be inherited fron the (*,G) entry
1091 */
1092 if (starch) {
1093 if (!pim_macro_ch_lost_assert(starch)
1094 && pim_macro_chisin_joins_or_include(starch))
1095 return 1;
1096 }
1097
1098 return 0;
1099}
1100
1101/*
1102 * Passed in up must be the upstream for ch. starch is NULL if no
1103 * information
1104 */
1105int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
1106 struct pim_ifchannel *ch,
1107 struct pim_ifchannel *starch)
1108{
1109 if (ch) {
1110 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)((ch->flags) & (1 << 2)))
1111 return 0;
1112
1113 if (!pim_macro_ch_lost_assert(ch)
1114 && pim_macro_chisin_joins_or_include(ch))
1115 return 1;
1116 }
1117
1118 /*
1119 * joins (*,G)
1120 */
1121 if (starch) {
1122 /* XXX: check on this with donald
1123 * we are looking for PIM_IF_FLAG_MASK_S_G_RPT in
1124 * upstream flags?
1125 */
1126#if 0
1127 if (PIM_IF_FLAG_TEST_S_G_RPT(starch->upstream->flags)((starch->upstream->flags) & (1 << 2)))
1128 return 0;
1129#endif
1130
1131 if (!pim_macro_ch_lost_assert(starch)
1132 && pim_macro_chisin_joins_or_include(starch))
1133 return 1;
1134 }
1135
1136 return 0;
1137}
1138
1139/* Returns true if immediate OIL is empty and is used to evaluate
1140 * JoinDesired. See pim_upstream_evaluate_join_desired.
1141 */
1142static bool_Bool pim_upstream_empty_immediate_olist(struct pim_instance *pim,
1143 struct pim_upstream *up)
1144{
1145 struct interface *ifp;
1146 struct pim_ifchannel *ch;
1147
1148 FOR_ALL_INTERFACES (pim->vrf, ifp)if (pim->vrf) for ((ifp) = if_name_head_RB_MIN((&pim->
vrf->ifaces_by_name)); (ifp) != ((void*)0); (ifp) = if_name_head_RB_NEXT
((ifp)))
{
1149 if (!ifp->info)
1150 continue;
1151
1152 ch = pim_ifchannel_find(ifp, &up->sg);
1153 if (!ch)
1154 continue;
1155
1156 /* If we have even one immediate OIF we can return with
1157 * not-empty
1158 */
1159 if (pim_upstream_evaluate_join_desired_interface(up, ch,
1160 NULL((void*)0) /* starch */))
1161 return false0;
1162 } /* scan iface channel list */
1163
1164 /* immediate_oil is empty */
1165 return true1;
1166}
1167
1168
1169static inline bool_Bool pim_upstream_is_msdp_peer_sa(struct pim_upstream *up)
1170{
1171 return PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(up->flags)((up->flags) & (1 << 6));
1172}
1173
1174/*
1175 * bool JoinDesired(*,G) {
1176 * if (immediate_olist(*,G) != NULL)
1177 * return TRUE
1178 * else
1179 * return FALSE
1180 * }
1181 *
1182 * bool JoinDesired(S,G) {
1183 * return( immediate_olist(S,G) != NULL
1184 * OR ( KeepaliveTimer(S,G) is running
1185 * AND inherited_olist(S,G) != NULL ) )
1186 * }
1187 */
1188bool_Bool pim_upstream_evaluate_join_desired(struct pim_instance *pim,
1189 struct pim_upstream *up)
1190{
1191 bool_Bool empty_imm_oil;
1192 bool_Bool empty_inh_oil;
1193
1194 empty_imm_oil = pim_upstream_empty_immediate_olist(pim, up);
1195
1196 /* (*,G) */
1197 if (pim_addr_is_any(up->sg.src))
1198 return !empty_imm_oil;
1199
1200 /* (S,G) */
1201 if (!empty_imm_oil)
1202 return true1;
1203 empty_inh_oil = pim_upstream_empty_inherited_olist(up);
1204 if (!empty_inh_oil &&
1205 (pim_upstream_is_kat_running(up) ||
1206 pim_upstream_is_msdp_peer_sa(up)))
1207 return true1;
1208
1209 return false0;
1210}
1211
1212/*
1213 See also pim_upstream_evaluate_join_desired() above.
1214*/
1215void pim_upstream_update_join_desired(struct pim_instance *pim,
1216 struct pim_upstream *up)
1217{
1218 int was_join_desired; /* boolean */
1219 int is_join_desired; /* boolean */
1220
1221 was_join_desired = PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)((up->flags) & (1 << 0));
1222
1223 is_join_desired = pim_upstream_evaluate_join_desired(pim, up);
1224 if (is_join_desired)
1225 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(up->flags)((up->flags) |= (1 << 0));
1226 else
1227 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(up->flags)((up->flags) &= ~(1 << 0));
1228
1229 /* switched from false to true */
1230 if (is_join_desired && (up->join_state == PIM_UPSTREAM_NOTJOINED)) {
1231 pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
1232 return;
1233 }
1234
1235 /* switched from true to false */
1236 if (!is_join_desired && was_join_desired) {
1237 pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
1238 return;
1239 }
1240}
1241
1242/*
1243 RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages
1244 Transitions from Joined State
1245 RPF'(S,G) GenID changes
1246
1247 The upstream (S,G) state machine remains in Joined state. If the
1248 Join Timer is set to expire in more than t_override seconds, reset
1249 it so that it expires after t_override seconds.
1250*/
1251void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
1252 pim_addr neigh_addr)
1253{
1254 struct pim_upstream *up;
1255
1256 /*
1257 * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
1258 */
1259 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
1260 pim_addr rpf_addr;
1261
1262 rpf_addr = up->rpf.rpf_addr;
1263
1264 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1265 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
1266 "%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
1267 __func__, &neigh_addr, up->sg_str,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
1268 pim->vrf->name,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
1269 up->join_state == PIM_UPSTREAM_JOINED,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
1270 &rpf_addr)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1270, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), .priority = (7), .ec = (0), .args = ("__func__, &neigh_addr, up->sg_str, pim->vrf->name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr"
), }; static const struct xref * const xref_p_123 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: matching neigh=%pPA against upstream (S,G)=%s[%s] joined=%d rpf_addr=%pPA"
), __func__, &neigh_addr, up->sg_str, pim->vrf->
name, up->join_state == PIM_UPSTREAM_JOINED, &rpf_addr
); } while (0)
;
1271
1272 /* consider only (S,G) upstream in Joined state */
1273 if (up->join_state != PIM_UPSTREAM_JOINED)
1274 continue;
1275
1276 /* match RPF'(S,G)=neigh_addr */
1277 if (pim_addr_cmp(rpf_addr, neigh_addr))
1278 continue;
1279
1280 pim_upstream_join_timer_decrease_to_t_override(
1281 "RPF'(S,G) GenID change", up);
1282 }
1283}
1284
1285
1286void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
1287 struct interface *old_rpf_ifp)
1288{
1289 struct listnode *chnode;
1290 struct listnode *chnextnode;
1291 struct pim_ifchannel *ch;
1292
1293 /* search all ifchannels */
1294 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1294, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_124 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1294, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_125 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
1295 if (ch->ifassert_state == PIM_IFASSERT_I_AM_LOSER) {
1296 if (
1297 /* RPF_interface(S) was NOT I */
1298 (old_rpf_ifp == ch->interface) &&
1299 /* RPF_interface(S) stopped being I */
1300 (ch->upstream->rpf.source_nexthop
1301 .interface) &&
1302 (ch->upstream->rpf.source_nexthop
1303 .interface != ch->interface)) {
1304 assert_action_a5(ch);
1305 }
1306 } /* PIM_IFASSERT_I_AM_LOSER */
1307
1308 pim_ifchannel_update_assert_tracking_desired(ch);
1309 }
1310}
1311
1312void pim_upstream_update_could_assert(struct pim_upstream *up)
1313{
1314 struct listnode *chnode;
1315 struct listnode *chnextnode;
1316 struct pim_ifchannel *ch;
1317
1318 /* scan per-interface (S,G) state */
1319 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1319, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_126 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1319, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_127 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
1320 pim_ifchannel_update_could_assert(ch);
1321 } /* scan iface channel list */
1322}
1323
1324void pim_upstream_update_my_assert_metric(struct pim_upstream *up)
1325{
1326 struct listnode *chnode;
1327 struct listnode *chnextnode;
1328 struct pim_ifchannel *ch;
1329
1330 /* scan per-interface (S,G) state */
1331 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1331, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_128 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1331, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_129 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
1332 pim_ifchannel_update_my_assert_metric(ch);
1333
1334 } /* scan iface channel list */
1335}
1336
1337static void pim_upstream_update_assert_tracking_desired(struct pim_upstream *up)
1338{
1339 struct listnode *chnode;
1340 struct listnode *chnextnode;
1341 struct pim_interface *pim_ifp;
1342 struct pim_ifchannel *ch;
1343
1344 /* scan per-interface (S,G) state */
1345 for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1345, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_130 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1345, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_131 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), (chnextnode) = chnode->next
, 1); (chnode) = (chnextnode), ((ch) = ((void*)0))
) {
1346 if (!ch->interface)
1347 continue;
1348 pim_ifp = ch->interface->info;
1349 if (!pim_ifp)
1350 continue;
1351
1352 pim_ifchannel_update_assert_tracking_desired(ch);
1353
1354 } /* scan iface channel list */
1355}
1356
1357/* When kat is stopped CouldRegister goes to false so we need to
1358 * transition the (S, G) on FHR to NI state and remove reg tunnel
1359 * from the OIL */
1360static void pim_upstream_fhr_kat_expiry(struct pim_instance *pim,
1361 struct pim_upstream *up)
1362{
1363 if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags)((up->flags) & (1 << 2)))
1364 return;
1365
1366 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1367 zlog_debug("kat expired on %s; clear fhr reg state",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat expired on %s; clear fhr reg state"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1368, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat expired on %s; clear fhr reg state"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_132 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat expired on %s; clear fhr reg state"
), up->sg_str); } while (0)
1368 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat expired on %s; clear fhr reg state"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1368, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat expired on %s; clear fhr reg state"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_132 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat expired on %s; clear fhr reg state"
), up->sg_str); } while (0)
;
1369
1370 /* stop reg-stop timer */
1371 EVENT_OFF(up->t_rs_timer)do { if ((up->t_rs_timer)) event_cancel(&(up->t_rs_timer
)); } while (0)
;
1372 /* remove regiface from the OIL if it is there*/
1373 pim_channel_del_oif(up->channel_oil, pim->regiface,
1374 PIM_OIF_FLAG_PROTO_PIM(1 << 1), __func__);
1375 /* clear the register state */
1376 up->reg_state = PIM_REG_NOINFO;
1377 PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags)((up->flags) &= ~(1 << 2));
1378}
1379
1380/* When kat is started CouldRegister can go to true. And if it does we
1381 * need to transition the (S, G) on FHR to JOINED state and add reg tunnel
1382 * to the OIL */
1383static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
1384{
1385 if (pim_upstream_could_register(up)) {
1386 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1387 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat started on %s; set fhr reg state to joined"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1389, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat started on %s; set fhr reg state to joined"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_133 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat started on %s; set fhr reg state to joined"
), up->sg_str); } while (0)
1388 "kat started on %s; set fhr reg state to joined",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat started on %s; set fhr reg state to joined"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1389, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat started on %s; set fhr reg state to joined"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_133 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat started on %s; set fhr reg state to joined"
), up->sg_str); } while (0)
1389 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat started on %s; set fhr reg state to joined"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1389, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat started on %s; set fhr reg state to joined"
), .priority = (7), .ec = (0), .args = ("up->sg_str"), }; static
const struct xref * const xref_p_133 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat started on %s; set fhr reg state to joined"
), up->sg_str); } while (0)
;
1390
1391 PIM_UPSTREAM_FLAG_SET_FHR(up->flags)((up->flags) |= (1 << 2));
1392 if (up->reg_state == PIM_REG_NOINFO)
1393 pim_register_join(up);
1394 pim_upstream_update_use_rpt(up, true1 /*update_mroute*/);
1395 }
1396}
1397
1398/*
1399 * On an RP, the PMBR value must be cleared when the
1400 * Keepalive Timer expires
1401 * KAT expiry indicates that flow is inactive. If the flow was created or
1402 * maintained by activity now is the time to deref it.
1403 */
1404struct pim_upstream *pim_upstream_keep_alive_timer_proc(
1405 struct pim_upstream *up)
1406{
1407 struct pim_instance *pim;
1408
1409 pim = up->channel_oil->pim;
1410
1411 if (PIM_UPSTREAM_FLAG_TEST_DISABLE_KAT_EXPIRY(up->flags)((up->flags) & (1 << 9))) {
1412 /* if the router is a PIM vxlan encapsulator we prevent expiry
1413 * of KAT as the mroute is pre-setup without any traffic
1414 */
1415 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
1416 return up;
1417 }
1418
1419 if (I_am_RP(pim, up->sg.grp)pim_rp_i_am_rp ((pim), (up->sg.grp))) {
1420 /*
1421 * Handle Border Router
1422 * We need to do more here :)
1423 * But this is the start.
1424 */
1425 }
1426
1427 /* source is no longer active - pull the SA from MSDP's cache */
1428 pim_msdp_sa_local_del(pim, &up->sg);
1429
1430 /* JoinDesired can change when KAT is started or stopped */
1431 pim_upstream_update_join_desired(pim, up);
1432
1433 /* if entry was created because of activity we need to deref it */
1434 if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)((up->flags) & (1 << 5))) {
1435 pim_upstream_fhr_kat_expiry(pim, up);
1436 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1437 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat expired on %s[%s]; remove stream reference"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1439, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat expired on %s[%s]; remove stream reference"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_134 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("kat expired on %s[%s]; remove stream reference"
), up->sg_str, pim->vrf->name); } while (0)
1438 "kat expired on %s[%s]; remove stream reference",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat expired on %s[%s]; remove stream reference"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1439, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat expired on %s[%s]; remove stream reference"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_134 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("kat expired on %s[%s]; remove stream reference"
), up->sg_str, pim->vrf->name); } while (0)
1439 up->sg_str, pim->vrf->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat expired on %s[%s]; remove stream reference"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1439, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat expired on %s[%s]; remove stream reference"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_134 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("kat expired on %s[%s]; remove stream reference"
), up->sg_str, pim->vrf->name); } while (0)
;
1440 PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags)((up->flags) &= ~(1 << 5));
1441
1442 /* Return if upstream entry got deleted.*/
1443 if (!pim_upstream_del(pim, up, __func__))
1444 return NULL((void*)0);
1445 }
1446 if (PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(up->flags)((up->flags) &(1 << 19))) {
1447 PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(up->flags)((up->flags) &= ~(1 << 19));
1448
1449 if (!pim_upstream_del(pim, up, __func__))
1450 return NULL((void*)0);
1451 }
1452
1453 /* upstream reference would have been added to track the local
1454 * membership if it is LHR. We have to clear it when KAT expires.
1455 * Otherwise would result in stale entry with uncleared ref count.
1456 */
1457 if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)((up->flags) & (1 << 8))) {
1458 struct pim_upstream *parent = up->parent;
1459
1460 PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags)((up->flags) &= ~(1 << 8));
1461 up = pim_upstream_del(pim, up, __func__);
1462
1463 if (parent) {
1464 pim_jp_agg_single_upstream_send(&parent->rpf, parent,
1465 true1);
1466 }
1467 }
1468
1469 return up;
1470}
1471static void pim_upstream_keep_alive_timer(struct event *t)
1472{
1473 struct pim_upstream *up;
1474
1475 up = EVENT_ARG(t)((t)->arg);
1476
1477 /* pull the stats and re-check */
1478 if (pim_upstream_sg_running_proc(up))
1479 /* kat was restarted because of new activity */
1480 return;
1481
1482 pim_upstream_keep_alive_timer_proc(up);
1483}
1484
1485void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
1486{
1487 if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)((up->flags) & (1 << 5))) {
1488 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1489 zlog_debug("kat start on %s with no stream reference",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat start on %s with no stream reference"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1490, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat start on %s with no stream reference"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_135 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat start on %s with no stream reference"
), up->sg_str); } while (0)
1490 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("kat start on %s with no stream reference"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1490, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("kat start on %s with no stream reference"), .priority
= (7), .ec = (0), .args = ("up->sg_str"), }; static const
struct xref * const xref_p_135 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("kat start on %s with no stream reference"
), up->sg_str); } while (0)
;
1491 }
1492 EVENT_OFF(up->t_ka_timer)do { if ((up->t_ka_timer)) event_cancel(&(up->t_ka_timer
)); } while (0)
;
1493 event_add_timer(router->master, pim_upstream_keep_alive_timer, up, time,({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1494, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_keep_alive_timer", .
dest = "&up->t_ka_timer", .event_type = EVENT_TIMER, }
; static const struct xref * const xref_p_136 __attribute__((
used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_keep_alive_timer
, up, time, &up->t_ka_timer); })
1494 &up->t_ka_timer)({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1494, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_keep_alive_timer", .
dest = "&up->t_ka_timer", .event_type = EVENT_TIMER, }
; static const struct xref * const xref_p_136 __attribute__((
used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_keep_alive_timer
, up, time, &up->t_ka_timer); })
;
1495
1496 /* any time keepalive is started against a SG we will have to
1497 * re-evaluate our active source database */
1498 pim_msdp_sa_local_update(up);
1499 /* JoinDesired can change when KAT is started or stopped */
1500 pim_upstream_update_join_desired(up->pim, up);
1501}
1502
1503/* MSDP on RP needs to know if a source is registerable to this RP */
1504static void pim_upstream_msdp_reg_timer(struct event *t)
1505{
1506 struct pim_upstream *up = EVENT_ARG(t)((t)->arg);
1507 struct pim_instance *pim = up->channel_oil->pim;
1508
1509 /* source is no longer active - pull the SA from MSDP's cache */
1510 pim_msdp_sa_local_del(pim, &up->sg);
1511}
1512
1513void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
1514{
1515 EVENT_OFF(up->t_msdp_reg_timer)do { if ((up->t_msdp_reg_timer)) event_cancel(&(up->
t_msdp_reg_timer)); } while (0)
;
1516 event_add_timer(router->master, pim_upstream_msdp_reg_timer, up,({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1517, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_msdp_reg_timer", .dest
= "&up->t_msdp_reg_timer", .event_type = EVENT_TIMER,
}; static const struct xref * const xref_p_137 __attribute__
((used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_msdp_reg_timer, up
, (3 * (1.5 * router->register_suppress_time)), &up->
t_msdp_reg_timer); })
1517 PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer)({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1517, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_msdp_reg_timer", .dest
= "&up->t_msdp_reg_timer", .event_type = EVENT_TIMER,
}; static const struct xref * const xref_p_137 __attribute__
((used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_msdp_reg_timer, up
, (3 * (1.5 * router->register_suppress_time)), &up->
t_msdp_reg_timer); })
;
1518
1519 pim_msdp_sa_local_update(up);
1520}
1521
1522/*
1523 * 4.2.1 Last-Hop Switchover to the SPT
1524 *
1525 * In Sparse-Mode PIM, last-hop routers join the shared tree towards the
1526 * RP. Once traffic from sources to joined groups arrives at a last-hop
1527 * router, it has the option of switching to receive the traffic on a
1528 * shortest path tree (SPT).
1529 *
1530 * The decision for a router to switch to the SPT is controlled as
1531 * follows:
1532 *
1533 * void
1534 * CheckSwitchToSpt(S,G) {
1535 * if ( ( pim_include(*,G) (-) pim_exclude(S,G)
1536 * (+) pim_include(S,G) != NULL )
1537 * AND SwitchToSptDesired(S,G) ) {
1538 * # Note: Restarting the KAT will result in the SPT switch
1539 * set KeepaliveTimer(S,G) to Keepalive_Period
1540 * }
1541 * }
1542 *
1543 * SwitchToSptDesired(S,G) is a policy function that is implementation
1544 * defined. An "infinite threshold" policy can be implemented by making
1545 * SwitchToSptDesired(S,G) return false all the time. A "switch on
1546 * first packet" policy can be implemented by making
1547 * SwitchToSptDesired(S,G) return true once a single packet has been
1548 * received for the source and group.
1549 */
1550int pim_upstream_switch_to_spt_desired_on_rp(struct pim_instance *pim,
1551 pim_sgaddr *sg)
1552{
1553 if (I_am_RP(pim, sg->grp)pim_rp_i_am_rp ((pim), (sg->grp)))
1554 return 1;
1555
1556 return 0;
1557}
1558
1559int pim_upstream_is_sg_rpt(struct pim_upstream *up)
1560{
1561 struct listnode *chnode;
1562 struct pim_ifchannel *ch;
1563
1564 for (ALL_LIST_ELEMENTS_RO(up->ifchannels, chnode, ch)(chnode) = ((up->ifchannels) ? ((up->ifchannels)->head
) : ((void*)0)), ((ch) = ((void*)0)); (chnode) != ((void*)0) &&
((ch) = ((({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1564, "pimd/pim_upstream.c"
, __func__, }, .expr = "chnode", }; static const struct xref *
const xref_p_138 __attribute__((used, section("xref_array"))
) = &(_xref.xref); if (__builtin_expect((chnode) ? 0 : 1,
0)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while
(chnode); }), ({ static const struct xref_assert _xref __attribute__
( (used)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 1564, "pimd/pim_upstream.c"
, __func__, }, .expr = "(chnode)->data != NULL", }; static
const struct xref * const xref_p_139 __attribute__((used, section
("xref_array"))) = &(_xref.xref); if (__builtin_expect(((
chnode)->data != ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while ((chnode)->data != ((void
*)0)); }), (chnode)->data)), 1); (chnode) = ((chnode) ? ((
chnode)->next) : ((void*)0)), ((ch) = ((void*)0))
) {
1565 if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)((ch->flags) & (1 << 2)))
1566 return 1;
1567 }
1568
1569 return 0;
1570}
1571/*
1572 * After receiving a packet set SPTbit:
1573 * void
1574 * Update_SPTbit(S,G,iif) {
1575 * if ( iif == RPF_interface(S)
1576 * AND JoinDesired(S,G) == true
1577 * AND ( DirectlyConnected(S) == true
1578 * OR RPF_interface(S) != RPF_interface(RP(G))
1579 * OR inherited_olist(S,G,rpt) == NULL
1580 * OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
1581 * ( RPF'(S,G) != NULL ) )
1582 * OR ( I_Am_Assert_Loser(S,G,iif) ) {
1583 * Set SPTbit(S,G) to true
1584 * }
1585 * }
1586 */
1587void pim_upstream_set_sptbit(struct pim_upstream *up,
1588 struct interface *incoming)
1589{
1590 struct pim_upstream *starup = up->parent;
1591
1592 // iif == RPF_interfvace(S)
1593 if (up->rpf.source_nexthop.interface != incoming) {
1594 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1595 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1598, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .priority = (7), .ec = (0), .args = ("__func__, incoming->name, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_140 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), __func__, incoming->name, up->rpf.source_nexthop.interface
->name); } while (0)
1596 "%s: Incoming Interface: %s is different than RPF_interface(S) %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1598, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .priority = (7), .ec = (0), .args = ("__func__, incoming->name, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_140 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), __func__, incoming->name, up->rpf.source_nexthop.interface
->name); } while (0)
1597 __func__, incoming->name,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1598, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .priority = (7), .ec = (0), .args = ("__func__, incoming->name, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_140 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), __func__, incoming->name, up->rpf.source_nexthop.interface
->name); } while (0)
1598 up->rpf.source_nexthop.interface->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1598, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), .priority = (7), .ec = (0), .args = ("__func__, incoming->name, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_140 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Incoming Interface: %s is different than RPF_interface(S) %s"
), __func__, incoming->name, up->rpf.source_nexthop.interface
->name); } while (0)
;
1599 return;
1600 }
1601
1602 // AND JoinDesired(S,G) == true
1603 if (!pim_upstream_evaluate_join_desired(up->channel_oil->pim, up)) {
1604 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1605 zlog_debug("%s: %s Join is not Desired", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s Join is not Desired"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1606, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s Join is not Desired"), .priority = (7), .
ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_141 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: %s Join is not Desired"
), __func__, up->sg_str); } while (0)
1606 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s Join is not Desired"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1606, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s Join is not Desired"), .priority = (7), .
ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_141 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: %s Join is not Desired"
), __func__, up->sg_str); } while (0)
;
1607 return;
1608 }
1609
1610 // DirectlyConnected(S) == true
1611 if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
1612 up->sg.src)) {
1613 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1614 zlog_debug("%s: %s is directly connected to the source",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s is directly connected to the source"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1615, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s is directly connected to the source"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_142 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s is directly connected to the source"), __func__
, up->sg_str); } while (0)
1615 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s is directly connected to the source"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1615, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s is directly connected to the source"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_142 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s is directly connected to the source"), __func__
, up->sg_str); } while (0)
;
1616 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
1617 return;
1618 }
1619
1620 // OR RPF_interface(S) != RPF_interface(RP(G))
1621 if (!starup
1622 || up->rpf.source_nexthop
1623 .interface != starup->rpf.source_nexthop.interface) {
1624 struct pim_upstream *starup = up->parent;
1625
1626 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1627 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1629, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_143 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), __func__, up->sg_str); } while (0)
1628 "%s: %s RPF_interface(S) != RPF_interface(RP(G))",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1629, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_143 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), __func__, up->sg_str); } while (0)
1629 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1629, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_143 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s RPF_interface(S) != RPF_interface(RP(G))"
), __func__, up->sg_str); } while (0)
;
1630 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
1631
1632 pim_jp_agg_single_upstream_send(&starup->rpf, starup, true1);
1633 return;
1634 }
1635
1636 // OR inherited_olist(S,G,rpt) == NULL
1637 if (pim_upstream_is_sg_rpt(up)
1638 && pim_upstream_empty_inherited_olist(up)) {
1639 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1640 zlog_debug("%s: %s OR inherited_olist(S,G,rpt) == NULL",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s OR inherited_olist(S,G,rpt) == NULL"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1641, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s OR inherited_olist(S,G,rpt) == NULL"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_144 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s OR inherited_olist(S,G,rpt) == NULL"), __func__
, up->sg_str); } while (0)
1641 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s OR inherited_olist(S,G,rpt) == NULL"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1641, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s OR inherited_olist(S,G,rpt) == NULL"), .
priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_144 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s OR inherited_olist(S,G,rpt) == NULL"), __func__
, up->sg_str); } while (0)
;
1642 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
1643 return;
1644 }
1645
1646 // OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
1647 // ( RPF'(S,G) != NULL ) )
1648 if (up->parent && pim_rpf_is_same(&up->rpf, &up->parent->rpf)) {
1649 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1650 zlog_debug("%s: %s RPF'(S,G) is the same as RPF'(*,G)",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1651, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str"), }; static
const struct xref * const xref_p_145 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"
), __func__, up->sg_str); } while (0)
1651 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1651, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str"), }; static
const struct xref * const xref_p_145 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: %s RPF'(S,G) is the same as RPF'(*,G)"
), __func__, up->sg_str); } while (0)
;
1652 up->sptbit = PIM_UPSTREAM_SPTBIT_TRUE;
1653 return;
1654 }
1655
1656 return;
1657}
1658
1659const char *pim_upstream_state2str(enum pim_upstream_state join_state)
1660{
1661 switch (join_state) {
1662 case PIM_UPSTREAM_NOTJOINED:
1663 return "NotJoined";
1664 case PIM_UPSTREAM_JOINED:
1665 return "Joined";
1666 }
1667 return "Unknown";
1668}
1669
1670const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str,
1671 size_t state_str_len)
1672{
1673 switch (reg_state) {
1674 case PIM_REG_NOINFO:
1675 strlcpy(state_str, "RegNoInfo", state_str_len);
1676 break;
1677 case PIM_REG_JOIN:
1678 strlcpy(state_str, "RegJoined", state_str_len);
1679 break;
1680 case PIM_REG_JOIN_PENDING:
1681 strlcpy(state_str, "RegJoinPend", state_str_len);
1682 break;
1683 case PIM_REG_PRUNE:
1684 strlcpy(state_str, "RegPrune", state_str_len);
1685 break;
1686 }
1687 return state_str;
1688}
1689
1690static void pim_upstream_register_stop_timer(struct event *t)
1691{
1692 struct pim_interface *pim_ifp;
1693 struct pim_instance *pim;
1694 struct pim_upstream *up;
1695 up = EVENT_ARG(t)((t)->arg);
1696 pim = up->channel_oil->pim;
1697
1698 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
1699 char state_str[PIM_REG_STATE_STR_LEN12];
1700 zlog_debug("%s: (S,G)=%s[%s] upstream register stop timer %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1703, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))"
), }; static const struct xref * const xref_p_146 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), __func__, up->sg_str, pim->vrf->name, pim_reg_state2str
(up->reg_state, state_str, sizeof(state_str))); } while (0
)
1701 __func__, up->sg_str, pim->vrf->name,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1703, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))"
), }; static const struct xref * const xref_p_146 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), __func__, up->sg_str, pim->vrf->name, pim_reg_state2str
(up->reg_state, state_str, sizeof(state_str))); } while (0
)
1702 pim_reg_state2str(up->reg_state, state_str,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1703, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))"
), }; static const struct xref * const xref_p_146 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), __func__, up->sg_str, pim->vrf->name, pim_reg_state2str
(up->reg_state, state_str, sizeof(state_str))); } while (0
)
1703 sizeof(state_str)))do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1703, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, pim_reg_state2str(up->reg_state, state_str, sizeof(state_str))"
), }; static const struct xref * const xref_p_146 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s[%s] upstream register stop timer %s"
), __func__, up->sg_str, pim->vrf->name, pim_reg_state2str
(up->reg_state, state_str, sizeof(state_str))); } while (0
)
;
1704 }
1705
1706 switch (up->reg_state) {
1707 case PIM_REG_JOIN_PENDING:
1708 up->reg_state = PIM_REG_JOIN;
1709 pim_channel_add_oif(up->channel_oil, pim->regiface,
1710 PIM_OIF_FLAG_PROTO_PIM(1 << 1),
1711 __func__);
1712 pim_vxlan_update_sg_reg_state(pim, up, true1 /*reg_join*/);
1713 break;
1714 case PIM_REG_JOIN:
1715 break;
1716 case PIM_REG_PRUNE:
1717 /* This is equalent to Couldreg -> False */
1718 if (!up->rpf.source_nexthop.interface) {
1719 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1720 zlog_debug("%s: up %s RPF is not present",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1721, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_147 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
1721 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1721, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_147 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
1722 up->reg_state = PIM_REG_NOINFO;
1723 PIM_UPSTREAM_FLAG_UNSET_FHR(up->flags)((up->flags) &= ~(1 << 2));
1724 return;
1725 }
1726
1727 pim_ifp = up->rpf.source_nexthop.interface->info;
1728 if (!pim_ifp) {
1729 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1730 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Interface: %s is not configured for pim"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1733, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Interface: %s is not configured for pim"), .
priority = (7), .ec = (0), .args = ("__func__, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_148 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Interface: %s is not configured for pim"),
__func__, up->rpf.source_nexthop.interface->name); } while
(0)
1731 "%s: Interface: %s is not configured for pim",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Interface: %s is not configured for pim"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1733, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Interface: %s is not configured for pim"), .
priority = (7), .ec = (0), .args = ("__func__, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_148 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Interface: %s is not configured for pim"),
__func__, up->rpf.source_nexthop.interface->name); } while
(0)
1732 __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Interface: %s is not configured for pim"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1733, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Interface: %s is not configured for pim"), .
priority = (7), .ec = (0), .args = ("__func__, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_148 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Interface: %s is not configured for pim"),
__func__, up->rpf.source_nexthop.interface->name); } while
(0)
1733 up->rpf.source_nexthop.interface->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Interface: %s is not configured for pim"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1733, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Interface: %s is not configured for pim"), .
priority = (7), .ec = (0), .args = ("__func__, up->rpf.source_nexthop.interface->name"
), }; static const struct xref * const xref_p_148 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Interface: %s is not configured for pim"),
__func__, up->rpf.source_nexthop.interface->name); } while
(0)
;
1734 return;
1735 }
1736 up->reg_state = PIM_REG_JOIN_PENDING;
1737 pim_upstream_start_register_stop_timer(up, 1);
1738
1739 if (((up->channel_oil->cc.lastused / 100)
1740 > pim->keep_alive_time)
1741 && (I_am_RP(pim_ifp->pim, up->sg.grp)pim_rp_i_am_rp ((pim_ifp->pim), (up->sg.grp)))) {
1742 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1743 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1745, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .priority = (7), .ec = (0), .args = ("__func__"), }; static
const struct xref * const xref_p_149 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), __func__); } while (0)
1744 "%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1745, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .priority = (7), .ec = (0), .args = ("__func__"), }; static
const struct xref * const xref_p_149 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), __func__); } while (0)
1745 __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1745, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), .priority = (7), .ec = (0), .args = ("__func__"), }; static
const struct xref * const xref_p_149 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: Stop sending the register, because I am the RP and we haven't seen a packet in a while"
), __func__); } while (0)
;
1746 return;
1747 }
1748 pim_null_register_send(up);
1749 break;
1750 case PIM_REG_NOINFO:
1751 break;
1752 }
1753}
1754
1755void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
1756 int null_register)
1757{
1758 uint32_t time;
1759
1760 EVENT_OFF(up->t_rs_timer)do { if ((up->t_rs_timer)) event_cancel(&(up->t_rs_timer
)); } while (0)
;
1761
1762 if (!null_register) {
1763 uint32_t lower = (0.5 * router->register_suppress_time);
1764 uint32_t upper = (1.5 * router->register_suppress_time);
1765 time = lower + (frr_weak_random() % (upper - lower + 1));
1766 /* Make sure we don't wrap around */
1767 if (time >= router->register_probe_time)
1768 time -= router->register_probe_time;
1769 else
1770 time = 0;
1771 } else
1772 time = router->register_probe_time;
1773
1774 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
1775 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1777, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, time"
), }; static const struct xref * const xref_p_150 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s Starting upstream register stop timer %d"
), __func__, up->sg_str, time); } while (0)
1776 "%s: (S,G)=%s Starting upstream register stop timer %d",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1777, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, time"
), }; static const struct xref * const xref_p_150 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s Starting upstream register stop timer %d"
), __func__, up->sg_str, time); } while (0)
1777 __func__, up->sg_str, time)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1777, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: (S,G)=%s Starting upstream register stop timer %d"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, time"
), }; static const struct xref * const xref_p_150 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: (S,G)=%s Starting upstream register stop timer %d"
), __func__, up->sg_str, time); } while (0)
;
1778 }
1779 event_add_timer(router->master, pim_upstream_register_stop_timer, up,({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1780, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_register_stop_timer"
, .dest = "&up->t_rs_timer", .event_type = EVENT_TIMER
, }; static const struct xref * const xref_p_151 __attribute__
((used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_register_stop_timer
, up, time, &up->t_rs_timer); })
1780 time, &up->t_rs_timer)({ static const struct xref_eventsched _xref __attribute__( (
used)) = { .xref = { (((void*)0)), (XREFT_EVENTSCHED), 1780, "pimd/pim_upstream.c"
, __func__, }, .funcname = "pim_upstream_register_stop_timer"
, .dest = "&up->t_rs_timer", .event_type = EVENT_TIMER
, }; static const struct xref * const xref_p_151 __attribute__
((used, section("xref_array"))) = &(_xref.xref); _event_add_timer
(&_xref, router->master, pim_upstream_register_stop_timer
, up, time, &up->t_rs_timer); })
;
1781}
1782
1783int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
1784 struct pim_upstream *up)
1785{
1786 struct interface *ifp;
1787 struct pim_ifchannel *ch, *starch;
1788 struct pim_upstream *starup = up->parent;
1789 int output_intf = 0;
1790
1791 if (!up->rpf.source_nexthop.interface)
1792 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1793 zlog_debug("%s: up %s RPF is not present", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1794, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_152 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
1794 up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: up %s RPF is not present"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1794, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: up %s RPF is not present"), .priority = (7)
, .ec = (0), .args = ("__func__, up->sg_str"), }; static const
struct xref * const xref_p_152 __attribute__((used, section(
"xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: up %s RPF is not present"
), __func__, up->sg_str); } while (0)
;
1795
1796 FOR_ALL_INTERFACES (pim->vrf, ifp)if (pim->vrf) for ((ifp) = if_name_head_RB_MIN((&pim->
vrf->ifaces_by_name)); (ifp) != ((void*)0); (ifp) = if_name_head_RB_NEXT
((ifp)))
{
1797 struct pim_interface *pim_ifp;
1798 if (!ifp->info)
1799 continue;
1800
1801 ch = pim_ifchannel_find(ifp, &up->sg);
1802
1803 if (starup)
1804 starch = pim_ifchannel_find(ifp, &starup->sg);
1805 else
1806 starch = NULL((void*)0);
1807
1808 if (!ch && !starch)
1809 continue;
1810
1811 pim_ifp = ifp->info;
1812 if (PIM_I_am_DualActive(pim_ifp)(pim_ifp)->activeactive == 1
1813 && PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)((up->flags)&(1 << 21))
1814 && (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)((up->flags) & (1 << 17))
1815 || !PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags)((up->flags) & (1 << 18))))
1816 continue;
1817 if (pim_upstream_evaluate_join_desired_interface(up, ch,
1818 starch)) {
1819 int flag = 0;
1820
1821 if (!ch)
1822 flag = PIM_OIF_FLAG_PROTO_STAR(1 << 2);
1823 else {
1824 if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)((ch->flags)&(1 << 4)))
1825 flag = PIM_OIF_FLAG_PROTO_GM(1 << 0);
1826 if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)((ch->flags)&(1 << 3)))
1827 flag |= PIM_OIF_FLAG_PROTO_PIM(1 << 1);
1828 if (starch)
1829 flag |= PIM_OIF_FLAG_PROTO_STAR(1 << 2);
1830 }
1831
1832 pim_channel_add_oif(up->channel_oil, ifp, flag,
1833 __func__);
1834 output_intf++;
1835 }
1836 }
1837
1838 return output_intf;
1839}
1840
1841/*
1842 * For a given upstream, determine the inherited_olist
1843 * and apply it.
1844 *
1845 * inherited_olist(S,G,rpt) =
1846 * ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
1847 * (+) ( pim_include(*,G) (-) pim_exclude(S,G))
1848 * (-) ( lost_assert(*,G) (+) lost_assert(S,G,rpt) )
1849 *
1850 * inherited_olist(S,G) =
1851 * inherited_olist(S,G,rpt) (+)
1852 * joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G)
1853 *
1854 * return 1 if there are any output interfaces
1855 * return 0 if there are not any output interfaces
1856 */
1857int pim_upstream_inherited_olist(struct pim_instance *pim,
1858 struct pim_upstream *up)
1859{
1860 int output_intf = pim_upstream_inherited_olist_decide(pim, up);
1861
1862 /*
1863 * If we have output_intf switch state to Join and work like normal
1864 * If we don't have an output_intf that means we are probably a
1865 * switch on a stick so turn on forwarding to just accept the
1866 * incoming packets so we don't bother the other stuff!
1867 */
1868 pim_upstream_update_join_desired(pim, up);
1869
1870 if (!output_intf)
1871 forward_on(up);
1872
1873 return output_intf;
1874}
1875
1876int pim_upstream_empty_inherited_olist(struct pim_upstream *up)
1877{
1878 return pim_channel_oil_empty(up->channel_oil);
1879}
1880
1881/*
1882 * When we have a new neighbor,
1883 * find upstreams that don't have their rpf_addr
1884 * set and see if the new neighbor allows
1885 * the join to be sent
1886 */
1887void pim_upstream_find_new_rpf(struct pim_instance *pim)
1888{
1889 struct pim_upstream *up;
1890 struct pim_rpf old;
1891 enum pim_rpf_result rpf_result;
1892
1893 /*
1894 * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
1895 */
1896 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
1897 if (pim_addr_is_any(up->upstream_addr)) {
1898 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1899 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RP not configured for Upstream %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1901, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RP not configured for Upstream %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str"), }; static
const struct xref * const xref_p_153 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RP not configured for Upstream %s"
), __func__, up->sg_str); } while (0)
1900 "%s: RP not configured for Upstream %s",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RP not configured for Upstream %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1901, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RP not configured for Upstream %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str"), }; static
const struct xref * const xref_p_153 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RP not configured for Upstream %s"
), __func__, up->sg_str); } while (0)
1901 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: RP not configured for Upstream %s"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1901, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: RP not configured for Upstream %s"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str"), }; static
const struct xref * const xref_p_153 __attribute__((used, section
("xref_array"))) = &(_xref.xref); zlog_ref(&_xref, ("%s: RP not configured for Upstream %s"
), __func__, up->sg_str); } while (0)
;
1902 continue;
1903 }
1904
1905 if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
1906 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
1907 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Upstream %s without a path to send join, checking"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1909, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Upstream %s without a path to send join, checking"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_154 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Upstream %s without a path to send join, checking"
), __func__, up->sg_str); } while (0)
1908 "%s: Upstream %s without a path to send join, checking",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Upstream %s without a path to send join, checking"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1909, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Upstream %s without a path to send join, checking"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_154 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Upstream %s without a path to send join, checking"
), __func__, up->sg_str); } while (0)
1909 __func__, up->sg_str)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Upstream %s without a path to send join, checking"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 1909, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Upstream %s without a path to send join, checking"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str"
), }; static const struct xref * const xref_p_154 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Upstream %s without a path to send join, checking"
), __func__, up->sg_str); } while (0)
;
1910 old.source_nexthop.interface =
1911 up->rpf.source_nexthop.interface;
1912 rpf_result = pim_rpf_update(pim, up, &old, __func__);
1913 if (rpf_result == PIM_RPF_CHANGED ||
1914 (rpf_result == PIM_RPF_FAILURE &&
1915 old.source_nexthop.interface))
1916 pim_zebra_upstream_rpf_changed(pim, up, &old);
1917 /* update kernel multicast forwarding cache (MFC) */
1918 pim_upstream_mroute_iif_update(up->channel_oil,
1919 __func__);
1920 }
1921 }
1922 pim_zebra_update_all_interfaces(pim);
1923}
1924
1925unsigned int pim_upstream_hash_key(const void *arg)
1926{
1927 const struct pim_upstream *up = arg;
1928
1929 return pim_sgaddr_hash(up->sg, 0);
1930}
1931
1932void pim_upstream_terminate(struct pim_instance *pim)
1933{
1934 struct pim_upstream *up;
1935
1936 while ((up = rb_pim_upstream_first(&pim->upstream_head))) {
1937 if (pim_upstream_del(pim, up, __func__))
1938 pim_upstream_timers_stop(up);
1939 }
1940
1941 rb_pim_upstream_fini(&pim->upstream_head);
1942
1943 if (pim->upstream_sg_wheel)
1944 wheel_delete(pim->upstream_sg_wheel);
1945 pim->upstream_sg_wheel = NULL((void*)0);
1946}
1947
1948bool_Bool pim_upstream_equal(const void *arg1, const void *arg2)
1949{
1950 const struct pim_upstream *up1 = (const struct pim_upstream *)arg1;
1951 const struct pim_upstream *up2 = (const struct pim_upstream *)arg2;
1952
1953 return !pim_sgaddr_cmp(up1->sg, up2->sg);
1954}
1955
1956/* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines
1957 * the cases where kat has to be restarted on rxing traffic -
1958 *
1959 * if( DirectlyConnected(S) == true AND iif == RPF_interface(S) ) {
1960 * set KeepaliveTimer(S,G) to Keepalive_Period
1961 * # Note: a register state transition or UpstreamJPState(S,G)
1962 * # transition may happen as a result of restarting
1963 * # KeepaliveTimer, and must be dealt with here.
1964 * }
1965 * if( iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined AND
1966 * inherited_olist(S,G) != NULL ) {
1967 * set KeepaliveTimer(S,G) to Keepalive_Period
1968 * }
1969 */
1970static bool_Bool pim_upstream_kat_start_ok(struct pim_upstream *up)
1971{
1972 struct channel_oil *c_oil = up->channel_oil;
1973 struct interface *ifp = up->rpf.source_nexthop.interface;
1974 struct pim_interface *pim_ifp;
1975 struct pim_instance *pim = up->channel_oil->pim;
1976
1977 /* "iif == RPF_interface(S)" check is not easy to do as the info
1978 * we get from the kernel/ASIC is really a "lookup/key hit".
1979 * So we will do an approximate check here to avoid starting KAT
1980 * because of (S,G,rpt) forwarding on a non-LHR.
1981 */
1982 if (!ifp)
1983 return false0;
1984
1985 pim_ifp = ifp->info;
1986 if (pim_ifp->mroute_vif_index != *oil_incoming_vif(c_oil))
1987 return false0;
1988
1989 if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
1990 up->sg.src)) {
1991 return true1;
1992 }
1993
1994 if ((up->join_state == PIM_UPSTREAM_JOINED)
1995 && !pim_upstream_empty_inherited_olist(up)) {
1996 if (I_am_RP(pim, up->sg.grp)pim_rp_i_am_rp ((pim), (up->sg.grp)))
1997 return true1;
1998 }
1999
2000 return false0;
2001}
2002
2003static bool_Bool pim_upstream_sg_running_proc(struct pim_upstream *up)
2004{
2005 bool_Bool rv = false0;
2006 struct pim_instance *pim = up->pim;
2007
2008 if (!up->channel_oil->installed)
2009 return rv;
2010
2011 pim_mroute_update_counters(up->channel_oil);
2012
2013 // Have we seen packets?
2014 if ((up->channel_oil->cc.oldpktcnt >= up->channel_oil->cc.pktcnt)
2015 && (up->channel_oil->cc.lastused / 100 > 30)) {
2016 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6)))) {
2017 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
2018 "%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
2019 __func__, up->sg_str, pim->vrf->name,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
2020 up->channel_oil->cc.oldpktcnt,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
2021 up->channel_oil->cc.pktcnt,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
2022 up->channel_oil->cc.lastused / 100)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2022, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name, up->channel_oil->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil->cc.lastused / 100"
), }; static const struct xref * const xref_p_155 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)"
), __func__, up->sg_str, pim->vrf->name, up->channel_oil
->cc.oldpktcnt, up->channel_oil->cc.pktcnt, up->channel_oil
->cc.lastused / 100); } while (0)
;
2023 }
2024 return rv;
2025 }
2026
2027 if (pim_upstream_kat_start_ok(up)) {
2028 /* Add a source reference to the stream if
2029 * one doesn't already exist */
2030 if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)((up->flags) & (1 << 5))) {
2031 if (PIM_DEBUG_PIM_TRACE(router->debugs & ((1 << 5) | (1 << 6))))
2032 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("source reference created on kat restart %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2034, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("source reference created on kat restart %s[%s]"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_156 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("source reference created on kat restart %s[%s]"
), up->sg_str, pim->vrf->name); } while (0)
2033 "source reference created on kat restart %s[%s]",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("source reference created on kat restart %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2034, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("source reference created on kat restart %s[%s]"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_156 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("source reference created on kat restart %s[%s]"
), up->sg_str, pim->vrf->name); } while (0)
2034 up->sg_str, pim->vrf->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("source reference created on kat restart %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2034, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("source reference created on kat restart %s[%s]"
), .priority = (7), .ec = (0), .args = ("up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_156 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("source reference created on kat restart %s[%s]"
), up->sg_str, pim->vrf->name); } while (0)
;
2035
2036 pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM(1 << 5),
2037 __func__);
2038 PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags)((up->flags) |= (1 << 5));
2039 pim_upstream_fhr_kat_start(up);
2040 }
2041 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
2042 rv = true1;
2043 } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)((up->flags) & (1 << 8))) {
2044 pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
2045 rv = true1;
2046 }
2047
2048 if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
2049 (up->rpf.source_nexthop.interface)) {
2050 pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
2051 pim_upstream_update_could_assert(up);
2052 }
2053
2054 return rv;
2055}
2056
2057/*
2058 * Code to check and see if we've received packets on a S,G mroute
2059 * and if so to set the SPT bit appropriately
2060 */
2061static void pim_upstream_sg_running(void *arg)
2062{
2063 struct pim_upstream *up = (struct pim_upstream *)arg;
2064 struct pim_instance *pim = up->channel_oil->pim;
2065
2066 // No packet can have arrived here if this is the case
2067 if (!up->channel_oil->installed) {
2068 if (PIM_DEBUG_TRACE(router->debugs & ((1 << 5) | (1 << 9))))
2069 zlog_debug("%s: %s[%s] is not installed in mroute",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s[%s] is not installed in mroute"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2070, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s[%s] is not installed in mroute"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_157 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s[%s] is not installed in mroute"), __func__
, up->sg_str, pim->vrf->name); } while (0)
2070 __func__, up->sg_str, pim->vrf->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: %s[%s] is not installed in mroute"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2070, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: %s[%s] is not installed in mroute"), .priority
= (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_157 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: %s[%s] is not installed in mroute"), __func__
, up->sg_str, pim->vrf->name); } while (0)
;
2071 return;
2072 }
2073
2074 /*
2075 * This is a bit of a hack
2076 * We've noted that we should rescan but
2077 * we've missed the window for doing so in
2078 * pim_zebra.c for some reason. I am
2079 * only doing this at this point in time
2080 * to get us up and working for the moment
2081 */
2082 if (up->channel_oil->oil_inherited_rescan) {
2083 if (PIM_DEBUG_TRACE(router->debugs & ((1 << 5) | (1 << 9))))
2084 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2086, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_158 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Handling unscanned inherited_olist for %s[%s]"
), __func__, up->sg_str, pim->vrf->name); } while (0
)
2085 "%s: Handling unscanned inherited_olist for %s[%s]",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2086, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_158 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Handling unscanned inherited_olist for %s[%s]"
), __func__, up->sg_str, pim->vrf->name); } while (0
)
2086 __func__, up->sg_str, pim->vrf->name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 2086, "pimd/pim_upstream.c", __func__, }, .
fmtstring = ("%s: Handling unscanned inherited_olist for %s[%s]"
), .priority = (7), .ec = (0), .args = ("__func__, up->sg_str, pim->vrf->name"
), }; static const struct xref * const xref_p_158 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: Handling unscanned inherited_olist for %s[%s]"
), __func__, up->sg_str, pim->vrf->name); } while (0
)
;
2087 pim_upstream_inherited_olist_decide(pim, up);
2088 up->channel_oil->oil_inherited_rescan = 0;
2089 }
2090
2091 pim_upstream_sg_running_proc(up);
2092}
2093
2094void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
2095{
2096 struct pim_upstream *up;
2097
2098 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
2099 if (!pim_addr_is_any(up->sg.src))
2100 continue;
2101
2102 if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)((up->flags) & ((1 << 3) | (1 << 15))))
2103 continue;
2104
2105 pim_channel_add_oif(up->channel_oil, pim->regiface,
2106 PIM_OIF_FLAG_PROTO_GM(1 << 0), __func__);
2107 }
2108}
2109
2110void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
2111 struct prefix_list *pl)
2112{
2113 const char *pname = prefix_list_name(pl);
2114
2115 if (pim->spt.plist && strcmp(pim->spt.plist, pname) == 0) {
2116 pim_upstream_remove_lhr_star_pimreg(pim, pname);
2117 }
2118}
2119
2120/*
2121 * nlist -> The new prefix list
2122 *
2123 * Per Group Application of pimreg to the OIL
2124 * If the prefix list tells us DENY then
2125 * we need to Switchover to SPT immediate
2126 * so add the pimreg.
2127 * If the prefix list tells us to ACCEPT than
2128 * we need to Never do the SPT so remove
2129 * the interface
2130 *
2131 */
2132void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
2133 const char *nlist)
2134{
2135 struct pim_upstream *up;
2136 struct prefix_list *np;
2137 struct prefix g;
2138 enum prefix_list_type apply_new;
2139
2140 np = prefix_list_lookup(PIM_AFIAFI_IP, nlist);
2141
2142 frr_each (rb_pim_upstream, &pim->upstream_head, up)for (up = rb_pim_upstream_first(&pim->upstream_head); up
; up = rb_pim_upstream_next(&pim->upstream_head, up))
{
2143 if (!pim_addr_is_any(up->sg.src))
2144 continue;
2145
2146 if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)((up->flags) & ((1 << 3) | (1 << 15))))
2147 continue;
2148
2149 if (!nlist) {
2150 pim_channel_del_oif(up->channel_oil, pim->regiface,
2151 PIM_OIF_FLAG_PROTO_GM(1 << 0), __func__);
2152 continue;
2153 }
2154 pim_addr_to_prefix(&g, up->sg.grp);
2155 apply_new = prefix_list_apply_ext(np, NULL((void*)0), &g, true1);
2156 if (apply_new == PREFIX_DENY)
2157 pim_channel_add_oif(up->channel_oil, pim->regiface,
2158 PIM_OIF_FLAG_PROTO_GM(1 << 0), __func__);
2159 else
2160 pim_channel_del_oif(up->channel_oil, pim->regiface,
2161 PIM_OIF_FLAG_PROTO_GM(1 << 0), __func__);
2162 }
2163}
2164
2165void pim_upstream_init(struct pim_instance *pim)
2166{
2167 char name[64];
2168
2169 snprintf(name, sizeof(name), "PIM %s Timer Wheel", pim->vrf->name);
2170 pim->upstream_sg_wheel =
2171 wheel_init(router->master, 31000, 100, pim_upstream_hash_key,
2172 pim_upstream_sg_running, name);
2173
2174 rb_pim_upstream_init(&pim->upstream_head);
2175}