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