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