1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2015 Cumulus Networks, Inc.
18 #include "pim_mroute.h"
19 #include "pim_iface.h"
24 #include "pim_register.h"
25 #include "pim_upstream.h"
28 #include "pim_zebra.h"
32 #include "pim_vxlan.h"
35 struct thread
*send_test_packet_timer
= NULL
;
37 void pim_register_join(struct pim_upstream
*up
)
39 struct pim_instance
*pim
= up
->channel_oil
->pim
;
41 if (pim_is_grp_ssm(pim
, up
->sg
.grp
)) {
42 if (PIM_DEBUG_PIM_EVENTS
)
43 zlog_debug("%s register setup skipped as group is SSM",
48 pim_channel_add_oif(up
->channel_oil
, pim
->regiface
,
49 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
50 up
->reg_state
= PIM_REG_JOIN
;
51 pim_vxlan_update_sg_reg_state(pim
, up
, true);
54 void pim_register_stop_send(struct interface
*ifp
, pim_sgaddr
*sg
, pim_addr src
,
57 struct pim_interface
*pinfo
;
58 unsigned char buffer
[10000];
59 unsigned int b1length
= 0;
63 if (PIM_DEBUG_PIM_REG
) {
64 zlog_debug("Sending Register stop for %pSG to %pPA on %s", sg
,
65 &originator
, ifp
->name
);
68 memset(buffer
, 0, 10000);
69 b1
= (uint8_t *)buffer
+ PIM_MSG_REGISTER_STOP_LEN
;
71 length
= pim_encode_addr_group(b1
, AFI_IP
, 0, 0, sg
->grp
);
75 length
= pim_encode_addr_ucast(b1
, sg
->src
);
78 pim_msg_build_header(src
, originator
, buffer
,
79 b1length
+ PIM_MSG_REGISTER_STOP_LEN
,
80 PIM_MSG_TYPE_REG_STOP
, false);
82 pinfo
= (struct pim_interface
*)ifp
->info
;
84 if (PIM_DEBUG_PIM_TRACE
)
85 zlog_debug("%s: No pinfo!", __func__
);
88 if (pim_msg_send(pinfo
->pim_sock_fd
, src
, originator
, buffer
,
89 b1length
+ PIM_MSG_REGISTER_STOP_LEN
, ifp
)) {
90 if (PIM_DEBUG_PIM_TRACE
) {
92 "%s: could not send PIM register stop message on interface %s",
97 if (!pinfo
->pim_passive_enable
)
98 ++pinfo
->pim_ifstat_reg_stop_send
;
101 static void pim_reg_stop_upstream(struct pim_instance
*pim
,
102 struct pim_upstream
*up
)
104 switch (up
->reg_state
) {
109 up
->reg_state
= PIM_REG_PRUNE
;
110 pim_channel_del_oif(up
->channel_oil
, pim
->regiface
,
111 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
112 pim_upstream_start_register_stop_timer(up
, 0);
113 pim_vxlan_update_sg_reg_state(pim
, up
, false);
115 case PIM_REG_JOIN_PENDING
:
116 up
->reg_state
= PIM_REG_PRUNE
;
117 pim_upstream_start_register_stop_timer(up
, 0);
122 int pim_register_stop_recv(struct interface
*ifp
, uint8_t *buf
, int buf_size
)
124 struct pim_interface
*pim_ifp
= ifp
->info
;
125 struct pim_instance
*pim
= pim_ifp
->pim
;
126 struct pim_upstream
*up
= NULL
;
129 struct listnode
*up_node
;
130 struct pim_upstream
*child
;
131 bool wrong_af
= false;
132 bool handling_star
= false;
135 if (pim_ifp
->pim_passive_enable
) {
136 if (PIM_DEBUG_PIM_PACKETS
)
138 "skip receiving PIM message on passive interface %s",
143 ++pim_ifp
->pim_ifstat_reg_stop_recv
;
145 memset(&sg
, 0, sizeof(sg
));
146 l
= pim_parse_addr_group(&sg
, buf
, buf_size
);
149 pim_parse_addr_ucast(&sg
.src
, buf
, buf_size
, &wrong_af
);
152 zlog_err("invalid AF in Register-Stop on %s", ifp
->name
);
157 if (PIM_DEBUG_PIM_REG
)
158 zlog_debug("Received Register stop for %pSG", &sg
);
160 rp
= RP(pim_ifp
->pim
, sg
.grp
);
162 /* As per RFC 7761, Section 4.9.4:
163 * A special wildcard value consisting of an address field of
164 * all zeros can be used to indicate any source.
166 if ((pim_addr_cmp(sg
.src
, rp
->rpf_addr
) == 0) ||
167 pim_addr_is_any(sg
.src
)) {
168 handling_star
= true;
169 sg
.src
= PIMADDR_ANY
;
175 * Handling Register-Stop(*,G) Messages at the DR:
176 * A Register-Stop(*,G) should be treated as a
177 * Register-Stop(S,G) for all (S,G) Register state
178 * machines that are not in the NoInfo state.
180 up
= pim_upstream_find(pim
, &sg
);
183 * If the upstream find actually found a particular
184 * S,G then we *know* that the following for loop
185 * is not going to execute and this is ok
187 for (ALL_LIST_ELEMENTS_RO(up
->sources
, up_node
, child
)) {
188 if (PIM_DEBUG_PIM_REG
)
189 zlog_debug("Executing Reg stop for %s",
192 pim_reg_stop_upstream(pim
, child
);
195 if (PIM_DEBUG_PIM_REG
)
196 zlog_debug("Executing Reg stop for %s", up
->sg_str
);
197 pim_reg_stop_upstream(pim
, up
);
202 * Unfortunately pim was unable to find a *,G
203 * but pim may still actually have individual
204 * S,G's that need to be processed. In that
205 * case pim must do the expensive walk to find
208 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
209 if (pim_addr_cmp(up
->sg
.grp
, sg
.grp
) == 0) {
210 if (PIM_DEBUG_PIM_REG
)
211 zlog_debug("Executing Reg stop for %s",
213 pim_reg_stop_upstream(pim
, up
);
222 struct in6_addr
pim_register_get_unicast_v6_addr(struct pim_interface
*p_ifp
)
224 struct listnode
*node
;
225 struct listnode
*nextnode
;
226 struct pim_secondary_addr
*sec_addr
;
227 struct pim_interface
*pim_ifp
;
228 struct interface
*ifp
;
229 struct pim_instance
*pim
= p_ifp
->pim
;
231 /* Trying to get the unicast address from the RPF interface first */
232 for (ALL_LIST_ELEMENTS(p_ifp
->sec_addr_list
, node
, nextnode
,
234 if (!is_ipv6_global_unicast(&sec_addr
->addr
.u
.prefix6
))
237 return sec_addr
->addr
.u
.prefix6
;
240 /* Loop through all the pim interface and try to return a global
241 * unicast ipv6 address
243 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
249 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
251 if (!is_ipv6_global_unicast(&sec_addr
->addr
.u
.prefix6
))
254 return sec_addr
->addr
.u
.prefix6
;
258 zlog_warn("No global address found for use to send register message");
263 void pim_register_send(const uint8_t *buf
, int buf_size
, pim_addr src
,
264 struct pim_rpf
*rpg
, int null_register
,
265 struct pim_upstream
*up
)
267 unsigned char buffer
[10000];
269 struct pim_interface
*pinfo
;
270 struct interface
*ifp
;
272 if (PIM_DEBUG_PIM_REG
) {
273 zlog_debug("Sending %s %sRegister Packet to %pPA", up
->sg_str
,
274 null_register
? "NULL " : "", &rpg
->rpf_addr
);
277 ifp
= rpg
->source_nexthop
.interface
;
279 if (PIM_DEBUG_PIM_REG
)
280 zlog_debug("%s: No interface to transmit register on",
284 pinfo
= (struct pim_interface
*)ifp
->info
;
286 if (PIM_DEBUG_PIM_REG
)
288 "%s: Interface: %s not configured for pim to transmit on!",
289 __func__
, ifp
->name
);
293 if (PIM_DEBUG_PIM_REG
) {
294 zlog_debug("%s: Sending %s %sRegister Packet to %pPA on %s",
295 __func__
, up
->sg_str
, null_register
? "NULL " : "",
296 &rpg
->rpf_addr
, ifp
->name
);
299 memset(buffer
, 0, 10000);
300 b1
= buffer
+ PIM_MSG_HEADER_LEN
;
301 *b1
|= null_register
<< 6;
302 b1
= buffer
+ PIM_MSG_REGISTER_LEN
;
304 memcpy(b1
, (const unsigned char *)buf
, buf_size
);
307 /* While sending Register message to RP, we cannot use link-local
308 * address therefore using unicast ipv6 address here, choosing it
309 * from the RPF Interface
311 src
= pim_register_get_unicast_v6_addr(pinfo
);
313 pim_msg_build_header(src
, rpg
->rpf_addr
, buffer
,
314 buf_size
+ PIM_MSG_REGISTER_LEN
,
315 PIM_MSG_TYPE_REGISTER
, false);
317 if (!pinfo
->pim_passive_enable
)
318 ++pinfo
->pim_ifstat_reg_send
;
320 if (pim_msg_send(pinfo
->pim
->reg_sock
, src
, rpg
->rpf_addr
, buffer
,
321 buf_size
+ PIM_MSG_REGISTER_LEN
, ifp
)) {
322 if (PIM_DEBUG_PIM_TRACE
) {
324 "%s: could not send PIM register message on interface %s",
325 __func__
, ifp
->name
);
332 void pim_null_register_send(struct pim_upstream
*up
)
335 struct pim_interface
*pim_ifp
;
339 pim_ifp
= up
->rpf
.source_nexthop
.interface
->info
;
341 if (PIM_DEBUG_PIM_TRACE
)
343 "%s: Cannot send null-register for %s no valid iif",
344 __func__
, up
->sg_str
);
348 rpg
= RP(pim_ifp
->pim
, up
->sg
.grp
);
350 if (PIM_DEBUG_PIM_TRACE
)
352 "%s: Cannot send null-register for %s no RPF to the RP",
353 __func__
, up
->sg_str
);
357 memset(&ip_hdr
, 0, sizeof(ip_hdr
));
358 ip_hdr
.ip_p
= PIM_IP_PROTO_PIM
;
361 ip_hdr
.ip_src
= up
->sg
.src
;
362 ip_hdr
.ip_dst
= up
->sg
.grp
;
363 ip_hdr
.ip_len
= htons(20);
365 /* checksum is broken */
366 src
= pim_ifp
->primary_address
;
367 if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up
->flags
)) {
368 if (!pim_vxlan_get_register_src(pim_ifp
->pim
, up
, &src
)) {
369 if (PIM_DEBUG_PIM_TRACE
)
371 "%s: Cannot send null-register for %s vxlan-aa PIP unavailable",
372 __func__
, up
->sg_str
);
376 pim_register_send((uint8_t *)&ip_hdr
, sizeof(struct ip
), src
, rpg
, 1,
380 void pim_null_register_send(struct pim_upstream
*up
)
382 struct ip6_hdr ip6_hdr
;
383 struct pim_msg_header pim_msg_header
;
384 struct pim_interface
*pim_ifp
;
387 unsigned char buffer
[sizeof(ip6_hdr
) + sizeof(pim_msg_header
)];
390 pim_ifp
= up
->rpf
.source_nexthop
.interface
->info
;
392 if (PIM_DEBUG_PIM_TRACE
)
394 "Cannot send null-register for %s no valid iif",
399 rpg
= RP(pim_ifp
->pim
, up
->sg
.grp
);
401 if (PIM_DEBUG_PIM_TRACE
)
403 "Cannot send null-register for %s no RPF to the RP",
408 memset(&ip6_hdr
, 0, sizeof(ip6_hdr
));
409 ip6_hdr
.ip6_nxt
= PIM_IP_PROTO_PIM
;
410 ip6_hdr
.ip6_plen
= PIM_MSG_HEADER_LEN
;
411 ip6_hdr
.ip6_vfc
= 6 << 4;
412 ip6_hdr
.ip6_hlim
= MAXTTL
;
413 ip6_hdr
.ip6_src
= up
->sg
.src
;
414 ip6_hdr
.ip6_dst
= up
->sg
.grp
;
416 memset(buffer
, 0, (sizeof(ip6_hdr
) + sizeof(pim_msg_header
)));
417 memcpy(buffer
, &ip6_hdr
, sizeof(ip6_hdr
));
419 pim_msg_header
.ver
= 0;
420 pim_msg_header
.type
= 0;
421 pim_msg_header
.reserved
= 0;
423 pim_msg_header
.checksum
= 0;
427 ph
.ulpl
= htonl(PIM_MSG_HEADER_LEN
);
428 ph
.next_hdr
= IPPROTO_PIM
;
429 pim_msg_header
.checksum
=
430 in_cksum_with_ph6(&ph
, &pim_msg_header
, PIM_MSG_HEADER_LEN
);
432 memcpy(buffer
+ sizeof(ip6_hdr
), &pim_msg_header
, PIM_MSG_HEADER_LEN
);
435 src
= pim_ifp
->primary_address
;
436 pim_register_send((uint8_t *)buffer
,
437 sizeof(ip6_hdr
) + PIM_MSG_HEADER_LEN
, src
, rpg
, 1,
443 * 4.4.2 Receiving Register Messages at the RP
445 * When an RP receives a Register message, the course of action is
446 * decided according to the following pseudocode:
448 * packet_arrives_on_rp_tunnel( pkt ) {
449 * if( outer.dst is not one of my addresses ) {
450 * drop the packet silently.
451 * # Note: this may be a spoofing attempt
453 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
454 * sentRegisterStop = false;
455 * if ( register.borderbit == true ) {
456 * if ( PMBR(S,G) == unknown ) {
457 * PMBR(S,G) = outer.src
458 * } else if ( outer.src != PMBR(S,G) ) {
459 * send Register-Stop(S,G) to outer.src
460 * drop the packet silently.
463 * if ( SPTbit(S,G) OR
464 * ( SwitchToSptDesired(S,G) AND
465 * ( inherited_olist(S,G) == NULL ))) {
466 * send Register-Stop(S,G) to outer.src
467 * sentRegisterStop = true;
469 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
470 * if ( sentRegisterStop == true ) {
471 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
473 * set KeepaliveTimer(S,G) to Keepalive_Period;
476 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
477 * decapsulate and forward the inner packet to
478 * inherited_olist(S,G,rpt) # Note (+)
481 * send Register-Stop(S,G) to outer.src
486 int pim_register_recv(struct interface
*ifp
, pim_addr dest_addr
,
487 pim_addr src_addr
, uint8_t *tlv_buf
, int tlv_buf_size
)
489 int sentRegisterStop
= 0;
494 struct pim_interface
*pim_ifp
= ifp
->info
;
495 struct pim_instance
*pim
= pim_ifp
->pim
;
498 if (pim_ifp
->pim_passive_enable
) {
499 if (PIM_DEBUG_PIM_PACKETS
)
501 "skip receiving PIM message on passive interface %s",
506 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
507 ip_hdr
= (tlv_buf
+ PIM_MSG_REGISTER_BIT_RESERVED_LEN
);
509 if (!if_address_is_local(&dest_addr
, PIM_AF
, pim
->vrf
->vrf_id
)) {
510 if (PIM_DEBUG_PIM_REG
)
512 "%s: Received Register message for destination address: %pPA that I do not own",
513 __func__
, &dest_addr
);
517 ++pim_ifp
->pim_ifstat_reg_recv
;
520 * Please note this is not drawn to get the correct bit/data size
522 * The entirety of the REGISTER packet looks like this:
523 * -------------------------------------------------------------
524 * | Ver | Type | Reserved | Checksum |
525 * |-----------------------------------------------------------|
527 * |-----------------------------------------------------------|
530 * | Packet |--------------------------------------------------|
535 * tlv_buf when received from the caller points at the B bit
536 * We need to know the inner source and dest
538 bits
= (uint32_t *)tlv_buf
;
541 * tlv_buf points to the start of the |B|N|... Reserved
542 * Line above. So we need to add 4 bytes to get to the
543 * start of the actual Encapsulated data.
545 memset(&sg
, 0, sizeof(sg
));
546 sg
= pim_sgaddr_from_iphdr(ip_hdr
);
550 * According to RFC section 4.9.3, If Dummy PIM Header is included
551 * in NULL Register as a payload there would be two PIM headers.
552 * The inner PIM Header's checksum field should also be validated
553 * in addition to the outer PIM Header's checksum. Validation of
554 * inner PIM header checksum is done here.
556 if ((*bits
& PIM_REGISTER_NR_BIT
) &&
557 ((tlv_buf_size
- PIM_MSG_REGISTER_BIT_RESERVED_LEN
) >
558 (int)sizeof(struct ip6_hdr
))) {
559 uint16_t computed_checksum
;
560 uint16_t received_checksum
;
562 struct pim_msg_header
*header
;
564 header
= (struct pim_msg_header
566 PIM_MSG_REGISTER_BIT_RESERVED_LEN
+
567 sizeof(struct ip6_hdr
));
570 ph
.ulpl
= htonl(PIM_MSG_HEADER_LEN
);
571 ph
.next_hdr
= IPPROTO_PIM
;
573 received_checksum
= header
->checksum
;
575 header
->checksum
= 0;
576 computed_checksum
= in_cksum_with_ph6(
577 &ph
, header
, htonl(PIM_MSG_HEADER_LEN
));
579 if (computed_checksum
!= received_checksum
) {
580 if (PIM_DEBUG_PIM_PACKETS
)
582 "Ignoring Null Register message%pSG from %pPA due to bad checksum in Encapsulated dummy PIM header",
588 i_am_rp
= I_am_RP(pim
, sg
.grp
);
590 if (PIM_DEBUG_PIM_REG
)
592 "Received Register message%pSG from %pPA on %s, rp: %d",
593 &sg
, &src_addr
, ifp
->name
, i_am_rp
);
595 if (pim_is_grp_ssm(pim_ifp
->pim
, sg
.grp
)) {
596 if (pim_addr_is_any(sg
.src
)) {
598 "%s: Received Register message for Group(%pPA) is now in SSM, dropping the packet",
600 /* Drop Packet Silently */
605 rp_addr
= (RP(pim
, sg
.grp
))->rpf_addr
;
606 if (i_am_rp
&& (!pim_addr_cmp(dest_addr
, rp_addr
))) {
607 sentRegisterStop
= 0;
609 if (pim
->register_plist
) {
610 struct prefix_list
*plist
;
613 plist
= prefix_list_lookup(PIM_AFI
,
614 pim
->register_plist
);
616 pim_addr_to_prefix(&src
, sg
.src
);
618 if (prefix_list_apply_ext(plist
, NULL
, &src
, true) ==
620 pim_register_stop_send(ifp
, &sg
, dest_addr
,
622 if (PIM_DEBUG_PIM_PACKETS
)
624 "%s: Sending register-stop to %pPA for %pSG due to prefix-list denial, dropping packet",
625 __func__
, &src_addr
, &sg
);
631 if (*bits
& PIM_REGISTER_BORDER_BIT
) {
632 if (PIM_DEBUG_PIM_PACKETS
)
634 "%s: Received Register message with Border bit set, ignoring",
637 /* Drop Packet Silently */
641 struct pim_upstream
*upstream
= pim_upstream_find(pim
, &sg
);
643 * If we don't have a place to send ignore the packet
646 upstream
= pim_upstream_add(
648 PIM_UPSTREAM_FLAG_MASK_SRC_STREAM
, __func__
,
651 zlog_warn("Failure to create upstream state");
655 upstream
->upstream_register
= src_addr
;
658 * If the FHR has set a very very fast register timer
659 * there exists a possibility that the incoming NULL
661 * is happening before we set the spt bit. If so
662 * Do a quick check to update the counters and
663 * then set the spt bit as appropriate
665 if (upstream
->sptbit
!= PIM_UPSTREAM_SPTBIT_TRUE
) {
666 pim_mroute_update_counters(
667 upstream
->channel_oil
);
669 * Have we seen packets?
671 if (upstream
->channel_oil
->cc
.oldpktcnt
672 < upstream
->channel_oil
->cc
.pktcnt
)
673 pim_upstream_set_sptbit(
675 upstream
->rpf
.source_nexthop
680 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
681 || ((SwitchToSptDesiredOnRp(pim
, &sg
))
682 && pim_upstream_inherited_olist(pim
, upstream
) == 0)) {
683 pim_register_stop_send(ifp
, &sg
, dest_addr
, src_addr
);
684 sentRegisterStop
= 1;
686 if (PIM_DEBUG_PIM_REG
)
687 zlog_debug("(%s) sptbit: %d", upstream
->sg_str
,
690 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
691 || (SwitchToSptDesiredOnRp(pim
, &sg
))) {
692 if (sentRegisterStop
) {
693 pim_upstream_keep_alive_timer_start(
694 upstream
, pim
->rp_keep_alive_time
);
696 pim_upstream_keep_alive_timer_start(
697 upstream
, pim
->keep_alive_time
);
701 if (!(upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
)
702 && !(*bits
& PIM_REGISTER_NR_BIT
)) {
703 // decapsulate and forward the iner packet to
704 // inherited_olist(S,G,rpt)
705 // This is taken care of by the kernel for us
707 pim_upstream_msdp_reg_timer_start(upstream
);
709 if (PIM_DEBUG_PIM_REG
) {
711 zlog_debug("Received Register packet for %pSG, Rejecting packet because I am not the RP configured for group",
714 zlog_debug("Received Register packet for %pSG, Rejecting packet because the dst ip address is not the actual RP",
717 pim_register_stop_send(ifp
, &sg
, dest_addr
, src_addr
);
724 * This routine scan all upstream and update register state and remove pimreg
725 * when couldreg becomes false.
727 void pim_reg_del_on_couldreg_fail(struct interface
*ifp
)
729 struct pim_interface
*pim_ifp
= ifp
->info
;
730 struct pim_instance
*pim
;
731 struct pim_upstream
*up
;
738 frr_each (rb_pim_upstream
, &pim
->upstream_head
, up
) {
739 if (ifp
!= up
->rpf
.source_nexthop
.interface
)
742 if (!pim_upstream_could_register(up
)
743 && (up
->reg_state
!= PIM_REG_NOINFO
)) {
744 pim_channel_del_oif(up
->channel_oil
, pim
->regiface
,
745 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
746 THREAD_OFF(up
->t_rs_timer
);
747 up
->reg_state
= PIM_REG_NOINFO
;