blob: dd78b904c5598fef35e395befe972604bee3a982 [file] [log] [blame]
Everton Marques871dbcf2009-08-11 15:43:05 -03001/*
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
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19
20 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include <zebra.h>
24
25#include "log.h"
26#include "thread.h"
27#include "memory.h"
28
29#include "pimd.h"
30#include "pim_pim.h"
31#include "pim_time.h"
32#include "pim_iface.h"
33#include "pim_sock.h"
34#include "pim_str.h"
35#include "pim_util.h"
36#include "pim_tlv.h"
37#include "pim_neighbor.h"
38#include "pim_hello.h"
39#include "pim_join.h"
40#include "pim_assert.h"
41#include "pim_msg.h"
42#include "pim_rand.h"
43
44static int on_pim_hello_send(struct thread *t);
45static int pim_hello_send(struct interface *ifp,
46 uint16_t holdtime);
47
48static void sock_close(struct interface *ifp)
49{
50 struct pim_interface *pim_ifp = ifp->info;
51
52 if (PIM_DEBUG_PIM_TRACE) {
53 if (pim_ifp->t_pim_sock_read) {
54 zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
55 pim_ifp->pim_sock_fd,
56 ifp->name);
57 }
58 }
59 THREAD_OFF(pim_ifp->t_pim_sock_read);
60
61 if (PIM_DEBUG_PIM_TRACE) {
62 if (pim_ifp->t_pim_hello_timer) {
63 zlog_debug("Cancelling PIM hello timer for interface %s",
64 ifp->name);
65 }
66 }
67 THREAD_OFF(pim_ifp->t_pim_hello_timer);
68
69 if (PIM_DEBUG_PIM_TRACE) {
70 zlog_debug("Deleting PIM socket fd=%d on interface %s",
71 pim_ifp->pim_sock_fd, ifp->name);
72 }
73
74 if (close(pim_ifp->pim_sock_fd)) {
75 zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
76 pim_ifp->pim_sock_fd, ifp->name,
Everton Marquese96f0af2009-08-11 15:48:02 -030077 errno, safe_strerror(errno));
Everton Marques871dbcf2009-08-11 15:43:05 -030078 }
79
80 pim_ifp->pim_sock_fd = -1;
81 pim_ifp->pim_sock_creation = 0;
82
83 zassert(pim_ifp->pim_sock_fd < 0);
84 zassert(!pim_ifp->t_pim_sock_read);
85 zassert(!pim_ifp->t_pim_hello_timer);
86 zassert(!pim_ifp->pim_sock_creation);
87}
88
89void pim_sock_delete(struct interface *ifp, const char *delete_message)
90{
91 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
92 ifp->name, delete_message);
93
Everton Marquese96f0af2009-08-11 15:48:02 -030094 if (!ifp->info) {
95 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
96 __PRETTY_FUNCTION__, delete_message, ifp->name);
97 return;
98 }
99
Everton Marques871dbcf2009-08-11 15:43:05 -0300100 /*
101 RFC 4601: 4.3.1. Sending Hello Messages
102
103 Before an interface goes down or changes primary IP address, a Hello
104 message with a zero HoldTime should be sent immediately (with the
105 old IP address if the IP address changed).
106 */
107 pim_hello_send(ifp, 0 /* zero-sec holdtime */);
108
109 pim_neighbor_delete_all(ifp, delete_message);
110
111 sock_close(ifp);
112}
113
114int pim_pim_packet(struct interface *ifp, char *buf, size_t len)
115{
116 struct ip *ip_hdr;
117 size_t ip_hlen; /* ip header length in bytes */
118 char src_str[100];
119 char dst_str[100];
120 char *pim_msg;
121 int pim_msg_len;
122 uint8_t pim_version;
123 uint8_t pim_type;
124 uint16_t pim_checksum; /* received checksum */
125 uint16_t checksum; /* computed checksum */
126 struct pim_neighbor *neigh;
127
128 if (!ifp->info) {
129 zlog_warn("%s: PIM not enabled on interface %s",
130 __PRETTY_FUNCTION__, ifp->name);
131 return -1;
132 }
133
134 if (len < sizeof(*ip_hdr)) {
135 zlog_warn("PIM packet size=%d shorter than minimum=%d",
136 len, sizeof(*ip_hdr));
137 return -1;
138 }
139
140 ip_hdr = (struct ip *) buf;
141
142 pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
143 pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str));
144
145 ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
146
147 if (PIM_DEBUG_PIM_PACKETS) {
148 zlog_debug("Recv IP packet from %s to %s on %s: size=%d ip_header_size=%d ip_proto=%d",
149 src_str, dst_str, ifp->name, len, ip_hlen, ip_hdr->ip_p);
150 }
151
152 if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) {
153 zlog_warn("IP packet protocol=%d is not PIM=%d",
154 ip_hdr->ip_p, PIM_IP_PROTO_PIM);
155 return -1;
156 }
157
158 if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
159 zlog_warn("IP packet header size=%d shorter than minimum=%d",
160 ip_hlen, PIM_IP_HEADER_MIN_LEN);
161 return -1;
162 }
163 if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
164 zlog_warn("IP packet header size=%d greater than maximum=%d",
165 ip_hlen, PIM_IP_HEADER_MAX_LEN);
166 return -1;
167 }
168
169 pim_msg = buf + ip_hlen;
170 pim_msg_len = len - ip_hlen;
171
172 if (pim_msg_len < PIM_PIM_MIN_LEN) {
173 zlog_warn("PIM message size=%d shorter than minimum=%d",
174 pim_msg_len, PIM_PIM_MIN_LEN);
175 return -1;
176 }
177
178 pim_version = PIM_MSG_HDR_GET_VERSION(pim_msg);
179 pim_type = PIM_MSG_HDR_GET_TYPE(pim_msg);
180
181 if (pim_version != PIM_PROTO_VERSION) {
182 zlog_warn("Ignoring PIM pkt from %s with unsupported version: %d",
183 ifp->name, pim_version);
184 return -1;
185 }
186
187 /* save received checksum */
188 pim_checksum = PIM_MSG_HDR_GET_CHECKSUM(pim_msg);
189
190 /* for computing checksum */
191 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
192
193 checksum = pim_inet_checksum(pim_msg, pim_msg_len);
194 if (checksum != pim_checksum) {
195 zlog_warn("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
196 ifp->name, pim_checksum, checksum);
197 return -1;
198 }
199
200 if (PIM_DEBUG_PIM_PACKETS) {
201 zlog_debug("Recv PIM packet from %s to %s on %s: ttl=%d pim_version=%d pim_type=%d pim_msg_size=%d checksum=%x",
202 src_str, dst_str, ifp->name, ip_hdr->ip_ttl,
203 pim_version, pim_type, pim_msg_len, checksum);
204 }
205
206 if (pim_type == PIM_MSG_TYPE_HELLO) {
207 return pim_hello_recv(ifp,
208 ip_hdr->ip_src,
209 pim_msg + PIM_MSG_HEADER_LEN,
210 pim_msg_len - PIM_MSG_HEADER_LEN);
211 }
212
213 neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
214 if (!neigh) {
215 zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
216 __FILE__, __PRETTY_FUNCTION__,
217 pim_type, src_str, ifp->name);
218 return -1;
219 }
220
221 switch (pim_type) {
222 case PIM_MSG_TYPE_JOIN_PRUNE:
223 return pim_joinprune_recv(ifp, neigh,
224 ip_hdr->ip_src,
225 pim_msg + PIM_MSG_HEADER_LEN,
226 pim_msg_len - PIM_MSG_HEADER_LEN);
227 case PIM_MSG_TYPE_ASSERT:
228 return pim_assert_recv(ifp, neigh,
229 ip_hdr->ip_src,
230 pim_msg + PIM_MSG_HEADER_LEN,
231 pim_msg_len - PIM_MSG_HEADER_LEN);
232 default:
233 zlog_warn("%s %s: unsupported PIM message type=%d from %s on %s",
234 __FILE__, __PRETTY_FUNCTION__,
235 pim_type, src_str, ifp->name);
236 }
237
238 return -1;
239}
240
241static void pim_sock_read_on(struct interface *ifp);
242
243static int pim_sock_read(struct thread *t)
244{
245 struct interface *ifp;
246 struct pim_interface *pim_ifp;
247 int fd;
248 struct sockaddr_in from;
249 struct sockaddr_in to;
250 socklen_t fromlen = sizeof(from);
251 socklen_t tolen = sizeof(to);
252 char buf[PIM_PIM_BUFSIZE_READ];
253 int len;
254 int ifindex = -1;
255 int result = -1; /* defaults to bad */
256
257 zassert(t);
258
259 ifp = THREAD_ARG(t);
260 zassert(ifp);
261
262 fd = THREAD_FD(t);
263
264 pim_ifp = ifp->info;
265 zassert(pim_ifp);
266
267 zassert(fd == pim_ifp->pim_sock_fd);
268
269 len = pim_socket_recvfromto(fd, buf, sizeof(buf),
270 &from, &fromlen,
271 &to, &tolen,
272 &ifindex);
273 if (len < 0) {
274 zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s",
Everton Marquese96f0af2009-08-11 15:48:02 -0300275 fd, errno, safe_strerror(errno));
Everton Marques871dbcf2009-08-11 15:43:05 -0300276 goto done;
277 }
278
279 if (PIM_DEBUG_PIM_PACKETS) {
280 char from_str[100];
281 char to_str[100];
282
283 if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str)))
284 sprintf(from_str, "<from?>");
285 if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str)))
286 sprintf(to_str, "<to?>");
287
288 zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)",
289 len, from_str, to_str, fd, ifindex, ifp->ifindex);
290 }
291
292#ifdef PIM_CHECK_RECV_IFINDEX_SANITY
293 /* ifindex sanity check */
294 if (ifindex != (int) ifp->ifindex) {
295 char from_str[100];
296 char to_str[100];
297 struct interface *recv_ifp;
298
299 if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str)))
300 sprintf(from_str, "<from?>");
301 if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str)))
302 sprintf(to_str, "<to?>");
303
304 recv_ifp = if_lookup_by_index(ifindex);
305 if (recv_ifp) {
306 zassert(ifindex == (int) recv_ifp->ifindex);
307 }
308
309#ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
310 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
311 from_str, to_str, fd,
312 ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>",
313 ifp->ifindex, ifp->name);
314#endif
315 goto done;
316 }
317#endif
318
319 if (pim_pim_packet(ifp, buf, len)) {
320 goto done;
321 }
322
323 result = 0; /* good */
324
325 done:
326 pim_sock_read_on(ifp);
327
328 if (result) {
329 ++pim_ifp->pim_ifstat_hello_recvfail;
330 }
331
332 return result;
333}
334
335static void pim_sock_read_on(struct interface *ifp)
336{
337 struct pim_interface *pim_ifp;
338
339 zassert(ifp);
340 zassert(ifp->info);
341
342 pim_ifp = ifp->info;
343
344 if (PIM_DEBUG_PIM_TRACE) {
345 zlog_debug("Scheduling READ event on PIM socket fd=%d",
346 pim_ifp->pim_sock_fd);
347 }
348 pim_ifp->t_pim_sock_read = 0;
349 zassert(!pim_ifp->t_pim_sock_read);
350 THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp,
351 pim_ifp->pim_sock_fd);
352}
353
354static int pim_sock_open(struct in_addr ifaddr, int ifindex)
355{
356 int fd;
357
358 fd = pim_socket_mcast(IPPROTO_PIM, ifaddr, 0 /* loop=false */);
359 if (fd < 0)
360 return -1;
361
362 if (pim_socket_join(fd, qpim_all_pim_routers_addr, ifaddr, ifindex)) {
363 return -2;
364 }
365
366 return fd;
367}
368
369void pim_ifstat_reset(struct interface *ifp)
370{
371 struct pim_interface *pim_ifp;
372
373 zassert(ifp);
374
375 pim_ifp = ifp->info;
376 if (!pim_ifp) {
377 return;
378 }
379
380 pim_ifp->pim_ifstat_start = pim_time_monotonic_sec();
381 pim_ifp->pim_ifstat_hello_sent = 0;
382 pim_ifp->pim_ifstat_hello_sendfail = 0;
383 pim_ifp->pim_ifstat_hello_recv = 0;
384 pim_ifp->pim_ifstat_hello_recvfail = 0;
385}
386
387void pim_sock_reset(struct interface *ifp)
388{
389 struct pim_interface *pim_ifp;
390
391 zassert(ifp);
392 zassert(ifp->info);
393
394 pim_ifp = ifp->info;
395
396 pim_ifp->primary_address = pim_find_primary_addr(ifp);
397
398 pim_ifp->pim_sock_fd = -1;
399 pim_ifp->pim_sock_creation = 0;
400 pim_ifp->t_pim_sock_read = 0;
401
402 pim_ifp->t_pim_hello_timer = 0;
403 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
404 pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */
405 pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY;
406 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
407 pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
408 pim_ifp->pim_override_interval_msec = PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
409 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION) {
410 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
411 }
412 else {
413 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
414 }
415
416 /* neighbors without lan_delay */
417 pim_ifp->pim_number_of_nonlandelay_neighbors = 0;
418 pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0;
419 pim_ifp->pim_neighbors_highest_override_interval_msec = 0;
420
421 /* DR Election */
422 pim_ifp->pim_dr_election_last = 0; /* timestamp */
423 pim_ifp->pim_dr_election_count = 0;
424 pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */
425 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
426
427 pim_ifstat_reset(ifp);
428}
429
430int pim_msg_send(int fd,
431 struct in_addr dst,
432 char *pim_msg,
433 int pim_msg_size,
434 const char *ifname)
435{
436 ssize_t sent;
437 struct sockaddr_in to;
438 socklen_t tolen;
439
440 if (PIM_DEBUG_PIM_PACKETS) {
441 char dst_str[100];
442 pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
443 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
444 __PRETTY_FUNCTION__,
445 dst_str, ifname, pim_msg_size,
446 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
447 }
448
449#if 0
450 memset(&to, 0, sizeof(to));
451#endif
452 to.sin_family = AF_INET;
453 to.sin_addr = dst;
454#if 0
455 to.sin_port = htons(0);
456#endif
457 tolen = sizeof(to);
458
459 sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT, &to, tolen);
460 if (sent != (ssize_t) pim_msg_size) {
461 int e = errno;
462 char dst_str[100];
463 pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
464 if (sent < 0) {
465 zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s",
466 __PRETTY_FUNCTION__,
467 dst_str, ifname, fd, pim_msg_size,
Everton Marquese96f0af2009-08-11 15:48:02 -0300468 e, safe_strerror(e));
Everton Marques871dbcf2009-08-11 15:43:05 -0300469 }
470 else {
471 zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%d",
472 __PRETTY_FUNCTION__,
473 dst_str, ifname, fd,
474 pim_msg_size, sent);
475 }
476 return -1;
477 }
478
479 return 0;
480}
481
482static int hello_send(struct interface *ifp,
483 uint16_t holdtime)
484{
485 char pim_msg[PIM_PIM_BUFSIZE_WRITE];
486 struct pim_interface *pim_ifp;
487 int pim_tlv_size;
488 int pim_msg_size;
489
490 pim_ifp = ifp->info;
491
492 if (PIM_DEBUG_PIM_PACKETS) {
493 char dst_str[100];
494 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str));
495 zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d",
496 __PRETTY_FUNCTION__,
497 dst_str, ifp->name,
498 holdtime,
499 pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec,
500 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
501 pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
502 listcount(ifp->connected));
503 }
504
505 pim_tlv_size = pim_hello_build_tlv(ifp->name,
506 pim_msg + PIM_PIM_MIN_LEN,
507 sizeof(pim_msg) - PIM_PIM_MIN_LEN,
508 holdtime,
509 pim_ifp->pim_dr_priority,
510 pim_ifp->pim_generation_id,
511 pim_ifp->pim_propagation_delay_msec,
512 pim_ifp->pim_override_interval_msec,
513 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
514 ifp->connected);
515 if (pim_tlv_size < 0) {
516 return -1;
517 }
518
519 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
520
521 zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
522 zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
523
524 pim_msg_build_header(pim_msg, pim_msg_size,
525 PIM_MSG_TYPE_HELLO);
526
527 if (pim_msg_send(pim_ifp->pim_sock_fd,
528 qpim_all_pim_routers_addr,
529 pim_msg,
530 pim_msg_size,
531 ifp->name)) {
532 zlog_warn("%s: could not send PIM message on interface %s",
533 __PRETTY_FUNCTION__, ifp->name);
534 return -2;
535 }
536
537 return 0;
538}
539
540static int pim_hello_send(struct interface *ifp,
541 uint16_t holdtime)
542{
543 struct pim_interface *pim_ifp;
544
545 zassert(ifp);
546 pim_ifp = ifp->info;
547 zassert(pim_ifp);
548
549 if (hello_send(ifp, holdtime)) {
550 ++pim_ifp->pim_ifstat_hello_sendfail;
551
552 zlog_warn("Could not send PIM hello on interface %s",
553 ifp->name);
554 return -1;
555 }
556
557 ++pim_ifp->pim_ifstat_hello_sent;
558
559 return 0;
560}
561
562static void hello_resched(struct interface *ifp)
563{
564 struct pim_interface *pim_ifp;
565
566 zassert(ifp);
567 pim_ifp = ifp->info;
568 zassert(pim_ifp);
569
570 if (PIM_DEBUG_PIM_TRACE) {
571 zlog_debug("Rescheduling %d sec hello on interface %s",
572 pim_ifp->pim_hello_period, ifp->name);
573 }
574 THREAD_OFF(pim_ifp->t_pim_hello_timer);
575 THREAD_TIMER_ON(master, pim_ifp->t_pim_hello_timer,
576 on_pim_hello_send,
577 ifp, pim_ifp->pim_hello_period);
578}
579
580/*
581 Periodic hello timer
582 */
583static int on_pim_hello_send(struct thread *t)
584{
585 struct pim_interface *pim_ifp;
586 struct interface *ifp;
587
588 zassert(t);
589 ifp = THREAD_ARG(t);
590 zassert(ifp);
591
592 pim_ifp = ifp->info;
593
594 /*
595 * Schedule next hello
596 */
597 pim_ifp->t_pim_hello_timer = 0;
598 hello_resched(ifp);
599
600 /*
601 * Send hello
602 */
603 return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
604}
605
606/*
607 RFC 4601: 4.3.1. Sending Hello Messages
608
609 Thus, if a router needs to send a Join/Prune or Assert message on an
610 interface on which it has not yet sent a Hello message with the
611 currently configured IP address, then it MUST immediately send the
612 relevant Hello message without waiting for the Hello Timer to
613 expire, followed by the Join/Prune or Assert message.
614 */
615void pim_hello_restart_now(struct interface *ifp)
616{
617 struct pim_interface *pim_ifp;
618
619 zassert(ifp);
620 pim_ifp = ifp->info;
621 zassert(pim_ifp);
622
623 /*
624 * Reset next hello timer
625 */
626 hello_resched(ifp);
627
628 /*
629 * Immediately send hello
630 */
631 pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
632}
633
634/*
635 RFC 4601: 4.3.1. Sending Hello Messages
636
637 To allow new or rebooting routers to learn of PIM neighbors quickly,
638 when a Hello message is received from a new neighbor, or a Hello
639 message with a new GenID is received from an existing neighbor, a
640 new Hello message should be sent on this interface after a
641 randomized delay between 0 and Triggered_Hello_Delay.
642 */
643void pim_hello_restart_triggered(struct interface *ifp)
644{
645 struct pim_interface *pim_ifp;
646 int triggered_hello_delay_msec;
647 int random_msec;
648
649 zassert(ifp);
650 pim_ifp = ifp->info;
651 zassert(pim_ifp);
652
653 triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
654
655 if (pim_ifp->t_pim_hello_timer) {
656 long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer);
657 if (remain_msec <= triggered_hello_delay_msec) {
658 /* Rescheduling hello would increase the delay, then it's faster
659 to just wait for the scheduled periodic hello. */
660 return;
661 }
662
663 THREAD_OFF(pim_ifp->t_pim_hello_timer);
664 pim_ifp->t_pim_hello_timer = 0;
665 }
666 zassert(!pim_ifp->t_pim_hello_timer);
667
668 random_msec = pim_rand_next(0, triggered_hello_delay_msec);
669
670 if (PIM_DEBUG_PIM_EVENTS) {
671 zlog_debug("Scheduling %d msec triggered hello on interface %s",
672 random_msec, ifp->name);
673 }
674
675 THREAD_TIMER_MSEC_ON(master, pim_ifp->t_pim_hello_timer,
676 on_pim_hello_send,
677 ifp, triggered_hello_delay_msec);
678}
679
680int pim_sock_add(struct interface *ifp)
681{
682 struct pim_interface *pim_ifp;
683 struct in_addr ifaddr;
684
685 pim_ifp = ifp->info;
686 zassert(pim_ifp);
687
688 if (pim_ifp->pim_sock_fd >= 0) {
689 zlog_warn("Can't recreate existing PIM socket fd=%d for interface %s",
690 pim_ifp->pim_sock_fd, ifp->name);
691 return -1;
692 }
693
694 ifaddr = pim_ifp->primary_address;
695
696 pim_ifp->pim_sock_fd = pim_sock_open(ifaddr, ifp->ifindex);
697 if (pim_ifp->pim_sock_fd < 0) {
698 zlog_warn("Could not open PIM socket on interface %s",
699 ifp->name);
700 return -2;
701 }
702
703 pim_ifp->t_pim_sock_read = 0;
704 pim_ifp->pim_sock_creation = pim_time_monotonic_sec();
705
706 pim_ifp->pim_generation_id = pim_rand() & (int64_t) 0xFFFFFFFF;
707
708 zlog_info("PIM INTERFACE UP: on interface %s",
709 ifp->name);
710
711 /*
712 * Start receiving PIM messages
713 */
714 pim_sock_read_on(ifp);
715
716 /*
717 * Start sending PIM hello's
718 */
719 pim_hello_restart_triggered(ifp);
720
721 return 0;
722}