]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_pim.c
pimd: Add debug messages as to why a register packet is rejected.
[mirror_frr.git] / pimd / pim_pim.c
CommitLineData
12e41d03
DL
1/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
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.
9
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.
14
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,
18 MA 02110-1301 USA
19
12e41d03
DL
20*/
21
22#include <zebra.h>
23
24#include "log.h"
25#include "thread.h"
26#include "memory.h"
744d91b3 27#include "if.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_pim.h"
31#include "pim_time.h"
32#include "pim_iface.h"
33#include "pim_sock.h"
34#include "pim_str.h"
35#include "pim_util.h"
36#include "pim_tlv.h"
37#include "pim_neighbor.h"
38#include "pim_hello.h"
39#include "pim_join.h"
40#include "pim_assert.h"
41#include "pim_msg.h"
77e390e5 42#include "pim_register.h"
12e41d03
DL
43
44static int on_pim_hello_send(struct thread *t);
45static int pim_hello_send(struct interface *ifp,
46 uint16_t holdtime);
47
7643f0a1
DS
48static
49const char *pim_pim_msgtype2str (enum pim_msg_type type)
50{
51 switch (type)
52 {
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";
7f0c1c5f 56 case PIM_MSG_TYPE_JOIN_PRUNE: return "JOINPRUNE";
7643f0a1
DS
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";
62 }
63
64 return "UNKNOWN";
65}
66
12e41d03
DL
67static void sock_close(struct interface *ifp)
68{
69 struct pim_interface *pim_ifp = ifp->info;
70
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",
74 pim_ifp->pim_sock_fd,
75 ifp->name);
76 }
77 }
78 THREAD_OFF(pim_ifp->t_pim_sock_read);
79
80 if (PIM_DEBUG_PIM_TRACE) {
81 if (pim_ifp->t_pim_hello_timer) {
82 zlog_debug("Cancelling PIM hello timer for interface %s",
83 ifp->name);
84 }
85 }
86 THREAD_OFF(pim_ifp->t_pim_hello_timer);
87
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);
91 }
92
6abb1fc2
DS
93 /*
94 * If the fd is already deleted no need to do anything here
95 */
96 if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) {
12e41d03
DL
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));
100 }
101
102 pim_ifp->pim_sock_fd = -1;
103 pim_ifp->pim_sock_creation = 0;
12e41d03
DL
104}
105
106void pim_sock_delete(struct interface *ifp, const char *delete_message)
107{
108 zlog_info("PIM INTERFACE DOWN: on interface %s: %s",
109 ifp->name, delete_message);
110
111 if (!ifp->info) {
112 zlog_err("%s: %s: but PIM not enabled on interface %s (!)",
113 __PRETTY_FUNCTION__, delete_message, ifp->name);
114 return;
115 }
116
117 /*
118 RFC 4601: 4.3.1. Sending Hello Messages
119
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).
123 */
124 pim_hello_send(ifp, 0 /* zero-sec holdtime */);
125
126 pim_neighbor_delete_all(ifp, delete_message);
127
128 sock_close(ifp);
129}
130
131int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
132{
133 struct ip *ip_hdr;
134 size_t ip_hlen; /* ip header length in bytes */
135 char src_str[100];
136 char dst_str[100];
137 uint8_t *pim_msg;
138 int pim_msg_len;
139 uint8_t pim_version;
7643f0a1 140 enum pim_msg_type pim_type;
12e41d03
DL
141 uint16_t pim_checksum; /* received checksum */
142 uint16_t checksum; /* computed checksum */
143 struct pim_neighbor *neigh;
144
145 if (!ifp->info) {
146 zlog_warn("%s: PIM not enabled on interface %s",
147 __PRETTY_FUNCTION__, ifp->name);
148 return -1;
149 }
150
151 if (len < sizeof(*ip_hdr)) {
152 zlog_warn("PIM packet size=%zu shorter than minimum=%zu",
153 len, sizeof(*ip_hdr));
154 return -1;
155 }
156
157 ip_hdr = (struct ip *) buf;
158
159 pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
160 pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str, sizeof(dst_str));
161
162 ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
163
164 if (PIM_DEBUG_PIM_PACKETS) {
165 zlog_debug("Recv IP packet from %s to %s on %s: size=%zu ip_header_size=%zu ip_proto=%d",
166 src_str, dst_str, ifp->name, len, ip_hlen, ip_hdr->ip_p);
167 }
168
169 if (ip_hdr->ip_p != PIM_IP_PROTO_PIM) {
170 zlog_warn("IP packet protocol=%d is not PIM=%d",
171 ip_hdr->ip_p, PIM_IP_PROTO_PIM);
172 return -1;
173 }
174
175 if (ip_hlen < PIM_IP_HEADER_MIN_LEN) {
176 zlog_warn("IP packet header size=%zu shorter than minimum=%d",
177 ip_hlen, PIM_IP_HEADER_MIN_LEN);
178 return -1;
179 }
180 if (ip_hlen > PIM_IP_HEADER_MAX_LEN) {
181 zlog_warn("IP packet header size=%zu greater than maximum=%d",
182 ip_hlen, PIM_IP_HEADER_MAX_LEN);
183 return -1;
184 }
185
186 pim_msg = buf + ip_hlen;
187 pim_msg_len = len - ip_hlen;
188
189 if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
190 pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len);
191 }
192
193 if (pim_msg_len < PIM_PIM_MIN_LEN) {
194 zlog_warn("PIM message size=%d shorter than minimum=%d",
195 pim_msg_len, PIM_PIM_MIN_LEN);
196 return -1;
197 }
198
199 pim_version = PIM_MSG_HDR_GET_VERSION(pim_msg);
200 pim_type = PIM_MSG_HDR_GET_TYPE(pim_msg);
201
202 if (pim_version != PIM_PROTO_VERSION) {
203 zlog_warn("Ignoring PIM pkt from %s with unsupported version: %d",
204 ifp->name, pim_version);
205 return -1;
206 }
207
208 /* save received checksum */
209 pim_checksum = PIM_MSG_HDR_GET_CHECKSUM(pim_msg);
210
211 /* for computing checksum */
212 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg) = 0;
213
214 checksum = in_cksum(pim_msg, pim_msg_len);
215 if (checksum != pim_checksum) {
216 zlog_warn("Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
217 ifp->name, pim_checksum, checksum);
218 return -1;
219 }
220
221 if (PIM_DEBUG_PIM_PACKETS) {
7643f0a1
DS
222 zlog_debug("Recv PIM %s packet from %s to %s on %s: ttl=%d pim_version=%d pim_msg_size=%d checksum=%x",
223 pim_pim_msgtype2str (pim_type), src_str, dst_str, ifp->name,
224 ip_hdr->ip_ttl, pim_version, pim_msg_len, checksum);
12e41d03
DL
225 }
226
4dffc880 227 switch (pim_type)
566b83cf 228 {
4dffc880
DS
229 case PIM_MSG_TYPE_HELLO:
230 return pim_hello_recv (ifp,
231 ip_hdr->ip_src,
232 pim_msg + PIM_MSG_HEADER_LEN,
233 pim_msg_len - PIM_MSG_HEADER_LEN);
234 break;
235 case PIM_MSG_TYPE_REGISTER:
236 return pim_register_recv (ifp,
237 ip_hdr->ip_dst,
238 ip_hdr->ip_src,
239 pim_msg + PIM_MSG_HEADER_LEN,
240 pim_msg_len - PIM_MSG_HEADER_LEN);
241 break;
242 case PIM_MSG_TYPE_REG_STOP:
56638739
DS
243 return pim_register_stop_recv (pim_msg + PIM_MSG_HEADER_LEN,
244 pim_msg_len - PIM_MSG_HEADER_LEN);
4dffc880
DS
245 break;
246 case PIM_MSG_TYPE_JOIN_PRUNE:
247 neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
248 if (!neigh) {
249 zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
250 __FILE__, __PRETTY_FUNCTION__,
251 pim_type, src_str, ifp->name);
252 return -1;
253 }
254 return pim_joinprune_recv(ifp, neigh,
255 ip_hdr->ip_src,
256 pim_msg + PIM_MSG_HEADER_LEN,
257 pim_msg_len - PIM_MSG_HEADER_LEN);
258 break;
259 case PIM_MSG_TYPE_ASSERT:
260 neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
261 if (!neigh) {
262 zlog_warn("%s %s: non-hello PIM message type=%d from non-neighbor %s on %s",
263 __FILE__, __PRETTY_FUNCTION__,
264 pim_type, src_str, ifp->name);
265 return -1;
266 }
267 return pim_assert_recv(ifp, neigh,
268 ip_hdr->ip_src,
269 pim_msg + PIM_MSG_HEADER_LEN,
270 pim_msg_len - PIM_MSG_HEADER_LEN);
271 break;
272 default:
566b83cf
DS
273 if (PIM_DEBUG_PIM_PACKETS) {
274 zlog_debug("Recv PIM packet type %d which is not currently understood",
275 pim_type);
276 }
277 return -1;
278 }
12e41d03
DL
279 return -1;
280}
281
282static void pim_sock_read_on(struct interface *ifp);
283
284static int pim_sock_read(struct thread *t)
285{
286 struct interface *ifp;
287 struct pim_interface *pim_ifp;
288 int fd;
289 struct sockaddr_in from;
290 struct sockaddr_in to;
291 socklen_t fromlen = sizeof(from);
292 socklen_t tolen = sizeof(to);
293 uint8_t buf[PIM_PIM_BUFSIZE_READ];
294 int len;
b892f1dd 295 ifindex_t ifindex = -1;
12e41d03
DL
296 int result = -1; /* defaults to bad */
297
298 zassert(t);
299
300 ifp = THREAD_ARG(t);
301 zassert(ifp);
302
303 fd = THREAD_FD(t);
304
305 pim_ifp = ifp->info;
306 zassert(pim_ifp);
307
308 zassert(fd == pim_ifp->pim_sock_fd);
309
310 len = pim_socket_recvfromto(fd, buf, sizeof(buf),
311 &from, &fromlen,
312 &to, &tolen,
313 &ifindex);
314 if (len < 0) {
315 zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s",
316 fd, errno, safe_strerror(errno));
317 goto done;
318 }
319
320 if (PIM_DEBUG_PIM_PACKETS) {
321 char from_str[100];
322 char to_str[100];
323
324 if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str)))
325 sprintf(from_str, "<from?>");
326 if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str)))
327 sprintf(to_str, "<to?>");
328
329 zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)",
330 len, from_str, to_str, fd, ifindex, ifp->ifindex);
331 }
332
333 if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
334 pim_pkt_dump(__PRETTY_FUNCTION__, buf, len);
335 }
336
337#ifdef PIM_CHECK_RECV_IFINDEX_SANITY
338 /* ifindex sanity check */
339 if (ifindex != (int) ifp->ifindex) {
340 char from_str[100];
341 char to_str[100];
342 struct interface *recv_ifp;
343
344 if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str)))
345 sprintf(from_str, "<from?>");
346 if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str)))
347 sprintf(to_str, "<to?>");
348
349 recv_ifp = if_lookup_by_index(ifindex);
350 if (recv_ifp) {
351 zassert(ifindex == (int) recv_ifp->ifindex);
352 }
353
354#ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH
355 zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)",
356 from_str, to_str, fd,
357 ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>",
358 ifp->ifindex, ifp->name);
359#endif
360 goto done;
361 }
362#endif
363
364 int fail = pim_pim_packet(ifp, buf, len);
365 if (fail) {
a22e470b
DS
366 if (PIM_DEBUG_PIM_PACKETS)
367 zlog_debug("%s: pim_pim_packet() return=%d",
368 __PRETTY_FUNCTION__, fail);
12e41d03
DL
369 goto done;
370 }
371
372 result = 0; /* good */
373
374 done:
375 pim_sock_read_on(ifp);
376
377 if (result) {
378 ++pim_ifp->pim_ifstat_hello_recvfail;
379 }
380
381 return result;
382}
383
384static void pim_sock_read_on(struct interface *ifp)
385{
386 struct pim_interface *pim_ifp;
387
388 zassert(ifp);
389 zassert(ifp->info);
390
391 pim_ifp = ifp->info;
392
3010e99a 393 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
12e41d03
DL
394 zlog_debug("Scheduling READ event on PIM socket fd=%d",
395 pim_ifp->pim_sock_fd);
396 }
59ba0ac3 397 pim_ifp->t_pim_sock_read = NULL;
12e41d03
DL
398 zassert(!pim_ifp->t_pim_sock_read);
399 THREAD_READ_ON(master, pim_ifp->t_pim_sock_read, pim_sock_read, ifp,
400 pim_ifp->pim_sock_fd);
401}
402
b892f1dd 403static int pim_sock_open(struct in_addr ifaddr, ifindex_t ifindex)
12e41d03
DL
404{
405 int fd;
406
61ea3951 407 fd = pim_socket_mcast(IPPROTO_PIM, ifaddr, ifindex, 0 /* loop=false */);
12e41d03
DL
408 if (fd < 0)
409 return -1;
410
411 if (pim_socket_join(fd, qpim_all_pim_routers_addr, ifaddr, ifindex)) {
2cd32c61 412 close(fd);
12e41d03
DL
413 return -2;
414 }
415
416 return fd;
417}
418
419void pim_ifstat_reset(struct interface *ifp)
420{
421 struct pim_interface *pim_ifp;
422
423 zassert(ifp);
424
425 pim_ifp = ifp->info;
426 if (!pim_ifp) {
427 return;
428 }
429
430 pim_ifp->pim_ifstat_start = pim_time_monotonic_sec();
431 pim_ifp->pim_ifstat_hello_sent = 0;
432 pim_ifp->pim_ifstat_hello_sendfail = 0;
433 pim_ifp->pim_ifstat_hello_recv = 0;
434 pim_ifp->pim_ifstat_hello_recvfail = 0;
435}
436
437void pim_sock_reset(struct interface *ifp)
438{
439 struct pim_interface *pim_ifp;
440
441 zassert(ifp);
442 zassert(ifp->info);
443
444 pim_ifp = ifp->info;
445
446 pim_ifp->primary_address = pim_find_primary_addr(ifp);
447
448 pim_ifp->pim_sock_fd = -1;
449 pim_ifp->pim_sock_creation = 0;
59ba0ac3 450 pim_ifp->t_pim_sock_read = NULL;
12e41d03 451
59ba0ac3 452 pim_ifp->t_pim_hello_timer = NULL;
12e41d03
DL
453 pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
454 pim_ifp->pim_default_holdtime = -1; /* unset: means 3.5 * pim_hello_period */
455 pim_ifp->pim_triggered_hello_delay = PIM_DEFAULT_TRIGGERED_HELLO_DELAY;
456 pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
457 pim_ifp->pim_propagation_delay_msec = PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
458 pim_ifp->pim_override_interval_msec = 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);
461 }
462 else {
463 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
464 }
465
466 /* neighbors without lan_delay */
467 pim_ifp->pim_number_of_nonlandelay_neighbors = 0;
468 pim_ifp->pim_neighbors_highest_propagation_delay_msec = 0;
469 pim_ifp->pim_neighbors_highest_override_interval_msec = 0;
470
471 /* DR Election */
472 pim_ifp->pim_dr_election_last = 0; /* timestamp */
473 pim_ifp->pim_dr_election_count = 0;
474 pim_ifp->pim_dr_election_changes = 0;
475 pim_ifp->pim_dr_num_nondrpri_neighbors = 0; /* neighbors without dr_pri */
476 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
477
478 pim_ifstat_reset(ifp);
479}
480
4df01a4e
DS
481static uint16_t ip_id = 0;
482
c305ed63
DS
483
484static int
485pim_msg_send_frame (int fd, char *buf, size_t len,
486 struct sockaddr *dst, size_t salen)
487{
488 struct ip *ip = (struct ip *)buf;
489
490 while (sendto (fd, buf, len, MSG_DONTWAIT, dst, salen) < 0)
491 {
492 char dst_str[100];
493
494 switch (errno)
495 {
496 case EMSGSIZE:
497 {
498 size_t hdrsize = sizeof (struct ip);
499 size_t newlen1 = ((len - hdrsize) / 2 ) & 0xFFF8;
500 size_t sendlen = newlen1 + hdrsize;
501 size_t offset = ntohs (ip->ip_off);
502
503 ip->ip_len = htons (sendlen);
504 ip->ip_off = htons (offset | IP_MF);
505 if (pim_msg_send_frame (fd, buf, sendlen, dst, salen) == 0)
506 {
507 struct ip *ip2 = (struct ip *)(buf + newlen1);
508 size_t newlen2 = len - sendlen;
509 sendlen = newlen2 + hdrsize;
510
511 memcpy (ip2, ip, hdrsize);
512 ip2->ip_len = htons (sendlen);
513 ip2->ip_off = htons (offset + (newlen1 >> 3));
514 return pim_msg_send_frame (fd, (char *)ip2, sendlen, dst, salen);
515 }
516 }
517
518 return -1;
519 break;
520 default:
521 pim_inet4_dump ("<dst?>", ip->ip_dst, dst_str, sizeof (dst_str));
522 zlog_warn ("%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
523 __PRETTY_FUNCTION__,
524 dst_str, fd, len,
525 errno, safe_strerror(errno));
c305ed63 526 return -1;
29444f8f 527 break;
c305ed63
DS
528 }
529 }
530
531 return 0;
532}
533
534int
535pim_msg_send(int fd, struct in_addr src,
536 struct in_addr dst, uint8_t *pim_msg,
537 int pim_msg_size, const char *ifname)
12e41d03 538{
12e41d03
DL
539 struct sockaddr_in to;
540 socklen_t tolen;
4df01a4e
DS
541 unsigned char buffer[3000];
542 unsigned char *msg_start;
543 struct ip *ip;
544
545 memset (buffer, 0, 3000);
546 int sendlen = sizeof (struct ip) + pim_msg_size;
547
548 msg_start = buffer + sizeof (struct ip);
549 memcpy (msg_start, pim_msg, pim_msg_size);
550
551 ip = (struct ip *)buffer;
552 ip->ip_id = htons (++ip_id);
553 ip->ip_hl = 5;
554 ip->ip_v = 4;
555 ip->ip_p = PIM_IP_PROTO_PIM;
556 ip->ip_src = src;
557 ip->ip_dst = dst;
558 ip->ip_ttl = MAXTTL;
559 ip->ip_len = htons (sendlen);
12e41d03
DL
560
561 if (PIM_DEBUG_PIM_PACKETS) {
562 char dst_str[100];
563 pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
564 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
565 __PRETTY_FUNCTION__,
566 dst_str, ifname, pim_msg_size,
567 *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
568 }
569
12e41d03 570 memset(&to, 0, sizeof(to));
12e41d03
DL
571 to.sin_family = AF_INET;
572 to.sin_addr = dst;
12e41d03
DL
573 tolen = sizeof(to);
574
575 if (PIM_DEBUG_PIM_PACKETDUMP_SEND) {
576 pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size);
577 }
578
c305ed63
DS
579 pim_msg_send_frame (fd, (char *)buffer, sendlen,
580 (struct sockaddr *)&to, tolen);
12e41d03
DL
581 return 0;
582}
583
584static int hello_send(struct interface *ifp,
585 uint16_t holdtime)
586{
587 uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE];
588 struct pim_interface *pim_ifp;
589 int pim_tlv_size;
590 int pim_msg_size;
591
592 pim_ifp = ifp->info;
593
aea6cb94 594 if (PIM_DEBUG_PIM_HELLO) {
12e41d03
DL
595 char dst_str[100];
596 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str));
597 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",
598 __PRETTY_FUNCTION__,
599 dst_str, ifp->name,
600 holdtime,
601 pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec,
602 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
603 pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
604 listcount(ifp->connected));
605 }
606
607 pim_tlv_size = pim_hello_build_tlv(ifp->name,
608 pim_msg + PIM_PIM_MIN_LEN,
609 sizeof(pim_msg) - PIM_PIM_MIN_LEN,
610 holdtime,
611 pim_ifp->pim_dr_priority,
612 pim_ifp->pim_generation_id,
613 pim_ifp->pim_propagation_delay_msec,
614 pim_ifp->pim_override_interval_msec,
615 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
616 ifp->connected);
617 if (pim_tlv_size < 0) {
618 return -1;
619 }
620
621 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
622
623 zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
624 zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
625
626 pim_msg_build_header(pim_msg, pim_msg_size,
627 PIM_MSG_TYPE_HELLO);
628
629 if (pim_msg_send(pim_ifp->pim_sock_fd,
4df01a4e 630 pim_ifp->primary_address,
12e41d03
DL
631 qpim_all_pim_routers_addr,
632 pim_msg,
633 pim_msg_size,
634 ifp->name)) {
aea6cb94
DS
635 if (PIM_DEBUG_PIM_HELLO) {
636 zlog_debug("%s: could not send PIM message on interface %s",
637 __PRETTY_FUNCTION__, ifp->name);
638 }
12e41d03
DL
639 return -2;
640 }
641
642 return 0;
643}
644
645static int pim_hello_send(struct interface *ifp,
646 uint16_t holdtime)
647{
648 struct pim_interface *pim_ifp;
649
650 zassert(ifp);
651 pim_ifp = ifp->info;
652 zassert(pim_ifp);
653
85b62aea
DS
654 if (if_is_loopback (ifp))
655 return 0;
656
12e41d03
DL
657 if (hello_send(ifp, holdtime)) {
658 ++pim_ifp->pim_ifstat_hello_sendfail;
659
aea6cb94
DS
660 if (PIM_DEBUG_PIM_HELLO) {
661 zlog_warn("Could not send PIM hello on interface %s",
662 ifp->name);
663 }
12e41d03
DL
664 return -1;
665 }
666
667 ++pim_ifp->pim_ifstat_hello_sent;
668
669 return 0;
670}
671
672static void hello_resched(struct interface *ifp)
673{
674 struct pim_interface *pim_ifp;
675
676 zassert(ifp);
677 pim_ifp = ifp->info;
678 zassert(pim_ifp);
679
aea6cb94 680 if (PIM_DEBUG_PIM_HELLO) {
12e41d03
DL
681 zlog_debug("Rescheduling %d sec hello on interface %s",
682 pim_ifp->pim_hello_period, ifp->name);
683 }
684 THREAD_OFF(pim_ifp->t_pim_hello_timer);
685 THREAD_TIMER_ON(master, pim_ifp->t_pim_hello_timer,
686 on_pim_hello_send,
687 ifp, pim_ifp->pim_hello_period);
688}
689
690/*
691 Periodic hello timer
692 */
693static int on_pim_hello_send(struct thread *t)
694{
695 struct pim_interface *pim_ifp;
696 struct interface *ifp;
697
698 zassert(t);
699 ifp = THREAD_ARG(t);
700 zassert(ifp);
701
702 pim_ifp = ifp->info;
703
704 /*
705 * Schedule next hello
706 */
59ba0ac3 707 pim_ifp->t_pim_hello_timer = NULL;
12e41d03
DL
708 hello_resched(ifp);
709
710 /*
711 * Send hello
712 */
713 return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
714}
715
716/*
717 RFC 4601: 4.3.1. Sending Hello Messages
718
719 Thus, if a router needs to send a Join/Prune or Assert message on an
720 interface on which it has not yet sent a Hello message with the
721 currently configured IP address, then it MUST immediately send the
722 relevant Hello message without waiting for the Hello Timer to
723 expire, followed by the Join/Prune or Assert message.
724 */
725void pim_hello_restart_now(struct interface *ifp)
726{
727 struct pim_interface *pim_ifp;
728
729 zassert(ifp);
730 pim_ifp = ifp->info;
731 zassert(pim_ifp);
732
733 /*
734 * Reset next hello timer
735 */
736 hello_resched(ifp);
737
738 /*
739 * Immediately send hello
740 */
741 pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
742}
743
744/*
745 RFC 4601: 4.3.1. Sending Hello Messages
746
747 To allow new or rebooting routers to learn of PIM neighbors quickly,
748 when a Hello message is received from a new neighbor, or a Hello
749 message with a new GenID is received from an existing neighbor, a
750 new Hello message should be sent on this interface after a
751 randomized delay between 0 and Triggered_Hello_Delay.
752 */
753void pim_hello_restart_triggered(struct interface *ifp)
754{
755 struct pim_interface *pim_ifp;
756 int triggered_hello_delay_msec;
757 int random_msec;
758
759 zassert(ifp);
760 pim_ifp = ifp->info;
761 zassert(pim_ifp);
762
763 triggered_hello_delay_msec = 1000 * pim_ifp->pim_triggered_hello_delay;
764
765 if (pim_ifp->t_pim_hello_timer) {
766 long remain_msec = pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer);
767 if (remain_msec <= triggered_hello_delay_msec) {
768 /* Rescheduling hello would increase the delay, then it's faster
769 to just wait for the scheduled periodic hello. */
770 return;
771 }
772
773 THREAD_OFF(pim_ifp->t_pim_hello_timer);
59ba0ac3 774 pim_ifp->t_pim_hello_timer = NULL;
12e41d03 775 }
12e41d03 776
60b40924 777 random_msec = random() % (triggered_hello_delay_msec + 1);
12e41d03 778
aea6cb94 779 if (PIM_DEBUG_PIM_HELLO) {
12e41d03
DL
780 zlog_debug("Scheduling %d msec triggered hello on interface %s",
781 random_msec, ifp->name);
782 }
783
784 THREAD_TIMER_MSEC_ON(master, pim_ifp->t_pim_hello_timer,
785 on_pim_hello_send,
786 ifp, random_msec);
787}
788
789int pim_sock_add(struct interface *ifp)
790{
791 struct pim_interface *pim_ifp;
792 struct in_addr ifaddr;
c29c0f61 793 uint32_t old_genid;
12e41d03
DL
794
795 pim_ifp = ifp->info;
796 zassert(pim_ifp);
797
798 if (pim_ifp->pim_sock_fd >= 0) {
799 zlog_warn("Can't recreate existing PIM socket fd=%d for interface %s",
800 pim_ifp->pim_sock_fd, ifp->name);
801 return -1;
802 }
803
804 ifaddr = pim_ifp->primary_address;
805
806 pim_ifp->pim_sock_fd = pim_sock_open(ifaddr, ifp->ifindex);
807 if (pim_ifp->pim_sock_fd < 0) {
808 zlog_warn("Could not open PIM socket on interface %s",
809 ifp->name);
810 return -2;
811 }
812
4df01a4e
DS
813 pim_socket_ip_hdr (pim_ifp->pim_sock_fd);
814
59ba0ac3 815 pim_ifp->t_pim_sock_read = NULL;
12e41d03
DL
816 pim_ifp->pim_sock_creation = pim_time_monotonic_sec();
817
c29c0f61
DS
818 /*
819 * Just ensure that the new generation id
820 * actually chooses something different.
821 * Actually ran across a case where this
822 * happened, pre-switch to random().
823 * While this is unlikely to happen now
824 * let's make sure it doesn't.
825 */
826 old_genid = pim_ifp->pim_generation_id;
827
828 while (old_genid == pim_ifp->pim_generation_id)
829 pim_ifp->pim_generation_id = random();
12e41d03
DL
830
831 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d",
832 ifp->name, ifp->ifindex);
833
834 /*
835 * Start receiving PIM messages
836 */
837 pim_sock_read_on(ifp);
838
839 /*
840 * Start sending PIM hello's
841 */
842 pim_hello_restart_triggered(ifp);
843
844 return 0;
845}