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
, uint16_t holdtime
);
46 static const char *pim_pim_msgtype2str(enum pim_msg_type type
)
49 case PIM_MSG_TYPE_HELLO
:
51 case PIM_MSG_TYPE_REGISTER
:
53 case PIM_MSG_TYPE_REG_STOP
:
55 case PIM_MSG_TYPE_JOIN_PRUNE
:
57 case PIM_MSG_TYPE_BOOTSTRAP
:
59 case PIM_MSG_TYPE_ASSERT
:
61 case PIM_MSG_TYPE_GRAFT
:
63 case PIM_MSG_TYPE_GRAFT_ACK
:
65 case PIM_MSG_TYPE_CANDIDATE
:
72 static void sock_close(struct interface
*ifp
)
74 struct pim_interface
*pim_ifp
= ifp
->info
;
76 if (PIM_DEBUG_PIM_TRACE
) {
77 if (pim_ifp
->t_pim_sock_read
) {
79 "Cancelling READ event for PIM socket fd=%d on interface %s",
80 pim_ifp
->pim_sock_fd
, ifp
->name
);
83 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
85 if (PIM_DEBUG_PIM_TRACE
) {
86 if (pim_ifp
->t_pim_hello_timer
) {
88 "Cancelling PIM hello timer for interface %s",
92 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
94 if (PIM_DEBUG_PIM_TRACE
) {
95 zlog_debug("Deleting PIM socket fd=%d on interface %s",
96 pim_ifp
->pim_sock_fd
, ifp
->name
);
100 * If the fd is already deleted no need to do anything here
102 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
104 "Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
105 pim_ifp
->pim_sock_fd
, ifp
->name
, errno
,
106 safe_strerror(errno
));
109 pim_ifp
->pim_sock_fd
= -1;
110 pim_ifp
->pim_sock_creation
= 0;
113 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
115 zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp
->name
,
119 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
120 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
125 RFC 4601: 4.3.1. Sending Hello Messages
127 Before an interface goes down or changes primary IP address, a Hello
128 message with a zero HoldTime should be sent immediately (with the
129 old IP address if the IP address changed).
131 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
133 pim_neighbor_delete_all(ifp
, delete_message
);
138 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
141 size_t ip_hlen
; /* ip header length in bytes */
142 char src_str
[INET_ADDRSTRLEN
];
143 char dst_str
[INET_ADDRSTRLEN
];
146 uint16_t pim_checksum
; /* received checksum */
147 uint16_t checksum
; /* computed checksum */
148 struct pim_neighbor
*neigh
;
149 struct pim_msg_header
*header
;
151 if (len
< sizeof(*ip_hdr
)) {
152 if (PIM_DEBUG_PIM_PACKETS
)
154 "PIM packet size=%zu shorter than minimum=%zu",
155 len
, sizeof(*ip_hdr
));
159 ip_hdr
= (struct ip
*)buf
;
160 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
162 pim_msg
= buf
+ ip_hlen
;
163 pim_msg_len
= len
- ip_hlen
;
165 header
= (struct pim_msg_header
*)pim_msg
;
166 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
167 if (PIM_DEBUG_PIM_PACKETS
)
169 "PIM message size=%d shorter than minimum=%d",
170 pim_msg_len
, PIM_PIM_MIN_LEN
);
174 if (header
->ver
!= PIM_PROTO_VERSION
) {
175 if (PIM_DEBUG_PIM_PACKETS
)
177 "Ignoring PIM pkt from %s with unsupported version: %d",
178 ifp
->name
, header
->ver
);
182 /* save received checksum */
183 pim_checksum
= header
->checksum
;
185 /* for computing checksum */
186 header
->checksum
= 0;
188 if (header
->type
== PIM_MSG_TYPE_REGISTER
) {
189 /* First 8 byte header checksum */
190 checksum
= in_cksum(pim_msg
, PIM_MSG_REGISTER_LEN
);
191 if (checksum
!= pim_checksum
) {
192 checksum
= in_cksum(pim_msg
, pim_msg_len
);
193 if (checksum
!= pim_checksum
) {
194 if (PIM_DEBUG_PIM_PACKETS
)
196 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
197 ifp
->name
, pim_checksum
,
204 checksum
= in_cksum(pim_msg
, pim_msg_len
);
205 if (checksum
!= pim_checksum
) {
206 if (PIM_DEBUG_PIM_PACKETS
)
208 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
209 ifp
->name
, pim_checksum
, checksum
);
215 if (PIM_DEBUG_PIM_PACKETS
) {
216 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
,
218 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
,
221 "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
222 pim_pim_msgtype2str(header
->type
), src_str
, dst_str
,
223 ifp
->name
, ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
,
225 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
226 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
230 switch (header
->type
) {
231 case PIM_MSG_TYPE_HELLO
:
232 return pim_hello_recv(ifp
, ip_hdr
->ip_src
,
233 pim_msg
+ PIM_MSG_HEADER_LEN
,
234 pim_msg_len
- PIM_MSG_HEADER_LEN
);
236 case PIM_MSG_TYPE_REGISTER
:
237 return pim_register_recv(ifp
, ip_hdr
->ip_dst
, ip_hdr
->ip_src
,
238 pim_msg
+ PIM_MSG_HEADER_LEN
,
239 pim_msg_len
- PIM_MSG_HEADER_LEN
);
241 case PIM_MSG_TYPE_REG_STOP
:
242 return pim_register_stop_recv(pim_msg
+ PIM_MSG_HEADER_LEN
,
243 pim_msg_len
- PIM_MSG_HEADER_LEN
);
245 case PIM_MSG_TYPE_JOIN_PRUNE
:
246 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
248 if (PIM_DEBUG_PIM_PACKETS
)
250 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
251 __FILE__
, __PRETTY_FUNCTION__
,
252 header
->type
, src_str
, ifp
->name
);
255 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
256 return pim_joinprune_recv(ifp
, neigh
, ip_hdr
->ip_src
,
257 pim_msg
+ PIM_MSG_HEADER_LEN
,
258 pim_msg_len
- PIM_MSG_HEADER_LEN
);
260 case PIM_MSG_TYPE_ASSERT
:
261 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
263 if (PIM_DEBUG_PIM_PACKETS
)
265 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
266 __FILE__
, __PRETTY_FUNCTION__
,
267 header
->type
, src_str
, ifp
->name
);
270 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
271 return pim_assert_recv(ifp
, neigh
, ip_hdr
->ip_src
,
272 pim_msg
+ PIM_MSG_HEADER_LEN
,
273 pim_msg_len
- PIM_MSG_HEADER_LEN
);
276 if (PIM_DEBUG_PIM_PACKETS
) {
278 "Recv PIM packet type %d which is not currently understood",
286 static void pim_sock_read_on(struct interface
*ifp
);
288 static int pim_sock_read(struct thread
*t
)
290 struct interface
*ifp
;
291 struct pim_interface
*pim_ifp
;
293 struct sockaddr_in from
;
294 struct sockaddr_in to
;
295 socklen_t fromlen
= sizeof(from
);
296 socklen_t tolen
= sizeof(to
);
297 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
299 ifindex_t ifindex
= -1;
300 int result
= -1; /* defaults to bad */
301 static long long count
= 0;
310 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
), &from
,
311 &fromlen
, &to
, &tolen
, &ifindex
);
315 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
318 if (PIM_DEBUG_PIM_PACKETS
)
319 zlog_debug("Received errno: %d %s", errno
,
320 safe_strerror(errno
));
324 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
325 /* ifindex sanity check */
326 if (ifindex
!= (int)ifp
->ifindex
) {
327 char from_str
[INET_ADDRSTRLEN
];
328 char to_str
[INET_ADDRSTRLEN
];
329 struct interface
*recv_ifp
;
331 if (!inet_ntop(AF_INET
, &from
.sin_addr
, from_str
,
333 sprintf(from_str
, "<from?>");
334 if (!inet_ntop(AF_INET
, &to
.sin_addr
, to_str
,
336 sprintf(to_str
, "<to?>");
338 recv_ifp
= if_lookup_by_index(ifindex
, VRF_DEFAULT
);
340 zassert(ifindex
== (int)recv_ifp
->ifindex
);
343 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
345 "Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
346 from_str
, to_str
, fd
, ifindex
,
347 recv_ifp
? recv_ifp
->name
: "<if-notfound>",
348 ifp
->ifindex
, ifp
->name
);
354 int fail
= pim_pim_packet(ifp
, buf
, len
);
356 if (PIM_DEBUG_PIM_PACKETS
)
357 zlog_debug("%s: pim_pim_packet() return=%d",
358 __PRETTY_FUNCTION__
, fail
);
363 if (count
% qpim_packet_process
== 0)
367 result
= 0; /* good */
370 pim_sock_read_on(ifp
);
373 ++pim_ifp
->pim_ifstat_hello_recvfail
;
379 static void pim_sock_read_on(struct interface
*ifp
)
381 struct pim_interface
*pim_ifp
;
388 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
389 zlog_debug("Scheduling READ event on PIM socket fd=%d",
390 pim_ifp
->pim_sock_fd
);
392 pim_ifp
->t_pim_sock_read
= NULL
;
393 THREAD_READ_ON(master
, pim_ifp
->t_pim_sock_read
, pim_sock_read
, ifp
,
394 pim_ifp
->pim_sock_fd
);
397 static int pim_sock_open(struct interface
*ifp
)
400 struct pim_interface
*pim_ifp
= ifp
->info
;
402 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
,
407 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
,
408 pim_ifp
->primary_address
, ifp
->ifindex
)) {
416 void pim_ifstat_reset(struct interface
*ifp
)
418 struct pim_interface
*pim_ifp
;
427 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
428 pim_ifp
->pim_ifstat_hello_sent
= 0;
429 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
430 pim_ifp
->pim_ifstat_hello_recv
= 0;
431 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
434 void pim_sock_reset(struct interface
*ifp
)
436 struct pim_interface
*pim_ifp
;
443 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
445 pim_ifp
->pim_sock_fd
= -1;
446 pim_ifp
->pim_sock_creation
= 0;
447 pim_ifp
->t_pim_sock_read
= NULL
;
449 pim_ifp
->t_pim_hello_timer
= NULL
;
450 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
451 pim_ifp
->pim_default_holdtime
=
452 -1; /* unset: means 3.5 * pim_hello_period */
453 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
454 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
455 pim_ifp
->pim_propagation_delay_msec
=
456 PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
457 pim_ifp
->pim_override_interval_msec
=
458 PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
459 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
460 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
462 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
465 /* neighbors without lan_delay */
466 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
467 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
468 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
471 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
472 pim_ifp
->pim_dr_election_count
= 0;
473 pim_ifp
->pim_dr_election_changes
= 0;
474 pim_ifp
->pim_dr_num_nondrpri_neighbors
=
475 0; /* neighbors without dr_pri */
476 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
478 pim_ifstat_reset(ifp
);
481 static uint16_t ip_id
= 0;
484 static int pim_msg_send_frame(int fd
, char *buf
, size_t len
,
485 struct sockaddr
*dst
, size_t salen
)
487 struct ip
*ip
= (struct ip
*)buf
;
489 while (sendto(fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0) {
490 char dst_str
[INET_ADDRSTRLEN
];
494 size_t hdrsize
= sizeof(struct ip
);
495 size_t newlen1
= ((len
- hdrsize
) / 2) & 0xFFF8;
496 size_t sendlen
= newlen1
+ hdrsize
;
497 size_t offset
= ntohs(ip
->ip_off
);
499 ip
->ip_len
= htons(sendlen
);
500 ip
->ip_off
= htons(offset
| IP_MF
);
501 if (pim_msg_send_frame(fd
, buf
, sendlen
, dst
, salen
)
503 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
504 size_t newlen2
= len
- sendlen
;
505 sendlen
= newlen2
+ hdrsize
;
507 memcpy(ip2
, ip
, hdrsize
);
508 ip2
->ip_len
= htons(sendlen
);
509 ip2
->ip_off
= htons(offset
+ (newlen1
>> 3));
510 return pim_msg_send_frame(fd
, (char *)ip2
,
511 sendlen
, dst
, salen
);
518 if (PIM_DEBUG_PIM_PACKETS
) {
519 pim_inet4_dump("<dst?>", ip
->ip_dst
, dst_str
,
522 "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
523 __PRETTY_FUNCTION__
, dst_str
, fd
, len
,
524 errno
, safe_strerror(errno
));
534 int pim_msg_send(int fd
, struct in_addr src
, struct in_addr dst
,
535 uint8_t *pim_msg
, int pim_msg_size
, const char *ifname
)
537 struct sockaddr_in to
;
539 unsigned char buffer
[10000];
540 unsigned char *msg_start
;
541 uint8_t ttl
= MAXTTL
;
542 struct pim_msg_header
*header
;
545 memset(buffer
, 0, 10000);
546 int sendlen
= sizeof(struct ip
) + pim_msg_size
;
548 msg_start
= buffer
+ sizeof(struct ip
);
549 memcpy(msg_start
, pim_msg
, pim_msg_size
);
551 header
= (struct pim_msg_header
*)pim_msg
;
553 * Omnios apparently doesn't have a #define for IP default
554 * ttl that is the same as all other platforms.
559 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
560 switch (header
->type
) {
561 case PIM_MSG_TYPE_HELLO
:
562 case PIM_MSG_TYPE_JOIN_PRUNE
:
563 case PIM_MSG_TYPE_BOOTSTRAP
:
564 case PIM_MSG_TYPE_ASSERT
:
567 case PIM_MSG_TYPE_REGISTER
:
568 case PIM_MSG_TYPE_REG_STOP
:
569 case PIM_MSG_TYPE_GRAFT
:
570 case PIM_MSG_TYPE_GRAFT_ACK
:
571 case PIM_MSG_TYPE_CANDIDATE
:
579 ip
= (struct ip
*)buffer
;
580 ip
->ip_id
= htons(++ip_id
);
583 ip
->ip_p
= PIM_IP_PROTO_PIM
;
587 ip
->ip_len
= htons(sendlen
);
589 if (PIM_DEBUG_PIM_PACKETS
) {
590 struct pim_msg_header
*header
=
591 (struct pim_msg_header
*)pim_msg
;
592 char dst_str
[INET_ADDRSTRLEN
];
593 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
594 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
595 __PRETTY_FUNCTION__
, dst_str
, ifname
, pim_msg_size
,
599 memset(&to
, 0, sizeof(to
));
600 to
.sin_family
= AF_INET
;
604 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
605 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
608 pim_msg_send_frame(fd
, (char *)buffer
, sendlen
, (struct sockaddr
*)&to
,
613 static int hello_send(struct interface
*ifp
, uint16_t holdtime
)
615 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
616 struct pim_interface
*pim_ifp
;
622 if (PIM_DEBUG_PIM_HELLO
) {
623 char dst_str
[INET_ADDRSTRLEN
];
624 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
,
627 "%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",
628 __PRETTY_FUNCTION__
, dst_str
, ifp
->name
, holdtime
,
629 pim_ifp
->pim_propagation_delay_msec
,
630 pim_ifp
->pim_override_interval_msec
,
631 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(
633 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
634 listcount(ifp
->connected
));
637 pim_tlv_size
= pim_hello_build_tlv(
638 ifp
->name
, pim_msg
+ PIM_PIM_MIN_LEN
,
639 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
, holdtime
,
640 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
641 pim_ifp
->pim_propagation_delay_msec
,
642 pim_ifp
->pim_override_interval_msec
,
643 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
645 if (pim_tlv_size
< 0) {
649 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
651 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
652 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
654 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
);
656 if (pim_msg_send(pim_ifp
->pim_sock_fd
, pim_ifp
->primary_address
,
657 qpim_all_pim_routers_addr
, pim_msg
, pim_msg_size
,
659 if (PIM_DEBUG_PIM_HELLO
) {
661 "%s: could not send PIM message on interface %s",
662 __PRETTY_FUNCTION__
, ifp
->name
);
670 static int pim_hello_send(struct interface
*ifp
, uint16_t holdtime
)
672 struct pim_interface
*pim_ifp
;
678 if (if_is_loopback(ifp
))
681 if (hello_send(ifp
, holdtime
)) {
682 ++pim_ifp
->pim_ifstat_hello_sendfail
;
684 if (PIM_DEBUG_PIM_HELLO
) {
685 zlog_warn("Could not send PIM hello on interface %s",
691 ++pim_ifp
->pim_ifstat_hello_sent
;
696 static void hello_resched(struct interface
*ifp
)
698 struct pim_interface
*pim_ifp
;
704 if (PIM_DEBUG_PIM_HELLO
) {
705 zlog_debug("Rescheduling %d sec hello on interface %s",
706 pim_ifp
->pim_hello_period
, ifp
->name
);
708 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
709 THREAD_TIMER_ON(master
, pim_ifp
->t_pim_hello_timer
, on_pim_hello_send
,
710 ifp
, pim_ifp
->pim_hello_period
);
716 static int on_pim_hello_send(struct thread
*t
)
718 struct pim_interface
*pim_ifp
;
719 struct interface
*ifp
;
726 * Schedule next hello
728 pim_ifp
->t_pim_hello_timer
= NULL
;
734 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
738 RFC 4601: 4.3.1. Sending Hello Messages
740 Thus, if a router needs to send a Join/Prune or Assert message on an
741 interface on which it has not yet sent a Hello message with the
742 currently configured IP address, then it MUST immediately send the
743 relevant Hello message without waiting for the Hello Timer to
744 expire, followed by the Join/Prune or Assert message.
746 void pim_hello_restart_now(struct interface
*ifp
)
748 struct pim_interface
*pim_ifp
;
755 * Reset next hello timer
760 * Immediately send hello
762 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
766 RFC 4601: 4.3.1. Sending Hello Messages
768 To allow new or rebooting routers to learn of PIM neighbors quickly,
769 when a Hello message is received from a new neighbor, or a Hello
770 message with a new GenID is received from an existing neighbor, a
771 new Hello message should be sent on this interface after a
772 randomized delay between 0 and Triggered_Hello_Delay.
774 void pim_hello_restart_triggered(struct interface
*ifp
)
776 struct pim_interface
*pim_ifp
;
777 int triggered_hello_delay_msec
;
785 * There exists situations where we have the a RPF out this
786 * interface, but we haven't formed a neighbor yet. This
787 * happens especially during interface flaps. While
788 * we would like to handle this more gracefully in other
789 * parts of the code. In order to get us up and running
790 * let's just send the hello immediate'ish
791 * This should be revisited when we get nexthop tracking
792 * in and when we have a better handle on safely
793 * handling the rpf information for upstreams that
794 * we cannot legally reach yet.
796 triggered_hello_delay_msec
= 1;
797 // triggered_hello_delay_msec = 1000 *
798 // pim_ifp->pim_triggered_hello_delay;
800 if (pim_ifp
->t_pim_hello_timer
) {
802 pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
803 if (remain_msec
<= triggered_hello_delay_msec
) {
804 /* Rescheduling hello would increase the delay, then
806 to just wait for the scheduled periodic hello. */
810 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
811 pim_ifp
->t_pim_hello_timer
= NULL
;
814 random_msec
= triggered_hello_delay_msec
;
815 // random_msec = random() % (triggered_hello_delay_msec + 1);
817 if (PIM_DEBUG_PIM_HELLO
) {
818 zlog_debug("Scheduling %d msec triggered hello on interface %s",
819 random_msec
, ifp
->name
);
822 THREAD_TIMER_MSEC_ON(master
, pim_ifp
->t_pim_hello_timer
,
823 on_pim_hello_send
, ifp
, random_msec
);
826 int pim_sock_add(struct interface
*ifp
)
828 struct pim_interface
*pim_ifp
;
834 if (pim_ifp
->pim_sock_fd
>= 0) {
835 if (PIM_DEBUG_PIM_PACKETS
)
837 "Can't recreate existing PIM socket fd=%d for interface %s",
838 pim_ifp
->pim_sock_fd
, ifp
->name
);
842 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
843 if (pim_ifp
->pim_sock_fd
< 0) {
844 if (PIM_DEBUG_PIM_PACKETS
)
845 zlog_debug("Could not open PIM socket on interface %s",
850 pim_socket_ip_hdr(pim_ifp
->pim_sock_fd
);
852 pim_ifp
->t_pim_sock_read
= NULL
;
853 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
856 * Just ensure that the new generation id
857 * actually chooses something different.
858 * Actually ran across a case where this
859 * happened, pre-switch to random().
860 * While this is unlikely to happen now
861 * let's make sure it doesn't.
863 old_genid
= pim_ifp
->pim_generation_id
;
865 while (old_genid
== pim_ifp
->pim_generation_id
)
866 pim_ifp
->pim_generation_id
= random();
868 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp
->name
,
872 * Start receiving PIM messages
874 pim_sock_read_on(ifp
);
877 * Start sending PIM hello's
879 pim_hello_restart_triggered(ifp
);