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