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