]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
12e41d03 | 2 | /* |
896014f4 DL |
3 | * PIM for Quagga |
4 | * Copyright (C) 2008 Everton da Silva Marques | |
896014f4 | 5 | */ |
12e41d03 DL |
6 | |
7 | #include <zebra.h> | |
8 | ||
9 | #include "log.h" | |
744d91b3 | 10 | #include "if.h" |
12e41d03 DL |
11 | |
12 | #include "pimd.h" | |
993e3d8e | 13 | #include "pim_instance.h" |
12e41d03 DL |
14 | #include "pim_pim.h" |
15 | #include "pim_str.h" | |
16 | #include "pim_tlv.h" | |
17 | #include "pim_util.h" | |
18 | #include "pim_hello.h" | |
19 | #include "pim_iface.h" | |
20 | #include "pim_neighbor.h" | |
21 | #include "pim_upstream.h" | |
6bb2ef35 | 22 | #include "pim_bsm.h" |
12e41d03 | 23 | |
11928ecf | 24 | static void on_trace(const char *label, struct interface *ifp, pim_addr src) |
12e41d03 | 25 | { |
11928ecf DL |
26 | if (PIM_DEBUG_PIM_TRACE) |
27 | zlog_debug("%s: from %pPAs on %s", label, &src, ifp->name); | |
12e41d03 DL |
28 | } |
29 | ||
30 | static void tlv_trace_bool(const char *label, const char *tlv_name, | |
11928ecf DL |
31 | const char *ifname, pim_addr src_addr, int isset, |
32 | int value) | |
12e41d03 | 33 | { |
11928ecf | 34 | if (isset) |
d62a17ae | 35 | zlog_debug( |
11928ecf DL |
36 | "%s: PIM hello option from %pPAs on interface %s: %s=%d", |
37 | label, &src_addr, ifname, tlv_name, value); | |
12e41d03 DL |
38 | } |
39 | ||
40 | static void tlv_trace_uint16(const char *label, const char *tlv_name, | |
11928ecf DL |
41 | const char *ifname, pim_addr src_addr, int isset, |
42 | uint16_t value) | |
12e41d03 | 43 | { |
11928ecf | 44 | if (isset) |
d62a17ae | 45 | zlog_debug( |
11928ecf DL |
46 | "%s: PIM hello option from %pPAs on interface %s: %s=%u", |
47 | label, &src_addr, ifname, tlv_name, value); | |
12e41d03 DL |
48 | } |
49 | ||
50 | static void tlv_trace_uint32(const char *label, const char *tlv_name, | |
11928ecf DL |
51 | const char *ifname, pim_addr src_addr, int isset, |
52 | uint32_t value) | |
12e41d03 | 53 | { |
11928ecf | 54 | if (isset) |
d62a17ae | 55 | zlog_debug( |
11928ecf DL |
56 | "%s: PIM hello option from %pPAs on interface %s: %s=%u", |
57 | label, &src_addr, ifname, tlv_name, value); | |
12e41d03 DL |
58 | } |
59 | ||
60 | static void tlv_trace_uint32_hex(const char *label, const char *tlv_name, | |
11928ecf | 61 | const char *ifname, pim_addr src_addr, |
12e41d03 DL |
62 | int isset, uint32_t value) |
63 | { | |
11928ecf | 64 | if (isset) |
d62a17ae | 65 | zlog_debug( |
11928ecf DL |
66 | "%s: PIM hello option from %pPAs on interface %s: %s=%08x", |
67 | label, &src_addr, ifname, tlv_name, value); | |
12e41d03 DL |
68 | } |
69 | ||
12e41d03 | 70 | static void tlv_trace_list(const char *label, const char *tlv_name, |
11928ecf DL |
71 | const char *ifname, pim_addr src_addr, int isset, |
72 | struct list *addr_list) | |
12e41d03 | 73 | { |
11928ecf | 74 | if (isset) |
d62a17ae | 75 | zlog_debug( |
11928ecf DL |
76 | "%s: PIM hello option from %pPAs on interface %s: %s size=%d list=%p", |
77 | label, &src_addr, ifname, tlv_name, | |
d62a17ae | 78 | addr_list ? ((int)listcount(addr_list)) : -1, |
79 | (void *)addr_list); | |
12e41d03 DL |
80 | } |
81 | ||
996c9314 LB |
82 | #define FREE_ADDR_LIST \ |
83 | if (hello_option_addr_list) { \ | |
6a154c88 | 84 | list_delete(&hello_option_addr_list); \ |
d62a17ae | 85 | } |
12e41d03 | 86 | |
d62a17ae | 87 | #define FREE_ADDR_LIST_THEN_RETURN(code) \ |
88 | { \ | |
89 | FREE_ADDR_LIST \ | |
90 | return (code); \ | |
91 | } | |
12e41d03 | 92 | |
11928ecf DL |
93 | int pim_hello_recv(struct interface *ifp, pim_addr src_addr, uint8_t *tlv_buf, |
94 | int tlv_buf_size) | |
12e41d03 | 95 | { |
d62a17ae | 96 | struct pim_interface *pim_ifp; |
97 | struct pim_neighbor *neigh; | |
98 | uint8_t *tlv_curr; | |
99 | uint8_t *tlv_pastend; | |
100 | pim_hello_options hello_options = | |
101 | 0; /* bit array recording options found */ | |
102 | uint16_t hello_option_holdtime = 0; | |
103 | uint16_t hello_option_propagation_delay = 0; | |
104 | uint16_t hello_option_override_interval = 0; | |
105 | uint32_t hello_option_dr_priority = 0; | |
106 | uint32_t hello_option_generation_id = 0; | |
107 | struct list *hello_option_addr_list = 0; | |
108 | ||
109 | if (PIM_DEBUG_PIM_HELLO) | |
15569c58 | 110 | on_trace(__func__, ifp, src_addr); |
d62a17ae | 111 | |
112 | pim_ifp = ifp->info; | |
df5dfb77 | 113 | assert(pim_ifp); |
d62a17ae | 114 | |
39c2130e | 115 | if (pim_ifp->pim_passive_enable) { |
116 | if (PIM_DEBUG_PIM_PACKETS) | |
117 | zlog_debug( | |
118 | "skip receiving PIM message on passive interface %s", | |
119 | ifp->name); | |
120 | return 0; | |
121 | } | |
122 | ||
d62a17ae | 123 | ++pim_ifp->pim_ifstat_hello_recv; |
124 | ||
125 | /* | |
126 | Parse PIM hello TLVs | |
127 | */ | |
df5dfb77 | 128 | assert(tlv_buf_size >= 0); |
d62a17ae | 129 | tlv_curr = tlv_buf; |
130 | tlv_pastend = tlv_buf + tlv_buf_size; | |
131 | ||
132 | while (tlv_curr < tlv_pastend) { | |
133 | uint16_t option_type; | |
134 | uint16_t option_len; | |
135 | int remain = tlv_pastend - tlv_curr; | |
136 | ||
137 | if (remain < PIM_TLV_MIN_SIZE) { | |
11928ecf | 138 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 139 | zlog_debug( |
11928ecf | 140 | "%s: short PIM hello TLV size=%d < min=%d from %pPAs on interface %s", |
15569c58 | 141 | __func__, remain, PIM_TLV_MIN_SIZE, |
11928ecf | 142 | &src_addr, ifp->name); |
d62a17ae | 143 | FREE_ADDR_LIST_THEN_RETURN(-1); |
144 | } | |
145 | ||
146 | option_type = PIM_TLV_GET_TYPE(tlv_curr); | |
147 | tlv_curr += PIM_TLV_TYPE_SIZE; | |
148 | option_len = PIM_TLV_GET_LENGTH(tlv_curr); | |
149 | tlv_curr += PIM_TLV_LENGTH_SIZE; | |
150 | ||
151 | if ((tlv_curr + option_len) > tlv_pastend) { | |
11928ecf | 152 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 153 | zlog_debug( |
11928ecf | 154 | "%s: long PIM hello TLV type=%d length=%d > left=%td from %pPAs on interface %s", |
15569c58 | 155 | __func__, option_type, option_len, |
11928ecf | 156 | tlv_pastend - tlv_curr, &src_addr, |
15569c58 | 157 | ifp->name); |
d62a17ae | 158 | FREE_ADDR_LIST_THEN_RETURN(-2); |
159 | } | |
160 | ||
11928ecf | 161 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 162 | zlog_debug( |
11928ecf | 163 | "%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %pPAs on %s", |
15569c58 | 164 | __func__, remain, option_type, option_len, |
11928ecf | 165 | &src_addr, ifp->name); |
d62a17ae | 166 | |
167 | switch (option_type) { | |
168 | case PIM_MSG_OPTION_TYPE_HOLDTIME: | |
169 | if (pim_tlv_parse_holdtime(ifp->name, src_addr, | |
170 | &hello_options, | |
171 | &hello_option_holdtime, | |
172 | option_len, tlv_curr)) { | |
173 | FREE_ADDR_LIST_THEN_RETURN(-3); | |
174 | } | |
175 | break; | |
176 | case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY: | |
177 | if (pim_tlv_parse_lan_prune_delay( | |
178 | ifp->name, src_addr, &hello_options, | |
179 | &hello_option_propagation_delay, | |
180 | &hello_option_override_interval, option_len, | |
12e41d03 | 181 | tlv_curr)) { |
d62a17ae | 182 | FREE_ADDR_LIST_THEN_RETURN(-4); |
183 | } | |
184 | break; | |
185 | case PIM_MSG_OPTION_TYPE_DR_PRIORITY: | |
186 | if (pim_tlv_parse_dr_priority(ifp->name, src_addr, | |
187 | &hello_options, | |
188 | &hello_option_dr_priority, | |
189 | option_len, tlv_curr)) { | |
190 | FREE_ADDR_LIST_THEN_RETURN(-5); | |
191 | } | |
192 | break; | |
193 | case PIM_MSG_OPTION_TYPE_GENERATION_ID: | |
194 | if (pim_tlv_parse_generation_id( | |
195 | ifp->name, src_addr, &hello_options, | |
196 | &hello_option_generation_id, option_len, | |
197 | tlv_curr)) { | |
198 | FREE_ADDR_LIST_THEN_RETURN(-6); | |
199 | } | |
200 | break; | |
201 | case PIM_MSG_OPTION_TYPE_ADDRESS_LIST: | |
202 | if (pim_tlv_parse_addr_list(ifp->name, src_addr, | |
203 | &hello_options, | |
204 | &hello_option_addr_list, | |
205 | option_len, tlv_curr)) { | |
206 | return -7; | |
207 | } | |
208 | break; | |
209 | case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH: | |
11928ecf | 210 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 211 | zlog_debug( |
11928ecf | 212 | "%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %pPAs on interface %s", |
15569c58 | 213 | __func__, option_type, option_len, |
11928ecf | 214 | &src_addr, ifp->name); |
d62a17ae | 215 | break; |
216 | default: | |
11928ecf | 217 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 218 | zlog_debug( |
11928ecf | 219 | "%s: ignoring unknown PIM hello TLV type=%d length=%d from %pPAs on interface %s", |
15569c58 | 220 | __func__, option_type, option_len, |
11928ecf | 221 | &src_addr, ifp->name); |
d62a17ae | 222 | } |
223 | ||
224 | tlv_curr += option_len; | |
225 | } | |
12e41d03 | 226 | |
d62a17ae | 227 | /* |
228 | Check received PIM hello options | |
229 | */ | |
12e41d03 | 230 | |
d62a17ae | 231 | if (PIM_DEBUG_PIM_HELLO) { |
15569c58 | 232 | tlv_trace_uint16(__func__, "holdtime", ifp->name, src_addr, |
d62a17ae | 233 | PIM_OPTION_IS_SET(hello_options, |
234 | PIM_OPTION_MASK_HOLDTIME), | |
235 | hello_option_holdtime); | |
236 | tlv_trace_uint16( | |
15569c58 | 237 | __func__, "propagation_delay", ifp->name, src_addr, |
d62a17ae | 238 | PIM_OPTION_IS_SET(hello_options, |
239 | PIM_OPTION_MASK_LAN_PRUNE_DELAY), | |
240 | hello_option_propagation_delay); | |
241 | tlv_trace_uint16( | |
15569c58 | 242 | __func__, "override_interval", ifp->name, src_addr, |
d62a17ae | 243 | PIM_OPTION_IS_SET(hello_options, |
244 | PIM_OPTION_MASK_LAN_PRUNE_DELAY), | |
245 | hello_option_override_interval); | |
246 | tlv_trace_bool( | |
15569c58 DA |
247 | __func__, "can_disable_join_suppression", ifp->name, |
248 | src_addr, | |
d62a17ae | 249 | PIM_OPTION_IS_SET(hello_options, |
250 | PIM_OPTION_MASK_LAN_PRUNE_DELAY), | |
251 | PIM_OPTION_IS_SET( | |
252 | hello_options, | |
253 | PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION)); | |
15569c58 | 254 | tlv_trace_uint32(__func__, "dr_priority", ifp->name, src_addr, |
d62a17ae | 255 | PIM_OPTION_IS_SET(hello_options, |
256 | PIM_OPTION_MASK_DR_PRIORITY), | |
257 | hello_option_dr_priority); | |
258 | tlv_trace_uint32_hex( | |
15569c58 | 259 | __func__, "generation_id", ifp->name, src_addr, |
d62a17ae | 260 | PIM_OPTION_IS_SET(hello_options, |
261 | PIM_OPTION_MASK_GENERATION_ID), | |
262 | hello_option_generation_id); | |
15569c58 | 263 | tlv_trace_list(__func__, "address_list", ifp->name, src_addr, |
d62a17ae | 264 | PIM_OPTION_IS_SET(hello_options, |
265 | PIM_OPTION_MASK_ADDRESS_LIST), | |
266 | hello_option_addr_list); | |
267 | } | |
12e41d03 | 268 | |
d62a17ae | 269 | if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { |
11928ecf | 270 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 271 | zlog_debug( |
11928ecf DL |
272 | "%s: PIM hello missing holdtime from %pPAs on interface %s", |
273 | __func__, &src_addr, ifp->name); | |
d62a17ae | 274 | } |
12e41d03 | 275 | |
d62a17ae | 276 | /* |
277 | New neighbor? | |
278 | */ | |
279 | ||
3dbf370a | 280 | neigh = pim_neighbor_find(ifp, src_addr, false); |
d62a17ae | 281 | if (!neigh) { |
282 | /* Add as new neighbor */ | |
283 | ||
284 | neigh = pim_neighbor_add( | |
285 | ifp, src_addr, hello_options, hello_option_holdtime, | |
286 | hello_option_propagation_delay, | |
287 | hello_option_override_interval, | |
288 | hello_option_dr_priority, hello_option_generation_id, | |
289 | hello_option_addr_list, PIM_NEIGHBOR_SEND_DELAY); | |
290 | if (!neigh) { | |
11928ecf | 291 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 292 | zlog_warn( |
11928ecf DL |
293 | "%s: failure creating PIM neighbor %pPAs on interface %s", |
294 | __func__, &src_addr, ifp->name); | |
d62a17ae | 295 | FREE_ADDR_LIST_THEN_RETURN(-8); |
296 | } | |
6bb2ef35 | 297 | /* Forward BSM if required */ |
298 | if (!pim_bsm_new_nbr_fwd(neigh, ifp)) { | |
299 | if (PIM_DEBUG_PIM_HELLO) | |
15569c58 DA |
300 | zlog_debug( |
301 | "%s: forwarding bsm to new nbr failed", | |
302 | __func__); | |
6bb2ef35 | 303 | } |
d62a17ae | 304 | |
305 | /* actual addr list has been saved under neighbor */ | |
306 | return 0; | |
aea6cb94 | 307 | } |
d62a17ae | 308 | |
309 | /* | |
310 | Received generation ID ? | |
311 | */ | |
312 | ||
313 | if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) { | |
314 | /* GenID mismatch ? */ | |
315 | if (!PIM_OPTION_IS_SET(neigh->hello_options, | |
316 | PIM_OPTION_MASK_GENERATION_ID) | |
317 | || (hello_option_generation_id != neigh->generation_id)) { | |
318 | /* GenID mismatch, then replace neighbor */ | |
319 | ||
11928ecf | 320 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 321 | zlog_debug( |
11928ecf | 322 | "%s: GenId mismatch new=%08x old=%08x: replacing neighbor %pPAs on %s", |
15569c58 | 323 | __func__, hello_option_generation_id, |
11928ecf | 324 | neigh->generation_id, &src_addr, |
d62a17ae | 325 | ifp->name); |
d62a17ae | 326 | |
9b29ea95 DS |
327 | pim_upstream_rpf_genid_changed(pim_ifp->pim, |
328 | neigh->source_addr); | |
d62a17ae | 329 | |
330 | pim_neighbor_delete(ifp, neigh, "GenID mismatch"); | |
331 | neigh = pim_neighbor_add(ifp, src_addr, hello_options, | |
332 | hello_option_holdtime, | |
333 | hello_option_propagation_delay, | |
334 | hello_option_override_interval, | |
335 | hello_option_dr_priority, | |
336 | hello_option_generation_id, | |
337 | hello_option_addr_list, | |
338 | PIM_NEIGHBOR_SEND_NOW); | |
339 | if (!neigh) { | |
11928ecf | 340 | if (PIM_DEBUG_PIM_HELLO) |
d62a17ae | 341 | zlog_debug( |
11928ecf DL |
342 | "%s: failure re-creating PIM neighbor %pPAs on interface %s", |
343 | __func__, &src_addr, ifp->name); | |
d62a17ae | 344 | FREE_ADDR_LIST_THEN_RETURN(-9); |
345 | } | |
6bb2ef35 | 346 | /* Forward BSM if required */ |
347 | if (!pim_bsm_new_nbr_fwd(neigh, ifp)) { | |
348 | if (PIM_DEBUG_PIM_HELLO) | |
15569c58 DA |
349 | zlog_debug( |
350 | "%s: forwarding bsm to new nbr failed", | |
351 | __func__); | |
6bb2ef35 | 352 | } |
d62a17ae | 353 | /* actual addr list is saved under neighbor */ |
354 | return 0; | |
355 | ||
356 | } /* GenId mismatch: replace neighbor */ | |
357 | ||
358 | } /* GenId received */ | |
359 | ||
360 | /* | |
361 | Update existing neighbor | |
362 | */ | |
363 | ||
364 | pim_neighbor_update(neigh, hello_options, hello_option_holdtime, | |
365 | hello_option_dr_priority, hello_option_addr_list); | |
366 | /* actual addr list is saved under neighbor */ | |
367 | return 0; | |
12e41d03 DL |
368 | } |
369 | ||
d62a17ae | 370 | int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf, |
371 | int tlv_buf_size, uint16_t holdtime, | |
372 | uint32_t dr_priority, uint32_t generation_id, | |
373 | uint16_t propagation_delay, uint16_t override_interval, | |
dba78609 | 374 | int can_disable_join_suppression) |
12e41d03 | 375 | { |
d62a17ae | 376 | uint8_t *curr = tlv_buf; |
377 | uint8_t *pastend = tlv_buf + tlv_buf_size; | |
378 | uint8_t *tmp; | |
6ea2a7fb | 379 | #if PIM_IPV == 4 |
88a3f5e1 DS |
380 | struct pim_interface *pim_ifp = ifp->info; |
381 | struct pim_instance *pim = pim_ifp->pim; | |
6ea2a7fb | 382 | #endif |
d62a17ae | 383 | |
384 | /* | |
385 | * Append options | |
386 | */ | |
387 | ||
388 | /* Holdtime */ | |
389 | curr = pim_tlv_append_uint16(curr, pastend, | |
390 | PIM_MSG_OPTION_TYPE_HOLDTIME, holdtime); | |
391 | if (!curr) { | |
392 | if (PIM_DEBUG_PIM_HELLO) { | |
393 | zlog_debug( | |
394 | "%s: could not set PIM hello Holdtime option for interface %s", | |
15569c58 | 395 | __func__, ifp->name); |
d62a17ae | 396 | } |
397 | return -1; | |
398 | } | |
12e41d03 | 399 | |
d62a17ae | 400 | /* LAN Prune Delay */ |
401 | tmp = pim_tlv_append_2uint16(curr, pastend, | |
402 | PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY, | |
403 | propagation_delay, override_interval); | |
404 | if (!tmp) { | |
405 | if (PIM_DEBUG_PIM_HELLO) { | |
406 | zlog_debug( | |
407 | "%s: could not set PIM LAN Prune Delay option for interface %s", | |
15569c58 | 408 | __func__, ifp->name); |
d62a17ae | 409 | } |
410 | return -1; | |
411 | } | |
412 | if (can_disable_join_suppression) { | |
c4efd0f4 | 413 | *(curr + 4) |= 0x80; /* enable T bit */ |
d62a17ae | 414 | } |
415 | curr = tmp; | |
416 | ||
417 | /* DR Priority */ | |
418 | curr = pim_tlv_append_uint32( | |
419 | curr, pastend, PIM_MSG_OPTION_TYPE_DR_PRIORITY, dr_priority); | |
420 | if (!curr) { | |
421 | if (PIM_DEBUG_PIM_HELLO) { | |
422 | zlog_debug( | |
423 | "%s: could not set PIM hello DR Priority option for interface %s", | |
15569c58 | 424 | __func__, ifp->name); |
d62a17ae | 425 | } |
426 | return -2; | |
427 | } | |
12e41d03 | 428 | |
d62a17ae | 429 | /* Generation ID */ |
430 | curr = pim_tlv_append_uint32(curr, pastend, | |
431 | PIM_MSG_OPTION_TYPE_GENERATION_ID, | |
432 | generation_id); | |
433 | if (!curr) { | |
434 | if (PIM_DEBUG_PIM_HELLO) { | |
435 | zlog_debug( | |
436 | "%s: could not set PIM hello Generation ID option for interface %s", | |
15569c58 | 437 | __func__, ifp->name); |
d62a17ae | 438 | } |
439 | return -3; | |
440 | } | |
12e41d03 | 441 | |
d62a17ae | 442 | /* Secondary Address List */ |
443 | if (ifp->connected->count) { | |
6ea2a7fb SP |
444 | curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp, |
445 | PIM_AF); | |
d62a17ae | 446 | if (!curr) { |
447 | if (PIM_DEBUG_PIM_HELLO) { | |
448 | zlog_debug( | |
6ea2a7fb SP |
449 | "%s: could not set PIM hello %s Secondary Address List option for interface %s", |
450 | __func__, PIM_AF_NAME, ifp->name); | |
d62a17ae | 451 | } |
452 | return -4; | |
453 | } | |
6ea2a7fb | 454 | #if PIM_IPV == 4 |
88a3f5e1 | 455 | if (pim->send_v6_secondary) { |
6ea2a7fb SP |
456 | curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp, |
457 | AF_INET6); | |
d62a17ae | 458 | if (!curr) { |
459 | if (PIM_DEBUG_PIM_HELLO) { | |
460 | zlog_debug( | |
461 | "%s: could not sent PIM hello v6 secondary Address List option for interface %s", | |
15569c58 | 462 | __func__, ifp->name); |
d62a17ae | 463 | } |
464 | return -4; | |
465 | } | |
466 | } | |
6ea2a7fb | 467 | #endif |
d62a17ae | 468 | } |
12e41d03 | 469 | |
d62a17ae | 470 | return curr - tlv_buf; |
12e41d03 DL |
471 | } |
472 | ||
473 | /* | |
474 | RFC 4601: 4.3.1. Sending Hello Messages | |
475 | ||
476 | Thus, if a router needs to send a Join/Prune or Assert message on an | |
477 | interface on which it has not yet sent a Hello message with the | |
478 | currently configured IP address, then it MUST immediately send the | |
479 | relevant Hello message without waiting for the Hello Timer to | |
480 | expire, followed by the Join/Prune or Assert message. | |
481 | */ | |
482 | void pim_hello_require(struct interface *ifp) | |
483 | { | |
d62a17ae | 484 | struct pim_interface *pim_ifp; |
12e41d03 | 485 | |
df5dfb77 | 486 | assert(ifp); |
12e41d03 | 487 | |
d62a17ae | 488 | pim_ifp = ifp->info; |
12e41d03 | 489 | |
df5dfb77 | 490 | assert(pim_ifp); |
12e41d03 | 491 | |
79992e8a | 492 | if (PIM_IF_FLAG_TEST_HELLO_SENT(pim_ifp->flags)) |
d62a17ae | 493 | return; |
12e41d03 | 494 | |
d62a17ae | 495 | pim_hello_restart_now(ifp); /* Send hello and restart timer */ |
12e41d03 | 496 | } |