/src/frr/bgpd/rfp-example/librfp/rfp_example.c
Line | Count | Source |
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 event_loop *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 | 0 | { |
38 | 0 | uint32_t value = 0; |
39 | 0 | struct rfp_instance_t *rfi = NULL; |
40 | 0 | rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ |
41 | 0 | assert(rfi != NULL); |
42 | |
|
43 | 0 | value = strtoul(argv[2]->arg, NULL, 10); |
44 | 0 | if (rfi) |
45 | 0 | rfi->config_var = value; |
46 | 0 | return CMD_SUCCESS; |
47 | 0 | } |
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 | 0 | { |
56 | 0 | struct rfp_instance_t *rfi; |
57 | 0 | uint32_t value = 0; |
58 | |
|
59 | 0 | value = strtoul((argv[--argc]->arg), NULL, 10); |
60 | 0 | rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ |
61 | 0 | if (!rfi) { |
62 | 0 | vty_out(vty, "VNC not configured\n"); |
63 | 0 | return CMD_WARNING; |
64 | 0 | } |
65 | 0 | rfi->rfapi_config.holddown_factor = value; |
66 | 0 | rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config); |
67 | 0 | return CMD_SUCCESS; |
68 | 0 | } |
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 | 0 | { |
79 | 0 | struct rfp_instance_t *rfi; |
80 | 0 | rfapi_rfp_download_type old; |
81 | |
|
82 | 0 | rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */ |
83 | 0 | if (!rfi) { |
84 | 0 | vty_out(vty, "VNC not configured\n"); |
85 | 0 | return CMD_WARNING; |
86 | 0 | } |
87 | 0 | old = rfi->rfapi_config.download_type; |
88 | 0 | if (argv[--argc]->arg[1] == 'n' || argv[argc]->arg[1] == 'N') |
89 | 0 | rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_FULL; |
90 | 0 | else |
91 | 0 | rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL; |
92 | 0 | if (old != rfi->rfapi_config.download_type) |
93 | 0 | rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config); |
94 | 0 | return CMD_SUCCESS; |
95 | 0 | } |
96 | | |
97 | | static void rfp_vty_install(void) |
98 | 1 | { |
99 | 1 | static int installed = 0; |
100 | 1 | if (installed) /* do this only once */ |
101 | 0 | return; |
102 | 1 | installed = 1; |
103 | | /* example of new cli command */ |
104 | 1 | install_element(BGP_NODE, &rfp_example_config_value_cmd); |
105 | 1 | install_element(BGP_NODE, &rfp_holddown_factor_cmd); |
106 | 1 | install_element(BGP_NODE, &rfp_full_table_download_cmd); |
107 | 1 | } |
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 | 0 | { |
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 | 0 | rfapi_free_next_hop_list(next_hops); |
153 | 0 | return; |
154 | 0 | } |
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 | 0 | { |
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 | 0 | rfapi_free_next_hop_list(next_hops); |
189 | 0 | return; |
190 | 0 | } |
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 | 0 | { |
208 | | /* close / invalidate NVE with the pHandle returned by the rfapi_open |
209 | | * call */ |
210 | 0 | return; |
211 | 0 | } |
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 | 0 | { |
232 | 0 | struct rfp_instance_t *rfi = rfp_start_val; |
233 | 0 | int write = 0; |
234 | 0 | assert(rfp_start_val != NULL); |
235 | 0 | if (rfi->config_var != 0) { |
236 | 0 | vty_out(vty, " rfp example-config-value %u", rfi->config_var); |
237 | 0 | vty_out(vty, "\n"); |
238 | 0 | write++; |
239 | 0 | } |
240 | 0 | if (rfi->rfapi_config.holddown_factor != 0) { |
241 | 0 | vty_out(vty, " rfp holddown-factor %u\n", |
242 | 0 | rfi->rfapi_config.holddown_factor); |
243 | 0 | write++; |
244 | 0 | } |
245 | 0 | if (rfi->rfapi_config.download_type == RFAPI_RFP_DOWNLOAD_FULL) { |
246 | 0 | vty_out(vty, " rfp full-table-download on\n"); |
247 | 0 | write++; |
248 | 0 | } |
249 | 0 | return write; |
250 | 0 | } |
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 event_loop *master, struct rfapi_rfp_cfg **cfgp, |
275 | | struct rfapi_rfp_cb_methods **cbmp) |
276 | 1 | { |
277 | 1 | memset(&global_rfi, 0, sizeof(global_rfi)); |
278 | 1 | global_rfi.master = master; /* for BGPD threads */ |
279 | | |
280 | | /* initilize struct rfapi_rfp_cfg, see rfapi.h */ |
281 | 1 | global_rfi.rfapi_config.download_type = |
282 | 1 | RFAPI_RFP_DOWNLOAD_PARTIAL; /* default=partial */ |
283 | 1 | global_rfi.rfapi_config.ftd_advertisement_interval = |
284 | 1 | RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL; |
285 | 1 | global_rfi.rfapi_config.holddown_factor = |
286 | 1 | 0; /* default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */ |
287 | 1 | global_rfi.rfapi_config.use_updated_response = 1; /* 0=no */ |
288 | 1 | global_rfi.rfapi_config.use_removes = 1; /* 0=no */ |
289 | | |
290 | | |
291 | | /* initilize structrfapi_rfp_cb_methods , see rfapi.h */ |
292 | 1 | global_rfi.rfapi_callbacks.cfg_cb = rfp_cfg_write_cb; |
293 | | /* no group config */ |
294 | 1 | global_rfi.rfapi_callbacks.response_cb = rfp_response_cb; |
295 | 1 | global_rfi.rfapi_callbacks.local_cb = rfp_local_cb; |
296 | 1 | global_rfi.rfapi_callbacks.close_cb = rfp_close_cb; |
297 | | |
298 | 1 | if (cfgp != NULL) |
299 | 1 | *cfgp = &global_rfi.rfapi_config; |
300 | 1 | if (cbmp != NULL) |
301 | 1 | *cbmp = &global_rfi.rfapi_callbacks; |
302 | | |
303 | 1 | rfp_vty_install(); |
304 | | |
305 | 1 | return &global_rfi; |
306 | 1 | } |
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 | 0 | { |
324 | 0 | assert(rfp_start_val != NULL); |
325 | 0 | } |
326 | | |
327 | | /* TO BE REMOVED */ |
328 | | void rfp_clear_vnc_nve_all(void) |
329 | 0 | { |
330 | 0 | return; |
331 | 0 | } |