66#include "test_skmsg_load_helpers.skel.h"
77#include "test_sockmap_update.skel.h"
88#include "test_sockmap_invalid_update.skel.h"
9+ #include "bpf_iter_sockmap.skel.h"
10+
11+ #include "progs/bpf_iter_sockmap.h"
912
1013#define TCP_REPAIR 19 /* TCP sock is under repair right now */
1114
@@ -193,6 +196,87 @@ static void test_sockmap_invalid_update(void)
193196 test_sockmap_invalid_update__destroy (skel );
194197}
195198
199+ static void test_sockmap_copy (enum bpf_map_type map_type )
200+ {
201+ DECLARE_LIBBPF_OPTS (bpf_iter_attach_opts , opts );
202+ int err , len , src_fd , iter_fd , duration ;
203+ union bpf_iter_link_info linfo = {0 };
204+ __s64 sock_fd [SOCKMAP_MAX_ENTRIES ];
205+ __u32 i , num_sockets , max_elems ;
206+ struct bpf_iter_sockmap * skel ;
207+ struct bpf_map * src , * dst ;
208+ struct bpf_link * link ;
209+ char buf [64 ];
210+
211+ skel = bpf_iter_sockmap__open_and_load ();
212+ if (CHECK (!skel , "bpf_iter_sockmap__open_and_load" , "skeleton open_and_load failed\n" ))
213+ return ;
214+
215+ for (i = 0 ; i < ARRAY_SIZE (sock_fd ); i ++ )
216+ sock_fd [i ] = -1 ;
217+
218+ /* Make sure we have at least one "empty" entry to test iteration of
219+ * an empty slot in an array.
220+ */
221+ num_sockets = ARRAY_SIZE (sock_fd ) - 1 ;
222+
223+ if (map_type == BPF_MAP_TYPE_SOCKMAP ) {
224+ src = skel -> maps .sockmap ;
225+ max_elems = bpf_map__max_entries (src );
226+ } else {
227+ src = skel -> maps .sockhash ;
228+ max_elems = num_sockets ;
229+ }
230+
231+ dst = skel -> maps .dst ;
232+ src_fd = bpf_map__fd (src );
233+
234+ for (i = 0 ; i < num_sockets ; i ++ ) {
235+ sock_fd [i ] = connected_socket_v4 ();
236+ if (CHECK (sock_fd [i ] == -1 , "connected_socket_v4" , "cannot connect\n" ))
237+ goto out ;
238+
239+ err = bpf_map_update_elem (src_fd , & i , & sock_fd [i ], BPF_NOEXIST );
240+ if (CHECK (err , "map_update" , "failed: %s\n" , strerror (errno )))
241+ goto out ;
242+ }
243+
244+ linfo .map .map_fd = src_fd ;
245+ opts .link_info = & linfo ;
246+ opts .link_info_len = sizeof (linfo );
247+ link = bpf_program__attach_iter (skel -> progs .copy_sockmap , & opts );
248+ if (CHECK (IS_ERR (link ), "attach_iter" , "attach_iter failed\n" ))
249+ goto out ;
250+
251+ iter_fd = bpf_iter_create (bpf_link__fd (link ));
252+ if (CHECK (iter_fd < 0 , "create_iter" , "create_iter failed\n" ))
253+ goto free_link ;
254+
255+ /* do some tests */
256+ while ((len = read (iter_fd , buf , sizeof (buf ))) > 0 )
257+ ;
258+ if (CHECK (len < 0 , "read" , "failed: %s\n" , strerror (errno )))
259+ goto close_iter ;
260+
261+ /* test results */
262+ if (CHECK (skel -> bss -> elems != max_elems , "elems" , "got %u expected %u\n" ,
263+ skel -> bss -> elems , max_elems ))
264+ goto close_iter ;
265+
266+ compare_cookies (src , dst );
267+
268+ close_iter :
269+ close (iter_fd );
270+ free_link :
271+ bpf_link__destroy (link );
272+ out :
273+ for (i = 0 ; i < num_sockets ; i ++ ) {
274+ if (sock_fd [i ] >= 0 )
275+ close (sock_fd [i ]);
276+ }
277+ bpf_iter_sockmap__destroy (skel );
278+ }
279+
196280void test_sockmap_basic (void )
197281{
198282 if (test__start_subtest ("sockmap create_update_free" ))
@@ -209,4 +293,8 @@ void test_sockmap_basic(void)
209293 test_sockmap_update (BPF_MAP_TYPE_SOCKHASH );
210294 if (test__start_subtest ("sockmap update in unsafe context" ))
211295 test_sockmap_invalid_update ();
296+ if (test__start_subtest ("sockmap copy" ))
297+ test_sockmap_copy (BPF_MAP_TYPE_SOCKMAP );
298+ if (test__start_subtest ("sockhash copy" ))
299+ test_sockmap_copy (BPF_MAP_TYPE_SOCKHASH );
212300}
0 commit comments