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
|
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Sample plugin for the FRR zebra dataplane.
*
* Copyright (c) 2019 Volta Networks, Inc.
*/
/*
* 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,
);
|