3 Copyright (C) 2008 Everton da Silva Marques
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.
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.
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,
32 #include "pim_iface.h"
37 #include "pim_neighbor.h"
38 #include "pim_hello.h"
40 #include "pim_assert.h"
42 #include "pim_register.h"
44 static int on_pim_hello_send(struct thread
*t
);
45 static int pim_hello_send(struct interface
*ifp
,
49 const char *pim_pim_msgtype2str (enum pim_msg_type type
)
53 case PIM_MSG_TYPE_HELLO
: return "HELLO";
54 case PIM_MSG_TYPE_REGISTER
: return "REGISTER";
55 case PIM_MSG_TYPE_REG_STOP
: return "REGSTOP";
56 case PIM_MSG_TYPE_JOIN_PRUNE
: return "JOINPRUNE";
57 case PIM_MSG_TYPE_BOOTSTRAP
: return "BOOT";
58 case PIM_MSG_TYPE_ASSERT
: return "ASSERT";
59 case PIM_MSG_TYPE_GRAFT
: return "GRAFT";
60 case PIM_MSG_TYPE_GRAFT_ACK
: return "GACK";
61 case PIM_MSG_TYPE_CANDIDATE
: return "CANDIDATE";
67 static void sock_close(struct interface
*ifp
)
69 struct pim_interface
*pim_ifp
= ifp
->info
;
71 if (PIM_DEBUG_PIM_TRACE
) {
72 if (pim_ifp
->t_pim_sock_read
) {
73 zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
78 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
80 if (PIM_DEBUG_PIM_TRACE
) {
81 if (pim_ifp
->t_pim_hello_timer
) {
82 zlog_debug("Cancelling PIM hello timer for interface %s",
86 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
88 if (PIM_DEBUG_PIM_TRACE
) {
89 zlog_debug("Deleting PIM socket fd=%d on interface %s",
90 pim_ifp
->pim_sock_fd
, ifp
->name
);
94 * If the fd is already deleted no need to do anything here
96 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
97 zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
98 pim_ifp
->pim_sock_fd
, ifp
->name
,
99 errno
, safe_strerror(errno
));
102 pim_ifp
->pim_sock_fd
= -1;
103 pim_ifp
->pim_sock_creation
= 0;
106 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
108 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
109 ifp
->name
, delete_message
);
112 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
113 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
118 RFC 4601: 4.3.1. Sending Hello Messages
120 Before an interface goes down or changes primary IP address, a Hello
121 message with a zero HoldTime should be sent immediately (with the
122 old IP address if the IP address changed).
124 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
126 pim_neighbor_delete_all(ifp
, delete_message
);
131 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
134 size_t ip_hlen
; /* ip header length in bytes */
135 char src_str
[INET_ADDRSTRLEN
];
136 char dst_str
[INET_ADDRSTRLEN
];
140 enum pim_msg_type pim_type
;
141 uint16_t pim_checksum
; /* received checksum */
142 uint16_t checksum
; /* computed checksum */
143 struct pim_neighbor
*neigh
;
145 if (len
< sizeof(*ip_hdr
)) {
146 if (PIM_DEBUG_PIM_PACKETS
)
147 zlog_debug("PIM packet size=%zu shorter than minimum=%zu",
148 len
, sizeof(*ip_hdr
));
152 ip_hdr
= (struct ip
*) buf
;
153 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
155 if (ip_hdr
->ip_p
!= PIM_IP_PROTO_PIM
) {
156 if (PIM_DEBUG_PIM_PACKETS
)
157 zlog_debug("IP packet protocol=%d is not PIM=%d",
158 ip_hdr
->ip_p
, PIM_IP_PROTO_PIM
);
162 if (ip_hlen
< PIM_IP_HEADER_MIN_LEN
) {
163 if (PIM_DEBUG_PIM_PACKETS
)
164 zlog_debug("IP packet header size=%zu shorter than minimum=%d",
165 ip_hlen
, PIM_IP_HEADER_MIN_LEN
);
168 if (ip_hlen
> PIM_IP_HEADER_MAX_LEN
) {
169 if (PIM_DEBUG_PIM_PACKETS
)
170 zlog_debug("IP packet header size=%zu greater than maximum=%d",
171 ip_hlen
, PIM_IP_HEADER_MAX_LEN
);
175 pim_msg
= buf
+ ip_hlen
;
176 pim_msg_len
= len
- ip_hlen
;
178 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
179 if (PIM_DEBUG_PIM_PACKETS
)
180 zlog_debug("PIM message size=%d shorter than minimum=%d",
181 pim_msg_len
, PIM_PIM_MIN_LEN
);
185 pim_version
= PIM_MSG_HDR_GET_VERSION(pim_msg
);
186 pim_type
= PIM_MSG_HDR_GET_TYPE(pim_msg
);
188 if (pim_version
!= PIM_PROTO_VERSION
) {
189 if (PIM_DEBUG_PIM_PACKETS
)
190 zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
191 ifp
->name
, pim_version
);
195 /* save received checksum */
196 pim_checksum
= PIM_MSG_HDR_GET_CHECKSUM(pim_msg
);
198 /* for computing checksum */
199 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg
) = 0;
201 checksum
= in_cksum(pim_msg
, pim_msg_len
);
202 if (checksum
!= pim_checksum
) {
203 if (PIM_DEBUG_PIM_PACKETS
)
204 zlog_debug("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
205 ifp
->name
, pim_checksum
, checksum
);
209 if (PIM_DEBUG_PIM_PACKETS
) {
210 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
, sizeof(src_str
));
211 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
, sizeof(dst_str
));
212 zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
213 pim_pim_msgtype2str (pim_type
), src_str
, dst_str
, ifp
->name
,
214 ip_hdr
->ip_ttl
, pim_version
, pim_msg_len
, checksum
);
215 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
216 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
222 case PIM_MSG_TYPE_HELLO
:
223 return pim_hello_recv (ifp
,
225 pim_msg
+ PIM_MSG_HEADER_LEN
,
226 pim_msg_len
- PIM_MSG_HEADER_LEN
);
228 case PIM_MSG_TYPE_REGISTER
:
229 return pim_register_recv (ifp
,
232 pim_msg
+ PIM_MSG_HEADER_LEN
,
233 pim_msg_len
- PIM_MSG_HEADER_LEN
);
235 case PIM_MSG_TYPE_REG_STOP
:
236 return pim_register_stop_recv (pim_msg
+ PIM_MSG_HEADER_LEN
,
237 pim_msg_len
- PIM_MSG_HEADER_LEN
);
239 case PIM_MSG_TYPE_JOIN_PRUNE
:
240 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
242 if (PIM_DEBUG_PIM_PACKETS
)
243 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
244 __FILE__
, __PRETTY_FUNCTION__
,
245 pim_type
, src_str
, ifp
->name
);
248 return pim_joinprune_recv(ifp
, neigh
,
250 pim_msg
+ PIM_MSG_HEADER_LEN
,
251 pim_msg_len
- PIM_MSG_HEADER_LEN
);
253 case PIM_MSG_TYPE_ASSERT
:
254 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
256 if (PIM_DEBUG_PIM_PACKETS
)
257 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
258 __FILE__
, __PRETTY_FUNCTION__
,
259 pim_type
, src_str
, ifp
->name
);
262 return pim_assert_recv(ifp
, neigh
,
264 pim_msg
+ PIM_MSG_HEADER_LEN
,
265 pim_msg_len
- PIM_MSG_HEADER_LEN
);
268 if (PIM_DEBUG_PIM_PACKETS
) {
269 zlog_debug("Recv PIM packet type %d which is not currently understood",
277 static void pim_sock_read_on(struct interface
*ifp
);
279 static int pim_sock_read(struct thread
*t
)
281 struct interface
*ifp
;
282 struct pim_interface
*pim_ifp
;
284 struct sockaddr_in from
;
285 struct sockaddr_in to
;
286 socklen_t fromlen
= sizeof(from
);
287 socklen_t tolen
= sizeof(to
);
288 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
290 ifindex_t ifindex
= -1;
291 int result
= -1; /* defaults to bad */
292 static long long count
= 0;
302 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
),
310 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
315 if (PIM_DEBUG_PIM_PACKETS
)
316 zlog_debug ("Received errno: %d %s", errno
, safe_strerror (errno
));
320 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
321 /* ifindex sanity check */
322 if (ifindex
!= (int) ifp
->ifindex
) {
323 char from_str
[INET_ADDRSTRLEN
];
324 char to_str
[INET_ADDRSTRLEN
];
325 struct interface
*recv_ifp
;
327 if (!inet_ntop(AF_INET
, &from
.sin_addr
, from_str
, sizeof(from_str
)))
328 sprintf(from_str
, "<from?>");
329 if (!inet_ntop(AF_INET
, &to
.sin_addr
, to_str
, sizeof(to_str
)))
330 sprintf(to_str
, "<to?>");
332 recv_ifp
= if_lookup_by_index(ifindex
);
334 zassert(ifindex
== (int) recv_ifp
->ifindex
);
337 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
338 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
339 from_str
, to_str
, fd
,
340 ifindex
, recv_ifp
? recv_ifp
->name
: "<if-notfound>",
341 ifp
->ifindex
, ifp
->name
);
347 int fail
= pim_pim_packet(ifp
, buf
, len
);
349 if (PIM_DEBUG_PIM_PACKETS
)
350 zlog_debug("%s: pim_pim_packet() return=%d",
351 __PRETTY_FUNCTION__
, fail
);
360 result
= 0; /* good */
363 pim_sock_read_on(ifp
);
366 ++pim_ifp
->pim_ifstat_hello_recvfail
;
372 static void pim_sock_read_on(struct interface
*ifp
)
374 struct pim_interface
*pim_ifp
;
381 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
382 zlog_debug("Scheduling READ event on PIM socket fd=%d",
383 pim_ifp
->pim_sock_fd
);
385 pim_ifp
->t_pim_sock_read
= NULL
;
386 zassert(!pim_ifp
->t_pim_sock_read
);
387 THREAD_READ_ON(master
, pim_ifp
->t_pim_sock_read
, pim_sock_read
, ifp
,
388 pim_ifp
->pim_sock_fd
);
391 static int pim_sock_open(struct in_addr ifaddr
, ifindex_t ifindex
)
395 fd
= pim_socket_mcast(IPPROTO_PIM
, ifaddr
, ifindex
, 0 /* loop=false */);
399 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
, ifaddr
, ifindex
)) {
407 void pim_ifstat_reset(struct interface
*ifp
)
409 struct pim_interface
*pim_ifp
;
418 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
419 pim_ifp
->pim_ifstat_hello_sent
= 0;
420 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
421 pim_ifp
->pim_ifstat_hello_recv
= 0;
422 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
425 void pim_sock_reset(struct interface
*ifp
)
427 struct pim_interface
*pim_ifp
;
434 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
436 pim_ifp
->pim_sock_fd
= -1;
437 pim_ifp
->pim_sock_creation
= 0;
438 pim_ifp
->t_pim_sock_read
= NULL
;
440 pim_ifp
->t_pim_hello_timer
= NULL
;
441 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
442 pim_ifp
->pim_default_holdtime
= -1; /* unset: means 3.5 * pim_hello_period */
443 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
444 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
445 pim_ifp
->pim_propagation_delay_msec
= PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
446 pim_ifp
->pim_override_interval_msec
= PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
447 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
448 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
451 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
454 /* neighbors without lan_delay */
455 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
456 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
457 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
460 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
461 pim_ifp
->pim_dr_election_count
= 0;
462 pim_ifp
->pim_dr_election_changes
= 0;
463 pim_ifp
->pim_dr_num_nondrpri_neighbors
= 0; /* neighbors without dr_pri */
464 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
466 pim_ifstat_reset(ifp
);
469 static uint16_t ip_id
= 0;
473 pim_msg_send_frame (int fd
, char *buf
, size_t len
,
474 struct sockaddr
*dst
, size_t salen
)
476 struct ip
*ip
= (struct ip
*)buf
;
478 while (sendto (fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0)
480 char dst_str
[INET_ADDRSTRLEN
];
486 size_t hdrsize
= sizeof (struct ip
);
487 size_t newlen1
= ((len
- hdrsize
) / 2 ) & 0xFFF8;
488 size_t sendlen
= newlen1
+ hdrsize
;
489 size_t offset
= ntohs (ip
->ip_off
);
491 ip
->ip_len
= htons (sendlen
);
492 ip
->ip_off
= htons (offset
| IP_MF
);
493 if (pim_msg_send_frame (fd
, buf
, sendlen
, dst
, salen
) == 0)
495 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
496 size_t newlen2
= len
- sendlen
;
497 sendlen
= newlen2
+ hdrsize
;
499 memcpy (ip2
, ip
, hdrsize
);
500 ip2
->ip_len
= htons (sendlen
);
501 ip2
->ip_off
= htons (offset
+ (newlen1
>> 3));
502 return pim_msg_send_frame (fd
, (char *)ip2
, sendlen
, dst
, salen
);
509 pim_inet4_dump ("<dst?>", ip
->ip_dst
, dst_str
, sizeof (dst_str
));
510 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
513 errno
, safe_strerror(errno
));
523 pim_msg_send(int fd
, struct in_addr src
,
524 struct in_addr dst
, uint8_t *pim_msg
,
525 int pim_msg_size
, const char *ifname
)
527 struct sockaddr_in to
;
529 unsigned char buffer
[10000];
530 unsigned char *msg_start
;
533 memset (buffer
, 0, 10000);
534 int sendlen
= sizeof (struct ip
) + pim_msg_size
;
536 msg_start
= buffer
+ sizeof (struct ip
);
537 memcpy (msg_start
, pim_msg
, pim_msg_size
);
539 ip
= (struct ip
*)buffer
;
540 ip
->ip_id
= htons (++ip_id
);
543 ip
->ip_p
= PIM_IP_PROTO_PIM
;
547 ip
->ip_len
= htons (sendlen
);
549 if (PIM_DEBUG_PIM_PACKETS
) {
550 char dst_str
[INET_ADDRSTRLEN
];
551 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
552 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
554 dst_str
, ifname
, pim_msg_size
,
555 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg
));
558 memset(&to
, 0, sizeof(to
));
559 to
.sin_family
= AF_INET
;
563 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
564 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
567 pim_msg_send_frame (fd
, (char *)buffer
, sendlen
,
568 (struct sockaddr
*)&to
, tolen
);
572 static int hello_send(struct interface
*ifp
,
575 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
576 struct pim_interface
*pim_ifp
;
582 if (PIM_DEBUG_PIM_HELLO
) {
583 char dst_str
[INET_ADDRSTRLEN
];
584 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
, sizeof(dst_str
));
585 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",
589 pim_ifp
->pim_propagation_delay_msec
, pim_ifp
->pim_override_interval_msec
,
590 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
591 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
592 listcount(ifp
->connected
));
595 pim_tlv_size
= pim_hello_build_tlv(ifp
->name
,
596 pim_msg
+ PIM_PIM_MIN_LEN
,
597 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
,
599 pim_ifp
->pim_dr_priority
,
600 pim_ifp
->pim_generation_id
,
601 pim_ifp
->pim_propagation_delay_msec
,
602 pim_ifp
->pim_override_interval_msec
,
603 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
605 if (pim_tlv_size
< 0) {
609 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
611 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
612 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
614 pim_msg_build_header(pim_msg
, pim_msg_size
,
617 if (pim_msg_send(pim_ifp
->pim_sock_fd
,
618 pim_ifp
->primary_address
,
619 qpim_all_pim_routers_addr
,
623 if (PIM_DEBUG_PIM_HELLO
) {
624 zlog_debug("%s: could not send PIM message on interface %s",
625 __PRETTY_FUNCTION__
, ifp
->name
);
633 static int pim_hello_send(struct interface
*ifp
,
636 struct pim_interface
*pim_ifp
;
642 if (if_is_loopback (ifp
))
645 if (hello_send(ifp
, holdtime
)) {
646 ++pim_ifp
->pim_ifstat_hello_sendfail
;
648 if (PIM_DEBUG_PIM_HELLO
) {
649 zlog_warn("Could not send PIM hello on interface %s",
655 ++pim_ifp
->pim_ifstat_hello_sent
;
660 static void hello_resched(struct interface
*ifp
)
662 struct pim_interface
*pim_ifp
;
668 if (PIM_DEBUG_PIM_HELLO
) {
669 zlog_debug("Rescheduling %d sec hello on interface %s",
670 pim_ifp
->pim_hello_period
, ifp
->name
);
672 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
673 THREAD_TIMER_ON(master
, pim_ifp
->t_pim_hello_timer
,
675 ifp
, pim_ifp
->pim_hello_period
);
681 static int on_pim_hello_send(struct thread
*t
)
683 struct pim_interface
*pim_ifp
;
684 struct interface
*ifp
;
691 * Schedule next hello
693 pim_ifp
->t_pim_hello_timer
= NULL
;
699 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
703 RFC 4601: 4.3.1. Sending Hello Messages
705 Thus, if a router needs to send a Join/Prune or Assert message on an
706 interface on which it has not yet sent a Hello message with the
707 currently configured IP address, then it MUST immediately send the
708 relevant Hello message without waiting for the Hello Timer to
709 expire, followed by the Join/Prune or Assert message.
711 void pim_hello_restart_now(struct interface
*ifp
)
713 struct pim_interface
*pim_ifp
;
720 * Reset next hello timer
725 * Immediately send hello
727 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
731 RFC 4601: 4.3.1. Sending Hello Messages
733 To allow new or rebooting routers to learn of PIM neighbors quickly,
734 when a Hello message is received from a new neighbor, or a Hello
735 message with a new GenID is received from an existing neighbor, a
736 new Hello message should be sent on this interface after a
737 randomized delay between 0 and Triggered_Hello_Delay.
739 void pim_hello_restart_triggered(struct interface
*ifp
)
741 struct pim_interface
*pim_ifp
;
742 int triggered_hello_delay_msec
;
749 triggered_hello_delay_msec
= 1000 * pim_ifp
->pim_triggered_hello_delay
;
751 if (pim_ifp
->t_pim_hello_timer
) {
752 long remain_msec
= pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
753 if (remain_msec
<= triggered_hello_delay_msec
) {
754 /* Rescheduling hello would increase the delay, then it's faster
755 to just wait for the scheduled periodic hello. */
759 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
760 pim_ifp
->t_pim_hello_timer
= NULL
;
763 random_msec
= random() % (triggered_hello_delay_msec
+ 1);
765 if (PIM_DEBUG_PIM_HELLO
) {
766 zlog_debug("Scheduling %d msec triggered hello on interface %s",
767 random_msec
, ifp
->name
);
770 THREAD_TIMER_MSEC_ON(master
, pim_ifp
->t_pim_hello_timer
,
775 int pim_sock_add(struct interface
*ifp
)
777 struct pim_interface
*pim_ifp
;
778 struct in_addr ifaddr
;
784 if (pim_ifp
->pim_sock_fd
>= 0) {
785 if (PIM_DEBUG_PIM_PACKETS
)
786 zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s",
787 pim_ifp
->pim_sock_fd
, ifp
->name
);
791 ifaddr
= pim_ifp
->primary_address
;
793 pim_ifp
->pim_sock_fd
= pim_sock_open(ifaddr
, ifp
->ifindex
);
794 if (pim_ifp
->pim_sock_fd
< 0) {
795 if (PIM_DEBUG_PIM_PACKETS
)
796 zlog_debug("Could not open PIM socket on interface %s",
801 pim_socket_ip_hdr (pim_ifp
->pim_sock_fd
);
803 pim_ifp
->t_pim_sock_read
= NULL
;
804 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
807 * Just ensure that the new generation id
808 * actually chooses something different.
809 * Actually ran across a case where this
810 * happened, pre-switch to random().
811 * While this is unlikely to happen now
812 * let's make sure it doesn't.
814 old_genid
= pim_ifp
->pim_generation_id
;
816 while (old_genid
== pim_ifp
->pim_generation_id
)
817 pim_ifp
->pim_generation_id
= random();
819 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
820 ifp
->name
, ifp
->ifindex
);
823 * Start receiving PIM messages
825 pim_sock_read_on(ifp
);
828 * Start sending PIM hello's
830 pim_hello_restart_triggered(ifp
);