@@ -45,11 +45,8 @@ static const struct option_wrapper long_options[] = {
45
45
{{"force" , no_argument , NULL , 'F' },
46
46
"Force install, replacing existing program on interface" },
47
47
48
- {{"unload" , no_argument , NULL , 'U' },
49
- "Unload XDP program instead of loading" },
50
-
51
- {{"reuse-maps" , no_argument , NULL , 'M' },
52
- "Reuse pinned maps" },
48
+ {{"unload" , required_argument , NULL , 'U' },
49
+ "Unload XDP program <id> instead of loading" , "<id>" },
53
50
54
51
{{"quiet" , no_argument , NULL , 'q' },
55
52
"Quiet mode (no output)" },
@@ -70,14 +67,94 @@ static const struct option_wrapper long_options[] = {
70
67
const char * pin_basedir = "/sys/fs/bpf" ;
71
68
const char * map_name = "xdp_stats_map" ;
72
69
70
+
71
+ /* Load BPF and XDP program with map reuse using libxdp */
72
+ struct xdp_program * load_bpf_and_xdp_attach_reuse_maps (struct config * cfg , const char * pin_dir , bool * map_reused )
73
+ {
74
+ struct xdp_program * prog = NULL ;
75
+ struct bpf_map * map ;
76
+ char map_path [PATH_MAX ];
77
+ int len , pinned_map_fd ;
78
+ int err ;
79
+
80
+ if (!cfg || !cfg -> filename [0 ] || !cfg -> progname [0 ] || !pin_dir || !map_reused ) {
81
+ fprintf (stderr , "ERR: invalid arguments\n" );
82
+ return NULL ;
83
+ }
84
+
85
+ * map_reused = false;
86
+
87
+ /* 1) Create XDP program through libxdp */
88
+ DECLARE_LIBXDP_OPTS (xdp_program_opts , xdp_opts ,
89
+ .prog_name = cfg -> progname ,
90
+ .open_filename = cfg -> filename );
91
+
92
+ prog = xdp_program__create (& xdp_opts );
93
+ if (!prog ) {
94
+ err = errno ;
95
+ fprintf (stderr , "ERR: xdp_program__create: %s\n" , strerror (err ));
96
+ return NULL ;
97
+ }
98
+
99
+ /* 2) Get BPF object from xdp_program and reuse the specific map
100
+ * At this point: BPF object and maps have not been loaded into the kernel
101
+ */
102
+ map = bpf_object__find_map_by_name (xdp_program__bpf_obj (prog ), map_name );
103
+ if (!map ) {
104
+ fprintf (stderr , "ERR: Map %s not found!\n" , map_name );
105
+ goto out ;
106
+ }
107
+
108
+ len = snprintf (map_path , PATH_MAX , "%s/%s" , pin_dir , map_name );
109
+ if (len < 0 || len >= PATH_MAX ) {
110
+ fprintf (stderr , "ERR: map path too long\n" );
111
+ goto out ;
112
+ }
113
+
114
+ pinned_map_fd = bpf_obj_get (map_path );
115
+ if (pinned_map_fd >= 0 ) {
116
+ err = bpf_map__reuse_fd (map , pinned_map_fd );
117
+ if (err ) {
118
+ close (pinned_map_fd );
119
+ fprintf (stderr , "ERR: bpf_map__reuse_fd: %s\n" , strerror (- err ));
120
+ goto out ;
121
+ }
122
+ * map_reused = true;
123
+ if (verbose )
124
+ printf (" - Reusing pinned map: %s\n" , map_path );
125
+ }
126
+
127
+ /* 3) Attach XDP program to interface
128
+ * BPF object will be loaded into the kernel as part of XDP attachment
129
+ */
130
+ err = xdp_program__attach (prog , cfg -> ifindex , cfg -> attach_mode , 0 );
131
+ if (err ) {
132
+ fprintf (stderr , "ERR: xdp_program__attach: %s\n" , strerror (- err ));
133
+ goto out ;
134
+ }
135
+
136
+ return prog ;
137
+
138
+ out :
139
+ xdp_program__close (prog );
140
+ return NULL ;
141
+ }
142
+
73
143
/* Pinning maps under /sys/fs/bpf in subdir */
74
- int pin_maps_in_bpf_object (struct bpf_object * bpf_obj , struct config * cfg )
144
+ int pin_maps_in_bpf_object (struct bpf_object * bpf_obj , const char * subdir )
75
145
{
76
146
char map_filename [PATH_MAX ];
147
+ char pin_dir [PATH_MAX ];
77
148
int err , len ;
78
149
150
+ len = snprintf (pin_dir , PATH_MAX , "%s/%s" , pin_basedir , subdir );
151
+ if (len < 0 ) {
152
+ fprintf (stderr , "ERR: creating pin dirname\n" );
153
+ return EXIT_FAIL_OPTION ;
154
+ }
155
+
79
156
len = snprintf (map_filename , PATH_MAX , "%s/%s/%s" ,
80
- cfg -> pin_dir , cfg -> ifname , map_name );
157
+ pin_basedir , subdir , map_name );
81
158
if (len < 0 ) {
82
159
fprintf (stderr , "ERR: creating map_name\n" );
83
160
return EXIT_FAIL_OPTION ;
@@ -87,22 +164,22 @@ int pin_maps_in_bpf_object(struct bpf_object *bpf_obj, struct config *cfg)
87
164
if (access (map_filename , F_OK ) != -1 ) {
88
165
if (verbose )
89
166
printf (" - Unpinning (remove) prev maps in %s/\n" ,
90
- cfg -> pin_dir );
167
+ pin_dir );
91
168
92
169
/* Basically calls unlink(3) on map_filename */
93
- err = bpf_object__unpin_maps (bpf_obj , cfg -> pin_dir );
170
+ err = bpf_object__unpin_maps (bpf_obj , pin_dir );
94
171
if (err ) {
95
- fprintf (stderr , "ERR: UNpinning maps in %s\n" , cfg -> pin_dir );
172
+ fprintf (stderr , "ERR: UNpinning maps in %s\n" , pin_dir );
96
173
return EXIT_FAIL_BPF ;
97
174
}
98
175
}
99
176
if (verbose )
100
- printf (" - Pinning maps in %s/\n" , cfg -> pin_dir );
177
+ printf (" - Pinning maps in %s/\n" , pin_dir );
101
178
102
179
/* This will pin all maps in our bpf_object */
103
- err = bpf_object__pin_maps (bpf_obj , cfg -> pin_dir );
180
+ err = bpf_object__pin_maps (bpf_obj , pin_dir );
104
181
if (err ) {
105
- fprintf (stderr , "ERR: Pinning maps in %s\n" , cfg -> pin_dir );
182
+ fprintf (stderr , "ERR: Pinning maps in %s\n" , pin_dir );
106
183
return EXIT_FAIL_BPF ;
107
184
}
108
185
@@ -111,8 +188,10 @@ int pin_maps_in_bpf_object(struct bpf_object *bpf_obj, struct config *cfg)
111
188
112
189
int main (int argc , char * * argv )
113
190
{
114
- struct xdp_program * program ;
115
191
int err , len ;
192
+ struct xdp_program * program ;
193
+ bool map_reused = false;
194
+ char path [PATH_MAX ];
116
195
117
196
struct config cfg = {
118
197
.attach_mode = XDP_MODE_NATIVE ,
@@ -131,23 +210,52 @@ int main(int argc, char **argv)
131
210
return EXIT_FAIL_OPTION ;
132
211
}
133
212
if (cfg .do_unload ) {
134
- if (!cfg .reuse_maps ) {
135
- /* TODO: Miss unpin of maps on unload */
213
+ /* unpin the maps */
214
+ len = snprintf (path , PATH_MAX , "%s/%s/%s" , pin_basedir ,
215
+ cfg .ifname , map_name );
216
+ if (len < 0 ) {
217
+ fprintf (stderr , "ERR: creating map filename for unload\n" );
218
+ return EXIT_FAIL_OPTION ;
219
+ }
220
+
221
+ /* If the map file exists, unpin it */
222
+ if (access (path , F_OK ) == 0 ) {
223
+ if (verbose )
224
+ printf (" - Unpinning map %s\n" , path );
225
+
226
+ /* Use unlink to remove the pinned map file */
227
+ err = unlink (path );
228
+ if (err ) {
229
+ fprintf (stderr , "ERR: Failed to unpin map %s: %s\n" ,
230
+ path , strerror (errno ));
231
+ }
136
232
}
137
- /* return xdp_link_detach(cfg.ifindex, cfg.xdp_flags, 0); */
233
+
234
+ /* unload the program */
235
+ err = do_unload (& cfg );
236
+ if (err ) {
237
+ char errmsg [1024 ];
238
+ libxdp_strerror (err , errmsg , sizeof (errmsg ));
239
+ fprintf (stderr , "Couldn't unload XDP program: %s\n" , errmsg );
240
+ return err ;
241
+ }
242
+
243
+ printf ("Success: Unloaded XDP program\n" );
244
+ return EXIT_OK ;
138
245
}
139
246
140
- /* Initialize the pin_dir configuration */
141
- len = snprintf (cfg . pin_dir , 512 , "%s/%s" , pin_basedir , cfg .ifname );
247
+ /* Try to reuse existing pinned maps before loading */
248
+ len = snprintf (path , PATH_MAX , "%s/%s" , pin_basedir , cfg .ifname );
142
249
if (len < 0 ) {
143
250
fprintf (stderr , "ERR: creating pin dirname\n" );
144
251
return EXIT_FAIL_OPTION ;
145
252
}
146
253
147
-
148
- program = load_bpf_and_xdp_attach (& cfg );
149
- if (!program )
150
- return EXIT_FAIL_BPF ;
254
+ program = load_bpf_and_xdp_attach_reuse_maps (& cfg , path , & map_reused );
255
+ if (!program ) {
256
+ err = EXIT_FAIL_BPF ;
257
+ goto out ;
258
+ }
151
259
152
260
if (verbose ) {
153
261
printf ("Success: Loaded BPF-object(%s) and used program(%s)\n" ,
@@ -156,14 +264,18 @@ int main(int argc, char **argv)
156
264
cfg .ifname , cfg .ifindex );
157
265
}
158
266
159
- /* Use the --dev name as subdir for exporting/pinning maps */
160
- if (! cfg . reuse_maps ) {
161
- err = pin_maps_in_bpf_object (xdp_program__bpf_obj (program ), & cfg );
267
+ if (! map_reused ) {
268
+ /* Use the --dev name as subdir for exporting/pinning maps */
269
+ err = pin_maps_in_bpf_object (xdp_program__bpf_obj (program ), cfg . ifname );
162
270
if (err ) {
163
271
fprintf (stderr , "ERR: pinning maps\n" );
164
- return err ;
272
+ goto out ;
165
273
}
166
274
}
167
275
168
- return EXIT_OK ;
276
+ err = EXIT_OK ;
277
+
278
+ out :
279
+ xdp_program__close (program );
280
+ return err ;
169
281
}
0 commit comments