mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
bpf-next-for-netdev
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQTFp0I1jqZrAX+hPRXbK58LschIgwUCZsiMrQAKCRDbK58LschI g1mtAP9wBoNO9sNRrJ2OUg69R5uSTT2//v7icN01xwVtx9ir/AD+PJ+v/WG1QVlM 6GNsPoGtQ53ptuiJFfXEkuVELGqKywY= =I/T4 -----END PGP SIGNATURE----- Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next Daniel Borkmann says: ==================== pull-request: bpf-next 2024-08-23 We've added 10 non-merge commits during the last 15 day(s) which contain a total of 10 files changed, 222 insertions(+), 190 deletions(-). The main changes are: 1) Add TCP_BPF_SOCK_OPS_CB_FLAGS to bpf_*sockopt() to address the case when long-lived sockets miss a chance to set additional callbacks if a sockops program was not attached early in their lifetime, from Alan Maguire. 2) Add a batch of BPF selftest improvements which fix a few bugs and add missing features to improve the test coverage of sockmap/sockhash, from Michal Luczaj. 3) Fix a false-positive Smatch-reported off-by-one in tcp_validate_cookie() which is part of the test_tcp_custom_syncookie BPF selftest, from Kuniyuki Iwashima. 4) Fix the flow_dissector BPF selftest which had a bug in IP header's tot_len calculation doing subtraction after htons() instead of inside htons(), from Asbjørn Sloth Tønnesen. * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: selftest: bpf: Remove mssind boundary check in test_tcp_custom_syncookie.c. selftests/bpf: Introduce __attribute__((cleanup)) in create_pair() selftests/bpf: Exercise SOCK_STREAM unix_inet_redir_to_connected() selftests/bpf: Honour the sotype of af_unix redir tests selftests/bpf: Simplify inet_socketpair() and vsock_socketpair_connectible() selftests/bpf: Socket pair creation, cleanups selftests/bpf: Support more socket types in create_pair() selftests/bpf: Avoid subtraction after htons() in ipip tests selftests/bpf: add sockopt tests for TCP_BPF_SOCK_OPS_CB_FLAGS bpf/bpf_get,set_sockopt: add option to set TCP-BPF sock ops flags ==================== Link: https://patch.msgid.link/20240823134959.1091-1-daniel@iogearbox.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
e540e3bcf2
|
|
@ -2851,7 +2851,7 @@ union bpf_attr {
|
|||
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
||||
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
||||
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
||||
* **TCP_BPF_RTO_MIN**.
|
||||
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
|
||||
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
||||
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
||||
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
||||
|
|
@ -7080,6 +7080,7 @@ enum {
|
|||
TCP_BPF_SYN = 1005, /* Copy the TCP header */
|
||||
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
|
||||
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
|
||||
TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -5279,6 +5279,11 @@ static int bpf_sol_tcp_setsockopt(struct sock *sk, int optname,
|
|||
return -EINVAL;
|
||||
inet_csk(sk)->icsk_rto_min = timeout;
|
||||
break;
|
||||
case TCP_BPF_SOCK_OPS_CB_FLAGS:
|
||||
if (val & ~(BPF_SOCK_OPS_ALL_CB_FLAGS))
|
||||
return -EINVAL;
|
||||
tp->bpf_sock_ops_cb_flags = val;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -5367,6 +5372,17 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
|
|||
if (*optlen < 1)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case TCP_BPF_SOCK_OPS_CB_FLAGS:
|
||||
if (*optlen != sizeof(int))
|
||||
return -EINVAL;
|
||||
if (getopt) {
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
int cb_flags = tp->bpf_sock_ops_cb_flags;
|
||||
|
||||
memcpy(optval, &cb_flags, *optlen);
|
||||
return 0;
|
||||
}
|
||||
return bpf_sol_tcp_setsockopt(sk, optname, optval, *optlen);
|
||||
default:
|
||||
if (getopt)
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -2851,7 +2851,7 @@ union bpf_attr {
|
|||
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
||||
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
||||
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
||||
* **TCP_BPF_RTO_MIN**.
|
||||
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
|
||||
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
||||
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
||||
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
||||
|
|
@ -7080,6 +7080,7 @@ enum {
|
|||
TCP_BPF_SYN = 1005, /* Copy the TCP header */
|
||||
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
|
||||
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
|
||||
TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ struct test tests[] = {
|
|||
.iph_inner.ihl = 5,
|
||||
.iph_inner.protocol = IPPROTO_TCP,
|
||||
.iph_inner.tot_len =
|
||||
__bpf_constant_htons(MAGIC_BYTES) -
|
||||
sizeof(struct iphdr),
|
||||
__bpf_constant_htons(MAGIC_BYTES -
|
||||
sizeof(struct iphdr)),
|
||||
.tcp.doff = 5,
|
||||
.tcp.source = 80,
|
||||
.tcp.dest = 8080,
|
||||
|
|
@ -407,8 +407,8 @@ struct test tests[] = {
|
|||
.iph_inner.ihl = 5,
|
||||
.iph_inner.protocol = IPPROTO_TCP,
|
||||
.iph_inner.tot_len =
|
||||
__bpf_constant_htons(MAGIC_BYTES) -
|
||||
sizeof(struct iphdr),
|
||||
__bpf_constant_htons(MAGIC_BYTES -
|
||||
sizeof(struct iphdr)),
|
||||
.tcp.doff = 5,
|
||||
.tcp.source = 80,
|
||||
.tcp.dest = 8080,
|
||||
|
|
@ -436,8 +436,8 @@ struct test tests[] = {
|
|||
.iph_inner.ihl = 5,
|
||||
.iph_inner.protocol = IPPROTO_TCP,
|
||||
.iph_inner.tot_len =
|
||||
__bpf_constant_htons(MAGIC_BYTES) -
|
||||
sizeof(struct iphdr),
|
||||
__bpf_constant_htons(MAGIC_BYTES -
|
||||
sizeof(struct iphdr)),
|
||||
.tcp.doff = 5,
|
||||
.tcp.source = 99,
|
||||
.tcp.dest = 9090,
|
||||
|
|
|
|||
|
|
@ -154,6 +154,51 @@ static void test_ktls(int family)
|
|||
close(sfd);
|
||||
}
|
||||
|
||||
static void test_nonstandard_opt(int family)
|
||||
{
|
||||
struct setget_sockopt__bss *bss = skel->bss;
|
||||
struct bpf_link *getsockopt_link = NULL;
|
||||
int sfd = -1, fd = -1, cfd = -1, flags;
|
||||
socklen_t flagslen = sizeof(flags);
|
||||
|
||||
memset(bss, 0, sizeof(*bss));
|
||||
|
||||
sfd = start_server(family, SOCK_STREAM,
|
||||
family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
|
||||
if (!ASSERT_GE(sfd, 0, "start_server"))
|
||||
return;
|
||||
|
||||
fd = connect_to_fd(sfd, 0);
|
||||
if (!ASSERT_GE(fd, 0, "connect_to_fd_server"))
|
||||
goto err_out;
|
||||
|
||||
/* cgroup/getsockopt prog will intercept getsockopt() below and
|
||||
* retrieve the tcp socket bpf_sock_ops_cb_flags value for the
|
||||
* accept()ed socket; this was set earlier in the passive established
|
||||
* callback for the accept()ed socket via bpf_setsockopt().
|
||||
*/
|
||||
getsockopt_link = bpf_program__attach_cgroup(skel->progs._getsockopt, cg_fd);
|
||||
if (!ASSERT_OK_PTR(getsockopt_link, "getsockopt prog"))
|
||||
goto err_out;
|
||||
|
||||
cfd = accept(sfd, NULL, 0);
|
||||
if (!ASSERT_GE(cfd, 0, "accept"))
|
||||
goto err_out;
|
||||
|
||||
if (!ASSERT_OK(getsockopt(cfd, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, &flagslen),
|
||||
"getsockopt_flags"))
|
||||
goto err_out;
|
||||
ASSERT_EQ(flags & BPF_SOCK_OPS_STATE_CB_FLAG, BPF_SOCK_OPS_STATE_CB_FLAG,
|
||||
"cb_flags_set");
|
||||
err_out:
|
||||
close(sfd);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
if (cfd != -1)
|
||||
close(cfd);
|
||||
bpf_link__destroy(getsockopt_link);
|
||||
}
|
||||
|
||||
void test_setget_sockopt(void)
|
||||
{
|
||||
cg_fd = test__join_cgroup(CG_NAME);
|
||||
|
|
@ -191,6 +236,8 @@ void test_setget_sockopt(void)
|
|||
test_udp(AF_INET);
|
||||
test_ktls(AF_INET6);
|
||||
test_ktls(AF_INET);
|
||||
test_nonstandard_opt(AF_INET);
|
||||
test_nonstandard_opt(AF_INET6);
|
||||
|
||||
done:
|
||||
setget_sockopt__destroy(skel);
|
||||
|
|
|
|||
|
|
@ -451,11 +451,11 @@ static void test_sockmap_progs_query(enum bpf_attach_type attach_type)
|
|||
#define MAX_EVENTS 10
|
||||
static void test_sockmap_skb_verdict_shutdown(void)
|
||||
{
|
||||
int n, err, map, verdict, c1 = -1, p1 = -1;
|
||||
struct epoll_event ev, events[MAX_EVENTS];
|
||||
int n, err, map, verdict, s, c1 = -1, p1 = -1;
|
||||
struct test_sockmap_pass_prog *skel;
|
||||
int epollfd;
|
||||
int zero = 0;
|
||||
int epollfd;
|
||||
char b;
|
||||
|
||||
skel = test_sockmap_pass_prog__open_and_load();
|
||||
|
|
@ -469,10 +469,7 @@ static void test_sockmap_skb_verdict_shutdown(void)
|
|||
if (!ASSERT_OK(err, "bpf_prog_attach"))
|
||||
goto out;
|
||||
|
||||
s = socket_loopback(AF_INET, SOCK_STREAM);
|
||||
if (s < 0)
|
||||
goto out;
|
||||
err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1);
|
||||
err = create_pair(AF_INET, SOCK_STREAM, &c1, &p1);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
|
|
@ -506,8 +503,8 @@ static void test_sockmap_skb_verdict_shutdown(void)
|
|||
|
||||
static void test_sockmap_skb_verdict_fionread(bool pass_prog)
|
||||
{
|
||||
int err, map, verdict, c0 = -1, c1 = -1, p0 = -1, p1 = -1;
|
||||
int expected, zero = 0, sent, recvd, avail;
|
||||
int err, map, verdict, s, c0 = -1, c1 = -1, p0 = -1, p1 = -1;
|
||||
struct test_sockmap_pass_prog *pass = NULL;
|
||||
struct test_sockmap_drop_prog *drop = NULL;
|
||||
char buf[256] = "0123456789";
|
||||
|
|
@ -534,11 +531,8 @@ static void test_sockmap_skb_verdict_fionread(bool pass_prog)
|
|||
if (!ASSERT_OK(err, "bpf_prog_attach"))
|
||||
goto out;
|
||||
|
||||
s = socket_loopback(AF_INET, SOCK_STREAM);
|
||||
if (!ASSERT_GT(s, -1, "socket_loopback(s)"))
|
||||
goto out;
|
||||
err = create_socket_pairs(s, AF_INET, SOCK_STREAM, &c0, &c1, &p0, &p1);
|
||||
if (!ASSERT_OK(err, "create_socket_pairs(s)"))
|
||||
err = create_socket_pairs(AF_INET, SOCK_STREAM, &c0, &c1, &p0, &p1);
|
||||
if (!ASSERT_OK(err, "create_socket_pairs()"))
|
||||
goto out;
|
||||
|
||||
err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
|
||||
|
|
@ -570,16 +564,12 @@ static void test_sockmap_skb_verdict_fionread(bool pass_prog)
|
|||
|
||||
static void test_sockmap_skb_verdict_peek_helper(int map)
|
||||
{
|
||||
int err, s, c1, p1, zero = 0, sent, recvd, avail;
|
||||
int err, c1, p1, zero = 0, sent, recvd, avail;
|
||||
char snd[256] = "0123456789";
|
||||
char rcv[256] = "0";
|
||||
|
||||
s = socket_loopback(AF_INET, SOCK_STREAM);
|
||||
if (!ASSERT_GT(s, -1, "socket_loopback(s)"))
|
||||
return;
|
||||
|
||||
err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1);
|
||||
if (!ASSERT_OK(err, "create_pairs(s)"))
|
||||
err = create_pair(AF_INET, SOCK_STREAM, &c1, &p1);
|
||||
if (!ASSERT_OK(err, "create_pair()"))
|
||||
return;
|
||||
|
||||
err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include <linux/vm_sockets.h>
|
||||
|
||||
/* include/linux/net.h */
|
||||
#define SOCK_TYPE_MASK 0xf
|
||||
|
||||
#define IO_TIMEOUT_SEC 30
|
||||
#define MAX_STRERR_LEN 256
|
||||
#define MAX_TEST_NAME 80
|
||||
|
|
@ -14,6 +17,17 @@
|
|||
|
||||
#define __always_unused __attribute__((__unused__))
|
||||
|
||||
/* include/linux/cleanup.h */
|
||||
#define __get_and_null(p, nullvalue) \
|
||||
({ \
|
||||
__auto_type __ptr = &(p); \
|
||||
__auto_type __val = *__ptr; \
|
||||
*__ptr = nullvalue; \
|
||||
__val; \
|
||||
})
|
||||
|
||||
#define take_fd(fd) __get_and_null(fd, -EBADF)
|
||||
|
||||
#define _FAIL(errnum, fmt...) \
|
||||
({ \
|
||||
error_at_line(0, (errnum), __func__, __LINE__, fmt); \
|
||||
|
|
@ -179,6 +193,14 @@
|
|||
__ret; \
|
||||
})
|
||||
|
||||
static inline void close_fd(int *fd)
|
||||
{
|
||||
if (*fd >= 0)
|
||||
xclose(*fd);
|
||||
}
|
||||
|
||||
#define __close_fd __attribute__((cleanup(close_fd)))
|
||||
|
||||
static inline int poll_connect(int fd, unsigned int timeout_sec)
|
||||
{
|
||||
struct timeval timeout = { .tv_sec = timeout_sec };
|
||||
|
|
@ -312,54 +334,6 @@ static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
|
|||
return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
|
||||
}
|
||||
|
||||
static inline int create_pair(int s, int family, int sotype, int *c, int *p)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
int err = 0;
|
||||
|
||||
len = sizeof(addr);
|
||||
err = xgetsockname(s, sockaddr(&addr), &len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*c = xsocket(family, sotype, 0);
|
||||
if (*c < 0)
|
||||
return errno;
|
||||
err = xconnect(*c, sockaddr(&addr), len);
|
||||
if (err) {
|
||||
err = errno;
|
||||
goto close_cli0;
|
||||
}
|
||||
|
||||
*p = xaccept_nonblock(s, NULL, NULL);
|
||||
if (*p < 0) {
|
||||
err = errno;
|
||||
goto close_cli0;
|
||||
}
|
||||
return err;
|
||||
close_cli0:
|
||||
close(*c);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int create_socket_pairs(int s, int family, int sotype,
|
||||
int *c0, int *c1, int *p0, int *p1)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = create_pair(s, family, sotype, c0, p0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = create_pair(s, family, sotype, c1, p1);
|
||||
if (err) {
|
||||
close(*c0);
|
||||
close(*p0);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int enable_reuseport(int s, int progfd)
|
||||
{
|
||||
int err, one = 1;
|
||||
|
|
@ -412,5 +386,84 @@ static inline int socket_loopback(int family, int sotype)
|
|||
return socket_loopback_reuseport(family, sotype, -1);
|
||||
}
|
||||
|
||||
static inline int create_pair(int family, int sotype, int *p0, int *p1)
|
||||
{
|
||||
__close_fd int s, c = -1, p = -1;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
int err;
|
||||
|
||||
s = socket_loopback(family, sotype);
|
||||
if (s < 0)
|
||||
return s;
|
||||
|
||||
err = xgetsockname(s, sockaddr(&addr), &len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
c = xsocket(family, sotype, 0);
|
||||
if (c < 0)
|
||||
return c;
|
||||
|
||||
err = connect(c, sockaddr(&addr), len);
|
||||
if (err) {
|
||||
if (errno != EINPROGRESS) {
|
||||
FAIL_ERRNO("connect");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = poll_connect(c, IO_TIMEOUT_SEC);
|
||||
if (err) {
|
||||
FAIL_ERRNO("poll_connect");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
switch (sotype & SOCK_TYPE_MASK) {
|
||||
case SOCK_DGRAM:
|
||||
err = xgetsockname(c, sockaddr(&addr), &len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xconnect(s, sockaddr(&addr), len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*p0 = take_fd(s);
|
||||
break;
|
||||
case SOCK_STREAM:
|
||||
case SOCK_SEQPACKET:
|
||||
p = xaccept_nonblock(s, NULL, NULL);
|
||||
if (p < 0)
|
||||
return p;
|
||||
|
||||
*p0 = take_fd(p);
|
||||
break;
|
||||
default:
|
||||
FAIL("Unsupported socket type %#x", sotype);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*p1 = take_fd(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int create_socket_pairs(int family, int sotype, int *c0, int *c1,
|
||||
int *p0, int *p1)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = create_pair(family, sotype, c0, p0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = create_pair(family, sotype, c1, p1);
|
||||
if (err) {
|
||||
close(*c0);
|
||||
close(*p0);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif // __SOCKMAP_HELPERS__
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
|
|||
int verd_mapfd, enum redir_mode mode)
|
||||
{
|
||||
const char *log_prefix = redir_mode_str(mode);
|
||||
int s, c0, c1, p0, p1;
|
||||
int c0, c1, p0, p1;
|
||||
unsigned int pass;
|
||||
int err, n;
|
||||
u32 key;
|
||||
|
|
@ -685,13 +685,10 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
|
|||
|
||||
zero_verdict_count(verd_mapfd);
|
||||
|
||||
s = socket_loopback(family, sotype | SOCK_NONBLOCK);
|
||||
if (s < 0)
|
||||
return;
|
||||
|
||||
err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
|
||||
err = create_socket_pairs(family, sotype | SOCK_NONBLOCK, &c0, &c1,
|
||||
&p0, &p1);
|
||||
if (err)
|
||||
goto close_srv;
|
||||
return;
|
||||
|
||||
err = add_to_sockmap(sock_mapfd, p0, p1);
|
||||
if (err)
|
||||
|
|
@ -722,8 +719,6 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
|
|||
xclose(c1);
|
||||
xclose(p0);
|
||||
xclose(c0);
|
||||
close_srv:
|
||||
xclose(s);
|
||||
}
|
||||
|
||||
static void test_skb_redir_to_connected(struct test_sockmap_listen *skel,
|
||||
|
|
@ -909,7 +904,7 @@ static void test_msg_redir_to_listening_with_link(struct test_sockmap_listen *sk
|
|||
|
||||
static void redir_partial(int family, int sotype, int sock_map, int parser_map)
|
||||
{
|
||||
int s, c0 = -1, c1 = -1, p0 = -1, p1 = -1;
|
||||
int c0 = -1, c1 = -1, p0 = -1, p1 = -1;
|
||||
int err, n, key, value;
|
||||
char buf[] = "abc";
|
||||
|
||||
|
|
@ -919,13 +914,10 @@ static void redir_partial(int family, int sotype, int sock_map, int parser_map)
|
|||
if (err)
|
||||
return;
|
||||
|
||||
s = socket_loopback(family, sotype | SOCK_NONBLOCK);
|
||||
if (s < 0)
|
||||
goto clean_parser_map;
|
||||
|
||||
err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
|
||||
err = create_socket_pairs(family, sotype | SOCK_NONBLOCK, &c0, &c1,
|
||||
&p0, &p1);
|
||||
if (err)
|
||||
goto close_srv;
|
||||
goto clean_parser_map;
|
||||
|
||||
err = add_to_sockmap(sock_map, p0, p1);
|
||||
if (err)
|
||||
|
|
@ -944,8 +936,6 @@ static void redir_partial(int family, int sotype, int sock_map, int parser_map)
|
|||
xclose(p0);
|
||||
xclose(c1);
|
||||
xclose(p1);
|
||||
close_srv:
|
||||
xclose(s);
|
||||
|
||||
clean_parser_map:
|
||||
key = 0;
|
||||
|
|
@ -1500,49 +1490,7 @@ static void test_unix_redir(struct test_sockmap_listen *skel, struct bpf_map *ma
|
|||
/* Returns two connected loopback vsock sockets */
|
||||
static int vsock_socketpair_connectible(int sotype, int *v0, int *v1)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
int s, p, c;
|
||||
|
||||
s = socket_loopback(AF_VSOCK, sotype);
|
||||
if (s < 0)
|
||||
return -1;
|
||||
|
||||
c = xsocket(AF_VSOCK, sotype | SOCK_NONBLOCK, 0);
|
||||
if (c == -1)
|
||||
goto close_srv;
|
||||
|
||||
if (getsockname(s, sockaddr(&addr), &len) < 0)
|
||||
goto close_cli;
|
||||
|
||||
if (connect(c, sockaddr(&addr), len) < 0 && errno != EINPROGRESS) {
|
||||
FAIL_ERRNO("connect");
|
||||
goto close_cli;
|
||||
}
|
||||
|
||||
len = sizeof(addr);
|
||||
p = accept_timeout(s, sockaddr(&addr), &len, IO_TIMEOUT_SEC);
|
||||
if (p < 0)
|
||||
goto close_cli;
|
||||
|
||||
if (poll_connect(c, IO_TIMEOUT_SEC) < 0) {
|
||||
FAIL_ERRNO("poll_connect");
|
||||
goto close_acc;
|
||||
}
|
||||
|
||||
*v0 = p;
|
||||
*v1 = c;
|
||||
|
||||
return 0;
|
||||
|
||||
close_acc:
|
||||
close(p);
|
||||
close_cli:
|
||||
close(c);
|
||||
close_srv:
|
||||
close(s);
|
||||
|
||||
return -1;
|
||||
return create_pair(AF_VSOCK, sotype | SOCK_NONBLOCK, v0, v1);
|
||||
}
|
||||
|
||||
static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd,
|
||||
|
|
@ -1691,44 +1639,7 @@ static void test_reuseport(struct test_sockmap_listen *skel,
|
|||
|
||||
static int inet_socketpair(int family, int type, int *s, int *c)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
int p0, c0;
|
||||
int err;
|
||||
|
||||
p0 = socket_loopback(family, type | SOCK_NONBLOCK);
|
||||
if (p0 < 0)
|
||||
return p0;
|
||||
|
||||
len = sizeof(addr);
|
||||
err = xgetsockname(p0, sockaddr(&addr), &len);
|
||||
if (err)
|
||||
goto close_peer0;
|
||||
|
||||
c0 = xsocket(family, type | SOCK_NONBLOCK, 0);
|
||||
if (c0 < 0) {
|
||||
err = c0;
|
||||
goto close_peer0;
|
||||
}
|
||||
err = xconnect(c0, sockaddr(&addr), len);
|
||||
if (err)
|
||||
goto close_cli0;
|
||||
err = xgetsockname(c0, sockaddr(&addr), &len);
|
||||
if (err)
|
||||
goto close_cli0;
|
||||
err = xconnect(p0, sockaddr(&addr), len);
|
||||
if (err)
|
||||
goto close_cli0;
|
||||
|
||||
*s = p0;
|
||||
*c = c0;
|
||||
return 0;
|
||||
|
||||
close_cli0:
|
||||
xclose(c0);
|
||||
close_peer0:
|
||||
xclose(p0);
|
||||
return err;
|
||||
return create_pair(family, type | SOCK_NONBLOCK, s, c);
|
||||
}
|
||||
|
||||
static void udp_redir_to_connected(int family, int sock_mapfd, int verd_mapfd,
|
||||
|
|
@ -1795,11 +1706,11 @@ static void inet_unix_redir_to_connected(int family, int type, int sock_mapfd,
|
|||
int sfd[2];
|
||||
int err;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, sfd))
|
||||
if (socketpair(AF_UNIX, type | SOCK_NONBLOCK, 0, sfd))
|
||||
return;
|
||||
c0 = sfd[0], p0 = sfd[1];
|
||||
|
||||
err = inet_socketpair(family, SOCK_DGRAM, &p1, &c1);
|
||||
err = inet_socketpair(family, type, &p1, &c1);
|
||||
if (err)
|
||||
goto close;
|
||||
|
||||
|
|
@ -1847,7 +1758,7 @@ static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd,
|
|||
int sfd[2];
|
||||
int err;
|
||||
|
||||
err = inet_socketpair(family, SOCK_DGRAM, &p0, &c0);
|
||||
err = inet_socketpair(family, type, &p0, &c0);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
|
|
@ -1882,7 +1793,7 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel,
|
|||
unix_inet_redir_to_connected(family, SOCK_DGRAM,
|
||||
sock_map, -1, verdict_map,
|
||||
REDIR_EGRESS, NO_FLAGS);
|
||||
unix_inet_redir_to_connected(family, SOCK_DGRAM,
|
||||
unix_inet_redir_to_connected(family, SOCK_STREAM,
|
||||
sock_map, -1, verdict_map,
|
||||
REDIR_EGRESS, NO_FLAGS);
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ static const struct sockopt_test sol_tcp_tests[] = {
|
|||
{ .opt = TCP_THIN_LINEAR_TIMEOUTS, .flip = 1, },
|
||||
{ .opt = TCP_USER_TIMEOUT, .new = 123400, .expected = 123400, },
|
||||
{ .opt = TCP_NOTSENT_LOWAT, .new = 1314, .expected = 1314, },
|
||||
{ .opt = TCP_BPF_SOCK_OPS_CB_FLAGS, .new = BPF_SOCK_OPS_ALL_CB_FLAGS,
|
||||
.expected = BPF_SOCK_OPS_ALL_CB_FLAGS, },
|
||||
{ .opt = 0, },
|
||||
};
|
||||
|
||||
|
|
@ -353,11 +355,30 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family,
|
|||
return 1;
|
||||
}
|
||||
|
||||
SEC("cgroup/getsockopt")
|
||||
int _getsockopt(struct bpf_sockopt *ctx)
|
||||
{
|
||||
struct bpf_sock *sk = ctx->sk;
|
||||
int *optval = ctx->optval;
|
||||
struct tcp_sock *tp;
|
||||
|
||||
if (!sk || ctx->level != SOL_TCP || ctx->optname != TCP_BPF_SOCK_OPS_CB_FLAGS)
|
||||
return 1;
|
||||
|
||||
tp = bpf_core_cast(sk, struct tcp_sock);
|
||||
if (ctx->optval + sizeof(int) <= ctx->optval_end) {
|
||||
*optval = tp->bpf_sock_ops_cb_flags;
|
||||
ctx->retval = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
SEC("sockops")
|
||||
int skops_sockopt(struct bpf_sock_ops *skops)
|
||||
{
|
||||
struct bpf_sock *bpf_sk = skops->sk;
|
||||
struct sock *sk;
|
||||
int flags;
|
||||
|
||||
if (!bpf_sk)
|
||||
return 1;
|
||||
|
|
@ -384,9 +405,8 @@ int skops_sockopt(struct bpf_sock_ops *skops)
|
|||
nr_passive += !(bpf_test_sockopt(skops, sk) ||
|
||||
test_tcp_maxseg(skops, sk) ||
|
||||
test_tcp_saved_syn(skops, sk));
|
||||
bpf_sock_ops_cb_flags_set(skops,
|
||||
skops->bpf_sock_ops_cb_flags |
|
||||
BPF_SOCK_OPS_STATE_CB_FLAG);
|
||||
flags = skops->bpf_sock_ops_cb_flags | BPF_SOCK_OPS_STATE_CB_FLAG;
|
||||
bpf_setsockopt(skops, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, sizeof(flags));
|
||||
break;
|
||||
case BPF_SOCK_OPS_STATE_CB:
|
||||
if (skops->args[1] == BPF_TCP_CLOSE_WAIT)
|
||||
|
|
|
|||
|
|
@ -486,17 +486,10 @@ static int tcp_validate_cookie(struct tcp_syncookie *ctx)
|
|||
goto err;
|
||||
|
||||
mssind = (cookie & (3 << 6)) >> 6;
|
||||
if (ctx->ipv4) {
|
||||
if (mssind > ARRAY_SIZE(msstab4))
|
||||
goto err;
|
||||
|
||||
if (ctx->ipv4)
|
||||
ctx->attrs.mss = msstab4[mssind];
|
||||
} else {
|
||||
if (mssind > ARRAY_SIZE(msstab6))
|
||||
goto err;
|
||||
|
||||
else
|
||||
ctx->attrs.mss = msstab6[mssind];
|
||||
}
|
||||
|
||||
ctx->attrs.snd_wscale = cookie & BPF_SYNCOOKIE_WSCALE_MASK;
|
||||
ctx->attrs.rcv_wscale = ctx->attrs.snd_wscale;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user