]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfp-example/librfp/rfp_example.c
bgpd: Allow self next-hop if `bgp allow-martian-nexthop` is enabled
[mirror_frr.git] / bgpd / rfp-example / librfp / rfp_example.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 *
4 * Copyright 2015-2016, LabN Consulting, L.L.C.
5 *
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 /* stub rfp */
13 #include "rfp_internal.h"
14 #include "bgpd/rfapi/rfapi.h"
15 #include "lib/command.h"
16
17 struct rfp_instance_t {
18 struct rfapi_rfp_cfg rfapi_config;
19 struct rfapi_rfp_cb_methods rfapi_callbacks;
20 struct thread_master *master;
21 uint32_t config_var;
22 };
23
24 struct rfp_instance_t
25 global_rfi; /* dynamically allocate in full implementation */
26
27 /***********************************************************************
28 * Sample VTY / internal function
29 **********************************************************************/
30 #define RFP_SHOW_STR "RFP information\n"
31 DEFUN (rfp_example_config_value,
32 rfp_example_config_value_cmd,
33 "rfp example-config-value VALUE",
34 RFP_SHOW_STR
35 "Example value to be configured\n"
36 "Value to display\n")
37 {
38 uint32_t value = 0;
39 struct rfp_instance_t *rfi = NULL;
40 rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
41 assert(rfi != NULL);
42
43 value = strtoul(argv[2]->arg, NULL, 10);
44 if (rfi)
45 rfi->config_var = value;
46 return CMD_SUCCESS;
47 }
48
49 DEFUN (rfp_holddown_factor,
50 rfp_holddown_factor_cmd,
51 "rfp holddown-factor (0-4294967295)",
52 RFP_SHOW_STR
53 "Set Hold-Down Factor as a percentage of registration lifetime.\n"
54 "Percentage of registration lifetime\n")
55 {
56 struct rfp_instance_t *rfi;
57 uint32_t value = 0;
58
59 value = strtoul((argv[--argc]->arg), NULL, 10);
60 rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
61 if (!rfi) {
62 vty_out(vty, "VNC not configured\n");
63 return CMD_WARNING;
64 }
65 rfi->rfapi_config.holddown_factor = value;
66 rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config);
67 return CMD_SUCCESS;
68 }
69
70
71 DEFUN (rfp_full_table_download,
72 rfp_full_table_download_cmd,
73 "rfp full-table-download <on|off>",
74 RFP_SHOW_STR
75 "RFP full table download support (default=on)\n"
76 "Enable RFP full table download\n"
77 "Disable RFP full table download\n")
78 {
79 struct rfp_instance_t *rfi;
80 rfapi_rfp_download_type old;
81
82 rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
83 if (!rfi) {
84 vty_out(vty, "VNC not configured\n");
85 return CMD_WARNING;
86 }
87 old = rfi->rfapi_config.download_type;
88 if (argv[--argc]->arg[1] == 'n' || argv[argc]->arg[1] == 'N')
89 rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_FULL;
90 else
91 rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL;
92 if (old != rfi->rfapi_config.download_type)
93 rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config);
94 return CMD_SUCCESS;
95 }
96
97 static void rfp_vty_install(void)
98 {
99 static int installed = 0;
100 if (installed) /* do this only once */
101 return;
102 installed = 1;
103 /* example of new cli command */
104 install_element(BGP_NODE, &rfp_example_config_value_cmd);
105 install_element(BGP_NODE, &rfp_holddown_factor_cmd);
106 install_element(BGP_NODE, &rfp_full_table_download_cmd);
107 }
108
109 /***********************************************************************
110 * RFAPI Callbacks
111 **********************************************************************/
112
113 /*------------------------------------------
114 * rfp_response_cb
115 *
116 * Callbacks of this type are used to provide asynchronous
117 * route updates from RFAPI to the RFP client.
118 *
119 * response_cb
120 * called to notify the rfp client that a next hop list
121 * that has previously been provided in response to an
122 * rfapi_query call has been updated. Deleted routes are indicated
123 * with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME.
124 *
125 * By default, the routes an NVE receives via this callback include
126 * its own routes (that it has registered). However, these may be
127 * filtered out if the global BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
128 * flag is set.
129 *
130 * input:
131 * next_hops a list of possible next hops.
132 * This is a linked list allocated within the
133 * rfapi. The response_cb callback function is responsible
134 * for freeing this memory via rfapi_free_next_hop_list()
135 * in order to avoid memory leaks.
136 *
137 * userdata value (cookie) originally specified in call to
138 * rfapi_open()
139 *
140 *------------------------------------------*/
141 static void rfp_response_cb(struct rfapi_next_hop_entry *next_hops,
142 void *userdata)
143 {
144 /*
145 * Identify NVE based on userdata, which is a value passed
146 * to RFAPI in the rfapi_open call
147 */
148
149 /* process list of next_hops */
150
151 /* free next hops */
152 rfapi_free_next_hop_list(next_hops);
153 return;
154 }
155
156 /*------------------------------------------
157 * rfp_local_cb
158 *
159 * Callbacks of this type are used to provide asynchronous
160 * route updates from RFAPI to the RFP client.
161 *
162 * local_cb
163 * called to notify the rfp client that a local route
164 * has been added or deleted. Deleted routes are indicated
165 * with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME.
166 *
167 * input:
168 * next_hops a list of possible next hops.
169 * This is a linked list allocated within the
170 * rfapi. The local_cb callback function is responsible
171 * for freeing this memory via rfapi_free_next_hop_list()
172 * in order to avoid memory leaks.
173 *
174 * userdata value (cookie) originally specified in call to
175 * rfapi_open()
176 *
177 *------------------------------------------*/
178 static void rfp_local_cb(struct rfapi_next_hop_entry *next_hops, void *userdata)
179 {
180 /*
181 * Identify NVE based on userdata, which is a value passed
182 * to RFAPI in the rfapi_open call
183 */
184
185 /* process list of local next_hops */
186
187 /* free next hops */
188 rfapi_free_next_hop_list(next_hops);
189 return;
190 }
191
192 /*------------------------------------------
193 * rfp_close_cb
194 *
195 * Callbacks used to provide asynchronous
196 * notification that an rfapi_handle was invalidated
197 *
198 * input:
199 * pHandle Firmerly valid rfapi_handle returned to
200 * client via rfapi_open().
201 *
202 * reason EIDRM handle administratively closed (clear nve ...)
203 * ESTALE handle invalidated by configuration change
204 *
205 *------------------------------------------*/
206 static void rfp_close_cb(rfapi_handle pHandle, int reason)
207 {
208 /* close / invalidate NVE with the pHandle returned by the rfapi_open
209 * call */
210 return;
211 }
212
213 /*------------------------------------------
214 * rfp_cfg_write_cb
215 *
216 * This callback is used to generate output for any config parameters
217 * that may supported by RFP via RFP defined vty commands at the bgp
218 * level. See loglevel as an example.
219 *
220 * input:
221 * vty -- quagga vty context
222 * rfp_start_val -- value returned by rfp_start
223 *
224 * output:
225 * to vty, rfp related configuration
226 *
227 * return value:
228 * lines written
229 --------------------------------------------*/
230 static int rfp_cfg_write_cb(struct vty *vty, void *rfp_start_val)
231 {
232 struct rfp_instance_t *rfi = rfp_start_val;
233 int write = 0;
234 assert(rfp_start_val != NULL);
235 if (rfi->config_var != 0) {
236 vty_out(vty, " rfp example-config-value %u", rfi->config_var);
237 vty_out(vty, "\n");
238 write++;
239 }
240 if (rfi->rfapi_config.holddown_factor != 0) {
241 vty_out(vty, " rfp holddown-factor %u\n",
242 rfi->rfapi_config.holddown_factor);
243 write++;
244 }
245 if (rfi->rfapi_config.download_type == RFAPI_RFP_DOWNLOAD_FULL) {
246 vty_out(vty, " rfp full-table-download on\n");
247 write++;
248 }
249 return write;
250 }
251
252 /***********************************************************************
253 * RFAPI required functions
254 **********************************************************************/
255
256 /*------------------------------------------
257 * rfp_start
258 *
259 * This function will start the RFP code
260 *
261 * input:
262 * master quagga thread_master to tie into bgpd threads
263 *
264 * output:
265 * cfgp Pointer to rfapi_rfp_cfg (null = use defaults),
266 * copied by caller, updated via rfp_set_configuration
267 * cbmp Pointer to rfapi_rfp_cb_methods, may be null
268 * copied by caller, updated via rfapi_rfp_set_cb_methods
269 *
270 * return value:
271 * rfp_start_val rfp returned value passed on rfp_stop and rfp_cfg_write
272 *
273 --------------------------------------------*/
274 void *rfp_start(struct thread_master *master, struct rfapi_rfp_cfg **cfgp,
275 struct rfapi_rfp_cb_methods **cbmp)
276 {
277 memset(&global_rfi, 0, sizeof(global_rfi));
278 global_rfi.master = master; /* for BGPD threads */
279
280 /* initilize struct rfapi_rfp_cfg, see rfapi.h */
281 global_rfi.rfapi_config.download_type =
282 RFAPI_RFP_DOWNLOAD_PARTIAL; /* default=partial */
283 global_rfi.rfapi_config.ftd_advertisement_interval =
284 RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL;
285 global_rfi.rfapi_config.holddown_factor =
286 0; /* default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */
287 global_rfi.rfapi_config.use_updated_response = 1; /* 0=no */
288 global_rfi.rfapi_config.use_removes = 1; /* 0=no */
289
290
291 /* initilize structrfapi_rfp_cb_methods , see rfapi.h */
292 global_rfi.rfapi_callbacks.cfg_cb = rfp_cfg_write_cb;
293 /* no group config */
294 global_rfi.rfapi_callbacks.response_cb = rfp_response_cb;
295 global_rfi.rfapi_callbacks.local_cb = rfp_local_cb;
296 global_rfi.rfapi_callbacks.close_cb = rfp_close_cb;
297
298 if (cfgp != NULL)
299 *cfgp = &global_rfi.rfapi_config;
300 if (cbmp != NULL)
301 *cbmp = &global_rfi.rfapi_callbacks;
302
303 rfp_vty_install();
304
305 return &global_rfi;
306 }
307
308 /*------------------------------------------
309 * rfp_stop
310 *
311 * This function is called on shutdown to trigger RFP cleanup
312 *
313 * input:
314 * none
315 *
316 * output:
317 * none
318 *
319 * return value:
320 * rfp_start_val
321 --------------------------------------------*/
322 void rfp_stop(void *rfp_start_val)
323 {
324 assert(rfp_start_val != NULL);
325 }
326
327 /* TO BE REMOVED */
328 void rfp_clear_vnc_nve_all(void)
329 {
330 return;
331 }