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,
31 #include "pim_iface.h"
36 #include "pim_neighbor.h"
37 #include "pim_hello.h"
39 #include "pim_assert.h"
41 #include "pim_register.h"
43 static int on_pim_hello_send(struct thread
*t
);
44 static int pim_hello_send(struct interface
*ifp
,
48 const char *pim_pim_msgtype2str (enum pim_msg_type type
)
52 case PIM_MSG_TYPE_HELLO
: return "HELLO";
53 case PIM_MSG_TYPE_REGISTER
: return "REGISTER";
54 case PIM_MSG_TYPE_REG_STOP
: return "REGSTOP";
55 case PIM_MSG_TYPE_JOIN_PRUNE
: return "JOINPRUNE";
56 case PIM_MSG_TYPE_BOOTSTRAP
: return "BOOT";
57 case PIM_MSG_TYPE_ASSERT
: return "ASSERT";
58 case PIM_MSG_TYPE_GRAFT
: return "GRAFT";
59 case PIM_MSG_TYPE_GRAFT_ACK
: return "GACK";
60 case PIM_MSG_TYPE_CANDIDATE
: return "CANDIDATE";
66 static void sock_close(struct interface
*ifp
)
68 struct pim_interface
*pim_ifp
= ifp
->info
;
70 if (PIM_DEBUG_PIM_TRACE
) {
71 if (pim_ifp
->t_pim_sock_read
) {
72 zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
77 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
79 if (PIM_DEBUG_PIM_TRACE
) {
80 if (pim_ifp
->t_pim_hello_timer
) {
81 zlog_debug("Cancelling PIM hello timer for interface %s",
85 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
87 if (PIM_DEBUG_PIM_TRACE
) {
88 zlog_debug("Deleting PIM socket fd=%d on interface %s",
89 pim_ifp
->pim_sock_fd
, ifp
->name
);
93 * If the fd is already deleted no need to do anything here
95 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
96 zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
97 pim_ifp
->pim_sock_fd
, ifp
->name
,
98 errno
, safe_strerror(errno
));
101 pim_ifp
->pim_sock_fd
= -1;
102 pim_ifp
->pim_sock_creation
= 0;
105 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
107 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
108 ifp
->name
, delete_message
);
111 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
112 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
117 RFC 4601: 4.3.1. Sending Hello Messages
119 Before an interface goes down or changes primary IP address, a Hello
120 message with a zero HoldTime should be sent immediately (with the
121 old IP address if the IP address changed).
123 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
125 pim_neighbor_delete_all(ifp
, delete_message
);
130 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
133 size_t ip_hlen
; /* ip header length in bytes */
134 char src_str
[INET_ADDRSTRLEN
];
135 char dst_str
[INET_ADDRSTRLEN
];
138 uint16_t pim_checksum
; /* received checksum */
139 uint16_t checksum
; /* computed checksum */
140 struct pim_neighbor
*neigh
;
141 struct pim_msg_header
*header
;
143 if (len
< sizeof(*ip_hdr
)) {
144 if (PIM_DEBUG_PIM_PACKETS
)
145 zlog_debug("PIM packet size=%zu shorter than minimum=%zu",
146 len
, sizeof(*ip_hdr
));
150 ip_hdr
= (struct ip
*) buf
;
151 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
153 pim_msg
= buf
+ ip_hlen
;
154 pim_msg_len
= len
- ip_hlen
;
156 header
= (struct pim_msg_header
*)pim_msg
;
157 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
158 if (PIM_DEBUG_PIM_PACKETS
)
159 zlog_debug("PIM message size=%d shorter than minimum=%d",
160 pim_msg_len
, PIM_PIM_MIN_LEN
);
164 if (header
->ver
!= PIM_PROTO_VERSION
) {
165 if (PIM_DEBUG_PIM_PACKETS
)
166 zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
167 ifp
->name
, header
->ver
);
171 /* save received checksum */
172 pim_checksum
= header
->checksum
;
174 /* for computing checksum */
175 header
->checksum
= 0;
177 if (header
->type
== PIM_MSG_TYPE_REGISTER
)
179 /* First 8 byte header checksum */
180 checksum
= in_cksum (pim_msg
, PIM_MSG_REGISTER_LEN
);
181 if (checksum
!= pim_checksum
)
183 checksum
= in_cksum (pim_msg
, pim_msg_len
);
184 if (checksum
!= pim_checksum
)
186 if (PIM_DEBUG_PIM_PACKETS
)
188 ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
189 ifp
->name
, pim_checksum
, checksum
);
197 checksum
= in_cksum (pim_msg
, pim_msg_len
);
198 if (checksum
!= pim_checksum
)
200 if (PIM_DEBUG_PIM_PACKETS
)
202 ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
203 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 (header
->type
), src_str
, dst_str
, ifp
->name
,
214 ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
, checksum
);
215 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
216 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
220 switch (header
->type
)
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 header
->type
, src_str
, ifp
->name
);
248 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
249 return pim_joinprune_recv(ifp
, neigh
,
251 pim_msg
+ PIM_MSG_HEADER_LEN
,
252 pim_msg_len
- PIM_MSG_HEADER_LEN
);
254 case PIM_MSG_TYPE_ASSERT
:
255 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
257 if (PIM_DEBUG_PIM_PACKETS
)
258 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
259 __FILE__
, __PRETTY_FUNCTION__
,
260 header
->type
, src_str
, ifp
->name
);
263 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
264 return pim_assert_recv(ifp
, neigh
,
266 pim_msg
+ PIM_MSG_HEADER_LEN
,
267 pim_msg_len
- PIM_MSG_HEADER_LEN
);
270 if (PIM_DEBUG_PIM_PACKETS
) {
271 zlog_debug("Recv PIM packet type %d which is not currently understood",
279 static void pim_sock_read_on(struct interface
*ifp
);
281 static int pim_sock_read(struct thread
*t
)
283 struct interface
*ifp
;
284 struct pim_interface
*pim_ifp
;
286 struct sockaddr_in from
;
287 struct sockaddr_in to
;
288 socklen_t fromlen
= sizeof(from
);
289 socklen_t tolen
= sizeof(to
);
290 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
292 ifindex_t ifindex
= -1;
293 int result
= -1; /* defaults to bad */
294 static long long count
= 0;
304 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
),
312 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
, VRF_DEFAULT
);
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
);
356 if (count
% qpim_packet_process
== 0)
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 THREAD_READ_ON(master
, pim_ifp
->t_pim_sock_read
, pim_sock_read
, ifp
,
387 pim_ifp
->pim_sock_fd
);
390 static int pim_sock_open(struct interface
*ifp
)
393 struct pim_interface
*pim_ifp
= ifp
->info
;
395 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
, 0 /* loop=false */);
399 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
, pim_ifp
->primary_address
, ifp
->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 if (PIM_DEBUG_PIM_PACKETS
)
511 pim_inet4_dump ("<dst?>", ip
->ip_dst
, dst_str
, sizeof (dst_str
));
512 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
515 errno
, safe_strerror(errno
));
526 pim_msg_send(int fd
, struct in_addr src
,
527 struct in_addr dst
, uint8_t *pim_msg
,
528 int pim_msg_size
, const char *ifname
)
530 struct sockaddr_in to
;
532 unsigned char buffer
[10000];
533 unsigned char *msg_start
;
534 uint8_t ttl
= MAXTTL
;
535 struct pim_msg_header
*header
;
538 memset (buffer
, 0, 10000);
539 int sendlen
= sizeof (struct ip
) + pim_msg_size
;
541 msg_start
= buffer
+ sizeof (struct ip
);
542 memcpy (msg_start
, pim_msg
, pim_msg_size
);
544 header
= (struct pim_msg_header
*)pim_msg
;
546 * Omnios apparently doesn't have a #define for IP default
547 * ttl that is the same as all other platforms.
552 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
553 switch (header
->type
)
555 case PIM_MSG_TYPE_HELLO
:
556 case PIM_MSG_TYPE_JOIN_PRUNE
:
557 case PIM_MSG_TYPE_BOOTSTRAP
:
558 case PIM_MSG_TYPE_ASSERT
:
561 case PIM_MSG_TYPE_REGISTER
:
562 case PIM_MSG_TYPE_REG_STOP
:
563 case PIM_MSG_TYPE_GRAFT
:
564 case PIM_MSG_TYPE_GRAFT_ACK
:
565 case PIM_MSG_TYPE_CANDIDATE
:
573 ip
= (struct ip
*) buffer
;
574 ip
->ip_id
= htons (++ip_id
);
577 ip
->ip_p
= PIM_IP_PROTO_PIM
;
581 ip
->ip_len
= htons (sendlen
);
583 if (PIM_DEBUG_PIM_PACKETS
) {
584 struct pim_msg_header
*header
= (struct pim_msg_header
*)pim_msg
;
585 char dst_str
[INET_ADDRSTRLEN
];
586 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
587 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
589 dst_str
, ifname
, pim_msg_size
,
593 memset(&to
, 0, sizeof(to
));
594 to
.sin_family
= AF_INET
;
598 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
599 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
602 pim_msg_send_frame (fd
, (char *)buffer
, sendlen
,
603 (struct sockaddr
*)&to
, tolen
);
607 static int hello_send(struct interface
*ifp
,
610 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
611 struct pim_interface
*pim_ifp
;
617 if (PIM_DEBUG_PIM_HELLO
) {
618 char dst_str
[INET_ADDRSTRLEN
];
619 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
, sizeof(dst_str
));
620 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",
624 pim_ifp
->pim_propagation_delay_msec
, pim_ifp
->pim_override_interval_msec
,
625 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
626 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
627 listcount(ifp
->connected
));
630 pim_tlv_size
= pim_hello_build_tlv(ifp
->name
,
631 pim_msg
+ PIM_PIM_MIN_LEN
,
632 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
,
634 pim_ifp
->pim_dr_priority
,
635 pim_ifp
->pim_generation_id
,
636 pim_ifp
->pim_propagation_delay_msec
,
637 pim_ifp
->pim_override_interval_msec
,
638 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
640 if (pim_tlv_size
< 0) {
644 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
646 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
647 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
649 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
);
651 if (pim_msg_send(pim_ifp
->pim_sock_fd
,
652 pim_ifp
->primary_address
,
653 qpim_all_pim_routers_addr
,
657 if (PIM_DEBUG_PIM_HELLO
) {
658 zlog_debug("%s: could not send PIM message on interface %s",
659 __PRETTY_FUNCTION__
, ifp
->name
);
667 static int pim_hello_send(struct interface
*ifp
,
670 struct pim_interface
*pim_ifp
;
676 if (if_is_loopback (ifp
))
679 if (hello_send(ifp
, holdtime
)) {
680 ++pim_ifp
->pim_ifstat_hello_sendfail
;
682 if (PIM_DEBUG_PIM_HELLO
) {
683 zlog_warn("Could not send PIM hello on interface %s",
689 ++pim_ifp
->pim_ifstat_hello_sent
;
694 static void hello_resched(struct interface
*ifp
)
696 struct pim_interface
*pim_ifp
;
702 if (PIM_DEBUG_PIM_HELLO
) {
703 zlog_debug("Rescheduling %d sec hello on interface %s",
704 pim_ifp
->pim_hello_period
, ifp
->name
);
706 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
707 THREAD_TIMER_ON(master
, pim_ifp
->t_pim_hello_timer
,
709 ifp
, pim_ifp
->pim_hello_period
);
715 static int on_pim_hello_send(struct thread
*t
)
717 struct pim_interface
*pim_ifp
;
718 struct interface
*ifp
;
725 * Schedule next hello
727 pim_ifp
->t_pim_hello_timer
= NULL
;
733 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
737 RFC 4601: 4.3.1. Sending Hello Messages
739 Thus, if a router needs to send a Join/Prune or Assert message on an
740 interface on which it has not yet sent a Hello message with the
741 currently configured IP address, then it MUST immediately send the
742 relevant Hello message without waiting for the Hello Timer to
743 expire, followed by the Join/Prune or Assert message.
745 void pim_hello_restart_now(struct interface
*ifp
)
747 struct pim_interface
*pim_ifp
;
754 * Reset next hello timer
759 * Immediately send hello
761 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
765 RFC 4601: 4.3.1. Sending Hello Messages
767 To allow new or rebooting routers to learn of PIM neighbors quickly,
768 when a Hello message is received from a new neighbor, or a Hello
769 message with a new GenID is received from an existing neighbor, a
770 new Hello message should be sent on this interface after a
771 randomized delay between 0 and Triggered_Hello_Delay.
773 void pim_hello_restart_triggered(struct interface
*ifp
)
775 struct pim_interface
*pim_ifp
;
776 int triggered_hello_delay_msec
;
784 * There exists situations where we have the a RPF out this
785 * interface, but we haven't formed a neighbor yet. This
786 * happens especially during interface flaps. While
787 * we would like to handle this more gracefully in other
788 * parts of the code. In order to get us up and running
789 * let's just send the hello immediate'ish
790 * This should be revisited when we get nexthop tracking
791 * in and when we have a better handle on safely
792 * handling the rpf information for upstreams that
793 * we cannot legally reach yet.
795 triggered_hello_delay_msec
= 1;
796 //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
798 if (pim_ifp
->t_pim_hello_timer
) {
799 long remain_msec
= pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
800 if (remain_msec
<= triggered_hello_delay_msec
) {
801 /* Rescheduling hello would increase the delay, then it's faster
802 to just wait for the scheduled periodic hello. */
806 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
807 pim_ifp
->t_pim_hello_timer
= NULL
;
810 random_msec
= triggered_hello_delay_msec
;
811 //random_msec = random() % (triggered_hello_delay_msec + 1);
813 if (PIM_DEBUG_PIM_HELLO
) {
814 zlog_debug("Scheduling %d msec triggered hello on interface %s",
815 random_msec
, ifp
->name
);
818 THREAD_TIMER_MSEC_ON(master
, pim_ifp
->t_pim_hello_timer
,
823 int pim_sock_add(struct interface
*ifp
)
825 struct pim_interface
*pim_ifp
;
831 if (pim_ifp
->pim_sock_fd
>= 0) {
832 if (PIM_DEBUG_PIM_PACKETS
)
833 zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s",
834 pim_ifp
->pim_sock_fd
, ifp
->name
);
838 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
839 if (pim_ifp
->pim_sock_fd
< 0) {
840 if (PIM_DEBUG_PIM_PACKETS
)
841 zlog_debug("Could not open PIM socket on interface %s",
846 pim_socket_ip_hdr (pim_ifp
->pim_sock_fd
);
848 pim_ifp
->t_pim_sock_read
= NULL
;
849 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
852 * Just ensure that the new generation id
853 * actually chooses something different.
854 * Actually ran across a case where this
855 * happened, pre-switch to random().
856 * While this is unlikely to happen now
857 * let's make sure it doesn't.
859 old_genid
= pim_ifp
->pim_generation_id
;
861 while (old_genid
== pim_ifp
->pim_generation_id
)
862 pim_ifp
->pim_generation_id
= random();
864 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
865 ifp
->name
, ifp
->ifindex
);
868 * Start receiving PIM messages
870 pim_sock_read_on(ifp
);
873 * Start sending PIM hello's
875 pim_hello_restart_triggered(ifp
);