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 if (ip_hdr
->ip_p
!= PIM_IP_PROTO_PIM
) {
154 if (PIM_DEBUG_PIM_PACKETS
)
155 zlog_debug("IP packet protocol=%d is not PIM=%d",
156 ip_hdr
->ip_p
, PIM_IP_PROTO_PIM
);
160 if (ip_hlen
< PIM_IP_HEADER_MIN_LEN
) {
161 if (PIM_DEBUG_PIM_PACKETS
)
162 zlog_debug("IP packet header size=%zu shorter than minimum=%d",
163 ip_hlen
, PIM_IP_HEADER_MIN_LEN
);
166 if (ip_hlen
> PIM_IP_HEADER_MAX_LEN
) {
167 if (PIM_DEBUG_PIM_PACKETS
)
168 zlog_debug("IP packet header size=%zu greater than maximum=%d",
169 ip_hlen
, PIM_IP_HEADER_MAX_LEN
);
173 pim_msg
= buf
+ ip_hlen
;
174 pim_msg_len
= len
- ip_hlen
;
176 header
= (struct pim_msg_header
*)pim_msg
;
177 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
178 if (PIM_DEBUG_PIM_PACKETS
)
179 zlog_debug("PIM message size=%d shorter than minimum=%d",
180 pim_msg_len
, PIM_PIM_MIN_LEN
);
184 if (header
->ver
!= PIM_PROTO_VERSION
) {
185 if (PIM_DEBUG_PIM_PACKETS
)
186 zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
187 ifp
->name
, header
->ver
);
191 /* save received checksum */
192 pim_checksum
= header
->checksum
;
194 /* for computing checksum */
195 header
->checksum
= 0;
197 if (header
->type
== PIM_MSG_TYPE_REGISTER
)
199 /* First 8 byte header checksum */
200 checksum
= in_cksum (pim_msg
, PIM_MSG_REGISTER_LEN
);
201 if (checksum
!= pim_checksum
)
203 checksum
= in_cksum (pim_msg
, pim_msg_len
);
204 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
);
217 checksum
= in_cksum (pim_msg
, pim_msg_len
);
218 if (checksum
!= pim_checksum
)
220 if (PIM_DEBUG_PIM_PACKETS
)
222 ("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
223 ifp
->name
, pim_checksum
, checksum
);
229 if (PIM_DEBUG_PIM_PACKETS
) {
230 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
, sizeof(src_str
));
231 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
, sizeof(dst_str
));
232 zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
233 pim_pim_msgtype2str (header
->type
), src_str
, dst_str
, ifp
->name
,
234 ip_hdr
->ip_ttl
, header
->ver
, pim_msg_len
, checksum
);
235 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
236 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
240 switch (header
->type
)
242 case PIM_MSG_TYPE_HELLO
:
243 return pim_hello_recv (ifp
,
245 pim_msg
+ PIM_MSG_HEADER_LEN
,
246 pim_msg_len
- PIM_MSG_HEADER_LEN
);
248 case PIM_MSG_TYPE_REGISTER
:
249 return pim_register_recv (ifp
,
252 pim_msg
+ PIM_MSG_HEADER_LEN
,
253 pim_msg_len
- PIM_MSG_HEADER_LEN
);
255 case PIM_MSG_TYPE_REG_STOP
:
256 return pim_register_stop_recv (pim_msg
+ PIM_MSG_HEADER_LEN
,
257 pim_msg_len
- PIM_MSG_HEADER_LEN
);
259 case PIM_MSG_TYPE_JOIN_PRUNE
:
260 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
262 if (PIM_DEBUG_PIM_PACKETS
)
263 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
264 __FILE__
, __PRETTY_FUNCTION__
,
265 header
->type
, src_str
, ifp
->name
);
268 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
269 return pim_joinprune_recv(ifp
, neigh
,
271 pim_msg
+ PIM_MSG_HEADER_LEN
,
272 pim_msg_len
- PIM_MSG_HEADER_LEN
);
274 case PIM_MSG_TYPE_ASSERT
:
275 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
277 if (PIM_DEBUG_PIM_PACKETS
)
278 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
279 __FILE__
, __PRETTY_FUNCTION__
,
280 header
->type
, src_str
, ifp
->name
);
283 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
284 return pim_assert_recv(ifp
, neigh
,
286 pim_msg
+ PIM_MSG_HEADER_LEN
,
287 pim_msg_len
- PIM_MSG_HEADER_LEN
);
290 if (PIM_DEBUG_PIM_PACKETS
) {
291 zlog_debug("Recv PIM packet type %d which is not currently understood",
299 static void pim_sock_read_on(struct interface
*ifp
);
301 static int pim_sock_read(struct thread
*t
)
303 struct interface
*ifp
;
304 struct pim_interface
*pim_ifp
;
306 struct sockaddr_in from
;
307 struct sockaddr_in to
;
308 socklen_t fromlen
= sizeof(from
);
309 socklen_t tolen
= sizeof(to
);
310 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
312 ifindex_t ifindex
= -1;
313 int result
= -1; /* defaults to bad */
314 static long long count
= 0;
324 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
),
332 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
337 if (PIM_DEBUG_PIM_PACKETS
)
338 zlog_debug ("Received errno: %d %s", errno
, safe_strerror (errno
));
342 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
343 /* ifindex sanity check */
344 if (ifindex
!= (int) ifp
->ifindex
) {
345 char from_str
[INET_ADDRSTRLEN
];
346 char to_str
[INET_ADDRSTRLEN
];
347 struct interface
*recv_ifp
;
349 if (!inet_ntop(AF_INET
, &from
.sin_addr
, from_str
, sizeof(from_str
)))
350 sprintf(from_str
, "<from?>");
351 if (!inet_ntop(AF_INET
, &to
.sin_addr
, to_str
, sizeof(to_str
)))
352 sprintf(to_str
, "<to?>");
354 recv_ifp
= if_lookup_by_index(ifindex
);
356 zassert(ifindex
== (int) recv_ifp
->ifindex
);
359 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
360 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
361 from_str
, to_str
, fd
,
362 ifindex
, recv_ifp
? recv_ifp
->name
: "<if-notfound>",
363 ifp
->ifindex
, ifp
->name
);
369 int fail
= pim_pim_packet(ifp
, buf
, len
);
371 if (PIM_DEBUG_PIM_PACKETS
)
372 zlog_debug("%s: pim_pim_packet() return=%d",
373 __PRETTY_FUNCTION__
, fail
);
378 if (count
% qpim_packet_process
== 0)
382 result
= 0; /* good */
385 pim_sock_read_on(ifp
);
388 ++pim_ifp
->pim_ifstat_hello_recvfail
;
394 static void pim_sock_read_on(struct interface
*ifp
)
396 struct pim_interface
*pim_ifp
;
403 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
404 zlog_debug("Scheduling READ event on PIM socket fd=%d",
405 pim_ifp
->pim_sock_fd
);
407 pim_ifp
->t_pim_sock_read
= NULL
;
408 zassert(!pim_ifp
->t_pim_sock_read
);
409 THREAD_READ_ON(master
, pim_ifp
->t_pim_sock_read
, pim_sock_read
, ifp
,
410 pim_ifp
->pim_sock_fd
);
413 static int pim_sock_open(struct interface
*ifp
)
416 struct pim_interface
*pim_ifp
= ifp
->info
;
418 fd
= pim_socket_mcast(IPPROTO_PIM
, pim_ifp
->primary_address
, ifp
, 0 /* loop=false */);
422 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
, pim_ifp
->primary_address
, ifp
->ifindex
)) {
430 void pim_ifstat_reset(struct interface
*ifp
)
432 struct pim_interface
*pim_ifp
;
441 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
442 pim_ifp
->pim_ifstat_hello_sent
= 0;
443 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
444 pim_ifp
->pim_ifstat_hello_recv
= 0;
445 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
448 void pim_sock_reset(struct interface
*ifp
)
450 struct pim_interface
*pim_ifp
;
457 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
459 pim_ifp
->pim_sock_fd
= -1;
460 pim_ifp
->pim_sock_creation
= 0;
461 pim_ifp
->t_pim_sock_read
= NULL
;
463 pim_ifp
->t_pim_hello_timer
= NULL
;
464 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
465 pim_ifp
->pim_default_holdtime
= -1; /* unset: means 3.5 * pim_hello_period */
466 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
467 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
468 pim_ifp
->pim_propagation_delay_msec
= PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
469 pim_ifp
->pim_override_interval_msec
= PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
470 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
471 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
474 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
477 /* neighbors without lan_delay */
478 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
479 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
480 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
483 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
484 pim_ifp
->pim_dr_election_count
= 0;
485 pim_ifp
->pim_dr_election_changes
= 0;
486 pim_ifp
->pim_dr_num_nondrpri_neighbors
= 0; /* neighbors without dr_pri */
487 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
489 pim_ifstat_reset(ifp
);
492 static uint16_t ip_id
= 0;
496 pim_msg_send_frame (int fd
, char *buf
, size_t len
,
497 struct sockaddr
*dst
, size_t salen
)
499 struct ip
*ip
= (struct ip
*)buf
;
501 while (sendto (fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0)
503 char dst_str
[INET_ADDRSTRLEN
];
509 size_t hdrsize
= sizeof (struct ip
);
510 size_t newlen1
= ((len
- hdrsize
) / 2 ) & 0xFFF8;
511 size_t sendlen
= newlen1
+ hdrsize
;
512 size_t offset
= ntohs (ip
->ip_off
);
514 ip
->ip_len
= htons (sendlen
);
515 ip
->ip_off
= htons (offset
| IP_MF
);
516 if (pim_msg_send_frame (fd
, buf
, sendlen
, dst
, salen
) == 0)
518 struct ip
*ip2
= (struct ip
*)(buf
+ newlen1
);
519 size_t newlen2
= len
- sendlen
;
520 sendlen
= newlen2
+ hdrsize
;
522 memcpy (ip2
, ip
, hdrsize
);
523 ip2
->ip_len
= htons (sendlen
);
524 ip2
->ip_off
= htons (offset
+ (newlen1
>> 3));
525 return pim_msg_send_frame (fd
, (char *)ip2
, sendlen
, dst
, salen
);
532 if (PIM_DEBUG_PIM_PACKETS
)
534 pim_inet4_dump ("<dst?>", ip
->ip_dst
, dst_str
, sizeof (dst_str
));
535 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
538 errno
, safe_strerror(errno
));
549 pim_msg_send(int fd
, struct in_addr src
,
550 struct in_addr dst
, uint8_t *pim_msg
,
551 int pim_msg_size
, const char *ifname
)
553 struct sockaddr_in to
;
555 unsigned char buffer
[10000];
556 unsigned char *msg_start
;
557 uint8_t ttl
= MAXTTL
;
558 struct pim_msg_header
*header
;
561 memset (buffer
, 0, 10000);
562 int sendlen
= sizeof (struct ip
) + pim_msg_size
;
564 msg_start
= buffer
+ sizeof (struct ip
);
565 memcpy (msg_start
, pim_msg
, pim_msg_size
);
567 header
= (struct pim_msg_header
*)pim_msg
;
569 * Omnios apparently doesn't have a #define for IP default
570 * ttl that is the same as all other platforms.
575 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
576 switch (header
->type
)
578 case PIM_MSG_TYPE_HELLO
:
579 case PIM_MSG_TYPE_JOIN_PRUNE
:
580 case PIM_MSG_TYPE_BOOTSTRAP
:
581 case PIM_MSG_TYPE_ASSERT
:
584 case PIM_MSG_TYPE_REGISTER
:
585 case PIM_MSG_TYPE_REG_STOP
:
586 case PIM_MSG_TYPE_GRAFT
:
587 case PIM_MSG_TYPE_GRAFT_ACK
:
588 case PIM_MSG_TYPE_CANDIDATE
:
596 ip
= (struct ip
*) buffer
;
597 ip
->ip_id
= htons (++ip_id
);
600 ip
->ip_p
= PIM_IP_PROTO_PIM
;
604 ip
->ip_len
= htons (sendlen
);
606 if (PIM_DEBUG_PIM_PACKETS
) {
607 struct pim_msg_header
*header
= (struct pim_msg_header
*)pim_msg
;
608 char dst_str
[INET_ADDRSTRLEN
];
609 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
610 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
612 dst_str
, ifname
, pim_msg_size
,
616 memset(&to
, 0, sizeof(to
));
617 to
.sin_family
= AF_INET
;
621 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
622 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
625 pim_msg_send_frame (fd
, (char *)buffer
, sendlen
,
626 (struct sockaddr
*)&to
, tolen
);
630 static int hello_send(struct interface
*ifp
,
633 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
634 struct pim_interface
*pim_ifp
;
640 if (PIM_DEBUG_PIM_HELLO
) {
641 char dst_str
[INET_ADDRSTRLEN
];
642 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
, sizeof(dst_str
));
643 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",
647 pim_ifp
->pim_propagation_delay_msec
, pim_ifp
->pim_override_interval_msec
,
648 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
649 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
650 listcount(ifp
->connected
));
653 pim_tlv_size
= pim_hello_build_tlv(ifp
->name
,
654 pim_msg
+ PIM_PIM_MIN_LEN
,
655 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
,
657 pim_ifp
->pim_dr_priority
,
658 pim_ifp
->pim_generation_id
,
659 pim_ifp
->pim_propagation_delay_msec
,
660 pim_ifp
->pim_override_interval_msec
,
661 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
663 if (pim_tlv_size
< 0) {
667 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
669 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
670 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
672 pim_msg_build_header(pim_msg
, pim_msg_size
, PIM_MSG_TYPE_HELLO
);
674 if (pim_msg_send(pim_ifp
->pim_sock_fd
,
675 pim_ifp
->primary_address
,
676 qpim_all_pim_routers_addr
,
680 if (PIM_DEBUG_PIM_HELLO
) {
681 zlog_debug("%s: could not send PIM message on interface %s",
682 __PRETTY_FUNCTION__
, ifp
->name
);
690 static int pim_hello_send(struct interface
*ifp
,
693 struct pim_interface
*pim_ifp
;
699 if (if_is_loopback (ifp
))
702 if (hello_send(ifp
, holdtime
)) {
703 ++pim_ifp
->pim_ifstat_hello_sendfail
;
705 if (PIM_DEBUG_PIM_HELLO
) {
706 zlog_warn("Could not send PIM hello on interface %s",
712 ++pim_ifp
->pim_ifstat_hello_sent
;
717 static void hello_resched(struct interface
*ifp
)
719 struct pim_interface
*pim_ifp
;
725 if (PIM_DEBUG_PIM_HELLO
) {
726 zlog_debug("Rescheduling %d sec hello on interface %s",
727 pim_ifp
->pim_hello_period
, ifp
->name
);
729 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
730 THREAD_TIMER_ON(master
, pim_ifp
->t_pim_hello_timer
,
732 ifp
, pim_ifp
->pim_hello_period
);
738 static int on_pim_hello_send(struct thread
*t
)
740 struct pim_interface
*pim_ifp
;
741 struct interface
*ifp
;
748 * Schedule next hello
750 pim_ifp
->t_pim_hello_timer
= NULL
;
756 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
760 RFC 4601: 4.3.1. Sending Hello Messages
762 Thus, if a router needs to send a Join/Prune or Assert message on an
763 interface on which it has not yet sent a Hello message with the
764 currently configured IP address, then it MUST immediately send the
765 relevant Hello message without waiting for the Hello Timer to
766 expire, followed by the Join/Prune or Assert message.
768 void pim_hello_restart_now(struct interface
*ifp
)
770 struct pim_interface
*pim_ifp
;
777 * Reset next hello timer
782 * Immediately send hello
784 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
788 RFC 4601: 4.3.1. Sending Hello Messages
790 To allow new or rebooting routers to learn of PIM neighbors quickly,
791 when a Hello message is received from a new neighbor, or a Hello
792 message with a new GenID is received from an existing neighbor, a
793 new Hello message should be sent on this interface after a
794 randomized delay between 0 and Triggered_Hello_Delay.
796 void pim_hello_restart_triggered(struct interface
*ifp
)
798 struct pim_interface
*pim_ifp
;
799 int triggered_hello_delay_msec
;
807 * There exists situations where we have the a RPF out this
808 * interface, but we haven't formed a neighbor yet. This
809 * happens especially during interface flaps. While
810 * we would like to handle this more gracefully in other
811 * parts of the code. In order to get us up and running
812 * let's just send the hello immediate'ish
813 * This should be revisited when we get nexthop tracking
814 * in and when we have a better handle on safely
815 * handling the rpf information for upstreams that
816 * we cannot legally reach yet.
818 triggered_hello_delay_msec
= 1;
819 //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
821 if (pim_ifp
->t_pim_hello_timer
) {
822 long remain_msec
= pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
823 if (remain_msec
<= triggered_hello_delay_msec
) {
824 /* Rescheduling hello would increase the delay, then it's faster
825 to just wait for the scheduled periodic hello. */
829 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
830 pim_ifp
->t_pim_hello_timer
= NULL
;
833 random_msec
= triggered_hello_delay_msec
;
834 //random_msec = random() % (triggered_hello_delay_msec + 1);
836 if (PIM_DEBUG_PIM_HELLO
) {
837 zlog_debug("Scheduling %d msec triggered hello on interface %s",
838 random_msec
, ifp
->name
);
841 THREAD_TIMER_MSEC_ON(master
, pim_ifp
->t_pim_hello_timer
,
846 int pim_sock_add(struct interface
*ifp
)
848 struct pim_interface
*pim_ifp
;
854 if (pim_ifp
->pim_sock_fd
>= 0) {
855 if (PIM_DEBUG_PIM_PACKETS
)
856 zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s",
857 pim_ifp
->pim_sock_fd
, ifp
->name
);
861 pim_ifp
->pim_sock_fd
= pim_sock_open(ifp
);
862 if (pim_ifp
->pim_sock_fd
< 0) {
863 if (PIM_DEBUG_PIM_PACKETS
)
864 zlog_debug("Could not open PIM socket on interface %s",
869 pim_socket_ip_hdr (pim_ifp
->pim_sock_fd
);
871 pim_ifp
->t_pim_sock_read
= NULL
;
872 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
875 * Just ensure that the new generation id
876 * actually chooses something different.
877 * Actually ran across a case where this
878 * happened, pre-switch to random().
879 * While this is unlikely to happen now
880 * let's make sure it doesn't.
882 old_genid
= pim_ifp
->pim_generation_id
;
884 while (old_genid
== pim_ifp
->pim_generation_id
)
885 pim_ifp
->pim_generation_id
= random();
887 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
888 ifp
->name
, ifp
->ifindex
);
891 * Start receiving PIM messages
893 pim_sock_read_on(ifp
);
896 * Start sending PIM hello's
898 pim_hello_restart_triggered(ifp
);