]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_pim.c
b367aa21f4f5bf26a75e3945f4ae8ac9323165c9
[mirror_frr.git] / pimd / pim_pim.c
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 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
18 */
19
20 #include <zebra.h>
21
22 #include "log.h"
23 #include "thread.h"
24 #include "memory.h"
25 #include "if.h"
26
27 #include "pimd.h"
28 #include "pim_pim.h"
29 #include "pim_time.h"
30 #include "pim_iface.h"
31 #include "pim_sock.h"
32 #include "pim_str.h"
33 #include "pim_util.h"
34 #include "pim_tlv.h"
35 #include "pim_neighbor.h"
36 #include "pim_hello.h"
37 #include "pim_join.h"
38 #include "pim_assert.h"
39 #include "pim_msg.h"
40 #include "pim_register.h"
41 #include "pim_errors.h"
42 #include "pim_bsm.h"
43
44 static int on_pim_hello_send(struct thread *t);
45 static int pim_hello_send(struct interface *ifp, uint16_t holdtime);
46
47 static const char *pim_pim_msgtype2str(enum pim_msg_type type)
48 {
49 switch (type) {
50 case PIM_MSG_TYPE_HELLO:
51 return "HELLO";
52 case PIM_MSG_TYPE_REGISTER:
53 return "REGISTER";
54 case PIM_MSG_TYPE_REG_STOP:
55 return "REGSTOP";
56 case PIM_MSG_TYPE_JOIN_PRUNE:
57 return "JOINPRUNE";
58 case PIM_MSG_TYPE_BOOTSTRAP:
59 return "BOOT";
60 case PIM_MSG_TYPE_ASSERT:
61 return "ASSERT";
62 case PIM_MSG_TYPE_GRAFT:
63 return "GRAFT";
64 case PIM_MSG_TYPE_GRAFT_ACK:
65 return "GACK";
66 case PIM_MSG_TYPE_CANDIDATE:
67 return "CANDIDATE";
68 }
69
70 return "UNKNOWN";
71 }
72
73 static void sock_close(struct interface *ifp)
74 {
75 struct pim_interface *pim_ifp = ifp->info;
76
77 if (PIM_DEBUG_PIM_TRACE) {
78 if (pim_ifp->t_pim_sock_read) {
79 zlog_debug(
80 "Cancelling READ event for PIM socket fd=%d on interface %s",
81 pim_ifp->pim_sock_fd, ifp->name);
82 }
83 }
84 THREAD_OFF(pim_ifp->t_pim_sock_read);
85
86 if (PIM_DEBUG_PIM_TRACE) {
87 if (pim_ifp->t_pim_hello_timer) {
88 zlog_debug(
89 "Cancelling PIM hello timer for interface %s",
90 ifp->name);
91 }
92 }
93 THREAD_OFF(pim_ifp->t_pim_hello_timer);
94
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);
98 }
99
100 /*
101 * If the fd is already deleted no need to do anything here
102 */
103 if (pim_ifp->pim_sock_fd > 0 && close(pim_ifp->pim_sock_fd)) {
104 zlog_warn(
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));
108 }
109
110 pim_ifp->pim_sock_fd = -1;
111 pim_ifp->pim_sock_creation = 0;
112 }
113
114 void pim_sock_delete(struct interface *ifp, const char *delete_message)
115 {
116 zlog_info("PIM INTERFACE DOWN: on interface %s: %s", ifp->name,
117 delete_message);
118
119 if (!ifp->info) {
120 flog_err(EC_PIM_CONFIG,
121 "%s: %s: but PIM not enabled on interface %s (!)",
122 __PRETTY_FUNCTION__, delete_message, ifp->name);
123 return;
124 }
125
126 /*
127 RFC 4601: 4.3.1. Sending Hello Messages
128
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).
132 */
133 pim_hello_send(ifp, 0 /* zero-sec holdtime */);
134
135 pim_neighbor_delete_all(ifp, delete_message);
136
137 sock_close(ifp);
138 }
139
140 int pim_pim_packet(struct interface *ifp, uint8_t *buf, size_t len)
141 {
142 struct ip *ip_hdr;
143 size_t ip_hlen; /* ip header length in bytes */
144 char src_str[INET_ADDRSTRLEN];
145 char dst_str[INET_ADDRSTRLEN];
146 uint8_t *pim_msg;
147 int pim_msg_len;
148 uint16_t pim_checksum; /* received checksum */
149 uint16_t checksum; /* computed checksum */
150 struct pim_neighbor *neigh;
151 struct pim_msg_header *header;
152 bool no_fwd;
153
154 if (len < sizeof(*ip_hdr)) {
155 if (PIM_DEBUG_PIM_PACKETS)
156 zlog_debug(
157 "PIM packet size=%zu shorter than minimum=%zu",
158 len, sizeof(*ip_hdr));
159 return -1;
160 }
161
162 ip_hdr = (struct ip *)buf;
163 ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
164
165 pim_msg = buf + ip_hlen;
166 pim_msg_len = len - ip_hlen;
167
168 header = (struct pim_msg_header *)pim_msg;
169 if (pim_msg_len < PIM_PIM_MIN_LEN) {
170 if (PIM_DEBUG_PIM_PACKETS)
171 zlog_debug(
172 "PIM message size=%d shorter than minimum=%d",
173 pim_msg_len, PIM_PIM_MIN_LEN);
174 return -1;
175 }
176
177 if (header->ver != PIM_PROTO_VERSION) {
178 if (PIM_DEBUG_PIM_PACKETS)
179 zlog_debug(
180 "Ignoring PIM pkt from %s with unsupported version: %d",
181 ifp->name, header->ver);
182 return -1;
183 }
184
185 /* save received checksum */
186 pim_checksum = header->checksum;
187
188 /* for computing checksum */
189 header->checksum = 0;
190 no_fwd = header->Nbit;
191
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);
197 return -1;
198 }
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)
205 zlog_debug(
206 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
207 ifp->name, pim_checksum,
208 checksum);
209
210 return -1;
211 }
212 }
213 } else {
214 checksum = in_cksum(pim_msg, pim_msg_len);
215 if (checksum != pim_checksum) {
216 if (PIM_DEBUG_PIM_PACKETS)
217 zlog_debug(
218 "Ignoring PIM pkt from %s with invalid checksum: received=%x calculated=%x",
219 ifp->name, pim_checksum, checksum);
220
221 return -1;
222 }
223 }
224
225 if (PIM_DEBUG_PIM_PACKETS) {
226 pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str,
227 sizeof(src_str));
228 pim_inet4_dump("<dst?>", ip_hdr->ip_dst, dst_str,
229 sizeof(dst_str));
230 zlog_debug(
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,
234 checksum);
235 if (PIM_DEBUG_PIM_PACKETDUMP_RECV) {
236 pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_len);
237 }
238 }
239
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);
245 break;
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);
250 break;
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);
254 break;
255 case PIM_MSG_TYPE_JOIN_PRUNE:
256 neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
257 if (!neigh) {
258 if (PIM_DEBUG_PIM_PACKETS)
259 zlog_debug(
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);
263 return -1;
264 }
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);
269 break;
270 case PIM_MSG_TYPE_ASSERT:
271 neigh = pim_neighbor_find(ifp, ip_hdr->ip_src);
272 if (!neigh) {
273 if (PIM_DEBUG_PIM_PACKETS)
274 zlog_debug(
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);
278 return -1;
279 }
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);
284 break;
285 case PIM_MSG_TYPE_BOOTSTRAP:
286 return pim_bsm_process(ifp, ip_hdr, pim_msg, pim_msg_len,
287 no_fwd);
288 break;
289
290 default:
291 if (PIM_DEBUG_PIM_PACKETS) {
292 zlog_debug(
293 "Recv PIM packet type %d which is not currently understood",
294 header->type);
295 }
296 return -1;
297 }
298 return -1;
299 }
300
301 static void pim_sock_read_on(struct interface *ifp);
302
303 static int pim_sock_read(struct thread *t)
304 {
305 struct interface *ifp, *orig_ifp;
306 struct pim_interface *pim_ifp;
307 int fd;
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];
313 int len;
314 ifindex_t ifindex = -1;
315 int result = -1; /* defaults to bad */
316 static long long count = 0;
317 int cont = 1;
318
319 orig_ifp = ifp = THREAD_ARG(t);
320 fd = THREAD_FD(t);
321
322 pim_ifp = ifp->info;
323
324 while (cont) {
325 len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from,
326 &fromlen, &to, &tolen, &ifindex);
327 if (len < 0) {
328 if (errno == EINTR)
329 continue;
330 if (errno == EWOULDBLOCK || errno == EAGAIN)
331 break;
332
333 if (PIM_DEBUG_PIM_PACKETS)
334 zlog_debug("Received errno: %d %s", errno,
335 safe_strerror(errno));
336 goto done;
337 }
338
339 /*
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
344 */
345 ifp = if_lookup_by_index(ifindex, pim_ifp->pim->vrf_id);
346 if (!ifp || !ifp->info) {
347 if (PIM_DEBUG_PIM_PACKETS)
348 zlog_debug(
349 "%s: Received incoming pim packet on interface(%s:%d) not yet configured for pim",
350 __PRETTY_FUNCTION__,
351 ifp ? ifp->name : "Unknown", ifindex);
352 goto done;
353 }
354 int fail = pim_pim_packet(ifp, buf, len);
355 if (fail) {
356 if (PIM_DEBUG_PIM_PACKETS)
357 zlog_debug("%s: pim_pim_packet() return=%d",
358 __PRETTY_FUNCTION__, fail);
359 goto done;
360 }
361
362 count++;
363 if (count % router->packet_process == 0)
364 cont = 0;
365 }
366
367 result = 0; /* good */
368
369 done:
370 pim_sock_read_on(orig_ifp);
371
372 if (result) {
373 ++pim_ifp->pim_ifstat_hello_recvfail;
374 }
375
376 return result;
377 }
378
379 static void pim_sock_read_on(struct interface *ifp)
380 {
381 struct pim_interface *pim_ifp;
382
383 zassert(ifp);
384 zassert(ifp->info);
385
386 pim_ifp = ifp->info;
387
388 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
389 zlog_debug("Scheduling READ event on PIM socket fd=%d",
390 pim_ifp->pim_sock_fd);
391 }
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);
395 }
396
397 static int pim_sock_open(struct interface *ifp)
398 {
399 int fd;
400 struct pim_interface *pim_ifp = ifp->info;
401
402 fd = pim_socket_mcast(IPPROTO_PIM, pim_ifp->primary_address, ifp,
403 0 /* loop=false */);
404 if (fd < 0)
405 return -1;
406
407 if (pim_socket_join(fd, qpim_all_pim_routers_addr,
408 pim_ifp->primary_address, ifp->ifindex)) {
409 close(fd);
410 return -2;
411 }
412
413 return fd;
414 }
415
416 void pim_ifstat_reset(struct interface *ifp)
417 {
418 struct pim_interface *pim_ifp;
419
420 zassert(ifp);
421
422 pim_ifp = ifp->info;
423 if (!pim_ifp) {
424 return;
425 }
426
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;
432 }
433
434 void pim_sock_reset(struct interface *ifp)
435 {
436 struct pim_interface *pim_ifp;
437
438 zassert(ifp);
439 zassert(ifp->info);
440
441 pim_ifp = ifp->info;
442
443 pim_ifp->primary_address = pim_find_primary_addr(ifp);
444
445 pim_ifp->pim_sock_fd = -1;
446 pim_ifp->pim_sock_creation = 0;
447 pim_ifp->t_pim_sock_read = NULL;
448
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);
461 } else {
462 PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options);
463 }
464
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;
469
470 /* DR Election */
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;
477
478 pim_ifstat_reset(ifp);
479 }
480
481 static uint16_t ip_id = 0;
482
483
484 static int pim_msg_send_frame(int fd, char *buf, size_t len,
485 struct sockaddr *dst, size_t salen)
486 {
487 struct ip *ip = (struct ip *)buf;
488
489 while (sendto(fd, buf, len, MSG_DONTWAIT, dst, salen) < 0) {
490 char dst_str[INET_ADDRSTRLEN];
491
492 switch (errno) {
493 case EMSGSIZE: {
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);
498
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)
502 == 0) {
503 struct ip *ip2 = (struct ip *)(buf + newlen1);
504 size_t newlen2 = len - sendlen;
505 sendlen = newlen2 + hdrsize;
506
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);
512 }
513 }
514
515 return -1;
516 default:
517 if (PIM_DEBUG_PIM_PACKETS) {
518 pim_inet4_dump("<dst?>", ip->ip_dst, dst_str,
519 sizeof(dst_str));
520 zlog_warn(
521 "%s: sendto() failure to %s: fd=%d msg_size=%zd: errno=%d: %s",
522 __PRETTY_FUNCTION__, dst_str, fd, len,
523 errno, safe_strerror(errno));
524 }
525 return -1;
526 }
527 }
528
529 return 0;
530 }
531
532 int pim_msg_send(int fd, struct in_addr src, struct in_addr dst,
533 uint8_t *pim_msg, int pim_msg_size, const char *ifname)
534 {
535 struct sockaddr_in to;
536 socklen_t tolen;
537 unsigned char buffer[10000];
538 unsigned char *msg_start;
539 uint8_t ttl;
540 struct pim_msg_header *header;
541 struct ip *ip;
542
543 memset(buffer, 0, 10000);
544 int sendlen = sizeof(struct ip) + pim_msg_size;
545
546 msg_start = buffer + sizeof(struct ip);
547 memcpy(msg_start, pim_msg, pim_msg_size);
548
549 header = (struct pim_msg_header *)pim_msg;
550 /*
551 * Omnios apparently doesn't have a #define for IP default
552 * ttl that is the same as all other platforms.
553 */
554 #ifndef IPDEFTTL
555 #define IPDEFTTL 64
556 #endif
557 /* TTL for packets destine to ALL-PIM-ROUTERS is 1 */
558 switch (header->type) {
559 case PIM_MSG_TYPE_HELLO:
560 case PIM_MSG_TYPE_JOIN_PRUNE:
561 case PIM_MSG_TYPE_BOOTSTRAP:
562 case PIM_MSG_TYPE_ASSERT:
563 ttl = 1;
564 break;
565 case PIM_MSG_TYPE_REGISTER:
566 case PIM_MSG_TYPE_REG_STOP:
567 case PIM_MSG_TYPE_GRAFT:
568 case PIM_MSG_TYPE_GRAFT_ACK:
569 case PIM_MSG_TYPE_CANDIDATE:
570 ttl = IPDEFTTL;
571 break;
572 default:
573 ttl = MAXTTL;
574 break;
575 }
576
577 ip = (struct ip *)buffer;
578 ip->ip_id = htons(++ip_id);
579 ip->ip_hl = 5;
580 ip->ip_v = 4;
581 ip->ip_tos = IPTOS_PREC_INTERNETCONTROL;
582 ip->ip_p = PIM_IP_PROTO_PIM;
583 ip->ip_src = src;
584 ip->ip_dst = dst;
585 ip->ip_ttl = ttl;
586 ip->ip_len = htons(sendlen);
587
588 if (PIM_DEBUG_PIM_PACKETS) {
589 char dst_str[INET_ADDRSTRLEN];
590 pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
591 zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
592 __PRETTY_FUNCTION__, dst_str, ifname, pim_msg_size,
593 header->checksum);
594 }
595
596 memset(&to, 0, sizeof(to));
597 to.sin_family = AF_INET;
598 to.sin_addr = dst;
599 tolen = sizeof(to);
600
601 if (PIM_DEBUG_PIM_PACKETDUMP_SEND) {
602 pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size);
603 }
604
605 pim_msg_send_frame(fd, (char *)buffer, sendlen, (struct sockaddr *)&to,
606 tolen);
607 return 0;
608 }
609
610 static int hello_send(struct interface *ifp, uint16_t holdtime)
611 {
612 uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE];
613 struct pim_interface *pim_ifp;
614 int pim_tlv_size;
615 int pim_msg_size;
616
617 pim_ifp = ifp->info;
618
619 if (PIM_DEBUG_PIM_HELLO) {
620 char dst_str[INET_ADDRSTRLEN];
621 pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str,
622 sizeof(dst_str));
623 zlog_debug(
624 "%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",
625 __PRETTY_FUNCTION__, dst_str, ifp->name, holdtime,
626 pim_ifp->pim_propagation_delay_msec,
627 pim_ifp->pim_override_interval_msec,
628 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(
629 pim_ifp->options),
630 pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
631 listcount(ifp->connected));
632 }
633
634 pim_tlv_size = pim_hello_build_tlv(
635 ifp, pim_msg + PIM_PIM_MIN_LEN,
636 sizeof(pim_msg) - PIM_PIM_MIN_LEN, holdtime,
637 pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
638 pim_ifp->pim_propagation_delay_msec,
639 pim_ifp->pim_override_interval_msec,
640 PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options));
641 if (pim_tlv_size < 0) {
642 return -1;
643 }
644
645 pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
646
647 zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
648 zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
649
650 pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO, false);
651
652 if (pim_msg_send(pim_ifp->pim_sock_fd, pim_ifp->primary_address,
653 qpim_all_pim_routers_addr, pim_msg, pim_msg_size,
654 ifp->name)) {
655 if (PIM_DEBUG_PIM_HELLO) {
656 zlog_debug(
657 "%s: could not send PIM message on interface %s",
658 __PRETTY_FUNCTION__, ifp->name);
659 }
660 return -2;
661 }
662
663 return 0;
664 }
665
666 static int pim_hello_send(struct interface *ifp, uint16_t holdtime)
667 {
668 struct pim_interface *pim_ifp = ifp->info;
669
670 if (if_is_loopback_or_vrf(ifp))
671 return 0;
672
673 if (hello_send(ifp, holdtime)) {
674 ++pim_ifp->pim_ifstat_hello_sendfail;
675
676 if (PIM_DEBUG_PIM_HELLO) {
677 zlog_warn("Could not send PIM hello on interface %s",
678 ifp->name);
679 }
680 return -1;
681 }
682
683 ++pim_ifp->pim_ifstat_hello_sent;
684
685 return 0;
686 }
687
688 static void hello_resched(struct interface *ifp)
689 {
690 struct pim_interface *pim_ifp;
691
692 pim_ifp = ifp->info;
693
694 if (PIM_DEBUG_PIM_HELLO) {
695 zlog_debug("Rescheduling %d sec hello on interface %s",
696 pim_ifp->pim_hello_period, ifp->name);
697 }
698 THREAD_OFF(pim_ifp->t_pim_hello_timer);
699 thread_add_timer(router->master, on_pim_hello_send, ifp,
700 pim_ifp->pim_hello_period,
701 &pim_ifp->t_pim_hello_timer);
702 }
703
704 /*
705 Periodic hello timer
706 */
707 static int on_pim_hello_send(struct thread *t)
708 {
709 struct pim_interface *pim_ifp;
710 struct interface *ifp;
711
712 ifp = THREAD_ARG(t);
713 pim_ifp = ifp->info;
714
715 /*
716 * Schedule next hello
717 */
718 hello_resched(ifp);
719
720 /*
721 * Send hello
722 */
723 return pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
724 }
725
726 /*
727 RFC 4601: 4.3.1. Sending Hello Messages
728
729 Thus, if a router needs to send a Join/Prune or Assert message on an
730 interface on which it has not yet sent a Hello message with the
731 currently configured IP address, then it MUST immediately send the
732 relevant Hello message without waiting for the Hello Timer to
733 expire, followed by the Join/Prune or Assert message.
734 */
735 void pim_hello_restart_now(struct interface *ifp)
736 {
737 struct pim_interface *pim_ifp;
738
739 pim_ifp = ifp->info;
740
741 /*
742 * Reset next hello timer
743 */
744 hello_resched(ifp);
745
746 /*
747 * Immediately send hello
748 */
749 pim_hello_send(ifp, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
750 }
751
752 /*
753 RFC 4601: 4.3.1. Sending Hello Messages
754
755 To allow new or rebooting routers to learn of PIM neighbors quickly,
756 when a Hello message is received from a new neighbor, or a Hello
757 message with a new GenID is received from an existing neighbor, a
758 new Hello message should be sent on this interface after a
759 randomized delay between 0 and Triggered_Hello_Delay.
760 */
761 void pim_hello_restart_triggered(struct interface *ifp)
762 {
763 struct pim_interface *pim_ifp;
764 int triggered_hello_delay_msec;
765 int random_msec;
766
767 pim_ifp = ifp->info;
768
769 /*
770 * No need to ever start loopback or vrf device hello's
771 */
772 if (if_is_loopback_or_vrf(ifp))
773 return;
774
775 /*
776 * There exists situations where we have the a RPF out this
777 * interface, but we haven't formed a neighbor yet. This
778 * happens especially during interface flaps. While
779 * we would like to handle this more gracefully in other
780 * parts of the code. In order to get us up and running
781 * let's just send the hello immediate'ish
782 * This should be revisited when we get nexthop tracking
783 * in and when we have a better handle on safely
784 * handling the rpf information for upstreams that
785 * we cannot legally reach yet.
786 */
787 triggered_hello_delay_msec = 1;
788 // triggered_hello_delay_msec = 1000 *
789 // pim_ifp->pim_triggered_hello_delay;
790
791 if (pim_ifp->t_pim_hello_timer) {
792 long remain_msec =
793 pim_time_timer_remain_msec(pim_ifp->t_pim_hello_timer);
794 if (remain_msec <= triggered_hello_delay_msec) {
795 /* Rescheduling hello would increase the delay, then
796 it's faster
797 to just wait for the scheduled periodic hello. */
798 return;
799 }
800
801 THREAD_OFF(pim_ifp->t_pim_hello_timer);
802 }
803
804 random_msec = triggered_hello_delay_msec;
805 // random_msec = random() % (triggered_hello_delay_msec + 1);
806
807 if (PIM_DEBUG_PIM_HELLO) {
808 zlog_debug("Scheduling %d msec triggered hello on interface %s",
809 random_msec, ifp->name);
810 }
811
812 thread_add_timer_msec(router->master, on_pim_hello_send, ifp,
813 random_msec, &pim_ifp->t_pim_hello_timer);
814 }
815
816 int pim_sock_add(struct interface *ifp)
817 {
818 struct pim_interface *pim_ifp;
819 uint32_t old_genid;
820
821 pim_ifp = ifp->info;
822 zassert(pim_ifp);
823
824 if (pim_ifp->pim_sock_fd >= 0) {
825 if (PIM_DEBUG_PIM_PACKETS)
826 zlog_debug(
827 "Can't recreate existing PIM socket fd=%d for interface %s",
828 pim_ifp->pim_sock_fd, ifp->name);
829 return -1;
830 }
831
832 pim_ifp->pim_sock_fd = pim_sock_open(ifp);
833 if (pim_ifp->pim_sock_fd < 0) {
834 if (PIM_DEBUG_PIM_PACKETS)
835 zlog_debug("Could not open PIM socket on interface %s",
836 ifp->name);
837 return -2;
838 }
839
840 pim_socket_ip_hdr(pim_ifp->pim_sock_fd);
841
842 pim_ifp->t_pim_sock_read = NULL;
843 pim_ifp->pim_sock_creation = pim_time_monotonic_sec();
844
845 /*
846 * Just ensure that the new generation id
847 * actually chooses something different.
848 * Actually ran across a case where this
849 * happened, pre-switch to random().
850 * While this is unlikely to happen now
851 * let's make sure it doesn't.
852 */
853 old_genid = pim_ifp->pim_generation_id;
854
855 while (old_genid == pim_ifp->pim_generation_id)
856 pim_ifp->pim_generation_id = random();
857
858 zlog_info("PIM INTERFACE UP: on interface %s ifindex=%d", ifp->name,
859 ifp->ifindex);
860
861 /*
862 * Start receiving PIM messages
863 */
864 pim_sock_read_on(ifp);
865
866 /*
867 * Start sending PIM hello's
868 */
869 pim_hello_restart_triggered(ifp);
870
871 return 0;
872 }