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 if (pim_msg_len
< PIM_MSG_REGISTER_LEN
) {
194 if (PIM_DEBUG_PIM_PACKETS
)
195 zlog_debug("PIM Register Message size=%d shorther than min length %d",
196 pim_msg_len
, PIM_MSG_REGISTER_LEN
);
199 /* First 8 byte header checksum */
200 checksum
= in_cksum(pim_msg
, PIM_MSG_REGISTER_LEN
);
201 if (checksum
!= pim_checksum
) {
202 checksum
= in_cksum(pim_msg
, pim_msg_len
);
203 if (checksum
!= pim_checksum
) {
204 if (PIM_DEBUG_PIM_PACKETS
)
206 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
207 ifp
->name
, pim_checksum
,
214 checksum
= in_cksum(pim_msg
, pim_msg_len
);
215 if (checksum
!= pim_checksum
) {
216 if (PIM_DEBUG_PIM_PACKETS
)
218 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
219 ifp
->name
, pim_checksum
, checksum
);
225 if (PIM_DEBUG_PIM_PACKETS
) {
226 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
,
228 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
,
231 "Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
232 pim_pim_msgtype2str(header
->type
), src_str
, dst_str
,
233 ifp
->name
, ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
,
235 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
236 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
240 switch (header
->type
) {
241 case PIM_MSG_TYPE_HELLO
:
242 return pim_hello_recv(ifp
, ip_hdr
->ip_src
,
243 pim_msg
+ PIM_MSG_HEADER_LEN
,
244 pim_msg_len
- PIM_MSG_HEADER_LEN
);
246 case PIM_MSG_TYPE_REGISTER
:
247 return pim_register_recv(ifp
, ip_hdr
->ip_dst
, ip_hdr
->ip_src
,
248 pim_msg
+ PIM_MSG_HEADER_LEN
,
249 pim_msg_len
- PIM_MSG_HEADER_LEN
);
251 case PIM_MSG_TYPE_REG_STOP
:
252 return pim_register_stop_recv(ifp
, pim_msg
+ PIM_MSG_HEADER_LEN
,
253 pim_msg_len
- PIM_MSG_HEADER_LEN
);
255 case PIM_MSG_TYPE_JOIN_PRUNE
:
256 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
258 if (PIM_DEBUG_PIM_PACKETS
)
260 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
261 __FILE__
, __PRETTY_FUNCTION__
,
262 header
->type
, src_str
, ifp
->name
);
265 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
266 return pim_joinprune_recv(ifp
, neigh
, ip_hdr
->ip_src
,
267 pim_msg
+ PIM_MSG_HEADER_LEN
,
268 pim_msg_len
- PIM_MSG_HEADER_LEN
);
270 case PIM_MSG_TYPE_ASSERT
:
271 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
273 if (PIM_DEBUG_PIM_PACKETS
)
275 "%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
276 __FILE__
, __PRETTY_FUNCTION__
,
277 header
->type
, src_str
, ifp
->name
);
280 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
281 return pim_assert_recv(ifp
, neigh
, ip_hdr
->ip_src
,
282 pim_msg
+ PIM_MSG_HEADER_LEN
,
283 pim_msg_len
- PIM_MSG_HEADER_LEN
);
285 case PIM_MSG_TYPE_BOOTSTRAP
:
286 return pim_bsm_process(ifp
, ip_hdr
, pim_msg
, pim_msg_len
,
291 if (PIM_DEBUG_PIM_PACKETS
) {
293 "Recv PIM packet type %d which is not currently understood",
301 static void pim_sock_read_on(struct interface
*ifp
);
303 static int pim_sock_read(struct thread
*t
)
305 struct interface
*ifp
, *orig_ifp
;
306 struct pim_interface
*pim_ifp
;
308 struct sockaddr_in from
;
309 struct sockaddr_in to
;
310 socklen_t fromlen
= sizeof(from
);
311 socklen_t tolen
= sizeof(to
);
312 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
314 ifindex_t ifindex
= -1;
315 int result
= -1; /* defaults to bad */
316 static long long count
= 0;
319 orig_ifp
= ifp
= THREAD_ARG(t
);
325 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
), &from
,
326 &fromlen
, &to
, &tolen
, &ifindex
);
330 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
333 if (PIM_DEBUG_PIM_PACKETS
)
334 zlog_debug("Received errno: %d %s", errno
,
335 safe_strerror(errno
));
340 * What? So with vrf's the incoming packet is received
341 * on the vrf interface but recvfromto above returns
342 * the right ifindex, so just use it. We know
343 * it's the right interface because we bind to it
345 ifp
= if_lookup_by_index(ifindex
, pim_ifp
->pim
->vrf_id
);
346 if (!ifp
|| !ifp
->info
) {
347 if (PIM_DEBUG_PIM_PACKETS
)
349 "%s: Received incoming pim packet on interface(%s:%d) not yet configured for pim",
351 ifp
? ifp
->name
: "Unknown", ifindex
);
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
% router
->packet_process
== 0)
367 result
= 0; /* good */
370 pim_sock_read_on(orig_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_add_read(router
->master
, pim_sock_read
, ifp
,
394 pim_ifp
->pim_sock_fd
, &pim_ifp
->t_pim_sock_read
);
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
;
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_tos
= IPTOS_PREC_INTERNETCONTROL
;
584 ip
->ip_p
= PIM_IP_PROTO_PIM
;
588 ip
->ip_len
= htons(sendlen
);
590 if (PIM_DEBUG_PIM_PACKETS
) {
591 char dst_str
[INET_ADDRSTRLEN
];
592 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
593 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
594 __PRETTY_FUNCTION__
, dst_str
, ifname
, pim_msg_size
,
598 memset(&to
, 0, sizeof(to
));
599 to
.sin_family
= AF_INET
;
603 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
604 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
607 pim_msg_send_frame(fd
, (char *)buffer
, sendlen
, (struct sockaddr
*)&to
,
612 static int hello_send(struct interface
*ifp
, uint16_t holdtime
)
614 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
615 struct pim_interface
*pim_ifp
;
621 if (PIM_DEBUG_PIM_HELLO
) {
622 char dst_str
[INET_ADDRSTRLEN
];
623 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
,
626 "%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",
627 __PRETTY_FUNCTION__
, dst_str
, ifp
->name
, holdtime
,
628 pim_ifp
->pim_propagation_delay_msec
,
629 pim_ifp
->pim_override_interval_msec
,
630 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(
632 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
633 listcount(ifp
->connected
));
636 pim_tlv_size
= pim_hello_build_tlv(
637 ifp
, pim_msg
+ PIM_PIM_MIN_LEN
,
638 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
, holdtime
,
639 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
640 pim_ifp
->pim_propagation_delay_msec
,
641 pim_ifp
->pim_override_interval_msec
,
642 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
));
643 if (pim_tlv_size
< 0) {
647 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
649 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
650 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
652 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
, false);
654 if (pim_msg_send(pim_ifp
->pim_sock_fd
, pim_ifp
->primary_address
,
655 qpim_all_pim_routers_addr
, pim_msg
, pim_msg_size
,
657 if (PIM_DEBUG_PIM_HELLO
) {
659 "%s: could not send PIM message on interface %s",
660 __PRETTY_FUNCTION__
, ifp
->name
);
668 static int pim_hello_send(struct interface
*ifp
, uint16_t holdtime
)
670 struct pim_interface
*pim_ifp
= ifp
->info
;
672 if (if_is_loopback_or_vrf(ifp
))
675 if (hello_send(ifp
, holdtime
)) {
676 ++pim_ifp
->pim_ifstat_hello_sendfail
;
678 if (PIM_DEBUG_PIM_HELLO
) {
679 zlog_warn("Could not send PIM hello on interface %s",
685 ++pim_ifp
->pim_ifstat_hello_sent
;
690 static void hello_resched(struct interface
*ifp
)
692 struct pim_interface
*pim_ifp
;
696 if (PIM_DEBUG_PIM_HELLO
) {
697 zlog_debug("Rescheduling %d sec hello on interface %s",
698 pim_ifp
->pim_hello_period
, ifp
->name
);
700 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
701 thread_add_timer(router
->master
, on_pim_hello_send
, ifp
,
702 pim_ifp
->pim_hello_period
,
703 &pim_ifp
->t_pim_hello_timer
);
709 static int on_pim_hello_send(struct thread
*t
)
711 struct pim_interface
*pim_ifp
;
712 struct interface
*ifp
;
718 * Schedule next hello
725 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
729 RFC 4601: 4.3.1. Sending Hello Messages
731 Thus, if a router needs to send a Join/Prune or Assert message on an
732 interface on which it has not yet sent a Hello message with the
733 currently configured IP address, then it MUST immediately send the
734 relevant Hello message without waiting for the Hello Timer to
735 expire, followed by the Join/Prune or Assert message.
737 void pim_hello_restart_now(struct interface
*ifp
)
739 struct pim_interface
*pim_ifp
;
744 * Reset next hello timer
749 * Immediately send hello
751 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
755 RFC 4601: 4.3.1. Sending Hello Messages
757 To allow new or rebooting routers to learn of PIM neighbors quickly,
758 when a Hello message is received from a new neighbor, or a Hello
759 message with a new GenID is received from an existing neighbor, a
760 new Hello message should be sent on this interface after a
761 randomized delay between 0 and Triggered_Hello_Delay.
763 void pim_hello_restart_triggered(struct interface
*ifp
)
765 struct pim_interface
*pim_ifp
;
766 int triggered_hello_delay_msec
;
772 * No need to ever start loopback or vrf device hello's
774 if (if_is_loopback_or_vrf(ifp
))
778 * There exists situations where we have the a RPF out this
779 * interface, but we haven't formed a neighbor yet. This
780 * happens especially during interface flaps. While
781 * we would like to handle this more gracefully in other
782 * parts of the code. In order to get us up and running
783 * let's just send the hello immediate'ish
784 * This should be revisited when we get nexthop tracking
785 * in and when we have a better handle on safely
786 * handling the rpf information for upstreams that
787 * we cannot legally reach yet.
789 triggered_hello_delay_msec
= 1;
790 // triggered_hello_delay_msec = 1000 *
791 // pim_ifp->pim_triggered_hello_delay;
793 if (pim_ifp
->t_pim_hello_timer
) {
795 pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
796 if (remain_msec
<= triggered_hello_delay_msec
) {
797 /* Rescheduling hello would increase the delay, then
799 to just wait for the scheduled periodic hello. */
803 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
806 random_msec
= triggered_hello_delay_msec
;
807 // random_msec = random() % (triggered_hello_delay_msec + 1);
809 if (PIM_DEBUG_PIM_HELLO
) {
810 zlog_debug("Scheduling %d msec triggered hello on interface %s",
811 random_msec
, ifp
->name
);
814 thread_add_timer_msec(router
->master
, on_pim_hello_send
, ifp
,
815 random_msec
, &pim_ifp
->t_pim_hello_timer
);
818 int pim_sock_add(struct interface
*ifp
)
820 struct pim_interface
*pim_ifp
;
826 if (pim_ifp
->pim_sock_fd
>= 0) {
827 if (PIM_DEBUG_PIM_PACKETS
)
829 "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", ifp
->name
,
864 * Start receiving PIM messages
866 pim_sock_read_on(ifp
);
869 * Start sending PIM hello's
871 pim_hello_restart_triggered(ifp
);