1 /*
2  * PIM for Quagga
3  * Copyright (C) 2008  Everton da Silva Marques
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; see the file COPYING; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifndef PIM_UPSTREAM_H
21 #define PIM_UPSTREAM_H
22 
23 #include <zebra.h>
24 #include <prefix.h>
25 #include "plist.h"
26 
27 #include <pimd/pim_rpf.h>
28 #include "pim_str.h"
29 #include "pim_ifchannel.h"
30 
31 #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED         (1 << 0)
32 #define PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED (1 << 1)
33 #define PIM_UPSTREAM_FLAG_MASK_FHR                     (1 << 2)
34 #define PIM_UPSTREAM_FLAG_MASK_SRC_IGMP                (1 << 3)
35 #define PIM_UPSTREAM_FLAG_MASK_SRC_PIM                 (1 << 4)
36 #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM              (1 << 5)
37 #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP                (1 << 6)
38 #define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE       (1 << 7)
39 #define PIM_UPSTREAM_FLAG_MASK_SRC_LHR                 (1 << 8)
40 /* In the case of pim vxlan we prime the pump by registering the
41  * vxlan source and keeping the SPT (FHR-RP) alive by sending periodic
42  * NULL registers. So we need to prevent KAT expiry because of the
43  * lack of BUM traffic.
44  */
45 #define PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY      (1 << 9)
46 /* for pim vxlan we need to pin the IIF to lo or MLAG-ISL on the
47  * originating VTEP. This flag allows that by setting IIF to the
48  * value specified and preventing next-hop-tracking on the entry
49  */
50 #define PIM_UPSTREAM_FLAG_MASK_STATIC_IIF              (1 << 10)
51 #define PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL        (1 << 11)
52 /* Disable pimreg encasulation for a flow */
53 #define PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA          (1 << 12)
54 /* For some MDTs we need to register the router as a source even
55  * if the not DR or directly connected on the IIF. This is typically
56  * needed on a VxLAN-AA (MLAG) setup.
57  */
58 #define PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG            (1 << 13)
59 /* VxLAN origination mroute - SG was registered by EVPN where S is the
60  * local VTEP IP and G is the BUM multicast group address
61  */
62 #define PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG          (1 << 14)
63 /* VxLAN termination mroute - *G entry where G is the BUM multicast group
64  * address
65  */
66 #define PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM          (1 << 15)
67 /* MLAG mroute - synced to the MLAG peer and subject to DF (designated
68  * forwarder) election
69  */
70 #define PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN              (1 << 16)
71 /* MLAG mroute that lost the DF election with peer and is installed in
72  * a dormant state i.e. MLAG OIFs are removed from the MFC.
73  * In most cases the OIL is empty (but not not always) simply
74  * blackholing the traffic pulled down to the LHR.
75  */
76 #define PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF             (1 << 17)
77 /* MLAG mroute rxed from the peer MLAG switch */
78 #define PIM_UPSTREAM_FLAG_MASK_MLAG_PEER               (1 << 18)
79 /*
80  * We are creating a non-joined upstream data structure
81  * for this S,G as that we want to have a channel oil
82  * associated with an upstream
83  */
84 #define PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE             (1 << 19)
85 /* By default as SG entry will use the SPT for forwarding traffic
86  * unless it was setup as a result of a Prune(S,G,rpt) from a
87  * downstream router and has JoinDesired(S,G) as False.
88  * This flag is only relevant for (S,G) entries.
89  */
90 #define PIM_UPSTREAM_FLAG_MASK_USE_RPT                 (1 << 20)
91 /* PIM Syncs upstream entries to peer Nodes via MLAG in 2 cases.
92  * one is to support plain PIM Redundancy and another one is to support
93  * PIM REdundancy.
94  */
95 #define PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE          (1 << 21)
96 
97 
98 #define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF
99 
100 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
101 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
102 #define PIM_UPSTREAM_FLAG_TEST_FHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FHR)
103 #define PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
104 #define PIM_UPSTREAM_FLAG_TEST_SRC_PIM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
105 #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
106 #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
107 #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
108 #define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
109 #define PIM_UPSTREAM_FLAG_TEST_DISABLE_KAT_EXPIRY(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
110 #define PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
111 #define PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
112 #define PIM_UPSTREAM_FLAG_TEST_NO_PIMREG_DATA(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
113 #define PIM_UPSTREAM_FLAG_TEST_FORCE_PIMREG(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
114 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
115 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_TERM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
116 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM))
117 #define PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
118 #define PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
119 #define PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
120 #define PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(flags) ((flags) &PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
121 #define PIM_UPSTREAM_FLAG_TEST_USE_RPT(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_USE_RPT)
122 #define PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_IGMP | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM))
123 #define PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(flags) ((flags)&PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
124 
125 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
126 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
127 #define PIM_UPSTREAM_FLAG_SET_FHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FHR)
128 #define PIM_UPSTREAM_FLAG_SET_SRC_IGMP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
129 #define PIM_UPSTREAM_FLAG_SET_SRC_PIM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
130 #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
131 #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
132 #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
133 #define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
134 #define PIM_UPSTREAM_FLAG_SET_DISABLE_KAT_EXPIRY(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
135 #define PIM_UPSTREAM_FLAG_SET_STATIC_IIF(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
136 #define PIM_UPSTREAM_FLAG_SET_ALLOW_IIF_IN_OIL(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
137 #define PIM_UPSTREAM_FLAG_SET_NO_PIMREG_DATA(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
138 #define PIM_UPSTREAM_FLAG_SET_FORCE_PIMREG(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
139 #define PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_ORIG(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
140 #define PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_TERM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
141 #define PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
142 #define PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
143 #define PIM_UPSTREAM_FLAG_SET_MLAG_PEER(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
144 #define PIM_UPSTREAM_FLAG_SET_USE_RPT(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_USE_RPT)
145 #define PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
146 
147 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
148 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
149 #define PIM_UPSTREAM_FLAG_UNSET_FHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FHR)
150 #define PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
151 #define PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
152 #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
153 #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
154 #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
155 #define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
156 #define PIM_UPSTREAM_FLAG_UNSET_DISABLE_KAT_EXPIRY(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
157 #define PIM_UPSTREAM_FLAG_UNSET_STATIC_IIF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
158 #define PIM_UPSTREAM_FLAG_UNSET_ALLOW_IIF_IN_OIL(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
159 #define PIM_UPSTREAM_FLAG_UNSET_NO_PIMREG_DATA(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
160 #define PIM_UPSTREAM_FLAG_UNSET_FORCE_PIMREG(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
161 #define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_ORIG(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
162 #define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_TERM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
163 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_VXLAN(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
164 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
165 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_PEER(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
166 #define PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
167 #define PIM_UPSTREAM_FLAG_UNSET_USE_RPT(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_USE_RPT)
168 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_INTERFACE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
169 
170 /* The RPF cost is incremented by 10 if the RPF interface is the peerlink-rif.
171  * This is used to force the MLAG switch with the lowest cost to the RPF
172  * to become the MLAG DF.
173  */
174 #define PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC 10
175 
176 enum pim_upstream_state {
177 	PIM_UPSTREAM_NOTJOINED,
178 	PIM_UPSTREAM_JOINED,
179 };
180 
181 enum pim_reg_state {
182 	PIM_REG_NOINFO,
183 	PIM_REG_JOIN,
184 	PIM_REG_JOIN_PENDING,
185 	PIM_REG_PRUNE,
186 };
187 
188 enum pim_upstream_sptbit {
189 	PIM_UPSTREAM_SPTBIT_FALSE,
190 	PIM_UPSTREAM_SPTBIT_TRUE
191 };
192 
193 struct pim_up_mlag {
194 	/* MRIB.metric(S) from the peer switch. This is used for DF election
195 	 * and switch with the lowest cost wins.
196 	 */
197 	uint32_t peer_mrib_metric;
198 };
199 
200 PREDECL_RBTREE_UNIQ(rb_pim_upstream);
201 /*
202   Upstream (S,G) channel in Joined state
203   (S,G) in the "Not Joined" state is not represented
204   See RFC 4601: 4.5.7.  Sending (S,G) Join/Prune Message
205 
206   upstream_addr : Who we are talking to.
207   For (*, G), upstream_addr is RP address or INADDR_ANY(if RP not configured)
208   For (S, G), upstream_addr is source address
209 
210   rpf: contains the nexthop information to whom we are talking to.
211 
212   join_state: JOINED/NOTJOINED
213 
214   In the case when FRR receives IGMP/PIM (*, G) join for group G and RP is not
215   configured, then create a pim_upstream with the below information.
216   pim_upstream->upstream address: INADDR_ANY
217   pim_upstream->rpf: Unknown
218   pim_upstream->state: NOTJOINED
219 
220   When a new RP gets configured for G, find the corresponding pim upstream (*,G)
221   entries and update the upstream address as new RP address if it the better one
222   for the group G.
223 
224   When RP becomes reachable, populate the nexthop information in
225   pim_upstream->rpf and update the state to JOINED.
226 
227 */
228 struct pim_upstream {
229 	struct pim_instance *pim;
230 	struct rb_pim_upstream_item upstream_rb;
231 	struct pim_upstream *parent;
232 	struct in_addr upstream_addr;     /* Who we are talking to */
233 	struct in_addr upstream_register; /*Who we received a register from*/
234 	struct prefix_sg sg;		  /* (S,G) group key */
235 	char sg_str[PIM_SG_LEN];
236 	uint32_t flags;
237 	struct channel_oil *channel_oil;
238 	struct list *sources;
239 	struct list *ifchannels;
240 	/* Counter for Dual active ifchannels*/
241 	uint32_t dualactive_ifchannel_count;
242 
243 	enum pim_upstream_state join_state;
244 	enum pim_reg_state reg_state;
245 	enum pim_upstream_sptbit sptbit;
246 
247 	int ref_count;
248 
249 	struct pim_rpf rpf;
250 
251 	struct pim_up_mlag mlag;
252 
253 	struct thread *t_join_timer;
254 
255 	/*
256 	 * RST(S,G)
257 	 */
258 	struct thread *t_rs_timer;
259 #define PIM_REGISTER_SUPPRESSION_PERIOD (60)
260 #define PIM_REGISTER_PROBE_PERIOD        (5)
261 
262 	/*
263 	 * KAT(S,G)
264 	 */
265 	struct thread *t_ka_timer;
266 #define PIM_KEEPALIVE_PERIOD  (210)
267 #define PIM_RP_KEEPALIVE_PERIOD                                                \
268 	(3 * router->register_suppress_time + router->register_probe_time)
269 
270 	/* on the RP we restart a timer to indicate if registers are being rxed
271 	 * for
272 	 * SG. This is needed by MSDP to determine its local SA cache */
273 	struct thread *t_msdp_reg_timer;
274 #define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * router->register_suppress_time))
275 
276 	int64_t state_transition; /* Record current state uptime */
277 };
278 
pim_upstream_is_kat_running(struct pim_upstream * up)279 static inline bool pim_upstream_is_kat_running(struct pim_upstream *up)
280 {
281 	return (up->t_ka_timer != NULL);
282 }
283 
pim_up_mlag_is_local(struct pim_upstream * up)284 static inline bool pim_up_mlag_is_local(struct pim_upstream *up)
285 {
286 	/* XXX: extend this to also return true if the channel-oil has
287 	 * any AA devices
288 	 */
289 	return (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN
290 			     | PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE));
291 }
292 
293 struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
294 				       struct prefix_sg *sg);
295 struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
296 					      struct interface *ifp, int flags,
297 					      const char *name);
298 struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
299 				      struct prefix_sg *sg,
300 				      struct interface *ifp, int flags,
301 				      const char *name,
302 				      struct pim_ifchannel *ch);
303 void pim_upstream_ref(struct pim_upstream *up,
304 		int flags, const char *name);
305 struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
306 				      struct pim_upstream *up,
307 				      const char *name);
308 
309 bool pim_upstream_evaluate_join_desired(struct pim_instance *pim,
310 					struct pim_upstream *up);
311 int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
312 						 struct pim_ifchannel *ch,
313 						 struct pim_ifchannel *starch);
314 int pim_upstream_eval_inherit_if(struct pim_upstream *up,
315 						 struct pim_ifchannel *ch,
316 						 struct pim_ifchannel *starch);
317 void pim_upstream_update_join_desired(struct pim_instance *pim,
318 				      struct pim_upstream *up);
319 
320 void pim_upstream_join_suppress(struct pim_upstream *up,
321 				struct in_addr rpf_addr, int holdtime);
322 
323 void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
324 						    struct pim_upstream *up);
325 
326 void pim_upstream_join_timer_restart(struct pim_upstream *up,
327 				     struct pim_rpf *old);
328 void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
329 				    struct in_addr neigh_addr);
330 void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
331 					struct interface *old_rpf_ifp);
332 
333 void pim_upstream_update_could_assert(struct pim_upstream *up);
334 void pim_upstream_update_my_assert_metric(struct pim_upstream *up);
335 
336 void pim_upstream_keep_alive_timer_start(struct pim_upstream *up,
337 					 uint32_t time);
338 
339 int pim_upstream_switch_to_spt_desired_on_rp(struct pim_instance *pim,
340 				       struct prefix_sg *sg);
341 #define SwitchToSptDesiredOnRp(pim, sg) pim_upstream_switch_to_spt_desired_on_rp (pim, sg)
342 int pim_upstream_is_sg_rpt(struct pim_upstream *up);
343 
344 void pim_upstream_set_sptbit(struct pim_upstream *up,
345 			     struct interface *incoming);
346 
347 void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
348 					    int null_register);
349 
350 void pim_upstream_send_join(struct pim_upstream *up);
351 
352 void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
353 			 enum pim_upstream_state new_state);
354 
355 const char *pim_upstream_state2str(enum pim_upstream_state join_state);
356 #define PIM_REG_STATE_STR_LEN 12
357 const char *pim_reg_state2str(enum pim_reg_state state, char *state_str,
358 			      size_t state_str_len);
359 
360 int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
361 					struct pim_upstream *up);
362 int pim_upstream_inherited_olist(struct pim_instance *pim,
363 				 struct pim_upstream *up);
364 int pim_upstream_empty_inherited_olist(struct pim_upstream *up);
365 
366 void pim_upstream_find_new_rpf(struct pim_instance *pim);
367 void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up);
368 
369 void pim_upstream_init(struct pim_instance *pim);
370 void pim_upstream_terminate(struct pim_instance *pim);
371 
372 void join_timer_start(struct pim_upstream *up);
373 int pim_upstream_compare(const struct pim_upstream *up1,
374 			 const struct pim_upstream *up2);
375 DECLARE_RBTREE_UNIQ(rb_pim_upstream, struct pim_upstream, upstream_rb,
376 		    pim_upstream_compare)
377 
378 void pim_upstream_register_reevaluate(struct pim_instance *pim);
379 
380 void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim);
381 void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
382 					 const char *nlist);
383 
384 void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
385 					 struct prefix_list *pl);
386 
387 unsigned int pim_upstream_hash_key(const void *arg);
388 bool pim_upstream_equal(const void *arg1, const void *arg2);
389 struct pim_upstream *pim_upstream_keep_alive_timer_proc(
390 		struct pim_upstream *up);
391 void pim_upstream_fill_static_iif(struct pim_upstream *up,
392 				struct interface *incoming);
393 void pim_upstream_update_use_rpt(struct pim_upstream *up,
394 		bool update_mroute);
395 uint32_t pim_up_mlag_local_cost(struct pim_upstream *up);
396 uint32_t pim_up_mlag_peer_cost(struct pim_upstream *up);
397 void pim_upstream_reeval_use_rpt(struct pim_instance *pim);
398 int pim_upstream_could_register(struct pim_upstream *up);
399 #endif /* PIM_UPSTREAM_H */
400