]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_register.c
pimd: Cleanup some comments and documentation
[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"
29#include "pim_str.h"
30#include "pim_rp.h"
31#include "pim_register.h"
32#include "pim_br.h"
33
34struct thread *send_test_packet_timer = NULL;
35
36/*
37 * This seems stupidly expensive. A list lookup. Why is this
38 * not a hash?
39 */
40static int
41pim_check_is_my_ip_address (struct in_addr dest_addr)
42{
43 /*
44 * See if we can short-cut some?
45 * This might not make sense if we ever leave a static RP
46 * type of configuration.
47 * Note - Premature optimization might bite our patooeys' here.
48 */
49 if (I_am_RP(dest_addr) && (dest_addr.s_addr == qpim_rp.s_addr))
50 return 1;
51
52 if (if_lookup_exact_address (&dest_addr, AF_INET))
53 return 1;
54
55 return 0;
56}
57
58static void
59pim_register_stop_send (struct in_addr src)
60{
61 return;
62}
63
64/*
65 * 4.4.2 Receiving Register Messages at the RP
66 *
67 * When an RP receives a Register message, the course of action is
68 * decided according to the following pseudocode:
69 *
70 * packet_arrives_on_rp_tunnel( pkt ) {
71 * if( outer.dst is not one of my addresses ) {
72 * drop the packet silently.
73 * # Note: this may be a spoofing attempt
74 * }
75 * if( I_am_RP(G) AND outer.dst == RP(G) ) {
76 * sentRegisterStop = FALSE;
77 * if ( register.borderbit == TRUE ) {
78 * if ( PMBR(S,G) == unknown ) {
79 * PMBR(S,G) = outer.src
80 * } else if ( outer.src != PMBR(S,G) ) {
81 * send Register-Stop(S,G) to outer.src
82 * drop the packet silently.
83 * }
84 * }
85 * if ( SPTbit(S,G) OR
86 * ( SwitchToSptDesired(S,G) AND
87 * ( inherited_olist(S,G) == NULL ))) {
88 * send Register-Stop(S,G) to outer.src
89 * sentRegisterStop = TRUE;
90 * }
91 * if ( SPTbit(S,G) OR SwitchToSptDesired(S,G) ) {
92 * if ( sentRegisterStop == TRUE ) {
93 * set KeepaliveTimer(S,G) to RP_Keepalive_Period;
94 * } else {
95 * set KeepaliveTimer(S,G) to Keepalive_Period;
96 * }
97 * }
98 * if( !SPTbit(S,G) AND ! pkt.NullRegisterBit ) {
99 * decapsulate and forward the inner packet to
100 * inherited_olist(S,G,rpt) # Note (+)
101 * }
102 * } else {
103 * send Register-Stop(S,G) to outer.src
104 * # Note (*)
105 * }
106 * }
107 */
108int
109pim_register_recv (struct interface *ifp,
110 struct in_addr dest_addr,
111 struct in_addr src_addr,
112 uint8_t *tlv_buf, int tlv_buf_size)
113{
77e390e5
DS
114 int sentRegisterStop = 0;
115 struct ip *ip_hdr;
116 size_t hlen;
01d68c9b
DS
117 struct in_addr group = { .s_addr = 0 };
118 struct in_addr source = { .s_addr = 0 };
77e390e5
DS
119 uint8_t *msg;
120 uint32_t *bits;
01d68c9b
DS
121
122 if (!pim_check_is_my_ip_address (dest_addr)) {
123 if (PIM_DEBUG_PIM_PACKETS) {
124 char dest[100];
125
126 pim_inet4_dump ("<dst?>", dest_addr, dest, sizeof(dest));
127 zlog_debug ("%s: Received Register message for %s that I do not own", __func__,
128 dest);
129 }
130 return 0;
131 }
132
77e390e5
DS
133 /*
134 * Please note this is not drawn to get the correct bit/data size
135 *
136 * The entirety of the REGISTER packet looks like this:
137 * -------------------------------------------------------------
138 * | Ver | Type | Reserved | Checksum |
139 * |-----------------------------------------------------------|
140 * |B|N| Reserved 2 |
141 * |-----------------------------------------------------------|
142 * | Encap | IP HDR |
143 * | Mcast | |
144 * | Packet |--------------------------------------------------|
145 * | | Mcast Data |
146 * | | |
147 * ...
148 *
149 * tlv_buf when received from the caller points at the B bit
150 * We need to know the inner source and dest
151 */
152 bits = (uint32_t *)tlv_buf;
153 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_LEN);
154 hlen = (ip_hdr->ip_hl << 2) | PIM_MSG_REGISTER_LEN;
155 msg = (uint8_t *)tlv_buf + hlen;
156 source = ip_hdr->ip_src;
157 group = ip_hdr->ip_dst;
158
01d68c9b 159 if (I_am_RP (group) && (dest_addr.s_addr == (RP (group).s_addr))) {
77e390e5 160 sentRegisterStop = 0;
01d68c9b
DS
161
162 if (*bits && PIM_REGISTER_BORDER_BIT) {
163 struct in_addr pimbr = pim_br_get_pmbr (source, group);
164 if (PIM_DEBUG_PIM_PACKETS)
165 zlog_debug("%s: Received Register message with Border bit set", __func__);
166
167 if (pimbr.s_addr == pim_br_unknown.s_addr)
168 pim_br_set_pmbr(source, group, outer_src);
77e390e5
DS
169 else if (outer.s_addr != pimbr.s_addr) {
170 pim_register_stop_send(outer);
01d68c9b
DS
171 if (PIM_DEBUG_PIM_PACKETS)
172 zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet",
173 __func__, "Sender");
77e390e5
DS
174 /* Drop Packet Silently */
175 return 1;
01d68c9b
DS
176 }
177 }
77e390e5
DS
178
179 struct pim_upstream *upstream = pim_upstream_find (source, group);
180 /*
181 * If we don't have a place to send ignore the packet
182 */
183 if (!upstream)
184 return 1;
185
186 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
187 ((SwitchToSptDesired(source, group)) &&
188 (inherited_list(source, group) == NULL))) {
189 pim_register_stop_send(outer);
190 sentRegisterStop = 1;
191 }
192
193 if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) ||
194 (SwitchToSptDesired(source, group))) {
195 if (SentRegisterStop) {
196 //set KeepaliveTimer(S,G) to RP_Keepalive_Period;
197 } else {
198 //set KeepaliveTimer(S,G) to Keepalive_Period;
199 }
200 }
201
202 if (!(upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) &&
203 !(*bits && PIM_REGISTER_NR_BIT)) {
204 //decapsulate and forward the iner packet to
205 //inherited_olist(S,G,rpt)
01d68c9b 206 }
77e390e5
DS
207 } else {
208 pim_register_stop_send(outer);
209 }
01d68c9b
DS
210
211 return 1;
212}
213
214
215static int
216pim_register_send_test_packet (struct thread *t)
217{
218 uint8_t *packet;
219
220 packet = THREAD_ARG(t);
221
222 *packet = 4;
223
224 return 1;
225}
226
227/*
228 * pim_register_send_test_packet
229 *
230 * Send a test packet to the RP from source, in group and pps packets per second
231 */
232void
233pim_register_send_test_packet_start (struct in_addr source,
234 struct in_addr group,
235 uint32_t pps)
236{
237 uint8_t *packet = NULL;
238
239 THREAD_TIMER_MSEC_ON(master, send_test_packet_timer,
240 pim_register_send_test_packet, packet, 1000/pps);
241
242 return;
243}