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
, uint16_t holdtime
);
45 static const char *pim_pim_msgtype2str(enum pim_msg_type type
)
48 case PIM_MSG_TYPE_HELLO
:
50 case PIM_MSG_TYPE_REGISTER
:
52 case PIM_MSG_TYPE_REG_STOP
:
54 case PIM_MSG_TYPE_JOIN_PRUNE
:
56 case PIM_MSG_TYPE_BOOTSTRAP
:
58 case PIM_MSG_TYPE_ASSERT
:
60 case PIM_MSG_TYPE_GRAFT
:
62 case PIM_MSG_TYPE_GRAFT_ACK
:
64 case PIM_MSG_TYPE_CANDIDATE
:
71 static void sock_close(struct interface
*ifp
)
73 struct pim_interface
*pim_ifp
= ifp
->info
;
75 if (PIM_DEBUG_PIM_TRACE
) {
76 if (pim_ifp
->t_pim_sock_read
) {
78 "Cancelling READ event for PIM socket fd=%d on interface %s",
79 pim_ifp
->pim_sock_fd
, ifp
->name
);
82 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
84 if (PIM_DEBUG_PIM_TRACE
) {
85 if (pim_ifp
->t_pim_hello_timer
) {
87 "Cancelling PIM hello timer for interface %s",
91 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
93 if (PIM_DEBUG_PIM_TRACE
) {
94 zlog_debug("Deleting PIM socket fd=%d on interface %s",
95 pim_ifp
->pim_sock_fd
, ifp
->name
);
99 * If the fd is already deleted no need to do anything here
101 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
103 "Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
104 pim_ifp
->pim_sock_fd
, ifp
->name
, errno
,
105 safe_strerror(errno
));
108 pim_ifp
->pim_sock_fd
= -1;
109 pim_ifp
->pim_sock_creation
= 0;
112 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
114 zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp
->name
,
118 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
119 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
124 RFC 4601: 4.3.1. Sending Hello Messages
126 Before an interface goes down or changes primary IP address, a Hello
127 message with a zero HoldTime should be sent immediately (with the
128 old IP address if the IP address changed).
130 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
132 pim_neighbor_delete_all(ifp
, delete_message
);
137 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
140 size_t ip_hlen
; /* ip header length in bytes */
141 char src_str
[INET_ADDRSTRLEN
];
142 char dst_str
[INET_ADDRSTRLEN
];
145 uint16_t pim_checksum
; /* received checksum */
146 uint16_t checksum
; /* computed checksum */
147 struct pim_neighbor
*neigh
;
148 struct pim_msg_header
*header
;
150 if (len
< sizeof(*ip_hdr
)) {
151 if (PIM_DEBUG_PIM_PACKETS
)
153 "PIM packet size=%zu shorter than minimum=%zu",
154 len
, sizeof(*ip_hdr
));
158 ip_hdr
= (struct ip
*)buf
;
159 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
161 pim_msg
= buf
+ ip_hlen
;
162 pim_msg_len
= len
- ip_hlen
;
164 header
= (struct pim_msg_header
*)pim_msg
;
165 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
166 if (PIM_DEBUG_PIM_PACKETS
)
168 "PIM message size=%d shorter than minimum=%d",
169 pim_msg_len
, PIM_PIM_MIN_LEN
);
173 if (header
->ver
!= PIM_PROTO_VERSION
) {
174 if (PIM_DEBUG_PIM_PACKETS
)
176 "Ignoring PIM pkt from %s with unsupported version: %d",
177 ifp
->name
, header
->ver
);
181 /* save received checksum */
182 pim_checksum
= header
->checksum
;
184 /* for computing checksum */
185 header
->checksum
= 0;
187 if (header
->type
== PIM_MSG_TYPE_REGISTER
) {
188 /* First 8 byte header checksum */
189 checksum
= in_cksum(pim_msg
, PIM_MSG_REGISTER_LEN
);
190 if (checksum
!= pim_checksum
) {
191 checksum
= in_cksum(pim_msg
, pim_msg_len
);
192 if (checksum
!= pim_checksum
) {
193 if (PIM_DEBUG_PIM_PACKETS
)
195 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
196 ifp
->name
, pim_checksum
,
203 checksum
= in_cksum(pim_msg
, pim_msg_len
);
204 if (checksum
!= pim_checksum
) {
205 if (PIM_DEBUG_PIM_PACKETS
)
207 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
208 ifp
->name
, pim_checksum
, checksum
);
214 if (PIM_DEBUG_PIM_PACKETS
) {
215 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
,
217 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
,
220 "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
221 pim_pim_msgtype2str(header
->type
), src_str
, dst_str
,
222 ifp
->name
, ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
,
224 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
225 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
229 switch (header
->type
) {
230 case PIM_MSG_TYPE_HELLO
:
231 return pim_hello_recv(ifp
, ip_hdr
->ip_src
,
232 pim_msg
+ PIM_MSG_HEADER_LEN
,
233 pim_msg_len
- PIM_MSG_HEADER_LEN
);
235 case PIM_MSG_TYPE_REGISTER
:
236 return pim_register_recv(ifp
, ip_hdr
->ip_dst
, ip_hdr
->ip_src
,
237 pim_msg
+ PIM_MSG_HEADER_LEN
,
238 pim_msg_len
- PIM_MSG_HEADER_LEN
);
240 case PIM_MSG_TYPE_REG_STOP
:
241 return pim_register_stop_recv(ifp
, pim_msg
+ PIM_MSG_HEADER_LEN
,
242 pim_msg_len
- PIM_MSG_HEADER_LEN
);
244 case PIM_MSG_TYPE_JOIN_PRUNE
:
245 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
247 if (PIM_DEBUG_PIM_PACKETS
)
249 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
250 __FILE__
, __PRETTY_FUNCTION__
,
251 header
->type
, src_str
, ifp
->name
);
254 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
255 return pim_joinprune_recv(ifp
, neigh
, ip_hdr
->ip_src
,
256 pim_msg
+ PIM_MSG_HEADER_LEN
,
257 pim_msg_len
- PIM_MSG_HEADER_LEN
);
259 case PIM_MSG_TYPE_ASSERT
:
260 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
262 if (PIM_DEBUG_PIM_PACKETS
)
264 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
265 __FILE__
, __PRETTY_FUNCTION__
,
266 header
->type
, src_str
, ifp
->name
);
269 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
270 return pim_assert_recv(ifp
, neigh
, ip_hdr
->ip_src
,
271 pim_msg
+ PIM_MSG_HEADER_LEN
,
272 pim_msg_len
- PIM_MSG_HEADER_LEN
);
275 if (PIM_DEBUG_PIM_PACKETS
) {
277 "Recv PIM packet type %d which is not currently understood",
285 static void pim_sock_read_on(struct interface
*ifp
);
287 static int pim_sock_read(struct thread
*t
)
289 struct interface
*ifp
, *orig_ifp
;
290 struct pim_interface
*pim_ifp
;
292 struct sockaddr_in from
;
293 struct sockaddr_in to
;
294 socklen_t fromlen
= sizeof(from
);
295 socklen_t tolen
= sizeof(to
);
296 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
298 ifindex_t ifindex
= -1;
299 int result
= -1; /* defaults to bad */
300 static long long count
= 0;
303 orig_ifp
= ifp
= THREAD_ARG(t
);
309 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
), &from
,
310 &fromlen
, &to
, &tolen
, &ifindex
);
314 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
317 if (PIM_DEBUG_PIM_PACKETS
)
318 zlog_debug("Received errno: %d %s", errno
,
319 safe_strerror(errno
));
324 * What? So with vrf's the incoming packet is received
325 * on the vrf interface but recvfromto above returns
326 * the right ifindex, so just use it. We know
327 * it's the right interface because we bind to it
329 ifp
= if_lookup_by_index(ifindex
, pim_ifp
->pim
->vrf_id
);
331 if (PIM_DEBUG_PIM_PACKETS
)
333 "%s: Received incoming pim packet on interface not yet configured for pim %s",
334 __PRETTY_FUNCTION__
, ifp
->name
);
337 int fail
= pim_pim_packet(ifp
, buf
, len
);
339 if (PIM_DEBUG_PIM_PACKETS
)
340 zlog_debug("%s: pim_pim_packet() return=%d",
341 __PRETTY_FUNCTION__
, fail
);
346 if (count
% qpim_packet_process
== 0)
350 result
= 0; /* good */
353 pim_sock_read_on(orig_ifp
);
356 ++pim_ifp
->pim_ifstat_hello_recvfail
;
362 static void pim_sock_read_on(struct interface
*ifp
)
364 struct pim_interface
*pim_ifp
;
371 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
372 zlog_debug("Scheduling READ event on PIM socket fd=%d",
373 pim_ifp
->pim_sock_fd
);
375 pim_ifp
->t_pim_sock_read
= NULL
;
376 thread_add_read(master
, pim_sock_read
, ifp
, pim_ifp
->pim_sock_fd
,
377 &pim_ifp
->t_pim_sock_read
);
380 static int pim_sock_open(struct interface
*ifp
)
383 struct pim_interface
*pim_ifp
= ifp
->info
;
385 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
,
390 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
,
391 pim_ifp
->primary_address
, ifp
->ifindex
)) {
399 void pim_ifstat_reset(struct interface
*ifp
)
401 struct pim_interface
*pim_ifp
;
410 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
411 pim_ifp
->pim_ifstat_hello_sent
= 0;
412 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
413 pim_ifp
->pim_ifstat_hello_recv
= 0;
414 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
417 void pim_sock_reset(struct interface
*ifp
)
419 struct pim_interface
*pim_ifp
;
426 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
428 pim_ifp
->pim_sock_fd
= -1;
429 pim_ifp
->pim_sock_creation
= 0;
430 pim_ifp
->t_pim_sock_read
= NULL
;
432 pim_ifp
->t_pim_hello_timer
= NULL
;
433 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
434 pim_ifp
->pim_default_holdtime
=
435 -1; /* unset: means 3.5 * pim_hello_period */
436 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
437 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
438 pim_ifp
->pim_propagation_delay_msec
=
439 PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
440 pim_ifp
->pim_override_interval_msec
=
441 PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
442 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
443 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
445 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
448 /* neighbors without lan_delay */
449 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
450 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
451 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
454 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
455 pim_ifp
->pim_dr_election_count
= 0;
456 pim_ifp
->pim_dr_election_changes
= 0;
457 pim_ifp
->pim_dr_num_nondrpri_neighbors
=
458 0; /* neighbors without dr_pri */
459 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
461 pim_ifstat_reset(ifp
);
464 static uint16_t ip_id
= 0;
467 static int pim_msg_send_frame(int fd
, char *buf
, size_t len
,
468 struct sockaddr
*dst
, size_t salen
)
470 struct ip
*ip
= (struct ip
*)buf
;
472 while (sendto(fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0) {
473 char dst_str
[INET_ADDRSTRLEN
];
477 size_t hdrsize
= sizeof(struct ip
);
478 size_t newlen1
= ((len
- hdrsize
) / 2) & 0xFFF8;
479 size_t sendlen
= newlen1
+ hdrsize
;
480 size_t offset
= ntohs(ip
->ip_off
);
482 ip
->ip_len
= htons(sendlen
);
483 ip
->ip_off
= htons(offset
| IP_MF
);
484 if (pim_msg_send_frame(fd
, buf
, sendlen
, dst
, salen
)
486 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
487 size_t newlen2
= len
- sendlen
;
488 sendlen
= newlen2
+ hdrsize
;
490 memcpy(ip2
, ip
, hdrsize
);
491 ip2
->ip_len
= htons(sendlen
);
492 ip2
->ip_off
= htons(offset
+ (newlen1
>> 3));
493 return pim_msg_send_frame(fd
, (char *)ip2
,
494 sendlen
, dst
, salen
);
501 if (PIM_DEBUG_PIM_PACKETS
) {
502 pim_inet4_dump("<dst?>", ip
->ip_dst
, dst_str
,
505 "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
506 __PRETTY_FUNCTION__
, dst_str
, fd
, len
,
507 errno
, safe_strerror(errno
));
517 int pim_msg_send(int fd
, struct in_addr src
, struct in_addr dst
,
518 uint8_t *pim_msg
, int pim_msg_size
, const char *ifname
)
520 struct sockaddr_in to
;
522 unsigned char buffer
[10000];
523 unsigned char *msg_start
;
524 uint8_t ttl
= MAXTTL
;
525 struct pim_msg_header
*header
;
528 memset(buffer
, 0, 10000);
529 int sendlen
= sizeof(struct ip
) + pim_msg_size
;
531 msg_start
= buffer
+ sizeof(struct ip
);
532 memcpy(msg_start
, pim_msg
, pim_msg_size
);
534 header
= (struct pim_msg_header
*)pim_msg
;
536 * Omnios apparently doesn't have a #define for IP default
537 * ttl that is the same as all other platforms.
542 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
543 switch (header
->type
) {
544 case PIM_MSG_TYPE_HELLO
:
545 case PIM_MSG_TYPE_JOIN_PRUNE
:
546 case PIM_MSG_TYPE_BOOTSTRAP
:
547 case PIM_MSG_TYPE_ASSERT
:
550 case PIM_MSG_TYPE_REGISTER
:
551 case PIM_MSG_TYPE_REG_STOP
:
552 case PIM_MSG_TYPE_GRAFT
:
553 case PIM_MSG_TYPE_GRAFT_ACK
:
554 case PIM_MSG_TYPE_CANDIDATE
:
562 ip
= (struct ip
*)buffer
;
563 ip
->ip_id
= htons(++ip_id
);
566 ip
->ip_p
= PIM_IP_PROTO_PIM
;
570 ip
->ip_len
= htons(sendlen
);
572 if (PIM_DEBUG_PIM_PACKETS
) {
573 struct pim_msg_header
*header
=
574 (struct pim_msg_header
*)pim_msg
;
575 char dst_str
[INET_ADDRSTRLEN
];
576 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
577 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
578 __PRETTY_FUNCTION__
, dst_str
, ifname
, pim_msg_size
,
582 memset(&to
, 0, sizeof(to
));
583 to
.sin_family
= AF_INET
;
587 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
588 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
591 pim_msg_send_frame(fd
, (char *)buffer
, sendlen
, (struct sockaddr
*)&to
,
596 static int hello_send(struct interface
*ifp
, uint16_t holdtime
)
598 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
599 struct pim_interface
*pim_ifp
;
605 if (PIM_DEBUG_PIM_HELLO
) {
606 char dst_str
[INET_ADDRSTRLEN
];
607 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
,
610 "%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",
611 __PRETTY_FUNCTION__
, dst_str
, ifp
->name
, holdtime
,
612 pim_ifp
->pim_propagation_delay_msec
,
613 pim_ifp
->pim_override_interval_msec
,
614 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(
616 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
617 listcount(ifp
->connected
));
620 pim_tlv_size
= pim_hello_build_tlv(
621 ifp
, pim_msg
+ PIM_PIM_MIN_LEN
,
622 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
, holdtime
,
623 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
624 pim_ifp
->pim_propagation_delay_msec
,
625 pim_ifp
->pim_override_interval_msec
,
626 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
));
627 if (pim_tlv_size
< 0) {
631 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
633 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
634 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
636 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
);
638 if (pim_msg_send(pim_ifp
->pim_sock_fd
, pim_ifp
->primary_address
,
639 qpim_all_pim_routers_addr
, pim_msg
, pim_msg_size
,
641 if (PIM_DEBUG_PIM_HELLO
) {
643 "%s: could not send PIM message on interface %s",
644 __PRETTY_FUNCTION__
, ifp
->name
);
652 static int pim_hello_send(struct interface
*ifp
, uint16_t holdtime
)
654 struct pim_interface
*pim_ifp
= ifp
->info
;
656 if (pim_if_is_loopback(pim_ifp
->pim
, ifp
))
659 if (hello_send(ifp
, holdtime
)) {
660 ++pim_ifp
->pim_ifstat_hello_sendfail
;
662 if (PIM_DEBUG_PIM_HELLO
) {
663 zlog_warn("Could not send PIM hello on interface %s",
669 ++pim_ifp
->pim_ifstat_hello_sent
;
674 static void hello_resched(struct interface
*ifp
)
676 struct pim_interface
*pim_ifp
;
682 if (PIM_DEBUG_PIM_HELLO
) {
683 zlog_debug("Rescheduling %d sec hello on interface %s",
684 pim_ifp
->pim_hello_period
, ifp
->name
);
686 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
687 thread_add_timer(master
, on_pim_hello_send
, ifp
,
688 pim_ifp
->pim_hello_period
,
689 &pim_ifp
->t_pim_hello_timer
);
695 static int on_pim_hello_send(struct thread
*t
)
697 struct pim_interface
*pim_ifp
;
698 struct interface
*ifp
;
705 * Schedule next hello
712 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
716 RFC 4601: 4.3.1. Sending Hello Messages
718 Thus, if a router needs to send a Join/Prune or Assert message on an
719 interface on which it has not yet sent a Hello message with the
720 currently configured IP address, then it MUST immediately send the
721 relevant Hello message without waiting for the Hello Timer to
722 expire, followed by the Join/Prune or Assert message.
724 void pim_hello_restart_now(struct interface
*ifp
)
726 struct pim_interface
*pim_ifp
;
733 * Reset next hello timer
738 * Immediately send hello
740 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
744 RFC 4601: 4.3.1. Sending Hello Messages
746 To allow new or rebooting routers to learn of PIM neighbors quickly,
747 when a Hello message is received from a new neighbor, or a Hello
748 message with a new GenID is received from an existing neighbor, a
749 new Hello message should be sent on this interface after a
750 randomized delay between 0 and Triggered_Hello_Delay.
752 void pim_hello_restart_triggered(struct interface
*ifp
)
754 struct pim_interface
*pim_ifp
;
755 int triggered_hello_delay_msec
;
763 * There exists situations where we have the a RPF out this
764 * interface, but we haven't formed a neighbor yet. This
765 * happens especially during interface flaps. While
766 * we would like to handle this more gracefully in other
767 * parts of the code. In order to get us up and running
768 * let's just send the hello immediate'ish
769 * This should be revisited when we get nexthop tracking
770 * in and when we have a better handle on safely
771 * handling the rpf information for upstreams that
772 * we cannot legally reach yet.
774 triggered_hello_delay_msec
= 1;
775 // triggered_hello_delay_msec = 1000 *
776 // pim_ifp->pim_triggered_hello_delay;
778 if (pim_ifp
->t_pim_hello_timer
) {
780 pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
781 if (remain_msec
<= triggered_hello_delay_msec
) {
782 /* Rescheduling hello would increase the delay, then
784 to just wait for the scheduled periodic hello. */
788 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
791 random_msec
= triggered_hello_delay_msec
;
792 // random_msec = random() % (triggered_hello_delay_msec + 1);
794 if (PIM_DEBUG_PIM_HELLO
) {
795 zlog_debug("Scheduling %d msec triggered hello on interface %s",
796 random_msec
, ifp
->name
);
799 thread_add_timer_msec(master
, on_pim_hello_send
, ifp
, random_msec
,
800 &pim_ifp
->t_pim_hello_timer
);
803 int pim_sock_add(struct interface
*ifp
)
805 struct pim_interface
*pim_ifp
;
811 if (pim_ifp
->pim_sock_fd
>= 0) {
812 if (PIM_DEBUG_PIM_PACKETS
)
814 "Can't recreate existing PIM socket fd=%d for interface %s",
815 pim_ifp
->pim_sock_fd
, ifp
->name
);
819 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
820 if (pim_ifp
->pim_sock_fd
< 0) {
821 if (PIM_DEBUG_PIM_PACKETS
)
822 zlog_debug("Could not open PIM socket on interface %s",
827 pim_socket_ip_hdr(pim_ifp
->pim_sock_fd
);
829 pim_ifp
->t_pim_sock_read
= NULL
;
830 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
833 * Just ensure that the new generation id
834 * actually chooses something different.
835 * Actually ran across a case where this
836 * happened, pre-switch to random().
837 * While this is unlikely to happen now
838 * let's make sure it doesn't.
840 old_genid
= pim_ifp
->pim_generation_id
;
842 while (old_genid
== pim_ifp
->pim_generation_id
)
843 pim_ifp
->pim_generation_id
= random();
845 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp
->name
,
849 * Start receiving PIM messages
851 pim_sock_read_on(ifp
);
854 * Start sending PIM hello's
856 pim_hello_restart_triggered(ifp
);