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
|
/*
* Sample plugin for the FRR zebra dataplane.
*
* Copyright (c) 2019 Volta Networks, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Should be possible to build this plugin using this sort of command:
*
* gcc -I ~/work/frr/ -I ~/work/frr/lib -I ~/work/frr/zebra \
* -g -O0 -o sample_plugin.so -shared -fPIC sample_plugin.c
*
* where 'frr' is a configured and built frr sandbox.
*
* Run zebra with '-M /path/to/sample_plugin.so' to load the module.
*/
#include "config.h" /* Include this explicitly */
#include "lib/zebra.h"
#include "lib/libfrr.h"
#include "zebra/zebra_dplane.h"
#include "zebra/debug.h"
static const char *plugin_name = "SAMPLE";
static struct zebra_dplane_provider *prov_p;
/*
* Startup/init callback, called from the dataplane.
*/
static int sample_start(struct zebra_dplane_provider *prov)
{
/* Nothing special to do - we don't allocate anything. */
return 0;
}
/*
* Shutdown/cleanup callback, called from the dataplane pthread.
*/
static int sample_fini(struct zebra_dplane_provider *prov, bool early)
{
/* Nothing special to do. */
return 0;
}
/*
* Callback from the dataplane to process incoming work; this runs in the
* dplane pthread.
*/
static int sample_process(struct zebra_dplane_provider *prov)
{
int counter, limit;
struct zebra_dplane_ctx *ctx;
limit = dplane_provider_get_work_limit(prov_p);
/* Respect the configured limit on the amount of work to do in
* any one call.
*/
for (counter = 0; counter < limit; counter++) {
ctx = dplane_provider_dequeue_in_ctx(prov_p);
if (!ctx)
break;
/* Just set 'success' status and return to the dataplane */
dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS);
dplane_provider_enqueue_out_ctx(prov_p, ctx);
}
return 0;
}
/*
* Init entry point called during zebra startup. This is registered during
* module init.
*/
static int init_sample_plugin(struct thread_master *tm)
{
int ret;
/* Note that we don't use or store the thread_master 'tm'. We
* don't use the zebra main pthread: our plugin code will run in
* the zebra dataplane pthread context.
*/
/* Register the plugin with the dataplane infrastructure. We
* register to be called before the kernel, and we register
* our init, process work, and shutdown callbacks.
*/
ret = dplane_provider_register(plugin_name, DPLANE_PRIO_PRE_KERNEL,
DPLANE_PROV_FLAGS_DEFAULT,
sample_start,
sample_process,
sample_fini,
NULL,
&prov_p);
if (IS_ZEBRA_DEBUG_DPLANE)
zlog_debug("sample plugin register => %d", ret);
return 0;
}
/*
* Base FRR loadable module info: basic info including module entry-point.
*/
static int module_init(void)
{
hook_register(frr_late_init, init_sample_plugin);
return 0;
}
FRR_MODULE_SETUP(
.name = "dplane_sample",
.version = "0.0.1",
.description = "Dataplane Sample Plugin",
.init = module_init,
);
|