]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_register.c
pimd: Reduce RP checks a bit
[mirror_frr.git] / pimd / pim_register.c
CommitLineData
01d68c9b
DS
1/*
2 * PIM for Quagga
3 * Copyright (C) 2015 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
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.
10 *
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.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
01d68c9b
DS
19 */
20
21#include <zebra.h>
22
23#include "log.h"
24#include "if.h"
25#include "thread.h"
13c2408c 26#include "prefix.h"
dfe43e25
DW
27#include "vty.h"
28#include "plist.h"
01d68c9b
DS
29
30#include "pimd.h"
998af219
DS
31#include "pim_mroute.h"
32#include "pim_iface.h"
33#include "pim_msg.h"
34#include "pim_pim.h"
01d68c9b
DS
35#include "pim_str.h"
36#include "pim_rp.h"
37#include "pim_register.h"
80c0d168 38#include "pim_upstream.h"
01d68c9b 39#include "pim_br.h"
2ca35b3d
DS
40#include "pim_rpf.h"
41#include "pim_oil.h"
42#include "pim_zebra.h"
43#include "pim_join.h"
13c2408c 44#include "pim_util.h"
15a5dafe 45#include "pim_ssm.h"
01d68c9b
DS
46
47struct thread *send_test_packet_timer = NULL;
48
d62a17ae 49void pim_register_join(struct pim_upstream *up)
15a5dafe 50{
ac7eaeb4
DS
51 struct pim_instance *pim = up->channel_oil->pim;
52
6f439a70 53 if (pim_is_grp_ssm(pim, up->sg.grp)) {
d62a17ae 54 if (PIM_DEBUG_PIM_EVENTS)
55 zlog_debug("%s register setup skipped as group is SSM",
56 up->sg_str);
57 return;
58 }
59
ac7eaeb4 60 pim_channel_add_oif(up->channel_oil, pim->regiface,
d62a17ae 61 PIM_OIF_FLAG_PROTO_PIM);
62 up->reg_state = PIM_REG_JOIN;
15a5dafe 63}
64
d62a17ae 65void pim_register_stop_send(struct interface *ifp, struct prefix_sg *sg,
66 struct in_addr src, struct in_addr originator)
01d68c9b 67{
d62a17ae 68 struct pim_interface *pinfo;
69 unsigned char buffer[10000];
70 unsigned int b1length = 0;
71 unsigned int length;
72 uint8_t *b1;
73 struct prefix p;
74
75 if (PIM_DEBUG_PIM_REG) {
76 zlog_debug("Sending Register stop for %s to %s on %s",
77 pim_str_sg_dump(sg), inet_ntoa(originator),
78 ifp->name);
79 }
80
81 memset(buffer, 0, 10000);
82 b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
83
84 length = pim_encode_addr_group(b1, AFI_IP, 0, 0, sg->grp);
85 b1length += length;
86 b1 += length;
87
88 p.family = AF_INET;
89 p.u.prefix4 = sg->src;
90 p.prefixlen = 32;
91 length = pim_encode_addr_ucast(b1, &p);
92 b1length += length;
93
94 pim_msg_build_header(buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
95 PIM_MSG_TYPE_REG_STOP);
96
97 pinfo = (struct pim_interface *)ifp->info;
98 if (!pinfo) {
99 if (PIM_DEBUG_PIM_TRACE)
9165c5f5 100 zlog_debug("%s: No pinfo!", __PRETTY_FUNCTION__);
d62a17ae 101 return;
13c2408c 102 }
d62a17ae 103 if (pim_msg_send(pinfo->pim_sock_fd, src, originator, buffer,
104 b1length + PIM_MSG_REGISTER_STOP_LEN, ifp->name)) {
105 if (PIM_DEBUG_PIM_TRACE) {
106 zlog_debug(
107 "%s: could not send PIM register stop message on interface %s",
108 __PRETTY_FUNCTION__, ifp->name);
109 }
110 }
111 ++pinfo->pim_ifstat_reg_stop_send;
01d68c9b
DS
112}
113
b206566b 114int pim_register_stop_recv(struct interface *ifp, uint8_t *buf, int buf_size)
4dffc880 115{
b206566b
DS
116 struct pim_interface *pim_ifp = ifp->info;
117 struct pim_instance *pim = pim_ifp->pim;
d62a17ae 118 struct pim_upstream *upstream = NULL;
119 struct prefix source;
120 struct prefix_sg sg;
121 int l;
122
123 memset(&sg, 0, sizeof(struct prefix_sg));
124 l = pim_parse_addr_group(&sg, buf, buf_size);
125 buf += l;
126 buf_size -= l;
127 pim_parse_addr_ucast(&source, buf, buf_size);
128 sg.src = source.u.prefix4;
129
b206566b 130 upstream = pim_upstream_find(pim, &sg);
d62a17ae 131 if (!upstream) {
132 return 0;
133 }
134
135 if (PIM_DEBUG_PIM_REG)
136 zlog_debug("Received Register stop for %s", upstream->sg_str);
137
138 switch (upstream->reg_state) {
139 case PIM_REG_NOINFO:
140 case PIM_REG_PRUNE:
141 return 0;
142 break;
143 case PIM_REG_JOIN:
144 upstream->reg_state = PIM_REG_PRUNE;
b206566b 145 pim_channel_del_oif(upstream->channel_oil, pim->regiface,
d62a17ae 146 PIM_OIF_FLAG_PROTO_PIM);
147 pim_upstream_start_register_stop_timer(upstream, 0);
148 break;
149 case PIM_REG_JOIN_PENDING:
150 upstream->reg_state = PIM_REG_PRUNE;
151 pim_upstream_start_register_stop_timer(upstream, 0);
152 return 0;
153 break;
154 }
155
156 return 0;
4dffc880
DS
157}
158
d62a17ae 159void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src,
160 struct pim_rpf *rpg, int null_register,
161 struct pim_upstream *up)
998af219 162{
d62a17ae 163 unsigned char buffer[10000];
164 unsigned char *b1;
165 struct pim_interface *pinfo;
166 struct interface *ifp;
167
168 if (PIM_DEBUG_PIM_REG) {
169 zlog_debug("Sending %s %sRegister Packet to %s", up->sg_str,
170 null_register ? "NULL " : "",
171 inet_ntoa(rpg->rpf_addr.u.prefix4));
172 }
173
174 ifp = rpg->source_nexthop.interface;
175 if (!ifp) {
176 if (PIM_DEBUG_PIM_REG)
177 zlog_debug("%s: No interface to transmit register on",
178 __PRETTY_FUNCTION__);
179 return;
180 }
181 pinfo = (struct pim_interface *)ifp->info;
182 if (!pinfo) {
183 if (PIM_DEBUG_PIM_REG)
184 zlog_debug(
185 "%s: Interface: %s not configured for pim to trasmit on!\n",
186 __PRETTY_FUNCTION__, ifp->name);
187 return;
188 }
189
190 if (PIM_DEBUG_PIM_REG) {
191 char rp_str[INET_ADDRSTRLEN];
81c077d0
QY
192 strlcpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4),
193 sizeof(rp_str));
d62a17ae 194 zlog_debug("%s: Sending %s %sRegister Packet to %s on %s",
195 __PRETTY_FUNCTION__, up->sg_str,
196 null_register ? "NULL " : "", rp_str, ifp->name);
197 }
198
199 memset(buffer, 0, 10000);
200 b1 = buffer + PIM_MSG_HEADER_LEN;
201 *b1 |= null_register << 6;
202 b1 = buffer + PIM_MSG_REGISTER_LEN;
203
204 memcpy(b1, (const unsigned char *)buf, buf_size);
205
206 pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN,
207 PIM_MSG_TYPE_REGISTER);
208
209 ++pinfo->pim_ifstat_reg_send;
210
211 if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr.u.prefix4,
212 buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp->name)) {
213 if (PIM_DEBUG_PIM_TRACE) {
214 zlog_debug(
215 "%s: could not send PIM register message on interface %s",
216 __PRETTY_FUNCTION__, ifp->name);
217 }
218 return;
219 }
998af219
DS
220}
221
01d68c9b
DS
222/*
223 * 4.4.2 Receiving Register Messages at the RP
224 *
225 * When an RP receives a Register message, the course of action is
226 * decided according to the following pseudocode:
227 *
228 * packet_arrives_on_rp_tunnel( pkt ) {
229 * if( outer.dst is not one of my addresses ) {
230 * drop the packet silently.
231 * # Note: this may be a spoofing attempt
232 * }
233 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
234 * sentRegisterStop = FALSE;
235 * if ( register.borderbit == TRUE ) {
236 * if ( PMBR(S,G) == unknown ) {
237 * PMBR(S,G) = outer.src
238 * } else if ( outer.src != PMBR(S,G) ) {
239 * send Register-Stop(S,G) to outer.src
240 * drop the packet silently.
241 * }
242 * }
243 * if ( SPTbit(S,G) OR
244 * ( SwitchToSptDesired(S,G) AND
245 * ( inherited_olist(S,G) == NULL ))) {
246 * send Register-Stop(S,G) to outer.src
247 * sentRegisterStop = TRUE;
248 * }
249 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
250 * if ( sentRegisterStop == TRUE ) {
251 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
252 * } else {
253 * set KeepaliveTimer(S,G) to Keepalive_Period;
254 * }
255 * }
256 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
257 * decapsulate and forward the inner packet to
258 * inherited_olist(S,G,rpt) # Note (+)
259 * }
260 * } else {
261 * send Register-Stop(S,G) to outer.src
262 * # Note (*)
263 * }
264 * }
265 */
d62a17ae 266int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
267 struct in_addr src_addr, uint8_t *tlv_buf,
268 int tlv_buf_size)
01d68c9b 269{
d62a17ae 270 int sentRegisterStop = 0;
271 struct ip *ip_hdr;
272 struct prefix_sg sg;
273 uint32_t *bits;
274 int i_am_rp = 0;
275 struct pim_interface *pim_ifp = NULL;
01d68c9b 276
fec883d9
DS
277 pim_ifp = ifp->info;
278
75a26779 279#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
d62a17ae 280 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
281
f43593d9 282 if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) {
d62a17ae 283 if (PIM_DEBUG_PIM_REG) {
284 char dest[INET_ADDRSTRLEN];
285
286 pim_inet4_dump("<dst?>", dest_addr, dest, sizeof(dest));
287 zlog_debug(
f43593d9 288 "%s: Received Register message for destination address: %s that I do not own",
d62a17ae 289 __func__, dest);
290 }
291 return 0;
292 }
293
d62a17ae 294 ++pim_ifp->pim_ifstat_reg_recv;
295
296 /*
297 * Please note this is not drawn to get the correct bit/data size
298 *
299 * The entirety of the REGISTER packet looks like this:
300 * -------------------------------------------------------------
301 * | Ver | Type | Reserved | Checksum |
302 * |-----------------------------------------------------------|
303 * |B|N| Reserved 2 |
304 * |-----------------------------------------------------------|
305 * | Encap | IP HDR |
306 * | Mcast | |
307 * | Packet |--------------------------------------------------|
308 * | | Mcast Data |
309 * | | |
310 * ...
311 *
312 * tlv_buf when received from the caller points at the B bit
313 * We need to know the inner source and dest
314 */
315 bits = (uint32_t *)tlv_buf;
316
317 /*
318 * tlv_buf points to the start of the |B|N|... Reserved
319 * Line above. So we need to add 4 bytes to get to the
320 * start of the actual Encapsulated data.
321 */
322 memset(&sg, 0, sizeof(struct prefix_sg));
323 sg.src = ip_hdr->ip_src;
324 sg.grp = ip_hdr->ip_dst;
325
d9c9a9ee 326 i_am_rp = I_am_RP(pim_ifp->pim, sg.grp);
d62a17ae 327
328 if (PIM_DEBUG_PIM_REG) {
329 char src_str[INET_ADDRSTRLEN];
330
331 pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
332 zlog_debug(
333 "Received Register message(%s) from %s on %s, rp: %d",
334 pim_str_sg_dump(&sg), src_str, ifp->name, i_am_rp);
335 }
336
fec883d9
DS
337 if (i_am_rp
338 && (dest_addr.s_addr
339 == ((RP(pim_ifp->pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) {
d62a17ae 340 sentRegisterStop = 0;
341
342 if (*bits & PIM_REGISTER_BORDER_BIT) {
343 struct in_addr pimbr = pim_br_get_pmbr(&sg);
344 if (PIM_DEBUG_PIM_PACKETS)
345 zlog_debug(
346 "%s: Received Register message with Border bit set",
347 __func__);
348
349 if (pimbr.s_addr == pim_br_unknown.s_addr)
350 pim_br_set_pmbr(&sg, src_addr);
351 else if (src_addr.s_addr != pimbr.s_addr) {
352 pim_register_stop_send(ifp, &sg, dest_addr,
353 src_addr);
354 if (PIM_DEBUG_PIM_PACKETS)
355 zlog_debug(
356 "%s: Sending register-Stop to %s and dropping mr. packet",
357 __func__, "Sender");
358 /* Drop Packet Silently */
359 return 0;
360 }
361 }
362
9b29ea95
DS
363 struct pim_upstream *upstream =
364 pim_upstream_find(pim_ifp->pim, &sg);
d62a17ae 365 /*
366 * If we don't have a place to send ignore the packet
367 */
368 if (!upstream) {
369 upstream = pim_upstream_add(
2002dcdb
DS
370 pim_ifp->pim, &sg, ifp,
371 PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
0885a9f1 372 __PRETTY_FUNCTION__, NULL);
d62a17ae 373 if (!upstream) {
374 zlog_warn("Failure to create upstream state");
375 return 1;
376 }
377
378 upstream->upstream_register = src_addr;
cc61055f
DS
379 } else {
380 /*
381 * If the FHR has set a very very fast register timer
382 * there exists a possibility that the incoming NULL
383 * register
384 * is happening before we set the spt bit. If so
385 * Do a quick check to update the counters and
386 * then set the spt bit as appropriate
387 */
388 if (upstream->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
389 pim_mroute_update_counters(
390 upstream->channel_oil);
391 /*
392 * Have we seen packets?
393 */
394 if (upstream->channel_oil->cc.oldpktcnt
395 < upstream->channel_oil->cc.pktcnt)
396 pim_upstream_set_sptbit(
397 upstream,
398 upstream->rpf.source_nexthop
399 .interface);
400 }
d62a17ae 401 }
402
403 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
8e5f97e3 404 || ((SwitchToSptDesired(pim_ifp->pim, &sg))
9b29ea95
DS
405 && pim_upstream_inherited_olist(pim_ifp->pim, upstream)
406 == 0)) {
d62a17ae 407 // pim_scan_individual_oil (upstream->channel_oil);
408 pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
409 sentRegisterStop = 1;
410 } else {
411 if (PIM_DEBUG_PIM_REG)
412 zlog_debug("(%s) sptbit: %d", upstream->sg_str,
413 upstream->sptbit);
414 }
415 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
8e5f97e3 416 || (SwitchToSptDesired(pim_ifp->pim, &sg))) {
d62a17ae 417 if (sentRegisterStop) {
418 pim_upstream_keep_alive_timer_start(
996c9314
LB
419 upstream,
420 pim_ifp->pim->rp_keep_alive_time);
d62a17ae 421 } else {
422 pim_upstream_keep_alive_timer_start(
996c9314
LB
423 upstream,
424 pim_ifp->pim->keep_alive_time);
d62a17ae 425 }
426 }
427
428 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE)
429 && !(*bits & PIM_REGISTER_NR_BIT)) {
430 // decapsulate and forward the iner packet to
431 // inherited_olist(S,G,rpt)
432 // This is taken care of by the kernel for us
433 }
434 pim_upstream_msdp_reg_timer_start(upstream);
435 } else {
436 if (PIM_DEBUG_PIM_REG) {
437 if (!i_am_rp)
438 zlog_debug(
439 "Received Register packet for %s, Rejecting packet because I am not the RP configured for group",
440 pim_str_sg_dump(&sg));
441 else
442 zlog_debug(
443 "Received Register packet for %s, Rejecting packet because the dst ip address is not the actual RP",
444 pim_str_sg_dump(&sg));
445 }
446 pim_register_stop_send(ifp, &sg, dest_addr, src_addr);
447 }
448
8dc60b69 449 return 0;
01d68c9b 450}