]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_register.c
pimd: Use Quagga as official bug report place
[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 *
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,
19 * MA 02110-1301 USA
20 */
21
22#include <zebra.h>
23
24#include "log.h"
25#include "if.h"
26#include "thread.h"
13c2408c 27#include "prefix.h"
01d68c9b
DS
28
29#include "pimd.h"
998af219
DS
30#include "pim_mroute.h"
31#include "pim_iface.h"
32#include "pim_msg.h"
33#include "pim_pim.h"
01d68c9b
DS
34#include "pim_str.h"
35#include "pim_rp.h"
36#include "pim_register.h"
80c0d168 37#include "pim_upstream.h"
01d68c9b 38#include "pim_br.h"
2ca35b3d
DS
39#include "pim_rpf.h"
40#include "pim_oil.h"
41#include "pim_zebra.h"
42#include "pim_join.h"
13c2408c 43#include "pim_util.h"
01d68c9b
DS
44
45struct thread *send_test_packet_timer = NULL;
46
8e38a2cf 47void
4ed0af70 48pim_register_stop_send (struct interface *ifp, struct prefix_sg *sg,
4df01a4e 49 struct in_addr src, struct in_addr originator)
01d68c9b 50{
13c2408c
DS
51 struct pim_interface *pinfo;
52 unsigned char buffer[3000];
53 unsigned int b1length = 0;
54 unsigned int length;
55 uint8_t *b1;
56 struct prefix p;
57
9add3b88
DS
58 if (PIM_DEBUG_PIM_REG)
59 {
60 zlog_debug ("Sending Register stop for %s to %s on %s",
61 pim_str_sg_dump (sg), inet_ntoa(originator), ifp->name);
62 }
63
13c2408c
DS
64 memset (buffer, 0, 3000);
65 b1 = (uint8_t *)buffer + PIM_MSG_REGISTER_STOP_LEN;
66
4ed0af70 67 length = pim_encode_addr_group (b1, AFI_IP, 0, 0, sg->grp);
13c2408c
DS
68 b1length += length;
69 b1 += length;
70
71 p.family = AF_INET;
4ed0af70 72 p.u.prefix4 = sg->src;
13c2408c
DS
73 p.prefixlen = 32;
74 length = pim_encode_addr_ucast (b1, &p);
75 b1length += length;
76
77 pim_msg_build_header (buffer, b1length + PIM_MSG_REGISTER_STOP_LEN, PIM_MSG_TYPE_REG_STOP);
78
79 pinfo = (struct pim_interface *)ifp->info;
80 if (!pinfo)
81 {
82 if (PIM_DEBUG_PIM_TRACE)
83 zlog_debug ("%s: No pinfo!\n", __PRETTY_FUNCTION__);
84 return;
85 }
4df01a4e 86 if (pim_msg_send (pinfo->pim_sock_fd, src, originator,
13c2408c
DS
87 buffer, b1length + PIM_MSG_REGISTER_STOP_LEN,
88 ifp->name))
89 {
90 if (PIM_DEBUG_PIM_TRACE)
91 {
92 zlog_debug ("%s: could not send PIM register stop message on interface %s",
93 __PRETTY_FUNCTION__, ifp->name);
94 }
95 }
01d68c9b
DS
96}
97
4dffc880 98int
56638739 99pim_register_stop_recv (uint8_t *buf, int buf_size)
4dffc880 100{
56638739
DS
101 struct pim_upstream *upstream = NULL;
102 struct prefix source;
103 struct prefix group;
4ed0af70 104 struct prefix_sg sg;
56638739
DS
105 int l;
106
56638739
DS
107 l = pim_parse_addr_group (&group, buf, buf_size);
108 buf += l;
109 buf_size -= l;
a878ba45 110 pim_parse_addr_ucast (&source, buf, buf_size);
4ed0af70
DS
111 memset (&sg, 0, sizeof (struct prefix_sg));
112 sg.src = source.u.prefix4;
113 sg.grp = group.u.prefix4;
9add3b88
DS
114
115 if (PIM_DEBUG_PIM_REG)
116 {
117 zlog_debug ("Received Register stop for %s",
118 pim_str_sg_dump (&sg));
119 }
120
5074a423 121 upstream = pim_upstream_find (&sg);
56638739
DS
122 if (!upstream)
123 {
124 return 0;
125 }
126
127 switch (upstream->join_state)
128 {
129 case PIM_UPSTREAM_NOTJOINED:
130 case PIM_UPSTREAM_PRUNE:
131 return 0;
132 break;
133 case PIM_UPSTREAM_JOINED:
bb027ee8
DS
134 upstream->join_state = PIM_UPSTREAM_PRUNE;
135 pim_channel_del_oif (upstream->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM);
136 pim_upstream_start_register_stop_timer (upstream, 0);
56638739
DS
137 case PIM_UPSTREAM_JOIN_PENDING:
138 upstream->join_state = PIM_UPSTREAM_PRUNE;
139 pim_upstream_start_register_stop_timer (upstream, 0);
56638739
DS
140 return 0;
141 break;
142 }
143
4dffc880
DS
144 return 0;
145}
146
998af219 147void
4df01a4e 148pim_register_send (const uint8_t *buf, int buf_size, struct in_addr src, struct pim_rpf *rpg, int null_register)
998af219
DS
149{
150 unsigned char buffer[3000];
151 unsigned char *b1;
152 struct pim_interface *pinfo;
153 struct interface *ifp;
998af219 154
9add3b88
DS
155 if (PIM_DEBUG_PIM_REG)
156 {
157 char rp_str[100];
158 strcpy (rp_str, inet_ntoa (rpg->rpf_addr));
159 zlog_debug ("Sending %sRegister Packet to %s", null_register ? "NULL " : "", rp_str);
160 }
161
998af219
DS
162 ifp = rpg->source_nexthop.interface;
163 pinfo = (struct pim_interface *)ifp->info;
164 if (!pinfo) {
165 zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__);
166 return;
167 }
168
169 memset(buffer, 0, 3000);
b100a4f5 170 b1 = buffer + PIM_MSG_HEADER_LEN;
dc686f82 171 *b1 |= null_register << 6;
998af219
DS
172 b1 = buffer + PIM_MSG_REGISTER_LEN;
173
b100a4f5 174 memcpy(b1, (const unsigned char *)buf, buf_size);
998af219 175
b100a4f5 176 pim_msg_build_header(buffer, buf_size + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER);
998af219
DS
177
178 if (pim_msg_send(pinfo->pim_sock_fd,
4df01a4e 179 src,
998af219
DS
180 rpg->rpf_addr,
181 buffer,
b100a4f5 182 buf_size + PIM_MSG_REGISTER_LEN,
998af219
DS
183 ifp->name)) {
184 if (PIM_DEBUG_PIM_TRACE) {
185 zlog_debug("%s: could not send PIM register message on interface %s",
186 __PRETTY_FUNCTION__, ifp->name);
187 }
188 return;
189 }
190}
191
01d68c9b
DS
192/*
193 * 4.4.2 Receiving Register Messages at the RP
194 *
195 * When an RP receives a Register message, the course of action is
196 * decided according to the following pseudocode:
197 *
198 * packet_arrives_on_rp_tunnel( pkt ) {
199 * if( outer.dst is not one of my addresses ) {
200 * drop the packet silently.
201 * # Note: this may be a spoofing attempt
202 * }
203 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
204 * sentRegisterStop = FALSE;
205 * if ( register.borderbit == TRUE ) {
206 * if ( PMBR(S,G) == unknown ) {
207 * PMBR(S,G) = outer.src
208 * } else if ( outer.src != PMBR(S,G) ) {
209 * send Register-Stop(S,G) to outer.src
210 * drop the packet silently.
211 * }
212 * }
213 * if ( SPTbit(S,G) OR
214 * ( SwitchToSptDesired(S,G) AND
215 * ( inherited_olist(S,G) == NULL ))) {
216 * send Register-Stop(S,G) to outer.src
217 * sentRegisterStop = TRUE;
218 * }
219 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
220 * if ( sentRegisterStop == TRUE ) {
221 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
222 * } else {
223 * set KeepaliveTimer(S,G) to Keepalive_Period;
224 * }
225 * }
226 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
227 * decapsulate and forward the inner packet to
228 * inherited_olist(S,G,rpt) # Note (+)
229 * }
230 * } else {
231 * send Register-Stop(S,G) to outer.src
232 * # Note (*)
233 * }
234 * }
235 */
236int
237pim_register_recv (struct interface *ifp,
238 struct in_addr dest_addr,
239 struct in_addr src_addr,
240 uint8_t *tlv_buf, int tlv_buf_size)
241{
77e390e5
DS
242 int sentRegisterStop = 0;
243 struct ip *ip_hdr;
4ed0af70 244 struct prefix_sg sg;
77e390e5 245 uint32_t *bits;
01d68c9b 246
75a26779
DS
247#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
248 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
249
250 if (!pim_rp_check_is_my_ip_address (ip_hdr->ip_dst, dest_addr)) {
d41b415c 251 if (PIM_DEBUG_PIM_REG) {
01d68c9b
DS
252 char dest[100];
253
254 pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest));
255 zlog_debug ("%s: Received Register message for %s that I do not own", __func__,
256 dest);
257 }
258 return 0;
259 }
260
9add3b88
DS
261 if (PIM_DEBUG_PIM_REG)
262 {
263 char src_str[100];
264
265 pim_inet4_dump ("<src?>", src_addr, src_str, sizeof (src_str));
266 zlog_debug ("Received Register message from %s on %s", src_str, ifp->name);
267 }
268
77e390e5
DS
269 /*
270 * Please note this is not drawn to get the correct bit/data size
271 *
272 * The entirety of the REGISTER packet looks like this:
273 * -------------------------------------------------------------
274 * | Ver | Type | Reserved | Checksum |
275 * |-----------------------------------------------------------|
276 * |B|N| Reserved 2 |
277 * |-----------------------------------------------------------|
278 * | Encap | IP HDR |
279 * | Mcast | |
280 * | Packet |--------------------------------------------------|
281 * | | Mcast Data |
282 * | | |
283 * ...
284 *
285 * tlv_buf when received from the caller points at the B bit
286 * We need to know the inner source and dest
287 */
288 bits = (uint32_t *)tlv_buf;
83d8ff00
DS
289
290 /*
291 * tlv_buf points to the start of the |B|N|... Reserved
292 * Line above. So we need to add 4 bytes to get to the
293 * start of the actual Encapsulated data.
294 */
4ed0af70
DS
295 memset (&sg, 0, sizeof (struct prefix_sg));
296 sg.src = ip_hdr->ip_src;
297 sg.grp = ip_hdr->ip_dst;
77e390e5 298
4ed0af70 299 if (I_am_RP (sg.grp) && (dest_addr.s_addr == ((RP (sg.grp))->rpf_addr.s_addr))) {
77e390e5 300 sentRegisterStop = 0;
01d68c9b 301
9eda95bd 302 if (*bits & PIM_REGISTER_BORDER_BIT) {
65e1fcd7 303 struct in_addr pimbr = pim_br_get_pmbr (&sg);
01d68c9b
DS
304 if (PIM_DEBUG_PIM_PACKETS)
305 zlog_debug("%s: Received Register message with Border bit set", __func__);
306
307 if (pimbr.s_addr == pim_br_unknown.s_addr)
65e1fcd7 308 pim_br_set_pmbr(&sg, src_addr);
80c0d168 309 else if (src_addr.s_addr != pimbr.s_addr) {
4df01a4e 310 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
01d68c9b
DS
311 if (PIM_DEBUG_PIM_PACKETS)
312 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
313 __func__, "Sender");
77e390e5
DS
314 /* Drop Packet Silently */
315 return 1;
01d68c9b
DS
316 }
317 }
77e390e5 318
5074a423 319 struct pim_upstream *upstream = pim_upstream_find (&sg);
77e390e5
DS
320 /*
321 * If we don't have a place to send ignore the packet
322 */
323 if (!upstream)
9fd309db 324 {
5074a423 325 upstream = pim_upstream_add (&sg, ifp);
4e85d209
DS
326 if (!upstream)
327 {
328 zlog_warn ("Failure to crate upstream state");
329 return 1;
330 }
8e38a2cf 331 upstream->upstream_register = src_addr;
36d6bd7d 332 pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp);
216bb84f 333 pim_nexthop_lookup (&upstream->rpf.source_nexthop,
f24405b1 334 upstream->upstream_addr);
4ed0af70 335 upstream->sg.src = sg.src;
216bb84f
DS
336 upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr;
337
8e38a2cf 338 upstream->join_state = PIM_UPSTREAM_PRUNE;
219e0013 339
9fd309db
DS
340 }
341
77e390e5 342 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
ad410c6c 343 ((SwitchToSptDesired(&sg)) &&
4fdc8f36 344 pim_upstream_inherited_olist (upstream) == 0)) {
216bb84f 345 //pim_scan_individual_oil (upstream->channel_oil);
4df01a4e 346 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
77e390e5
DS
347 sentRegisterStop = 1;
348 }
349
350 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
ad410c6c 351 (SwitchToSptDesired(&sg))) {
80c0d168 352 if (sentRegisterStop) {
01408ede 353 pim_upstream_keep_alive_timer_start (upstream, qpim_rp_keep_alive_time);
77e390e5 354 } else {
4304f95c 355 pim_upstream_keep_alive_timer_start (upstream, qpim_keep_alive_time);
77e390e5
DS
356 }
357 }
358
359 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) &&
2ca35b3d
DS
360 !(*bits & PIM_REGISTER_NR_BIT))
361 {
2ca35b3d
DS
362 //decapsulate and forward the iner packet to
363 //inherited_olist(S,G,rpt)
0365f56b 364 // This is taken care of by the kernel for us
2ca35b3d 365 }
77e390e5 366 } else {
4df01a4e 367 pim_register_stop_send (ifp, &sg, dest_addr, src_addr);
77e390e5 368 }
01d68c9b
DS
369
370 return 1;
371}
372
373
374static int
375pim_register_send_test_packet (struct thread *t)
376{
377 uint8_t *packet;
378
379 packet = THREAD_ARG(t);
380
381 *packet = 4;
382
383 return 1;
384}
385
386/*
387 * pim_register_send_test_packet
388 *
389 * Send a test packet to the RP from source, in group and pps packets per second
390 */
391void
392pim_register_send_test_packet_start (struct in_addr source,
393 struct in_addr group,
394 uint32_t pps)
395{
396 uint8_t *packet = NULL;
397
398 THREAD_TIMER_MSEC_ON(master, send_test_packet_timer,
399 pim_register_send_test_packet, packet, 1000/pps);
400
401 return;
402}