89 lines
3.4 KiB
Diff
89 lines
3.4 KiB
Diff
From b193256f4e3e5967ec2fc85600ec0883edc4bcc1 Mon Sep 17 00:00:00 2001
|
|
From: hkk <hankangkang5@huawei.com>
|
|
Date: Thu, 8 Aug 2024 10:54:40 +0800
|
|
Subject: [PATCH] virtio_user: solve the issue that failed to bind
|
|
virtio_user's IPv6 address
|
|
|
|
---
|
|
src/lstack/api/lstack_wrap.c | 57 ++++++++++++++++++++++++++----------
|
|
1 file changed, 42 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c
|
|
index 5e60c36..afcd227 100644
|
|
--- a/src/lstack/api/lstack_wrap.c
|
|
+++ b/src/lstack/api/lstack_wrap.c
|
|
@@ -199,6 +199,46 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen,
|
|
return posix_api->accept4_fn(s, addr, addrlen, flags);
|
|
}
|
|
|
|
+static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t namelen)
|
|
+{
|
|
+ struct lwip_sock *sock = NULL;
|
|
+ int times = 10;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (get_global_cfg_params()->kni_switch == 0 && get_global_cfg_params()->flow_bifurcation == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+ ret = posix_api->bind_fn(s, name, namelen);
|
|
+ /* maybe kni addr, ipv6 addr maybe is tentative,need to wait a few seconds */
|
|
+ if (name->sa_family == AF_INET6 && ret < 0 && errno == EADDRNOTAVAIL) {
|
|
+ LSTACK_LOG(WARNING, LSTACK, "virtio_user addr is tentative, please wait... \n");
|
|
+ while (ret != 0 && times-- > 0) {
|
|
+ sleep(1);
|
|
+ ret = posix_api->bind_fn(s, name, namelen);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ret == 0) {
|
|
+ /* reuse the port allocated by kernel when port == 0 */
|
|
+ if (((struct sockaddr_in *)name)->sin_port == 0) {
|
|
+ struct sockaddr_in kerneladdr;
|
|
+ socklen_t len = sizeof(kerneladdr);
|
|
+ if (posix_api->getsockname_fn(s, (struct sockaddr *)&kerneladdr, &len) < 0) {
|
|
+ LSTACK_LOG(ERR, LSTACK, "kernel getsockname failed, fd=%d, errno=%d\n", s, errno);
|
|
+ return -1;
|
|
+ }
|
|
+ ((struct sockaddr_in *)name)->sin_port = kerneladdr.sin_port;
|
|
+ }
|
|
+ /* not sure POSIX_LWIP or POSIX_KERNEL */
|
|
+ } else {
|
|
+ sock = lwip_get_socket(s);
|
|
+ POSIX_SET_TYPE(sock, POSIX_LWIP);
|
|
+ LSTACK_LOG(ERR, LSTACK, "kernel bind failed ret %d errno %d sa_family %u times %u\n",
|
|
+ ret, errno, name->sa_family, times);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen)
|
|
{
|
|
if (name == NULL) {
|
|
@@ -231,21 +271,8 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen
|
|
return posix_api->bind_fn(s, name, namelen);
|
|
}
|
|
|
|
- /* maybe kni addr */
|
|
- if (posix_api->bind_fn(s, name, namelen) == 0) {
|
|
- /* reuse the port allocated by kernel when port == 0 */
|
|
- if (((struct sockaddr_in *)name)->sin_port == 0) {
|
|
- struct sockaddr_in kerneladdr;
|
|
- socklen_t len = sizeof(kerneladdr);
|
|
- if (posix_api->getsockname_fn(s, (struct sockaddr *)&kerneladdr, &len) < 0) {
|
|
- LSTACK_LOG(ERR, LSTACK, "kernel getsockname failed, fd=%d, errno=%d\n", s, errno);
|
|
- return -1;
|
|
- }
|
|
- ((struct sockaddr_in *)name)->sin_port = kerneladdr.sin_port;
|
|
- }
|
|
- /* not sure POSIX_LWIP or POSIX_KERNEL */
|
|
- } else {
|
|
- POSIX_SET_TYPE(sock, POSIX_LWIP);
|
|
+ if (kernel_bind_process(s, name, namelen) < 0) {
|
|
+ return -1;
|
|
}
|
|
return g_wrap_api->bind_fn(s, name, namelen);
|
|
}
|
|
--
|
|
2.33.0
|
|
|