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,
32 #include "pim_iface.h"
37 #include "pim_neighbor.h"
38 #include "pim_hello.h"
40 #include "pim_assert.h"
42 #include "pim_register.h"
44 static int on_pim_hello_send(struct thread
*t
);
45 static int pim_hello_send(struct interface
*ifp
,
49 const char *pim_pim_msgtype2str (enum pim_msg_type type
)
53 case PIM_MSG_TYPE_HELLO
: return "HELLO";
54 case PIM_MSG_TYPE_REGISTER
: return "REGISTER";
55 case PIM_MSG_TYPE_REG_STOP
: return "REGSTOP";
56 case PIM_MSG_TYPE_JOIN_PRUNE
: return "JOINPRUNE";
57 case PIM_MSG_TYPE_BOOTSTRAP
: return "BOOT";
58 case PIM_MSG_TYPE_ASSERT
: return "ASSERT";
59 case PIM_MSG_TYPE_GRAFT
: return "GRAFT";
60 case PIM_MSG_TYPE_GRAFT_ACK
: return "GACK";
61 case PIM_MSG_TYPE_CANDIDATE
: return "CANDIDATE";
67 static void sock_close(struct interface
*ifp
)
69 struct pim_interface
*pim_ifp
= ifp
->info
;
71 if (PIM_DEBUG_PIM_TRACE
) {
72 if (pim_ifp
->t_pim_sock_read
) {
73 zlog_debug("Cancelling READ event for PIM socket fd=%d on interface %s",
78 THREAD_OFF(pim_ifp
->t_pim_sock_read
);
80 if (PIM_DEBUG_PIM_TRACE
) {
81 if (pim_ifp
->t_pim_hello_timer
) {
82 zlog_debug("Cancelling PIM hello timer for interface %s",
86 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
88 if (PIM_DEBUG_PIM_TRACE
) {
89 zlog_debug("Deleting PIM socket fd=%d on interface %s",
90 pim_ifp
->pim_sock_fd
, ifp
->name
);
94 * If the fd is already deleted no need to do anything here
96 if (pim_ifp
->pim_sock_fd
> 0 && close(pim_ifp
->pim_sock_fd
)) {
97 zlog_warn("Failure closing PIM socket fd=%d on interface %s: errno=%d: %s",
98 pim_ifp
->pim_sock_fd
, ifp
->name
,
99 errno
, safe_strerror(errno
));
102 pim_ifp
->pim_sock_fd
= -1;
103 pim_ifp
->pim_sock_creation
= 0;
106 void pim_sock_delete(struct interface
*ifp
, const char *delete_message
)
108 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
109 ifp
->name
, delete_message
);
112 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
113 __PRETTY_FUNCTION__
, delete_message
, ifp
->name
);
118 RFC 4601: 4.3.1. Sending Hello Messages
120 Before an interface goes down or changes primary IP address, a Hello
121 message with a zero HoldTime should be sent immediately (with the
122 old IP address if the IP address changed).
124 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
126 pim_neighbor_delete_all(ifp
, delete_message
);
131 int pim_pim_packet(struct interface
*ifp
, uint8_t *buf
, size_t len
)
134 size_t ip_hlen
; /* ip header length in bytes */
135 char src_str
[INET_ADDRSTRLEN
];
136 char dst_str
[INET_ADDRSTRLEN
];
140 enum pim_msg_type pim_type
;
141 uint16_t pim_checksum
; /* received checksum */
142 uint16_t checksum
; /* computed checksum */
143 struct pim_neighbor
*neigh
;
145 if (len
< sizeof(*ip_hdr
)) {
146 if (PIM_DEBUG_PIM_PACKETS
)
147 zlog_debug("PIM packet size=%zu shorter than minimum=%zu",
148 len
, sizeof(*ip_hdr
));
152 ip_hdr
= (struct ip
*) buf
;
153 ip_hlen
= ip_hdr
->ip_hl
<< 2; /* ip_hl gives length in 4-byte words */
155 if (ip_hdr
->ip_p
!= PIM_IP_PROTO_PIM
) {
156 if (PIM_DEBUG_PIM_PACKETS
)
157 zlog_debug("IP packet protocol=%d is not PIM=%d",
158 ip_hdr
->ip_p
, PIM_IP_PROTO_PIM
);
162 if (ip_hlen
< PIM_IP_HEADER_MIN_LEN
) {
163 if (PIM_DEBUG_PIM_PACKETS
)
164 zlog_debug("IP packet header size=%zu shorter than minimum=%d",
165 ip_hlen
, PIM_IP_HEADER_MIN_LEN
);
168 if (ip_hlen
> PIM_IP_HEADER_MAX_LEN
) {
169 if (PIM_DEBUG_PIM_PACKETS
)
170 zlog_debug("IP packet header size=%zu greater than maximum=%d",
171 ip_hlen
, PIM_IP_HEADER_MAX_LEN
);
175 pim_msg
= buf
+ ip_hlen
;
176 pim_msg_len
= len
- ip_hlen
;
178 if (pim_msg_len
< PIM_PIM_MIN_LEN
) {
179 if (PIM_DEBUG_PIM_PACKETS
)
180 zlog_debug("PIM message size=%d shorter than minimum=%d",
181 pim_msg_len
, PIM_PIM_MIN_LEN
);
185 pim_version
= PIM_MSG_HDR_GET_VERSION(pim_msg
);
186 pim_type
= PIM_MSG_HDR_GET_TYPE(pim_msg
);
188 if (pim_version
!= PIM_PROTO_VERSION
) {
189 if (PIM_DEBUG_PIM_PACKETS
)
190 zlog_debug("Ignoring PIM pkt from %s with unsupported version: %d",
191 ifp
->name
, pim_version
);
195 /* save received checksum */
196 pim_checksum
= PIM_MSG_HDR_GET_CHECKSUM(pim_msg
);
198 /* for computing checksum */
199 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg
) = 0;
201 checksum
= in_cksum(pim_msg
, pim_msg_len
);
202 if (checksum
!= pim_checksum
) {
203 if (PIM_DEBUG_PIM_PACKETS
)
204 zlog_debug("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
205 ifp
->name
, pim_checksum
, checksum
);
209 if (PIM_DEBUG_PIM_PACKETS
) {
210 pim_inet4_dump("<src?>", ip_hdr
->ip_src
, src_str
, sizeof(src_str
));
211 pim_inet4_dump("<dst?>", ip_hdr
->ip_dst
, dst_str
, sizeof(dst_str
));
212 zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
213 pim_pim_msgtype2str (pim_type
), src_str
, dst_str
, ifp
->name
,
214 ip_hdr
->ip_ttl
, pim_version
, pim_msg_len
, checksum
);
215 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
) {
216 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_len
);
222 case PIM_MSG_TYPE_HELLO
:
223 return pim_hello_recv (ifp
,
225 pim_msg
+ PIM_MSG_HEADER_LEN
,
226 pim_msg_len
- PIM_MSG_HEADER_LEN
);
228 case PIM_MSG_TYPE_REGISTER
:
229 return pim_register_recv (ifp
,
232 pim_msg
+ PIM_MSG_HEADER_LEN
,
233 pim_msg_len
- PIM_MSG_HEADER_LEN
);
235 case PIM_MSG_TYPE_REG_STOP
:
236 return pim_register_stop_recv (pim_msg
+ PIM_MSG_HEADER_LEN
,
237 pim_msg_len
- PIM_MSG_HEADER_LEN
);
239 case PIM_MSG_TYPE_JOIN_PRUNE
:
240 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
242 if (PIM_DEBUG_PIM_PACKETS
)
243 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
244 __FILE__
, __PRETTY_FUNCTION__
,
245 pim_type
, src_str
, ifp
->name
);
248 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
249 return pim_joinprune_recv(ifp
, neigh
,
251 pim_msg
+ PIM_MSG_HEADER_LEN
,
252 pim_msg_len
- PIM_MSG_HEADER_LEN
);
254 case PIM_MSG_TYPE_ASSERT
:
255 neigh
= pim_neighbor_find(ifp
, ip_hdr
->ip_src
);
257 if (PIM_DEBUG_PIM_PACKETS
)
258 zlog_debug("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
259 __FILE__
, __PRETTY_FUNCTION__
,
260 pim_type
, src_str
, ifp
->name
);
263 pim_neighbor_timer_reset(neigh
, neigh
->holdtime
);
264 return pim_assert_recv(ifp
, neigh
,
266 pim_msg
+ PIM_MSG_HEADER_LEN
,
267 pim_msg_len
- PIM_MSG_HEADER_LEN
);
270 if (PIM_DEBUG_PIM_PACKETS
) {
271 zlog_debug("Recv PIM packet type %d which is not currently understood",
279 static void pim_sock_read_on(struct interface
*ifp
);
281 static int pim_sock_read(struct thread
*t
)
283 struct interface
*ifp
;
284 struct pim_interface
*pim_ifp
;
286 struct sockaddr_in from
;
287 struct sockaddr_in to
;
288 socklen_t fromlen
= sizeof(from
);
289 socklen_t tolen
= sizeof(to
);
290 uint8_t buf
[PIM_PIM_BUFSIZE_READ
];
292 ifindex_t ifindex
= -1;
293 int result
= -1; /* defaults to bad */
294 static long long count
= 0;
304 len
= pim_socket_recvfromto(fd
, buf
, sizeof(buf
),
312 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
317 if (PIM_DEBUG_PIM_PACKETS
)
318 zlog_debug ("Received errno: %d %s", errno
, safe_strerror (errno
));
322 #ifdef PIM_CHECK_RECV_IFINDEX_SANITY
323 /* ifindex sanity check */
324 if (ifindex
!= (int) ifp
->ifindex
) {
325 char from_str
[INET_ADDRSTRLEN
];
326 char to_str
[INET_ADDRSTRLEN
];
327 struct interface
*recv_ifp
;
329 if (!inet_ntop(AF_INET
, &from
.sin_addr
, from_str
, sizeof(from_str
)))
330 sprintf(from_str
, "<from?>");
331 if (!inet_ntop(AF_INET
, &to
.sin_addr
, to_str
, sizeof(to_str
)))
332 sprintf(to_str
, "<to?>");
334 recv_ifp
= if_lookup_by_index(ifindex
);
336 zassert(ifindex
== (int) recv_ifp
->ifindex
);
339 #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
340 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
341 from_str
, to_str
, fd
,
342 ifindex
, recv_ifp
? recv_ifp
->name
: "<if-notfound>",
343 ifp
->ifindex
, ifp
->name
);
349 int fail
= pim_pim_packet(ifp
, buf
, len
);
351 if (PIM_DEBUG_PIM_PACKETS
)
352 zlog_debug("%s: pim_pim_packet() return=%d",
353 __PRETTY_FUNCTION__
, fail
);
358 if (count
% qpim_packet_process
== 0)
362 result
= 0; /* good */
365 pim_sock_read_on(ifp
);
368 ++pim_ifp
->pim_ifstat_hello_recvfail
;
374 static void pim_sock_read_on(struct interface
*ifp
)
376 struct pim_interface
*pim_ifp
;
383 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
384 zlog_debug("Scheduling READ event on PIM socket fd=%d",
385 pim_ifp
->pim_sock_fd
);
387 pim_ifp
->t_pim_sock_read
= NULL
;
388 zassert(!pim_ifp
->t_pim_sock_read
);
389 THREAD_READ_ON(master
, pim_ifp
->t_pim_sock_read
, pim_sock_read
, ifp
,
390 pim_ifp
->pim_sock_fd
);
393 static int pim_sock_open(struct in_addr ifaddr
, ifindex_t ifindex
)
397 fd
= pim_socket_mcast(IPPROTO_PIM
, ifaddr
, ifindex
, 0 /* loop=false */);
401 if (pim_socket_join(fd
, qpim_all_pim_routers_addr
, ifaddr
, ifindex
)) {
409 void pim_ifstat_reset(struct interface
*ifp
)
411 struct pim_interface
*pim_ifp
;
420 pim_ifp
->pim_ifstat_start
= pim_time_monotonic_sec();
421 pim_ifp
->pim_ifstat_hello_sent
= 0;
422 pim_ifp
->pim_ifstat_hello_sendfail
= 0;
423 pim_ifp
->pim_ifstat_hello_recv
= 0;
424 pim_ifp
->pim_ifstat_hello_recvfail
= 0;
427 void pim_sock_reset(struct interface
*ifp
)
429 struct pim_interface
*pim_ifp
;
436 pim_ifp
->primary_address
= pim_find_primary_addr(ifp
);
438 pim_ifp
->pim_sock_fd
= -1;
439 pim_ifp
->pim_sock_creation
= 0;
440 pim_ifp
->t_pim_sock_read
= NULL
;
442 pim_ifp
->t_pim_hello_timer
= NULL
;
443 pim_ifp
->pim_hello_period
= PIM_DEFAULT_HELLO_PERIOD
;
444 pim_ifp
->pim_default_holdtime
= -1; /* unset: means 3.5 * pim_hello_period */
445 pim_ifp
->pim_triggered_hello_delay
= PIM_DEFAULT_TRIGGERED_HELLO_DELAY
;
446 pim_ifp
->pim_dr_priority
= PIM_DEFAULT_DR_PRIORITY
;
447 pim_ifp
->pim_propagation_delay_msec
= PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
448 pim_ifp
->pim_override_interval_msec
= PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
449 if (PIM_DEFAULT_CAN_DISABLE_JOIN_SUPPRESSION
) {
450 PIM_IF_DO_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
453 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
);
456 /* neighbors without lan_delay */
457 pim_ifp
->pim_number_of_nonlandelay_neighbors
= 0;
458 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= 0;
459 pim_ifp
->pim_neighbors_highest_override_interval_msec
= 0;
462 pim_ifp
->pim_dr_election_last
= 0; /* timestamp */
463 pim_ifp
->pim_dr_election_count
= 0;
464 pim_ifp
->pim_dr_election_changes
= 0;
465 pim_ifp
->pim_dr_num_nondrpri_neighbors
= 0; /* neighbors without dr_pri */
466 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
468 pim_ifstat_reset(ifp
);
471 static uint16_t ip_id
= 0;
475 pim_msg_send_frame (int fd
, char *buf
, size_t len
,
476 struct sockaddr
*dst
, size_t salen
)
478 struct ip
*ip
= (struct ip
*)buf
;
480 while (sendto (fd
, buf
, len
, MSG_DONTWAIT
, dst
, salen
) < 0)
482 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
) == 0)
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
, sendlen
, dst
, salen
);
511 if (PIM_DEBUG_PIM_PACKETS
)
513 pim_inet4_dump ("<dst?>", ip
->ip_dst
, dst_str
, sizeof (dst_str
));
514 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
517 errno
, safe_strerror(errno
));
528 pim_msg_send(int fd
, struct in_addr src
,
529 struct in_addr dst
, uint8_t *pim_msg
,
530 int pim_msg_size
, const char *ifname
)
532 struct sockaddr_in to
;
534 unsigned char buffer
[10000];
535 unsigned char *msg_start
;
538 memset (buffer
, 0, 10000);
539 int sendlen
= sizeof (struct ip
) + pim_msg_size
;
541 msg_start
= buffer
+ sizeof (struct ip
);
542 memcpy (msg_start
, pim_msg
, pim_msg_size
);
544 ip
= (struct ip
*)buffer
;
545 ip
->ip_id
= htons (++ip_id
);
548 ip
->ip_p
= PIM_IP_PROTO_PIM
;
552 ip
->ip_len
= htons (sendlen
);
554 if (PIM_DEBUG_PIM_PACKETS
) {
555 char dst_str
[INET_ADDRSTRLEN
];
556 pim_inet4_dump("<dst?>", dst
, dst_str
, sizeof(dst_str
));
557 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
559 dst_str
, ifname
, pim_msg_size
,
560 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg
));
563 memset(&to
, 0, sizeof(to
));
564 to
.sin_family
= AF_INET
;
568 if (PIM_DEBUG_PIM_PACKETDUMP_SEND
) {
569 pim_pkt_dump(__PRETTY_FUNCTION__
, pim_msg
, pim_msg_size
);
572 pim_msg_send_frame (fd
, (char *)buffer
, sendlen
,
573 (struct sockaddr
*)&to
, tolen
);
577 static int hello_send(struct interface
*ifp
,
580 uint8_t pim_msg
[PIM_PIM_BUFSIZE_WRITE
];
581 struct pim_interface
*pim_ifp
;
587 if (PIM_DEBUG_PIM_HELLO
) {
588 char dst_str
[INET_ADDRSTRLEN
];
589 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr
, dst_str
, sizeof(dst_str
));
590 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",
594 pim_ifp
->pim_propagation_delay_msec
, pim_ifp
->pim_override_interval_msec
,
595 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
596 pim_ifp
->pim_dr_priority
, pim_ifp
->pim_generation_id
,
597 listcount(ifp
->connected
));
600 pim_tlv_size
= pim_hello_build_tlv(ifp
->name
,
601 pim_msg
+ PIM_PIM_MIN_LEN
,
602 sizeof(pim_msg
) - PIM_PIM_MIN_LEN
,
604 pim_ifp
->pim_dr_priority
,
605 pim_ifp
->pim_generation_id
,
606 pim_ifp
->pim_propagation_delay_msec
,
607 pim_ifp
->pim_override_interval_msec
,
608 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
),
610 if (pim_tlv_size
< 0) {
614 pim_msg_size
= pim_tlv_size
+ PIM_PIM_MIN_LEN
;
616 zassert(pim_msg_size
>= PIM_PIM_MIN_LEN
);
617 zassert(pim_msg_size
<= PIM_PIM_BUFSIZE_WRITE
);
619 pim_msg_build_header(pim_msg
, pim_msg_size
,
622 if (pim_msg_send(pim_ifp
->pim_sock_fd
,
623 pim_ifp
->primary_address
,
624 qpim_all_pim_routers_addr
,
628 if (PIM_DEBUG_PIM_HELLO
) {
629 zlog_debug("%s: could not send PIM message on interface %s",
630 __PRETTY_FUNCTION__
, ifp
->name
);
638 static int pim_hello_send(struct interface
*ifp
,
641 struct pim_interface
*pim_ifp
;
647 if (if_is_loopback (ifp
))
650 if (hello_send(ifp
, holdtime
)) {
651 ++pim_ifp
->pim_ifstat_hello_sendfail
;
653 if (PIM_DEBUG_PIM_HELLO
) {
654 zlog_warn("Could not send PIM hello on interface %s",
660 ++pim_ifp
->pim_ifstat_hello_sent
;
665 static void hello_resched(struct interface
*ifp
)
667 struct pim_interface
*pim_ifp
;
673 if (PIM_DEBUG_PIM_HELLO
) {
674 zlog_debug("Rescheduling %d sec hello on interface %s",
675 pim_ifp
->pim_hello_period
, ifp
->name
);
677 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
678 THREAD_TIMER_ON(master
, pim_ifp
->t_pim_hello_timer
,
680 ifp
, pim_ifp
->pim_hello_period
);
686 static int on_pim_hello_send(struct thread
*t
)
688 struct pim_interface
*pim_ifp
;
689 struct interface
*ifp
;
696 * Schedule next hello
698 pim_ifp
->t_pim_hello_timer
= NULL
;
704 return pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
708 RFC 4601: 4.3.1. Sending Hello Messages
710 Thus, if a router needs to send a Join/Prune or Assert message on an
711 interface on which it has not yet sent a Hello message with the
712 currently configured IP address, then it MUST immediately send the
713 relevant Hello message without waiting for the Hello Timer to
714 expire, followed by the Join/Prune or Assert message.
716 void pim_hello_restart_now(struct interface
*ifp
)
718 struct pim_interface
*pim_ifp
;
725 * Reset next hello timer
730 * Immediately send hello
732 pim_hello_send(ifp
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
736 RFC 4601: 4.3.1. Sending Hello Messages
738 To allow new or rebooting routers to learn of PIM neighbors quickly,
739 when a Hello message is received from a new neighbor, or a Hello
740 message with a new GenID is received from an existing neighbor, a
741 new Hello message should be sent on this interface after a
742 randomized delay between 0 and Triggered_Hello_Delay.
744 void pim_hello_restart_triggered(struct interface
*ifp
)
746 struct pim_interface
*pim_ifp
;
747 int triggered_hello_delay_msec
;
755 * There exists situations where we have the a RPF out this
756 * interface, but we haven't formed a neighbor yet. This
757 * happens especially during interface flaps. While
758 * we would like to handle this more gracefully in other
759 * parts of the code. In order to get us up and running
760 * let's just send the hello immediate'ish
761 * This should be revisited when we get nexthop tracking
762 * in and when we have a better handle on safely
763 * handling the rpf information for upstreams that
764 * we cannot legally reach yet.
766 triggered_hello_delay_msec
= 1;
767 //triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
769 if (pim_ifp
->t_pim_hello_timer
) {
770 long remain_msec
= pim_time_timer_remain_msec(pim_ifp
->t_pim_hello_timer
);
771 if (remain_msec
<= triggered_hello_delay_msec
) {
772 /* Rescheduling hello would increase the delay, then it's faster
773 to just wait for the scheduled periodic hello. */
777 THREAD_OFF(pim_ifp
->t_pim_hello_timer
);
778 pim_ifp
->t_pim_hello_timer
= NULL
;
781 random_msec
= triggered_hello_delay_msec
;
782 //random_msec = random() % (triggered_hello_delay_msec + 1);
784 if (PIM_DEBUG_PIM_HELLO
) {
785 zlog_debug("Scheduling %d msec triggered hello on interface %s",
786 random_msec
, ifp
->name
);
789 THREAD_TIMER_MSEC_ON(master
, pim_ifp
->t_pim_hello_timer
,
794 int pim_sock_add(struct interface
*ifp
)
796 struct pim_interface
*pim_ifp
;
797 struct in_addr ifaddr
;
803 if (pim_ifp
->pim_sock_fd
>= 0) {
804 if (PIM_DEBUG_PIM_PACKETS
)
805 zlog_debug("Can't recreate existing PIM socket fd=%d for interface %s",
806 pim_ifp
->pim_sock_fd
, ifp
->name
);
810 ifaddr
= pim_ifp
->primary_address
;
812 pim_ifp
->pim_sock_fd
= pim_sock_open(ifaddr
, ifp
->ifindex
);
813 if (pim_ifp
->pim_sock_fd
< 0) {
814 if (PIM_DEBUG_PIM_PACKETS
)
815 zlog_debug("Could not open PIM socket on interface %s",
820 pim_socket_ip_hdr (pim_ifp
->pim_sock_fd
);
822 pim_ifp
->t_pim_sock_read
= NULL
;
823 pim_ifp
->pim_sock_creation
= pim_time_monotonic_sec();
826 * Just ensure that the new generation id
827 * actually chooses something different.
828 * Actually ran across a case where this
829 * happened, pre-switch to random().
830 * While this is unlikely to happen now
831 * let's make sure it doesn't.
833 old_genid
= pim_ifp
->pim_generation_id
;
835 while (old_genid
== pim_ifp
->pim_generation_id
)
836 pim_ifp
->pim_generation_id
= random();
838 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
839 ifp
->name
, ifp
->ifindex
);
842 * Start receiving PIM messages
844 pim_sock_read_on(ifp
);
847 * Start sending PIM hello's
849 pim_hello_restart_triggered(ifp
);