]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_upstream.h
c6c9291eed493a1559f74b73728465d56107375d
[mirror_frr.git] / pimd / pim_upstream.h
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 /*
78 * We are creating a non-joined upstream data structure
79 * for this S,G as that we want to have a channel oil
80 * associated with an upstream
81 */
82 #define PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE (1 << 19)
83
84 #define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF
85
86 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
87 #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
88 #define PIM_UPSTREAM_FLAG_TEST_FHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FHR)
89 #define PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
90 #define PIM_UPSTREAM_FLAG_TEST_SRC_PIM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
91 #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
92 #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
93 #define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
94 #define PIM_UPSTREAM_FLAG_TEST_SRC_LHR(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
95 #define PIM_UPSTREAM_FLAG_TEST_DISABLE_KAT_EXPIRY(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
96 #define PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
97 #define PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
98 #define PIM_UPSTREAM_FLAG_TEST_NO_PIMREG_DATA(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
99 #define PIM_UPSTREAM_FLAG_TEST_FORCE_PIMREG(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
100 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
101 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_TERM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
102 #define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM))
103 #define PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
104 #define PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
105 #define PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(flags) ((flags) &PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
106
107 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
108 #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
109 #define PIM_UPSTREAM_FLAG_SET_FHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FHR)
110 #define PIM_UPSTREAM_FLAG_SET_SRC_IGMP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
111 #define PIM_UPSTREAM_FLAG_SET_SRC_PIM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
112 #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
113 #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
114 #define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
115 #define PIM_UPSTREAM_FLAG_SET_SRC_LHR(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
116 #define PIM_UPSTREAM_FLAG_SET_DISABLE_KAT_EXPIRY(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
117 #define PIM_UPSTREAM_FLAG_SET_STATIC_IIF(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
118 #define PIM_UPSTREAM_FLAG_SET_ALLOW_IIF_IN_OIL(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
119 #define PIM_UPSTREAM_FLAG_SET_NO_PIMREG_DATA(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
120 #define PIM_UPSTREAM_FLAG_SET_FORCE_PIMREG(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
121 #define PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_ORIG(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
122 #define PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_TERM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
123 #define PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
124 #define PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
125
126 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
127 #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
128 #define PIM_UPSTREAM_FLAG_UNSET_FHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FHR)
129 #define PIM_UPSTREAM_FLAG_UNSET_SRC_IGMP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
130 #define PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_PIM)
131 #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM)
132 #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP)
133 #define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE)
134 #define PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_LHR)
135 #define PIM_UPSTREAM_FLAG_UNSET_DISABLE_KAT_EXPIRY(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DISABLE_KAT_EXPIRY)
136 #define PIM_UPSTREAM_FLAG_UNSET_STATIC_IIF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_STATIC_IIF)
137 #define PIM_UPSTREAM_FLAG_UNSET_ALLOW_IIF_IN_OIL(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_ALLOW_IIF_IN_OIL)
138 #define PIM_UPSTREAM_FLAG_UNSET_NO_PIMREG_DATA(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_NO_PIMREG_DATA)
139 #define PIM_UPSTREAM_FLAG_UNSET_FORCE_PIMREG(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_FORCE_PIMREG)
140 #define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_ORIG(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG)
141 #define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_TERM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
142 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_VXLAN(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
143 #define PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
144 #define PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
145
146 enum pim_upstream_state {
147 PIM_UPSTREAM_NOTJOINED,
148 PIM_UPSTREAM_JOINED,
149 };
150
151 enum pim_reg_state {
152 PIM_REG_NOINFO,
153 PIM_REG_JOIN,
154 PIM_REG_JOIN_PENDING,
155 PIM_REG_PRUNE,
156 };
157
158 enum pim_upstream_sptbit {
159 PIM_UPSTREAM_SPTBIT_FALSE,
160 PIM_UPSTREAM_SPTBIT_TRUE
161 };
162
163 /*
164 Upstream (S,G) channel in Joined state
165 (S,G) in the "Not Joined" state is not represented
166 See RFC 4601: 4.5.7. Sending (S,G) Join/Prune Message
167
168 upstream_addr : Who we are talking to.
169 For (*, G), upstream_addr is RP address or INADDR_ANY(if RP not configured)
170 For (S, G), upstream_addr is source address
171
172 rpf: contains the nexthop information to whom we are talking to.
173
174 join_state: JOINED/NOTJOINED
175
176 In the case when FRR receives IGMP/PIM (*, G) join for group G and RP is not
177 configured, then create a pim_upstream with the below information.
178 pim_upstream->upstream address: INADDR_ANY
179 pim_upstream->rpf: Unknown
180 pim_upstream->state: NOTJOINED
181
182 When a new RP gets configured for G, find the corresponding pim upstream (*,G)
183 entries and update the upstream address as new RP address if it the better one
184 for the group G.
185
186 When RP becomes reachable, populate the nexthop information in
187 pim_upstream->rpf and update the state to JOINED.
188
189 */
190 struct pim_upstream {
191 struct pim_upstream *parent;
192 struct in_addr upstream_addr; /* Who we are talking to */
193 struct in_addr upstream_register; /*Who we received a register from*/
194 struct prefix_sg sg; /* (S,G) group key */
195 char sg_str[PIM_SG_LEN];
196 uint32_t flags;
197 struct channel_oil *channel_oil;
198 struct list *sources;
199 struct list *ifchannels;
200
201 enum pim_upstream_state join_state;
202 enum pim_reg_state reg_state;
203 enum pim_upstream_sptbit sptbit;
204
205 int ref_count;
206
207 struct pim_rpf rpf;
208
209 struct thread *t_join_timer;
210
211 /*
212 * RST(S,G)
213 */
214 struct thread *t_rs_timer;
215 #define PIM_REGISTER_SUPPRESSION_PERIOD (60)
216 #define PIM_REGISTER_PROBE_PERIOD (5)
217
218 /*
219 * KAT(S,G)
220 */
221 struct thread *t_ka_timer;
222 #define PIM_KEEPALIVE_PERIOD (210)
223 #define PIM_RP_KEEPALIVE_PERIOD \
224 (3 * router->register_suppress_time + router->register_probe_time)
225
226 /* on the RP we restart a timer to indicate if registers are being rxed
227 * for
228 * SG. This is needed by MSDP to determine its local SA cache */
229 struct thread *t_msdp_reg_timer;
230 #define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * router->register_suppress_time))
231
232 int64_t state_transition; /* Record current state uptime */
233 };
234
235 struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
236 struct prefix_sg *sg);
237 struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
238 struct interface *ifp, int flags,
239 const char *name);
240 struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
241 struct prefix_sg *sg,
242 struct interface *ifp, int flags,
243 const char *name,
244 struct pim_ifchannel *ch);
245 void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name);
246 struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
247 struct pim_upstream *up,
248 const char *name);
249
250 int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
251 struct pim_upstream *up);
252 int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up,
253 struct pim_ifchannel *ch,
254 struct pim_ifchannel *starch);
255 void pim_upstream_update_join_desired(struct pim_instance *pim,
256 struct pim_upstream *up);
257
258 void pim_upstream_join_suppress(struct pim_upstream *up,
259 struct in_addr rpf_addr, int holdtime);
260
261 void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
262 struct pim_upstream *up);
263
264 void pim_upstream_join_timer_restart(struct pim_upstream *up,
265 struct pim_rpf *old);
266 void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
267 struct in_addr neigh_addr);
268 void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
269 struct interface *old_rpf_ifp);
270
271 void pim_upstream_update_could_assert(struct pim_upstream *up);
272 void pim_upstream_update_my_assert_metric(struct pim_upstream *up);
273
274 void pim_upstream_keep_alive_timer_start(struct pim_upstream *up,
275 uint32_t time);
276
277 int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
278 struct prefix_sg *sg);
279 #define SwitchToSptDesired(pim, sg) pim_upstream_switch_to_spt_desired (pim, sg)
280 int pim_upstream_is_sg_rpt(struct pim_upstream *up);
281
282 void pim_upstream_set_sptbit(struct pim_upstream *up,
283 struct interface *incoming);
284
285 void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
286 int null_register);
287
288 void pim_upstream_send_join(struct pim_upstream *up);
289
290 void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
291 enum pim_upstream_state new_state);
292
293 const char *pim_upstream_state2str(enum pim_upstream_state join_state);
294 #define PIM_REG_STATE_STR_LEN 12
295 const char *pim_reg_state2str(enum pim_reg_state state, char *state_str,
296 size_t state_str_len);
297
298 int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
299 struct pim_upstream *up);
300 int pim_upstream_inherited_olist(struct pim_instance *pim,
301 struct pim_upstream *up);
302 int pim_upstream_empty_inherited_olist(struct pim_upstream *up);
303
304 void pim_upstream_find_new_rpf(struct pim_instance *pim);
305 void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up);
306
307 void pim_upstream_init(struct pim_instance *pim);
308 void pim_upstream_terminate(struct pim_instance *pim);
309
310 void join_timer_start(struct pim_upstream *up);
311 int pim_upstream_compare(void *arg1, void *arg2);
312 void pim_upstream_register_reevaluate(struct pim_instance *pim);
313
314 void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim);
315 void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
316 const char *nlist);
317
318 void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
319 struct prefix_list *pl);
320
321 unsigned int pim_upstream_hash_key(const void *arg);
322 bool pim_upstream_equal(const void *arg1, const void *arg2);
323 struct pim_upstream *pim_upstream_keep_alive_timer_proc(
324 struct pim_upstream *up);
325 void pim_upstream_fill_static_iif(struct pim_upstream *up,
326 struct interface *incoming);
327 #endif /* PIM_UPSTREAM_H */