18
18
#include <string.h>
19
19
#include <sys/select.h>
20
20
#include <unistd.h>
21
+ #include <linux/vm_sockets.h>
21
22
22
23
#include <bpf/bpf.h>
23
24
#include <bpf/libbpf.h>
@@ -251,6 +252,16 @@ static void init_addr_loopback6(struct sockaddr_storage *ss, socklen_t *len)
251
252
* len = sizeof (* addr6 );
252
253
}
253
254
255
+ static void init_addr_loopback_vsock (struct sockaddr_storage * ss , socklen_t * len )
256
+ {
257
+ struct sockaddr_vm * addr = memset (ss , 0 , sizeof (* ss ));
258
+
259
+ addr -> svm_family = AF_VSOCK ;
260
+ addr -> svm_port = VMADDR_PORT_ANY ;
261
+ addr -> svm_cid = VMADDR_CID_LOCAL ;
262
+ * len = sizeof (* addr );
263
+ }
264
+
254
265
static void init_addr_loopback (int family , struct sockaddr_storage * ss ,
255
266
socklen_t * len )
256
267
{
@@ -261,6 +272,9 @@ static void init_addr_loopback(int family, struct sockaddr_storage *ss,
261
272
case AF_INET6 :
262
273
init_addr_loopback6 (ss , len );
263
274
return ;
275
+ case AF_VSOCK :
276
+ init_addr_loopback_vsock (ss , len );
277
+ return ;
264
278
default :
265
279
FAIL ("unsupported address family %d" , family );
266
280
}
@@ -1478,6 +1492,8 @@ static const char *family_str(sa_family_t family)
1478
1492
return "IPv6" ;
1479
1493
case AF_UNIX :
1480
1494
return "Unix" ;
1495
+ case AF_VSOCK :
1496
+ return "VSOCK" ;
1481
1497
default :
1482
1498
return "unknown" ;
1483
1499
}
@@ -1689,6 +1705,151 @@ static void test_unix_redir(struct test_sockmap_listen *skel, struct bpf_map *ma
1689
1705
unix_skb_redir_to_connected (skel , map , sotype );
1690
1706
}
1691
1707
1708
+ /* Returns two connected loopback vsock sockets */
1709
+ static int vsock_socketpair_connectible (int sotype , int * v0 , int * v1 )
1710
+ {
1711
+ struct sockaddr_storage addr ;
1712
+ socklen_t len = sizeof (addr );
1713
+ int s , p , c ;
1714
+
1715
+ s = socket_loopback (AF_VSOCK , sotype );
1716
+ if (s < 0 )
1717
+ return -1 ;
1718
+
1719
+ c = xsocket (AF_VSOCK , sotype | SOCK_NONBLOCK , 0 );
1720
+ if (c == -1 )
1721
+ goto close_srv ;
1722
+
1723
+ if (getsockname (s , sockaddr (& addr ), & len ) < 0 )
1724
+ goto close_cli ;
1725
+
1726
+ if (connect (c , sockaddr (& addr ), len ) < 0 && errno != EINPROGRESS ) {
1727
+ FAIL_ERRNO ("connect" );
1728
+ goto close_cli ;
1729
+ }
1730
+
1731
+ len = sizeof (addr );
1732
+ p = accept_timeout (s , sockaddr (& addr ), & len , IO_TIMEOUT_SEC );
1733
+ if (p < 0 )
1734
+ goto close_cli ;
1735
+
1736
+ * v0 = p ;
1737
+ * v1 = c ;
1738
+
1739
+ return 0 ;
1740
+
1741
+ close_cli :
1742
+ close (c );
1743
+ close_srv :
1744
+ close (s );
1745
+
1746
+ return -1 ;
1747
+ }
1748
+
1749
+ static void vsock_unix_redir_connectible (int sock_mapfd , int verd_mapfd ,
1750
+ enum redir_mode mode , int sotype )
1751
+ {
1752
+ const char * log_prefix = redir_mode_str (mode );
1753
+ char a = 'a' , b = 'b' ;
1754
+ int u0 , u1 , v0 , v1 ;
1755
+ int sfd [2 ];
1756
+ unsigned int pass ;
1757
+ int err , n ;
1758
+ u32 key ;
1759
+
1760
+ zero_verdict_count (verd_mapfd );
1761
+
1762
+ if (socketpair (AF_UNIX , SOCK_STREAM | SOCK_NONBLOCK , 0 , sfd ))
1763
+ return ;
1764
+
1765
+ u0 = sfd [0 ];
1766
+ u1 = sfd [1 ];
1767
+
1768
+ err = vsock_socketpair_connectible (sotype , & v0 , & v1 );
1769
+ if (err ) {
1770
+ FAIL ("vsock_socketpair_connectible() failed" );
1771
+ goto close_uds ;
1772
+ }
1773
+
1774
+ err = add_to_sockmap (sock_mapfd , u0 , v0 );
1775
+ if (err ) {
1776
+ FAIL ("add_to_sockmap failed" );
1777
+ goto close_vsock ;
1778
+ }
1779
+
1780
+ n = write (v1 , & a , sizeof (a ));
1781
+ if (n < 0 )
1782
+ FAIL_ERRNO ("%s: write" , log_prefix );
1783
+ if (n == 0 )
1784
+ FAIL ("%s: incomplete write" , log_prefix );
1785
+ if (n < 1 )
1786
+ goto out ;
1787
+
1788
+ n = recv (mode == REDIR_INGRESS ? u0 : u1 , & b , sizeof (b ), MSG_DONTWAIT );
1789
+ if (n < 0 )
1790
+ FAIL ("%s: recv() err, errno=%d" , log_prefix , errno );
1791
+ if (n == 0 )
1792
+ FAIL ("%s: incomplete recv" , log_prefix );
1793
+ if (b != a )
1794
+ FAIL ("%s: vsock socket map failed, %c != %c" , log_prefix , a , b );
1795
+
1796
+ key = SK_PASS ;
1797
+ err = xbpf_map_lookup_elem (verd_mapfd , & key , & pass );
1798
+ if (err )
1799
+ goto out ;
1800
+ if (pass != 1 )
1801
+ FAIL ("%s: want pass count 1, have %d" , log_prefix , pass );
1802
+ out :
1803
+ key = 0 ;
1804
+ bpf_map_delete_elem (sock_mapfd , & key );
1805
+ key = 1 ;
1806
+ bpf_map_delete_elem (sock_mapfd , & key );
1807
+
1808
+ close_vsock :
1809
+ close (v0 );
1810
+ close (v1 );
1811
+
1812
+ close_uds :
1813
+ close (u0 );
1814
+ close (u1 );
1815
+ }
1816
+
1817
+ static void vsock_unix_skb_redir_connectible (struct test_sockmap_listen * skel ,
1818
+ struct bpf_map * inner_map ,
1819
+ int sotype )
1820
+ {
1821
+ int verdict = bpf_program__fd (skel -> progs .prog_skb_verdict );
1822
+ int verdict_map = bpf_map__fd (skel -> maps .verdict_map );
1823
+ int sock_map = bpf_map__fd (inner_map );
1824
+ int err ;
1825
+
1826
+ err = xbpf_prog_attach (verdict , sock_map , BPF_SK_SKB_VERDICT , 0 );
1827
+ if (err )
1828
+ return ;
1829
+
1830
+ skel -> bss -> test_ingress = false;
1831
+ vsock_unix_redir_connectible (sock_map , verdict_map , REDIR_EGRESS , sotype );
1832
+ skel -> bss -> test_ingress = true;
1833
+ vsock_unix_redir_connectible (sock_map , verdict_map , REDIR_INGRESS , sotype );
1834
+
1835
+ xbpf_prog_detach2 (verdict , sock_map , BPF_SK_SKB_VERDICT );
1836
+ }
1837
+
1838
+ static void test_vsock_redir (struct test_sockmap_listen * skel , struct bpf_map * map )
1839
+ {
1840
+ const char * family_name , * map_name ;
1841
+ char s [MAX_TEST_NAME ];
1842
+
1843
+ family_name = family_str (AF_VSOCK );
1844
+ map_name = map_type_str (map );
1845
+ snprintf (s , sizeof (s ), "%s %s %s" , map_name , family_name , __func__ );
1846
+ if (!test__start_subtest (s ))
1847
+ return ;
1848
+
1849
+ vsock_unix_skb_redir_connectible (skel , map , SOCK_STREAM );
1850
+ vsock_unix_skb_redir_connectible (skel , map , SOCK_SEQPACKET );
1851
+ }
1852
+
1692
1853
static void test_reuseport (struct test_sockmap_listen * skel ,
1693
1854
struct bpf_map * map , int family , int sotype )
1694
1855
{
@@ -2060,12 +2221,14 @@ void serial_test_sockmap_listen(void)
2060
2221
run_tests (skel , skel -> maps .sock_map , AF_INET6 );
2061
2222
test_unix_redir (skel , skel -> maps .sock_map , SOCK_DGRAM );
2062
2223
test_unix_redir (skel , skel -> maps .sock_map , SOCK_STREAM );
2224
+ test_vsock_redir (skel , skel -> maps .sock_map );
2063
2225
2064
2226
skel -> bss -> test_sockmap = false;
2065
2227
run_tests (skel , skel -> maps .sock_hash , AF_INET );
2066
2228
run_tests (skel , skel -> maps .sock_hash , AF_INET6 );
2067
2229
test_unix_redir (skel , skel -> maps .sock_hash , SOCK_DGRAM );
2068
2230
test_unix_redir (skel , skel -> maps .sock_hash , SOCK_STREAM );
2231
+ test_vsock_redir (skel , skel -> maps .sock_hash );
2069
2232
2070
2233
test_sockmap_listen__destroy (skel );
2071
2234
}
0 commit comments