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"
41 #include "pim_errors.h"
44 static int on_pim_hello_send(struct thread
*t
);
45 static int pim_hello_send(struct interface
*ifp
, uint16_t holdtime
);
47 static const char *pim_pim_msgtype2str(enum pim_msg_type type
)
50 case PIM_MSG_TYPE_HELLO
:
52 case PIM_MSG_TYPE_REGISTER
:
54 case PIM_MSG_TYPE_REG_STOP
:
56 case PIM_MSG_TYPE_JOIN_PRUNE
:
58 case PIM_MSG_TYPE_BOOTSTRAP
:
60 case PIM_MSG_TYPE_ASSERT
:
62 case PIM_MSG_TYPE_GRAFT
:
64 case PIM_MSG_TYPE_GRAFT_ACK
:
66 case PIM_MSG_TYPE_CANDIDATE
:
73 static void sock_close(struct interface
*ifp
)
75 struct pim_interface
*pim_ifp
= ifp
->info
;
77 if (PIM_DEBUG_PIM_TRACE
) {
78 if (pim_ifp
->t_pim_sock_read
) {
80 "Cancelling READ event for PIM socket fd=%d on interface %s",
81 pim_ifp
->pim_sock_fd
, ifp
->name
);
84 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
86 if (PIM_DEBUG_PIM_TRACE
) {
87 if (pim_ifp
->t_pim_hello_timer
) {
89 "Cancelling PIM hello timer for interface %s",
93 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
95 if (PIM_DEBUG_PIM_TRACE
) {
96 zlog_debug("Deleting PIM socket fd=%d on interface %s",
97 pim_ifp
->pim_sock_fd
, ifp
->name
);
101 * If the fd is already deleted no need to do anything here
103 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
105 "Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
106 pim_ifp
->pim_sock_fd
, ifp
->name
, errno
,
107 safe_strerror(errno
));
110 pim_ifp
->pim_sock_fd
= -1;
111 pim_ifp
->pim_sock_creation
= 0;
114 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
116 zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp
->name
,
120 flog_err(EC_PIM_CONFIG
,
121 "%s: %s: but PIM not enabled on interface %s (!)",
122 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
127 RFC 4601: 4.3.1. Sending Hello Messages
129 Before an interface goes down or changes primary IP address, a Hello
130 message with a zero HoldTime should be sent immediately (with the
131 old IP address if the IP address changed).
133 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
135 pim_neighbor_delete_all(ifp
, delete_message
);
140 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
143 size_t ip_hlen
; /* ip header length in bytes */
144 char src_str
[INET_ADDRSTRLEN
];
145 char dst_str
[INET_ADDRSTRLEN
];
148 uint16_t pim_checksum
; /* received checksum */
149 uint16_t checksum
; /* computed checksum */
150 struct pim_neighbor
*neigh
;
151 struct pim_msg_header
*header
;
154 if (len
< sizeof(*ip_hdr
)) {
155 if (PIM_DEBUG_PIM_PACKETS
)
157 "PIM packet size=%zu shorter than minimum=%zu",
158 len
, sizeof(*ip_hdr
));
162 ip_hdr
= (struct ip
*)buf
;
163 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
165 pim_msg
= buf
+ ip_hlen
;
166 pim_msg_len
= len
- ip_hlen
;
168 header
= (struct pim_msg_header
*)pim_msg
;
169 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
170 if (PIM_DEBUG_PIM_PACKETS
)
172 "PIM message size=%d shorter than minimum=%d",
173 pim_msg_len
, PIM_PIM_MIN_LEN
);
177 if (header
->ver
!= PIM_PROTO_VERSION
) {
178 if (PIM_DEBUG_PIM_PACKETS
)
180 "Ignoring PIM pkt from %s with unsupported version: %d",
181 ifp
->name
, header
->ver
);
185 /* save received checksum */
186 pim_checksum
= header
->checksum
;
188 /* for computing checksum */
189 header
->checksum
= 0;
190 no_fwd
= header
->Nbit
;
192 if (header
->type
== PIM_MSG_TYPE_REGISTER
) {
193 /* First 8 byte header checksum */
194 checksum
= in_cksum(pim_msg
, PIM_MSG_REGISTER_LEN
);
195 if (checksum
!= pim_checksum
) {
196 checksum
= in_cksum(pim_msg
, pim_msg_len
);
197 if (checksum
!= pim_checksum
) {
198 if (PIM_DEBUG_PIM_PACKETS
)
200 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
201 ifp
->name
, pim_checksum
,
208 checksum
= in_cksum(pim_msg
, pim_msg_len
);
209 if (checksum
!= pim_checksum
) {
210 if (PIM_DEBUG_PIM_PACKETS
)
212 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
213 ifp
->name
, pim_checksum
, checksum
);
219 if (PIM_DEBUG_PIM_PACKETS
) {
220 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
,
222 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
,
225 "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
226 pim_pim_msgtype2str(header
->type
), src_str
, dst_str
,
227 ifp
->name
, ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
,
229 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
230 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
234 switch (header
->type
) {
235 case PIM_MSG_TYPE_HELLO
:
236 return pim_hello_recv(ifp
, ip_hdr
->ip_src
,
237 pim_msg
+ PIM_MSG_HEADER_LEN
,
238 pim_msg_len
- PIM_MSG_HEADER_LEN
);
240 case PIM_MSG_TYPE_REGISTER
:
241 return pim_register_recv(ifp
, ip_hdr
->ip_dst
, ip_hdr
->ip_src
,
242 pim_msg
+ PIM_MSG_HEADER_LEN
,
243 pim_msg_len
- PIM_MSG_HEADER_LEN
);
245 case PIM_MSG_TYPE_REG_STOP
:
246 return pim_register_stop_recv(ifp
, pim_msg
+ PIM_MSG_HEADER_LEN
,
247 pim_msg_len
- PIM_MSG_HEADER_LEN
);
249 case PIM_MSG_TYPE_JOIN_PRUNE
:
250 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
252 if (PIM_DEBUG_PIM_PACKETS
)
254 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
255 __FILE__
, __PRETTY_FUNCTION__
,
256 header
->type
, src_str
, ifp
->name
);
259 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
260 return pim_joinprune_recv(ifp
, neigh
, ip_hdr
->ip_src
,
261 pim_msg
+ PIM_MSG_HEADER_LEN
,
262 pim_msg_len
- PIM_MSG_HEADER_LEN
);
264 case PIM_MSG_TYPE_ASSERT
:
265 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
267 if (PIM_DEBUG_PIM_PACKETS
)
269 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
270 __FILE__
, __PRETTY_FUNCTION__
,
271 header
->type
, src_str
, ifp
->name
);
274 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
275 return pim_assert_recv(ifp
, neigh
, ip_hdr
->ip_src
,
276 pim_msg
+ PIM_MSG_HEADER_LEN
,
277 pim_msg_len
- PIM_MSG_HEADER_LEN
);
279 case PIM_MSG_TYPE_BOOTSTRAP
:
280 return pim_bsm_process(ifp
, ip_hdr
, pim_msg
, pim_msg_len
,
285 if (PIM_DEBUG_PIM_PACKETS
) {
287 "Recv PIM packet type %d which is not currently understood",
295 static void pim_sock_read_on(struct interface
*ifp
);
297 static int pim_sock_read(struct thread
*t
)
299 struct interface
*ifp
, *orig_ifp
;
300 struct pim_interface
*pim_ifp
;
302 struct sockaddr_in from
;
303 struct sockaddr_in to
;
304 socklen_t fromlen
= sizeof(from
);
305 socklen_t tolen
= sizeof(to
);
306 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
308 ifindex_t ifindex
= -1;
309 int result
= -1; /* defaults to bad */
310 static long long count
= 0;
313 orig_ifp
= ifp
= THREAD_ARG(t
);
319 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
), &from
,
320 &fromlen
, &to
, &tolen
, &ifindex
);
324 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
327 if (PIM_DEBUG_PIM_PACKETS
)
328 zlog_debug("Received errno: %d %s", errno
,
329 safe_strerror(errno
));
334 * What? So with vrf's the incoming packet is received
335 * on the vrf interface but recvfromto above returns
336 * the right ifindex, so just use it. We know
337 * it's the right interface because we bind to it
339 ifp
= if_lookup_by_index(ifindex
, pim_ifp
->pim
->vrf_id
);
340 if (!ifp
|| !ifp
->info
) {
341 if (PIM_DEBUG_PIM_PACKETS
)
343 "%s: Received incoming pim packet on interface(%s:%d) not yet configured for pim",
345 ifp
? ifp
->name
: "Unknown", ifindex
);
348 int fail
= pim_pim_packet(ifp
, buf
, len
);
350 if (PIM_DEBUG_PIM_PACKETS
)
351 zlog_debug("%s: pim_pim_packet() return=%d",
352 __PRETTY_FUNCTION__
, fail
);
357 if (count
% router
->packet_process
== 0)
361 result
= 0; /* good */
364 pim_sock_read_on(orig_ifp
);
367 ++pim_ifp
->pim_ifstat_hello_recvfail
;
373 static void pim_sock_read_on(struct interface
*ifp
)
375 struct pim_interface
*pim_ifp
;
382 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
383 zlog_debug("Scheduling READ event on PIM socket fd=%d",
384 pim_ifp
->pim_sock_fd
);
386 pim_ifp
->t_pim_sock_read
= NULL
;
387 thread_add_read(router
->master
, pim_sock_read
, ifp
,
388 pim_ifp
->pim_sock_fd
, &pim_ifp
->t_pim_sock_read
);
391 static int pim_sock_open(struct interface
*ifp
)
394 struct pim_interface
*pim_ifp
= ifp
->info
;
396 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
,
401 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
,
402 pim_ifp
->primary_address
, ifp
->ifindex
)) {
410 void pim_ifstat_reset(struct interface
*ifp
)
412 struct pim_interface
*pim_ifp
;
421 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
422 pim_ifp
->pim_ifstat_hello_sent
= 0;
423 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
424 pim_ifp
->pim_ifstat_hello_recv
= 0;
425 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
428 void pim_sock_reset(struct interface
*ifp
)
430 struct pim_interface
*pim_ifp
;
437 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
439 pim_ifp
->pim_sock_fd
= -1;
440 pim_ifp
->pim_sock_creation
= 0;
441 pim_ifp
->t_pim_sock_read
= NULL
;
443 pim_ifp
->t_pim_hello_timer
= NULL
;
444 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
445 pim_ifp
->pim_default_holdtime
=
446 -1; /* unset: means 3.5 * pim_hello_period */
447 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
448 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
449 pim_ifp
->pim_propagation_delay_msec
=
450 PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
451 pim_ifp
->pim_override_interval_msec
=
452 PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
453 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
454 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
456 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
459 /* neighbors without lan_delay */
460 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
461 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
462 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
465 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
466 pim_ifp
->pim_dr_election_count
= 0;
467 pim_ifp
->pim_dr_election_changes
= 0;
468 pim_ifp
->pim_dr_num_nondrpri_neighbors
=
469 0; /* neighbors without dr_pri */
470 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
472 pim_ifstat_reset(ifp
);
475 static uint16_t ip_id
= 0;
478 static int pim_msg_send_frame(int fd
, char *buf
, size_t len
,
479 struct sockaddr
*dst
, size_t salen
)
481 struct ip
*ip
= (struct ip
*)buf
;
483 while (sendto(fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0) {
484 char dst_str
[INET_ADDRSTRLEN
];
488 size_t hdrsize
= sizeof(struct ip
);
489 size_t newlen1
= ((len
- hdrsize
) / 2) & 0xFFF8;
490 size_t sendlen
= newlen1
+ hdrsize
;
491 size_t offset
= ntohs(ip
->ip_off
);
493 ip
->ip_len
= htons(sendlen
);
494 ip
->ip_off
= htons(offset
| IP_MF
);
495 if (pim_msg_send_frame(fd
, buf
, sendlen
, dst
, salen
)
497 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
498 size_t newlen2
= len
- sendlen
;
499 sendlen
= newlen2
+ hdrsize
;
501 memcpy(ip2
, ip
, hdrsize
);
502 ip2
->ip_len
= htons(sendlen
);
503 ip2
->ip_off
= htons(offset
+ (newlen1
>> 3));
504 return pim_msg_send_frame(fd
, (char *)ip2
,
505 sendlen
, dst
, salen
);
512 if (PIM_DEBUG_PIM_PACKETS
) {
513 pim_inet4_dump("<dst?>", ip
->ip_dst
, dst_str
,
516 "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
517 __PRETTY_FUNCTION__
, dst_str
, fd
, len
,
518 errno
, safe_strerror(errno
));
528 int pim_msg_send(int fd
, struct in_addr src
, struct in_addr dst
,
529 uint8_t *pim_msg
, int pim_msg_size
, const char *ifname
)
531 struct sockaddr_in to
;
533 unsigned char buffer
[10000];
534 unsigned char *msg_start
;
536 struct pim_msg_header
*header
;
539 memset(buffer
, 0, 10000);
540 int sendlen
= sizeof(struct ip
) + pim_msg_size
;
542 msg_start
= buffer
+ sizeof(struct ip
);
543 memcpy(msg_start
, pim_msg
, pim_msg_size
);
545 header
= (struct pim_msg_header
*)pim_msg
;
547 * Omnios apparently doesn't have a #define for IP default
548 * ttl that is the same as all other platforms.
553 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
554 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_tos
= IPTOS_PREC_INTERNETCONTROL
;
578 ip
->ip_p
= PIM_IP_PROTO_PIM
;
582 ip
->ip_len
= htons(sendlen
);
584 if (PIM_DEBUG_PIM_PACKETS
) {
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",
588 __PRETTY_FUNCTION__
, 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
, (struct sockaddr
*)&to
,
606 static int hello_send(struct interface
*ifp
, uint16_t holdtime
)
608 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
609 struct pim_interface
*pim_ifp
;
615 if (PIM_DEBUG_PIM_HELLO
) {
616 char dst_str
[INET_ADDRSTRLEN
];
617 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
,
620 "%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",
621 __PRETTY_FUNCTION__
, dst_str
, ifp
->name
, holdtime
,
622 pim_ifp
->pim_propagation_delay_msec
,
623 pim_ifp
->pim_override_interval_msec
,
624 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(
626 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
627 listcount(ifp
->connected
));
630 pim_tlv_size
= pim_hello_build_tlv(
631 ifp
, pim_msg
+ PIM_PIM_MIN_LEN
,
632 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
, holdtime
,
633 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
634 pim_ifp
->pim_propagation_delay_msec
,
635 pim_ifp
->pim_override_interval_msec
,
636 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
));
637 if (pim_tlv_size
< 0) {
641 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
643 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
644 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
646 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
, false);
648 if (pim_msg_send(pim_ifp
->pim_sock_fd
, pim_ifp
->primary_address
,
649 qpim_all_pim_routers_addr
, pim_msg
, pim_msg_size
,
651 if (PIM_DEBUG_PIM_HELLO
) {
653 "%s: could not send PIM message on interface %s",
654 __PRETTY_FUNCTION__
, ifp
->name
);
662 static int pim_hello_send(struct interface
*ifp
, uint16_t holdtime
)
664 struct pim_interface
*pim_ifp
= ifp
->info
;
666 if (if_is_loopback_or_vrf(ifp
))
669 if (hello_send(ifp
, holdtime
)) {
670 ++pim_ifp
->pim_ifstat_hello_sendfail
;
672 if (PIM_DEBUG_PIM_HELLO
) {
673 zlog_warn("Could not send PIM hello on interface %s",
679 ++pim_ifp
->pim_ifstat_hello_sent
;
684 static void hello_resched(struct interface
*ifp
)
686 struct pim_interface
*pim_ifp
;
690 if (PIM_DEBUG_PIM_HELLO
) {
691 zlog_debug("Rescheduling %d sec hello on interface %s",
692 pim_ifp
->pim_hello_period
, ifp
->name
);
694 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
695 thread_add_timer(router
->master
, on_pim_hello_send
, ifp
,
696 pim_ifp
->pim_hello_period
,
697 &pim_ifp
->t_pim_hello_timer
);
703 static int on_pim_hello_send(struct thread
*t
)
705 struct pim_interface
*pim_ifp
;
706 struct interface
*ifp
;
712 * Schedule next hello
719 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
723 RFC 4601: 4.3.1. Sending Hello Messages
725 Thus, if a router needs to send a Join/Prune or Assert message on an
726 interface on which it has not yet sent a Hello message with the
727 currently configured IP address, then it MUST immediately send the
728 relevant Hello message without waiting for the Hello Timer to
729 expire, followed by the Join/Prune or Assert message.
731 void pim_hello_restart_now(struct interface
*ifp
)
733 struct pim_interface
*pim_ifp
;
738 * Reset next hello timer
743 * Immediately send hello
745 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
749 RFC 4601: 4.3.1. Sending Hello Messages
751 To allow new or rebooting routers to learn of PIM neighbors quickly,
752 when a Hello message is received from a new neighbor, or a Hello
753 message with a new GenID is received from an existing neighbor, a
754 new Hello message should be sent on this interface after a
755 randomized delay between 0 and Triggered_Hello_Delay.
757 void pim_hello_restart_triggered(struct interface
*ifp
)
759 struct pim_interface
*pim_ifp
;
760 int triggered_hello_delay_msec
;
766 * No need to ever start loopback or vrf device hello's
768 if (if_is_loopback_or_vrf(ifp
))
772 * There exists situations where we have the a RPF out this
773 * interface, but we haven't formed a neighbor yet. This
774 * happens especially during interface flaps. While
775 * we would like to handle this more gracefully in other
776 * parts of the code. In order to get us up and running
777 * let's just send the hello immediate'ish
778 * This should be revisited when we get nexthop tracking
779 * in and when we have a better handle on safely
780 * handling the rpf information for upstreams that
781 * we cannot legally reach yet.
783 triggered_hello_delay_msec
= 1;
784 // triggered_hello_delay_msec = 1000 *
785 // pim_ifp->pim_triggered_hello_delay;
787 if (pim_ifp
->t_pim_hello_timer
) {
789 pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
790 if (remain_msec
<= triggered_hello_delay_msec
) {
791 /* Rescheduling hello would increase the delay, then
793 to just wait for the scheduled periodic hello. */
797 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
800 random_msec
= triggered_hello_delay_msec
;
801 // random_msec = random() % (triggered_hello_delay_msec + 1);
803 if (PIM_DEBUG_PIM_HELLO
) {
804 zlog_debug("Scheduling %d msec triggered hello on interface %s",
805 random_msec
, ifp
->name
);
808 thread_add_timer_msec(router
->master
, on_pim_hello_send
, ifp
,
809 random_msec
, &pim_ifp
->t_pim_hello_timer
);
812 int pim_sock_add(struct interface
*ifp
)
814 struct pim_interface
*pim_ifp
;
820 if (pim_ifp
->pim_sock_fd
>= 0) {
821 if (PIM_DEBUG_PIM_PACKETS
)
823 "Can't recreate existing PIM socket fd=%d for interface %s",
824 pim_ifp
->pim_sock_fd
, ifp
->name
);
828 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
829 if (pim_ifp
->pim_sock_fd
< 0) {
830 if (PIM_DEBUG_PIM_PACKETS
)
831 zlog_debug("Could not open PIM socket on interface %s",
836 pim_socket_ip_hdr(pim_ifp
->pim_sock_fd
);
838 pim_ifp
->t_pim_sock_read
= NULL
;
839 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
842 * Just ensure that the new generation id
843 * actually chooses something different.
844 * Actually ran across a case where this
845 * happened, pre-switch to random().
846 * While this is unlikely to happen now
847 * let's make sure it doesn't.
849 old_genid
= pim_ifp
->pim_generation_id
;
851 while (old_genid
== pim_ifp
->pim_generation_id
)
852 pim_ifp
->pim_generation_id
= random();
854 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp
->name
,
858 * Start receiving PIM messages
860 pim_sock_read_on(ifp
);
863 * Start sending PIM hello's
865 pim_hello_restart_triggered(ifp
);