]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_register.c
pimd: Set correct parameters to pim_register_stop_send
[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"
27
28#include "pimd.h"
998af219
DS
29#include "pim_mroute.h"
30#include "pim_iface.h"
31#include "pim_msg.h"
32#include "pim_pim.h"
01d68c9b
DS
33#include "pim_str.h"
34#include "pim_rp.h"
35#include "pim_register.h"
80c0d168 36#include "pim_upstream.h"
01d68c9b 37#include "pim_br.h"
2ca35b3d
DS
38#include "pim_rpf.h"
39#include "pim_oil.h"
40#include "pim_zebra.h"
41#include "pim_join.h"
01d68c9b
DS
42
43struct thread *send_test_packet_timer = NULL;
44
45/*
46 * This seems stupidly expensive. A list lookup. Why is this
47 * not a hash?
48 */
49static int
50pim_check_is_my_ip_address (struct in_addr dest_addr)
51{
52 /*
53 * See if we can short-cut some?
54 * This might not make sense if we ever leave a static RP
55 * type of configuration.
56 * Note - Premature optimization might bite our patooeys' here.
57 */
c8ae3ce8 58 if (I_am_RP(dest_addr) && (dest_addr.s_addr == qpim_rp.rpf_addr.s_addr))
01d68c9b
DS
59 return 1;
60
61 if (if_lookup_exact_address (&dest_addr, AF_INET))
62 return 1;
63
64 return 0;
65}
66
67static void
6352a6cf 68pim_register_stop_send (struct in_addr source, struct in_addr group, struct in_addr originator)
01d68c9b 69{
6352a6cf 70 zlog_debug ("Send Register Stop");
01d68c9b
DS
71 return;
72}
73
998af219
DS
74void
75pim_register_send (const struct ip *ip_hdr, struct pim_rpf *rpg)
76{
77 unsigned char buffer[3000];
78 unsigned char *b1;
79 struct pim_interface *pinfo;
80 struct interface *ifp;
81 uint32_t plen;
82
83 ifp = rpg->source_nexthop.interface;
84 pinfo = (struct pim_interface *)ifp->info;
85 if (!pinfo) {
86 zlog_debug("%s: No pinfo!\n", __PRETTY_FUNCTION__);
87 return;
88 }
89
90 memset(buffer, 0, 3000);
91 b1 = buffer + PIM_MSG_REGISTER_LEN;
92
93 plen = ntohs(ip_hdr->ip_len);
9f6d6b12 94 memcpy(b1, (const unsigned char *)ip_hdr, plen);
998af219 95
f5e6574b 96 pim_msg_build_header(buffer, plen + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER);
998af219
DS
97
98 if (pim_msg_send(pinfo->pim_sock_fd,
99 rpg->rpf_addr,
100 buffer,
101 plen + PIM_MSG_REGISTER_LEN,
102 ifp->name)) {
103 if (PIM_DEBUG_PIM_TRACE) {
104 zlog_debug("%s: could not send PIM register message on interface %s",
105 __PRETTY_FUNCTION__, ifp->name);
106 }
107 return;
108 }
109}
110
01d68c9b
DS
111/*
112 * 4.4.2 Receiving Register Messages at the RP
113 *
114 * When an RP receives a Register message, the course of action is
115 * decided according to the following pseudocode:
116 *
117 * packet_arrives_on_rp_tunnel( pkt ) {
118 * if( outer.dst is not one of my addresses ) {
119 * drop the packet silently.
120 * # Note: this may be a spoofing attempt
121 * }
122 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
123 * sentRegisterStop = FALSE;
124 * if ( register.borderbit == TRUE ) {
125 * if ( PMBR(S,G) == unknown ) {
126 * PMBR(S,G) = outer.src
127 * } else if ( outer.src != PMBR(S,G) ) {
128 * send Register-Stop(S,G) to outer.src
129 * drop the packet silently.
130 * }
131 * }
132 * if ( SPTbit(S,G) OR
133 * ( SwitchToSptDesired(S,G) AND
134 * ( inherited_olist(S,G) == NULL ))) {
135 * send Register-Stop(S,G) to outer.src
136 * sentRegisterStop = TRUE;
137 * }
138 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
139 * if ( sentRegisterStop == TRUE ) {
140 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
141 * } else {
142 * set KeepaliveTimer(S,G) to Keepalive_Period;
143 * }
144 * }
145 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
146 * decapsulate and forward the inner packet to
147 * inherited_olist(S,G,rpt) # Note (+)
148 * }
149 * } else {
150 * send Register-Stop(S,G) to outer.src
151 * # Note (*)
152 * }
153 * }
154 */
155int
156pim_register_recv (struct interface *ifp,
157 struct in_addr dest_addr,
158 struct in_addr src_addr,
159 uint8_t *tlv_buf, int tlv_buf_size)
160{
77e390e5
DS
161 int sentRegisterStop = 0;
162 struct ip *ip_hdr;
9f6d6b12 163 //size_t hlen;
01d68c9b
DS
164 struct in_addr group = { .s_addr = 0 };
165 struct in_addr source = { .s_addr = 0 };
9f6d6b12 166 //uint8_t *msg;
77e390e5 167 uint32_t *bits;
01d68c9b
DS
168
169 if (!pim_check_is_my_ip_address (dest_addr)) {
170 if (PIM_DEBUG_PIM_PACKETS) {
171 char dest[100];
172
173 pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest));
174 zlog_debug ("%s: Received Register message for %s that I do not own", __func__,
175 dest);
176 }
177 return 0;
178 }
179
80c0d168 180#define inherited_olist(S,G) NULL
77e390e5
DS
181 /*
182 * Please note this is not drawn to get the correct bit/data size
183 *
184 * The entirety of the REGISTER packet looks like this:
185 * -------------------------------------------------------------
186 * | Ver | Type | Reserved | Checksum |
187 * |-----------------------------------------------------------|
188 * |B|N| Reserved 2 |
189 * |-----------------------------------------------------------|
190 * | Encap | IP HDR |
191 * | Mcast | |
192 * | Packet |--------------------------------------------------|
193 * | | Mcast Data |
194 * | | |
195 * ...
196 *
197 * tlv_buf when received from the caller points at the B bit
198 * We need to know the inner source and dest
199 */
200 bits = (uint32_t *)tlv_buf;
83d8ff00
DS
201
202 /*
203 * tlv_buf points to the start of the |B|N|... Reserved
204 * Line above. So we need to add 4 bytes to get to the
205 * start of the actual Encapsulated data.
206 */
207#define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4
208 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN);
83d8ff00
DS
209 source = ip_hdr->ip_src;
210 group = ip_hdr->ip_dst;
77e390e5 211
ed66602c 212 if (I_am_RP (group) && (dest_addr.s_addr == ((RP (group))->rpf_addr.s_addr))) {
77e390e5 213 sentRegisterStop = 0;
01d68c9b 214
9eda95bd 215 if (*bits & PIM_REGISTER_BORDER_BIT) {
01d68c9b
DS
216 struct in_addr pimbr = pim_br_get_pmbr (source, group);
217 if (PIM_DEBUG_PIM_PACKETS)
218 zlog_debug("%s: Received Register message with Border bit set", __func__);
219
220 if (pimbr.s_addr == pim_br_unknown.s_addr)
80c0d168
DS
221 pim_br_set_pmbr(source, group, src_addr);
222 else if (src_addr.s_addr != pimbr.s_addr) {
6352a6cf 223 pim_register_stop_send(source, group, src_addr);
01d68c9b
DS
224 if (PIM_DEBUG_PIM_PACKETS)
225 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
226 __func__, "Sender");
77e390e5
DS
227 /* Drop Packet Silently */
228 return 1;
01d68c9b
DS
229 }
230 }
77e390e5
DS
231
232 struct pim_upstream *upstream = pim_upstream_find (source, group);
233 /*
234 * If we don't have a place to send ignore the packet
235 */
236 if (!upstream)
6352a6cf
DS
237 {
238 pim_register_stop_send (source, group, src_addr);
239 return 1;
240 }
77e390e5
DS
241
242 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
243 ((SwitchToSptDesired(source, group)) &&
80c0d168 244 (inherited_olist(source, group) == NULL))) {
6352a6cf 245 pim_register_stop_send(source, group, src_addr);
77e390e5
DS
246 sentRegisterStop = 1;
247 }
248
249 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
250 (SwitchToSptDesired(source, group))) {
80c0d168
DS
251 if (sentRegisterStop) {
252 pim_upstream_keep_alive_timer_start (upstream, PIM_RP_KEEPALIVE_PERIOD);
77e390e5 253 } else {
80c0d168 254 pim_upstream_keep_alive_timer_start (upstream, PIM_KEEPALIVE_PERIOD);
77e390e5
DS
255 }
256 }
257
258 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) &&
2ca35b3d
DS
259 !(*bits & PIM_REGISTER_NR_BIT))
260 {
261 pim_rp_set_upstream_addr (&upstream->upstream_addr, source);
262 pim_nexthop_lookup (&upstream->rpf.source_nexthop,
263 upstream->upstream_addr, NULL);
264 upstream->rpf.source_nexthop.interface = ifp;
265 upstream->source_addr.s_addr = source.s_addr;
266 upstream->rpf.rpf_addr.s_addr = source.s_addr;
267 upstream->channel_oil->oil.mfcc_origin = source;
268 pim_scan_individual_oil (upstream->channel_oil);
269 pim_joinprune_send(upstream->rpf.source_nexthop.interface,
270 upstream->rpf.source_nexthop.mrib_nexthop_addr,
271 upstream->source_addr,
272 upstream->group_addr,
273 1);
274
275 //decapsulate and forward the iner packet to
276 //inherited_olist(S,G,rpt)
277 }
77e390e5 278 } else {
6352a6cf 279 pim_register_stop_send(source, group, src_addr);
77e390e5 280 }
01d68c9b
DS
281
282 return 1;
283}
284
285
286static int
287pim_register_send_test_packet (struct thread *t)
288{
289 uint8_t *packet;
290
291 packet = THREAD_ARG(t);
292
293 *packet = 4;
294
295 return 1;
296}
297
298/*
299 * pim_register_send_test_packet
300 *
301 * Send a test packet to the RP from source, in group and pps packets per second
302 */
303void
304pim_register_send_test_packet_start (struct in_addr source,
305 struct in_addr group,
306 uint32_t pps)
307{
308 uint8_t *packet = NULL;
309
310 THREAD_TIMER_MSEC_ON(master, send_test_packet_timer,
311 pim_register_send_test_packet, packet, 1000/pps);
312
313 return;
314}