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 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
30 #include "pim_iface.h"
35 #include "pim_neighbor.h"
36 #include "pim_hello.h"
38 #include "pim_assert.h"
40 #include "pim_register.h"
42 static int on_pim_hello_send(struct thread
*t
);
43 static int pim_hello_send(struct interface
*ifp
,
47 const char *pim_pim_msgtype2str (enum pim_msg_type type
)
51 case PIM_MSG_TYPE_HELLO
: return "HELLO";
52 case PIM_MSG_TYPE_REGISTER
: return "REGISTER";
53 case PIM_MSG_TYPE_REG_STOP
: return "REGSTOP";
54 case PIM_MSG_TYPE_JOIN_PRUNE
: return "JOINPRUNE";
55 case PIM_MSG_TYPE_BOOTSTRAP
: return "BOOT";
56 case PIM_MSG_TYPE_ASSERT
: return "ASSERT";
57 case PIM_MSG_TYPE_GRAFT
: return "GRAFT";
58 case PIM_MSG_TYPE_GRAFT_ACK
: return "GACK";
59 case PIM_MSG_TYPE_CANDIDATE
: return "CANDIDATE";
65 static void sock_close(struct interface
*ifp
)
67 struct pim_interface
*pim_ifp
= ifp
->info
;
69 if (PIM_DEBUG_PIM_TRACE
) {
70 if (pim_ifp
->t_pim_sock_read
) {
71 zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
76 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
78 if (PIM_DEBUG_PIM_TRACE
) {
79 if (pim_ifp
->t_pim_hello_timer
) {
80 zlog_debug("Cancelling PIM hello timer for interface %s",
84 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
86 if (PIM_DEBUG_PIM_TRACE
) {
87 zlog_debug("Deleting PIM socket fd=%d on interface %s",
88 pim_ifp
->pim_sock_fd
, ifp
->name
);
92 * If the fd is already deleted no need to do anything here
94 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
95 zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
96 pim_ifp
->pim_sock_fd
, ifp
->name
,
97 errno
, safe_strerror(errno
));
100 pim_ifp
->pim_sock_fd
= -1;
101 pim_ifp
->pim_sock_creation
= 0;
104 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
106 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
107 ifp
->name
, delete_message
);
110 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
111 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
116 RFC 4601: 4.3.1. Sending Hello Messages
118 Before an interface goes down or changes primary IP address, a Hello
119 message with a zero HoldTime should be sent immediately (with the
120 old IP address if the IP address changed).
122 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
124 pim_neighbor_delete_all(ifp
, delete_message
);
129 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
132 size_t ip_hlen
; /* ip header length in bytes */
133 char src_str
[INET_ADDRSTRLEN
];
134 char dst_str
[INET_ADDRSTRLEN
];
137 uint16_t pim_checksum
; /* received checksum */
138 uint16_t checksum
; /* computed checksum */
139 struct pim_neighbor
*neigh
;
140 struct pim_msg_header
*header
;
142 if (len
< sizeof(*ip_hdr
)) {
143 if (PIM_DEBUG_PIM_PACKETS
)
144 zlog_debug("PIM packet size=%zu shorter than minimum=%zu",
145 len
, sizeof(*ip_hdr
));
149 ip_hdr
= (struct ip
*) buf
;
150 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
152 pim_msg
= buf
+ ip_hlen
;
153 pim_msg_len
= len
- ip_hlen
;
155 header
= (struct pim_msg_header
*)pim_msg
;
156 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
157 if (PIM_DEBUG_PIM_PACKETS
)
158 zlog_debug("PIM message size=%d shorter than minimum=%d",
159 pim_msg_len
, PIM_PIM_MIN_LEN
);
163 if (header
->ver
!= PIM_PROTO_VERSION
) {
164 if (PIM_DEBUG_PIM_PACKETS
)
165 zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
166 ifp
->name
, header
->ver
);
170 /* save received checksum */
171 pim_checksum
= header
->checksum
;
173 /* for computing checksum */
174 header
->checksum
= 0;
176 if (header
->type
== PIM_MSG_TYPE_REGISTER
)
178 /* First 8 byte header checksum */
179 checksum
= in_cksum (pim_msg
, PIM_MSG_REGISTER_LEN
);
180 if (checksum
!= pim_checksum
)
182 checksum
= in_cksum (pim_msg
, pim_msg_len
);
183 if (checksum
!= pim_checksum
)
185 if (PIM_DEBUG_PIM_PACKETS
)
187 ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
188 ifp
->name
, pim_checksum
, checksum
);
196 checksum
= in_cksum (pim_msg
, pim_msg_len
);
197 if (checksum
!= pim_checksum
)
199 if (PIM_DEBUG_PIM_PACKETS
)
201 ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
202 ifp
->name
, pim_checksum
, checksum
);
208 if (PIM_DEBUG_PIM_PACKETS
) {
209 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
, sizeof(src_str
));
210 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
, sizeof(dst_str
));
211 zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
212 pim_pim_msgtype2str (header
->type
), src_str
, dst_str
, ifp
->name
,
213 ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
, checksum
);
214 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
215 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
219 switch (header
->type
)
221 case PIM_MSG_TYPE_HELLO
:
222 return pim_hello_recv (ifp
,
224 pim_msg
+ PIM_MSG_HEADER_LEN
,
225 pim_msg_len
- PIM_MSG_HEADER_LEN
);
227 case PIM_MSG_TYPE_REGISTER
:
228 return pim_register_recv (ifp
,
231 pim_msg
+ PIM_MSG_HEADER_LEN
,
232 pim_msg_len
- PIM_MSG_HEADER_LEN
);
234 case PIM_MSG_TYPE_REG_STOP
:
235 return pim_register_stop_recv (pim_msg
+ PIM_MSG_HEADER_LEN
,
236 pim_msg_len
- PIM_MSG_HEADER_LEN
);
238 case PIM_MSG_TYPE_JOIN_PRUNE
:
239 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
241 if (PIM_DEBUG_PIM_PACKETS
)
242 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
243 __FILE__
, __PRETTY_FUNCTION__
,
244 header
->type
, src_str
, ifp
->name
);
247 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
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 header
->type
, src_str
, ifp
->name
);
262 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
263 return pim_assert_recv(ifp
, neigh
,
265 pim_msg
+ PIM_MSG_HEADER_LEN
,
266 pim_msg_len
- PIM_MSG_HEADER_LEN
);
269 if (PIM_DEBUG_PIM_PACKETS
) {
270 zlog_debug("Recv PIM packet type %d which is not currently understood",
278 static void pim_sock_read_on(struct interface
*ifp
);
280 static int pim_sock_read(struct thread
*t
)
282 struct interface
*ifp
;
283 struct pim_interface
*pim_ifp
;
285 struct sockaddr_in from
;
286 struct sockaddr_in to
;
287 socklen_t fromlen
= sizeof(from
);
288 socklen_t tolen
= sizeof(to
);
289 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
291 ifindex_t ifindex
= -1;
292 int result
= -1; /* defaults to bad */
293 static long long count
= 0;
303 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
),
311 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
314 if (PIM_DEBUG_PIM_PACKETS
)
315 zlog_debug ("Received errno: %d %s", errno
, safe_strerror (errno
));
319 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
320 /* ifindex sanity check */
321 if (ifindex
!= (int) ifp
->ifindex
) {
322 char from_str
[INET_ADDRSTRLEN
];
323 char to_str
[INET_ADDRSTRLEN
];
324 struct interface
*recv_ifp
;
326 if (!inet_ntop(AF_INET
, &from
.sin_addr
, from_str
, sizeof(from_str
)))
327 sprintf(from_str
, "<from?>");
328 if (!inet_ntop(AF_INET
, &to
.sin_addr
, to_str
, sizeof(to_str
)))
329 sprintf(to_str
, "<to?>");
331 recv_ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
333 zassert(ifindex
== (int) recv_ifp
->ifindex
);
336 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
337 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
338 from_str
, to_str
, fd
,
339 ifindex
, recv_ifp
? recv_ifp
->name
: "<if-notfound>",
340 ifp
->ifindex
, ifp
->name
);
346 int fail
= pim_pim_packet(ifp
, buf
, len
);
348 if (PIM_DEBUG_PIM_PACKETS
)
349 zlog_debug("%s: pim_pim_packet() return=%d",
350 __PRETTY_FUNCTION__
, fail
);
355 if (count
% qpim_packet_process
== 0)
359 result
= 0; /* good */
362 pim_sock_read_on(ifp
);
365 ++pim_ifp
->pim_ifstat_hello_recvfail
;
371 static void pim_sock_read_on(struct interface
*ifp
)
373 struct pim_interface
*pim_ifp
;
380 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
381 zlog_debug("Scheduling READ event on PIM socket fd=%d",
382 pim_ifp
->pim_sock_fd
);
384 pim_ifp
->t_pim_sock_read
= NULL
;
385 thread_add_read(master
, pim_sock_read
, ifp
, pim_ifp
->pim_sock_fd
,
386 &pim_ifp
->t_pim_sock_read
);
389 static int pim_sock_open(struct interface
*ifp
)
392 struct pim_interface
*pim_ifp
= ifp
->info
;
394 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
, 0 /* loop=false */);
398 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
, pim_ifp
->primary_address
, ifp
->ifindex
)) {
406 void pim_ifstat_reset(struct interface
*ifp
)
408 struct pim_interface
*pim_ifp
;
417 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
418 pim_ifp
->pim_ifstat_hello_sent
= 0;
419 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
420 pim_ifp
->pim_ifstat_hello_recv
= 0;
421 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
424 void pim_sock_reset(struct interface
*ifp
)
426 struct pim_interface
*pim_ifp
;
433 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
435 pim_ifp
->pim_sock_fd
= -1;
436 pim_ifp
->pim_sock_creation
= 0;
437 pim_ifp
->t_pim_sock_read
= NULL
;
439 pim_ifp
->t_pim_hello_timer
= NULL
;
440 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
441 pim_ifp
->pim_default_holdtime
= -1; /* unset: means 3.5 * pim_hello_period */
442 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
443 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
444 pim_ifp
->pim_propagation_delay_msec
= PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
445 pim_ifp
->pim_override_interval_msec
= PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
446 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
447 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
450 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
453 /* neighbors without lan_delay */
454 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
455 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
456 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
459 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
460 pim_ifp
->pim_dr_election_count
= 0;
461 pim_ifp
->pim_dr_election_changes
= 0;
462 pim_ifp
->pim_dr_num_nondrpri_neighbors
= 0; /* neighbors without dr_pri */
463 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
465 pim_ifstat_reset(ifp
);
468 static uint16_t ip_id
= 0;
472 pim_msg_send_frame (int fd
, char *buf
, size_t len
,
473 struct sockaddr
*dst
, size_t salen
)
475 struct ip
*ip
= (struct ip
*)buf
;
477 while (sendto (fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0)
479 char dst_str
[INET_ADDRSTRLEN
];
485 size_t hdrsize
= sizeof (struct ip
);
486 size_t newlen1
= ((len
- hdrsize
) / 2 ) & 0xFFF8;
487 size_t sendlen
= newlen1
+ hdrsize
;
488 size_t offset
= ntohs (ip
->ip_off
);
490 ip
->ip_len
= htons (sendlen
);
491 ip
->ip_off
= htons (offset
| IP_MF
);
492 if (pim_msg_send_frame (fd
, buf
, sendlen
, dst
, salen
) == 0)
494 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
495 size_t newlen2
= len
- sendlen
;
496 sendlen
= newlen2
+ hdrsize
;
498 memcpy (ip2
, ip
, hdrsize
);
499 ip2
->ip_len
= htons (sendlen
);
500 ip2
->ip_off
= htons (offset
+ (newlen1
>> 3));
501 return pim_msg_send_frame (fd
, (char *)ip2
, sendlen
, dst
, salen
);
508 if (PIM_DEBUG_PIM_PACKETS
)
510 pim_inet4_dump ("<dst?>", ip
->ip_dst
, dst_str
, sizeof (dst_str
));
511 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
514 errno
, safe_strerror(errno
));
525 pim_msg_send(int fd
, struct in_addr src
,
526 struct in_addr dst
, uint8_t *pim_msg
,
527 int pim_msg_size
, const char *ifname
)
529 struct sockaddr_in to
;
531 unsigned char buffer
[10000];
532 unsigned char *msg_start
;
533 uint8_t ttl
= MAXTTL
;
534 struct pim_msg_header
*header
;
537 memset (buffer
, 0, 10000);
538 int sendlen
= sizeof (struct ip
) + pim_msg_size
;
540 msg_start
= buffer
+ sizeof (struct ip
);
541 memcpy (msg_start
, pim_msg
, pim_msg_size
);
543 header
= (struct pim_msg_header
*)pim_msg
;
545 * Omnios apparently doesn't have a #define for IP default
546 * ttl that is the same as all other platforms.
551 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
552 switch (header
->type
)
554 case PIM_MSG_TYPE_HELLO
:
555 case PIM_MSG_TYPE_JOIN_PRUNE
:
556 case PIM_MSG_TYPE_BOOTSTRAP
:
557 case PIM_MSG_TYPE_ASSERT
:
560 case PIM_MSG_TYPE_REGISTER
:
561 case PIM_MSG_TYPE_REG_STOP
:
562 case PIM_MSG_TYPE_GRAFT
:
563 case PIM_MSG_TYPE_GRAFT_ACK
:
564 case PIM_MSG_TYPE_CANDIDATE
:
572 ip
= (struct ip
*) buffer
;
573 ip
->ip_id
= htons (++ip_id
);
576 ip
->ip_p
= PIM_IP_PROTO_PIM
;
580 ip
->ip_len
= htons (sendlen
);
582 if (PIM_DEBUG_PIM_PACKETS
) {
583 struct pim_msg_header
*header
= (struct pim_msg_header
*)pim_msg
;
584 char dst_str
[INET_ADDRSTRLEN
];
585 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
586 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
588 dst_str
, ifname
, pim_msg_size
,
592 memset(&to
, 0, sizeof(to
));
593 to
.sin_family
= AF_INET
;
597 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
598 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
601 pim_msg_send_frame (fd
, (char *)buffer
, sendlen
,
602 (struct sockaddr
*)&to
, tolen
);
606 static int hello_send(struct interface
*ifp
,
609 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
610 struct pim_interface
*pim_ifp
;
616 if (PIM_DEBUG_PIM_HELLO
) {
617 char dst_str
[INET_ADDRSTRLEN
];
618 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
, sizeof(dst_str
));
619 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",
623 pim_ifp
->pim_propagation_delay_msec
, pim_ifp
->pim_override_interval_msec
,
624 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
625 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
626 listcount(ifp
->connected
));
629 pim_tlv_size
= pim_hello_build_tlv(ifp
,
630 pim_msg
+ PIM_PIM_MIN_LEN
,
631 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
,
633 pim_ifp
->pim_dr_priority
,
634 pim_ifp
->pim_generation_id
,
635 pim_ifp
->pim_propagation_delay_msec
,
636 pim_ifp
->pim_override_interval_msec
,
637 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
));
638 if (pim_tlv_size
< 0) {
642 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
644 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
645 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
647 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
);
649 if (pim_msg_send(pim_ifp
->pim_sock_fd
,
650 pim_ifp
->primary_address
,
651 qpim_all_pim_routers_addr
,
655 if (PIM_DEBUG_PIM_HELLO
) {
656 zlog_debug("%s: could not send PIM message on interface %s",
657 __PRETTY_FUNCTION__
, ifp
->name
);
665 static int pim_hello_send(struct interface
*ifp
,
668 struct pim_interface
*pim_ifp
;
674 if (if_is_loopback (ifp
))
677 if (hello_send(ifp
, holdtime
)) {
678 ++pim_ifp
->pim_ifstat_hello_sendfail
;
680 if (PIM_DEBUG_PIM_HELLO
) {
681 zlog_warn("Could not send PIM hello on interface %s",
687 ++pim_ifp
->pim_ifstat_hello_sent
;
692 static void hello_resched(struct interface
*ifp
)
694 struct pim_interface
*pim_ifp
;
700 if (PIM_DEBUG_PIM_HELLO
) {
701 zlog_debug("Rescheduling %d sec hello on interface %s",
702 pim_ifp
->pim_hello_period
, ifp
->name
);
704 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
705 thread_add_timer(master
, on_pim_hello_send
, ifp
, pim_ifp
->pim_hello_period
,
706 &pim_ifp
->t_pim_hello_timer
);
712 static int on_pim_hello_send(struct thread
*t
)
714 struct pim_interface
*pim_ifp
;
715 struct interface
*ifp
;
722 * Schedule next hello
724 pim_ifp
->t_pim_hello_timer
= NULL
;
730 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
734 RFC 4601: 4.3.1. Sending Hello Messages
736 Thus, if a router needs to send a Join/Prune or Assert message on an
737 interface on which it has not yet sent a Hello message with the
738 currently configured IP address, then it MUST immediately send the
739 relevant Hello message without waiting for the Hello Timer to
740 expire, followed by the Join/Prune or Assert message.
742 void pim_hello_restart_now(struct interface
*ifp
)
744 struct pim_interface
*pim_ifp
;
751 * Reset next hello timer
756 * Immediately send hello
758 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
762 RFC 4601: 4.3.1. Sending Hello Messages
764 To allow new or rebooting routers to learn of PIM neighbors quickly,
765 when a Hello message is received from a new neighbor, or a Hello
766 message with a new GenID is received from an existing neighbor, a
767 new Hello message should be sent on this interface after a
768 randomized delay between 0 and Triggered_Hello_Delay.
770 void pim_hello_restart_triggered(struct interface
*ifp
)
772 struct pim_interface
*pim_ifp
;
773 int triggered_hello_delay_msec
;
781 * There exists situations where we have the a RPF out this
782 * interface, but we haven't formed a neighbor yet. This
783 * happens especially during interface flaps. While
784 * we would like to handle this more gracefully in other
785 * parts of the code. In order to get us up and running
786 * let's just send the hello immediate'ish
787 * This should be revisited when we get nexthop tracking
788 * in and when we have a better handle on safely
789 * handling the rpf information for upstreams that
790 * we cannot legally reach yet.
792 triggered_hello_delay_msec
= 1;
793 //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
795 if (pim_ifp
->t_pim_hello_timer
) {
796 long remain_msec
= pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
797 if (remain_msec
<= triggered_hello_delay_msec
) {
798 /* Rescheduling hello would increase the delay, then it's faster
799 to just wait for the scheduled periodic hello. */
803 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
804 pim_ifp
->t_pim_hello_timer
= NULL
;
807 random_msec
= triggered_hello_delay_msec
;
808 //random_msec = random() % (triggered_hello_delay_msec + 1);
810 if (PIM_DEBUG_PIM_HELLO
) {
811 zlog_debug("Scheduling %d msec triggered hello on interface %s",
812 random_msec
, ifp
->name
);
815 thread_add_timer_msec(master
, on_pim_hello_send
, ifp
, random_msec
,
816 &pim_ifp
->t_pim_hello_timer
);
819 int pim_sock_add(struct interface
*ifp
)
821 struct pim_interface
*pim_ifp
;
827 if (pim_ifp
->pim_sock_fd
>= 0) {
828 if (PIM_DEBUG_PIM_PACKETS
)
829 zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s",
830 pim_ifp
->pim_sock_fd
, ifp
->name
);
834 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
835 if (pim_ifp
->pim_sock_fd
< 0) {
836 if (PIM_DEBUG_PIM_PACKETS
)
837 zlog_debug("Could not open PIM socket on interface %s",
842 pim_socket_ip_hdr (pim_ifp
->pim_sock_fd
);
844 pim_ifp
->t_pim_sock_read
= NULL
;
845 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
848 * Just ensure that the new generation id
849 * actually chooses something different.
850 * Actually ran across a case where this
851 * happened, pre-switch to random().
852 * While this is unlikely to happen now
853 * let's make sure it doesn't.
855 old_genid
= pim_ifp
->pim_generation_id
;
857 while (old_genid
== pim_ifp
->pim_generation_id
)
858 pim_ifp
->pim_generation_id
= random();
860 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
861 ifp
->name
, ifp
->ifindex
);
864 * Start receiving PIM messages
866 pim_sock_read_on(ifp
);
869 * Start sending PIM hello's
871 pim_hello_restart_triggered(ifp
);