3 * Copyright (C) 2015 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
30 #include "pim_mroute.h"
31 #include "pim_iface.h"
36 #include "pim_register.h"
37 #include "pim_upstream.h"
41 #include "pim_zebra.h"
45 struct thread
*send_test_packet_timer
= NULL
;
48 * This seems stupidly expensive. A list lookup. Why is this
52 pim_check_is_my_ip_address (struct in_addr dest_addr
)
55 * See if we can short-cut some?
56 * This might not make sense if we ever leave a static RP
57 * type of configuration.
58 * Note - Premature optimization might bite our patooeys' here.
60 if (I_am_RP(dest_addr
) && (dest_addr
.s_addr
== qpim_rp
.rpf_addr
.s_addr
))
63 if (if_lookup_exact_address (&dest_addr
, AF_INET
))
70 pim_register_stop_send (struct interface
*ifp
, struct prefix
*sg
,
71 struct in_addr originator
)
73 struct pim_interface
*pinfo
;
74 unsigned char buffer
[3000];
75 unsigned int b1length
= 0;
80 memset (buffer
, 0, 3000);
81 b1
= (uint8_t *)buffer
+ PIM_MSG_REGISTER_STOP_LEN
;
83 length
= pim_encode_addr_group (b1
, AFI_IP
, 0, 0, sg
->u
.sg
.grp
);
88 p
.u
.prefix4
= sg
->u
.sg
.src
;
90 length
= pim_encode_addr_ucast (b1
, &p
);
93 pim_msg_build_header (buffer
, b1length
+ PIM_MSG_REGISTER_STOP_LEN
, PIM_MSG_TYPE_REG_STOP
);
95 pinfo
= (struct pim_interface
*)ifp
->info
;
98 if (PIM_DEBUG_PIM_TRACE
)
99 zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__
);
102 if (pim_msg_send (pinfo
->pim_sock_fd
, originator
,
103 buffer
, b1length
+ PIM_MSG_REGISTER_STOP_LEN
,
106 if (PIM_DEBUG_PIM_TRACE
)
108 zlog_debug ("%s: could not send PIM register stop message on interface %s",
109 __PRETTY_FUNCTION__
, ifp
->name
);
115 pim_register_stop_recv (uint8_t *buf
, int buf_size
)
117 struct pim_upstream
*upstream
= NULL
;
118 struct prefix source
;
123 if (PIM_DEBUG_PIM_PACKETDUMP_RECV
)
124 pim_pkt_dump ("Received Register Stop", buf
, buf_size
);
126 l
= pim_parse_addr_group (&group
, buf
, buf_size
);
129 l
= pim_parse_addr_ucast (&source
, buf
, buf_size
);
130 memset (&sg
, 0, sizeof (struct prefix
));
131 sg
.u
.sg
.src
= source
.u
.prefix4
;
132 sg
.u
.sg
.grp
= group
.u
.prefix4
;
133 upstream
= pim_upstream_find (&sg
);
139 switch (upstream
->join_state
)
141 case PIM_UPSTREAM_NOTJOINED
:
142 case PIM_UPSTREAM_PRUNE
:
145 case PIM_UPSTREAM_JOINED
:
146 case PIM_UPSTREAM_JOIN_PENDING
:
147 upstream
->join_state
= PIM_UPSTREAM_PRUNE
;
148 pim_upstream_start_register_stop_timer (upstream
, 0);
149 pim_channel_del_oif (upstream
->channel_oil
, pim_regiface
, PIM_OIF_FLAG_PROTO_PIM
);
158 pim_register_send (const uint8_t *buf
, int buf_size
, struct pim_rpf
*rpg
, int null_register
)
160 unsigned char buffer
[3000];
162 struct pim_interface
*pinfo
;
163 struct interface
*ifp
;
165 ifp
= rpg
->source_nexthop
.interface
;
166 pinfo
= (struct pim_interface
*)ifp
->info
;
168 zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__
);
172 memset(buffer
, 0, 3000);
173 b1
= buffer
+ PIM_MSG_HEADER_LEN
;
174 *b1
|= null_register
<< 31;
175 b1
= buffer
+ PIM_MSG_REGISTER_LEN
;
177 memcpy(b1
, (const unsigned char *)buf
, buf_size
);
179 pim_msg_build_header(buffer
, buf_size
+ PIM_MSG_REGISTER_LEN
, PIM_MSG_TYPE_REGISTER
);
181 if (pim_msg_send(pinfo
->pim_sock_fd
,
184 buf_size
+ PIM_MSG_REGISTER_LEN
,
186 if (PIM_DEBUG_PIM_TRACE
) {
187 zlog_debug("%s: could not send PIM register message on interface %s",
188 __PRETTY_FUNCTION__
, ifp
->name
);
195 * 4.4.2 Receiving Register Messages at the RP
197 * When an RP receives a Register message, the course of action is
198 * decided according to the following pseudocode:
200 * packet_arrives_on_rp_tunnel( pkt ) {
201 * if( outer.dst is not one of my addresses ) {
202 * drop the packet silently.
203 * # Note: this may be a spoofing attempt
205 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
206 * sentRegisterStop = FALSE;
207 * if ( register.borderbit == TRUE ) {
208 * if ( PMBR(S,G) == unknown ) {
209 * PMBR(S,G) = outer.src
210 * } else if ( outer.src != PMBR(S,G) ) {
211 * send Register-Stop(S,G) to outer.src
212 * drop the packet silently.
215 * if ( SPTbit(S,G) OR
216 * ( SwitchToSptDesired(S,G) AND
217 * ( inherited_olist(S,G) == NULL ))) {
218 * send Register-Stop(S,G) to outer.src
219 * sentRegisterStop = TRUE;
221 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
222 * if ( sentRegisterStop == TRUE ) {
223 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
225 * set KeepaliveTimer(S,G) to Keepalive_Period;
228 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
229 * decapsulate and forward the inner packet to
230 * inherited_olist(S,G,rpt) # Note (+)
233 * send Register-Stop(S,G) to outer.src
239 pim_register_recv (struct interface
*ifp
,
240 struct in_addr dest_addr
,
241 struct in_addr src_addr
,
242 uint8_t *tlv_buf
, int tlv_buf_size
)
244 int sentRegisterStop
= 0;
249 if (!pim_check_is_my_ip_address (dest_addr
)) {
250 if (PIM_DEBUG_PIM_PACKETS
) {
253 pim_inet4_dump ("<dst?>", dest_addr
, dest
, sizeof(dest
));
254 zlog_debug ("%s: Received Register message for %s that I do not own", __func__
,
261 * Please note this is not drawn to get the correct bit/data size
263 * The entirety of the REGISTER packet looks like this:
264 * -------------------------------------------------------------
265 * | Ver | Type | Reserved | Checksum |
266 * |-----------------------------------------------------------|
268 * |-----------------------------------------------------------|
271 * | Packet |--------------------------------------------------|
276 * tlv_buf when received from the caller points at the B bit
277 * We need to know the inner source and dest
279 bits
= (uint32_t *)tlv_buf
;
282 * tlv_buf points to the start of the |B|N|... Reserved
283 * Line above. So we need to add 4 bytes to get to the
284 * start of the actual Encapsulated data.
286 #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
287 ip_hdr
= (struct ip
*)(tlv_buf
+ PIM_MSG_REGISTER_BIT_RESERVED_LEN
);
288 memset (&sg
, 0, sizeof (struct prefix
));
289 sg
.u
.sg
.src
= ip_hdr
->ip_src
;
290 sg
.u
.sg
.grp
= ip_hdr
->ip_dst
;
292 if (I_am_RP (sg
.u
.sg
.grp
) && (dest_addr
.s_addr
== ((RP (sg
.u
.sg
.grp
))->rpf_addr
.s_addr
))) {
293 sentRegisterStop
= 0;
295 if (*bits
& PIM_REGISTER_BORDER_BIT
) {
296 struct in_addr pimbr
= pim_br_get_pmbr (&sg
);
297 if (PIM_DEBUG_PIM_PACKETS
)
298 zlog_debug("%s: Received Register message with Border bit set", __func__
);
300 if (pimbr
.s_addr
== pim_br_unknown
.s_addr
)
301 pim_br_set_pmbr(&sg
, src_addr
);
302 else if (src_addr
.s_addr
!= pimbr
.s_addr
) {
303 pim_register_stop_send (ifp
, &sg
, src_addr
);
304 if (PIM_DEBUG_PIM_PACKETS
)
305 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
307 /* Drop Packet Silently */
312 struct pim_upstream
*upstream
= pim_upstream_find (&sg
);
314 * If we don't have a place to send ignore the packet
318 upstream
= pim_upstream_add (&sg
, ifp
);
319 pim_upstream_switch (upstream
, PIM_UPSTREAM_PRUNE
);
323 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) ||
324 ((SwitchToSptDesired(&sg
)) &&
325 pim_upstream_inherited_olist (upstream
) == 0)) {
326 pim_rp_set_upstream_addr (&upstream
->upstream_addr
, sg
.u
.sg
.src
);
327 pim_nexthop_lookup (&upstream
->rpf
.source_nexthop
,
328 upstream
->upstream_addr
, NULL
);
329 upstream
->rpf
.source_nexthop
.interface
= ifp
;
330 upstream
->sg
.u
.sg
.src
= sg
.u
.sg
.src
;
331 upstream
->rpf
.rpf_addr
= upstream
->rpf
.source_nexthop
.mrib_nexthop_addr
;
332 upstream
->channel_oil
->oil
.mfcc_origin
= sg
.u
.sg
.src
;
333 pim_scan_individual_oil (upstream
->channel_oil
);
334 pim_register_stop_send (ifp
, &sg
, src_addr
);
335 sentRegisterStop
= 1;
338 if ((upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) ||
339 (SwitchToSptDesired(&sg
))) {
340 if (sentRegisterStop
) {
341 pim_upstream_keep_alive_timer_start (upstream
, PIM_RP_KEEPALIVE_PERIOD
);
343 pim_upstream_keep_alive_timer_start (upstream
, PIM_KEEPALIVE_PERIOD
);
347 if (!(upstream
->sptbit
== PIM_UPSTREAM_SPTBIT_TRUE
) &&
348 !(*bits
& PIM_REGISTER_NR_BIT
))
350 //decapsulate and forward the iner packet to
351 //inherited_olist(S,G,rpt)
354 pim_register_stop_send (ifp
, &sg
, src_addr
);
362 pim_register_send_test_packet (struct thread
*t
)
366 packet
= THREAD_ARG(t
);
374 * pim_register_send_test_packet
376 * Send a test packet to the RP from source, in group and pps packets per second
379 pim_register_send_test_packet_start (struct in_addr source
,
380 struct in_addr group
,
383 uint8_t *packet
= NULL
;
385 THREAD_TIMER_MSEC_ON(master
, send_test_packet_timer
,
386 pim_register_send_test_packet
, packet
, 1000/pps
);