From ac17ffcc14ab2e02f9c40586e933581516bc8b3c Mon Sep 17 00:00:00 2001 From: Dmytro Podgornyi Date: Mon, 19 Aug 2024 13:07:56 +0300 Subject: [PATCH] WIP Signed-off-by: Dmytro Podgornyi --- src/core/event/event_handler_manager.cpp | 18 ++- src/core/event/event_handler_manager.h | 2 + src/core/event/poll_group.cpp | 8 +- src/core/event/poll_group.h | 2 + src/core/sock/sock-extra.cpp | 43 ++++++ src/core/sock/sockinfo.cpp | 4 +- src/core/sock/sockinfo_tcp.cpp | 177 ++++++++++++++++++----- src/core/sock/sockinfo_tcp.h | 15 +- src/core/xlio.h | 8 + src/core/xlio_extra.h | 3 + src/core/xlio_types.h | 4 + 11 files changed, 240 insertions(+), 44 deletions(-) diff --git a/src/core/event/event_handler_manager.cpp b/src/core/event/event_handler_manager.cpp index d13ab4636..6c8d804a2 100644 --- a/src/core/event/event_handler_manager.cpp +++ b/src/core/event/event_handler_manager.cpp @@ -182,11 +182,21 @@ void event_handler_manager::unregister_timers_event_and_delete(timer_handler *ha post_new_reg_action(reg_action); } -void event_handler_manager::unregister_socket_timer_and_delete(sockinfo_tcp *sock_tcp) +void event_handler_manager::unregister_socket_timer_event(sockinfo_tcp *sock_tcp) { evh_logdbg("Unregistering TCP socket timer: %p", sock_tcp); reg_action_t reg_action; memset(®_action, 0, sizeof(reg_action)); + reg_action.type = UNREGISTER_TCP_SOCKET_TIMER; + reg_action.info.timer.user_data = sock_tcp; + post_new_reg_action(reg_action); +} + +void event_handler_manager::unregister_socket_timer_and_delete(sockinfo_tcp *sock_tcp) +{ + evh_logdbg("Unregistering TCP socket timer and destroying: %p", sock_tcp); + reg_action_t reg_action; + memset(®_action, 0, sizeof(reg_action)); reg_action.type = UNREGISTER_TCP_SOCKET_TIMER_AND_DELETE; reg_action.info.timer.user_data = sock_tcp; post_new_reg_action(reg_action); @@ -447,6 +457,8 @@ const char *event_handler_manager::reg_action_str(event_action_type_e reg_action switch (reg_action_type) { case REGISTER_TCP_SOCKET_TIMER: return "REGISTER_TCP_SOCKET_TIMER"; + case UNREGISTER_TCP_SOCKET_TIMER: + return "UNREGISTER_TCP_SOCKET_TIMER"; case UNREGISTER_TCP_SOCKET_TIMER_AND_DELETE: return "UNREGISTER_TCP_SOCKET_TIMER_AND_DELETE"; case REGISTER_TIMER: @@ -729,6 +741,10 @@ void event_handler_manager::handle_registration_action(reg_action_t ®_action) sock = reinterpret_cast(reg_action.info.timer.user_data); sock->get_tcp_timer_collection()->add_new_timer(sock); break; + case UNREGISTER_TCP_SOCKET_TIMER: + sock = reinterpret_cast(reg_action.info.timer.user_data); + sock->get_tcp_timer_collection()->remove_timer(sock); + break; case UNREGISTER_TCP_SOCKET_TIMER_AND_DELETE: sock = reinterpret_cast(reg_action.info.timer.user_data); sock->get_tcp_timer_collection()->remove_timer(sock); diff --git a/src/core/event/event_handler_manager.h b/src/core/event/event_handler_manager.h index f554c0431..44c3d2130 100644 --- a/src/core/event/event_handler_manager.h +++ b/src/core/event/event_handler_manager.h @@ -54,6 +54,7 @@ typedef std::mapsocket_event_cb) , m_socket_comp_cb(attr->socket_comp_cb) , m_socket_rx_cb(attr->socket_rx_cb) + , m_socket_accept_cb(attr->socket_accept_cb) , m_group_flags(attr->flags) { /* @@ -178,7 +179,7 @@ void poll_group::add_socket(sockinfo_tcp *si) g_p_fd_collection->set_socket(si->get_fd(), si); } -void poll_group::close_socket(sockinfo_tcp *si, bool force /*=false*/) +void poll_group::remove_socket(sockinfo_tcp *si) { g_p_fd_collection->clear_socket(si->get_fd()); m_sockets_list.erase(si); @@ -187,6 +188,11 @@ void poll_group::close_socket(sockinfo_tcp *si, bool force /*=false*/) if (iter != std::end(m_dirty_sockets)) { m_dirty_sockets.erase(iter); } +} + +void poll_group::close_socket(sockinfo_tcp *si, bool force /*=false*/) +{ + remove_socket(si); bool closed = si->prepare_to_close(force); if (closed) { diff --git a/src/core/event/poll_group.h b/src/core/event/poll_group.h index 3fbbf59c6..8156c64a1 100644 --- a/src/core/event/poll_group.h +++ b/src/core/event/poll_group.h @@ -61,6 +61,7 @@ class poll_group { void add_ring(ring *rng, ring_alloc_logic_attr *attr); void add_socket(sockinfo_tcp *si); + void remove_socket(sockinfo_tcp *si); void close_socket(sockinfo_tcp *si, bool force = false); unsigned get_flags() const { return m_group_flags; } @@ -71,6 +72,7 @@ class poll_group { xlio_socket_event_cb_t m_socket_event_cb; xlio_socket_comp_cb_t m_socket_comp_cb; xlio_socket_rx_cb_t m_socket_rx_cb; + xlio_socket_accept_cb_t m_socket_accept_cb; private: std::vector m_rings; diff --git a/src/core/sock/sock-extra.cpp b/src/core/sock/sock-extra.cpp index ddb58088d..190f46496 100644 --- a/src/core/sock/sock-extra.cpp +++ b/src/core/sock/sock-extra.cpp @@ -382,7 +382,10 @@ struct xlio_api_t *extra_api() SET_EXTRA_API(xlio_socket_setsockopt, xlio_socket_setsockopt, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_socket_bind, xlio_socket_bind, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_socket_connect, xlio_socket_connect, XLIO_EXTRA_API_XLIO_SOCKET); + SET_EXTRA_API(xlio_socket_listen, xlio_socket_listen, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_socket_get_pd, xlio_socket_get_pd, XLIO_EXTRA_API_XLIO_SOCKET); + SET_EXTRA_API(xlio_socket_detach_group, xlio_socket_detach_group, XLIO_EXTRA_API_XLIO_SOCKET); + SET_EXTRA_API(xlio_socket_attach_group, xlio_socket_attach_group, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_socket_send, xlio_socket_send, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_socket_sendv, xlio_socket_sendv, XLIO_EXTRA_API_XLIO_SOCKET); SET_EXTRA_API(xlio_poll_group_flush, xlio_poll_group_flush, XLIO_EXTRA_API_XLIO_SOCKET); @@ -503,6 +506,12 @@ extern "C" int xlio_socket_destroy(xlio_socket_t sock) return 0; } +extern "C" int xlio_socket_update(xlio_socket_t sock, unsigned flags, uintptr_t userdata_sq) +{ + sockinfo_tcp *si = reinterpret_cast(sock); + return si->update_xlio_socket(flags, userdata_sq); +} + extern "C" int xlio_socket_setsockopt(xlio_socket_t sock, int level, int optname, const void *optval, socklen_t optlen) { @@ -516,6 +525,13 @@ extern "C" int xlio_socket_setsockopt(xlio_socket_t sock, int level, int optname return rc; } +extern "C" int xlio_socket_getpeername(xlio_socket_t sock, struct sockaddr *addr, + socklen_t *addrlen) +{ + sockinfo_tcp *si = reinterpret_cast(sock); + return si->getpeername(addr, addrlen); +} + extern "C" int xlio_socket_bind(xlio_socket_t sock, const struct sockaddr *addr, socklen_t addrlen) { sockinfo_tcp *si = reinterpret_cast(sock); @@ -542,6 +558,18 @@ extern "C" int xlio_socket_connect(xlio_socket_t sock, const struct sockaddr *to return rc; } +extern "C" int xlio_socket_listen(xlio_socket_t sock) +{ + sockinfo_tcp *si = reinterpret_cast(sock); + poll_group *group = si->get_poll_group(); + + if (!group->m_socket_accept_cb) { + errno = ENOTCONN; + return -1; + } + return si->listen(-1); +} + extern "C" struct ibv_pd *xlio_socket_get_pd(xlio_socket_t sock) { sockinfo_tcp *si = reinterpret_cast(sock); @@ -550,6 +578,21 @@ extern "C" struct ibv_pd *xlio_socket_get_pd(xlio_socket_t sock) return ctx ? ctx->get_ibv_pd() : nullptr; } +int xlio_socket_detach_group(xlio_socket_t sock) +{ + sockinfo_tcp *si = reinterpret_cast(sock); + + return si->detach_xlio_group(); +} + +int xlio_socket_attach_group(xlio_socket_t sock, xlio_poll_group_t group) +{ + sockinfo_tcp *si = reinterpret_cast(sock); + poll_group *grp = reinterpret_cast(group); + + return si->attach_xlio_group(grp); +} + static void xlio_buf_free(struct xlio_buf *buf) { mem_buf_desc_t *desc = mem_buf_desc_t::from_xlio_buf(buf); diff --git a/src/core/sock/sockinfo.cpp b/src/core/sock/sockinfo.cpp index 1bb41952a..ab27bd7e1 100644 --- a/src/core/sock/sockinfo.cpp +++ b/src/core/sock/sockinfo.cpp @@ -969,9 +969,7 @@ bool sockinfo::attach_receiver(flow_tuple_with_local_if &flow_key) // Registered as receiver successfully si_logdbg("Attached %s to ring %p", flow_key.to_str().c_str(), p_nd_resources->p_ring); - /* Verify 5 tuple over 3 tuple - * and replace flow rule with the strongest - */ + // Verify 5 tuple over 3 tuple and replace flow rule with the strongest if (flow_key.is_5_tuple()) { // Check and remove lesser 3 tuple flow_tuple_with_local_if flow_key_3t( diff --git a/src/core/sock/sockinfo_tcp.cpp b/src/core/sock/sockinfo_tcp.cpp index b7f0d351d..34ee285d2 100644 --- a/src/core/sock/sockinfo_tcp.cpp +++ b/src/core/sock/sockinfo_tcp.cpp @@ -429,6 +429,80 @@ void sockinfo_tcp::set_xlio_socket(const struct xlio_socket_attr *attr) m_pcb.snd_queuelen_max = TCP_SNDQUEUELEN_OVERFLOW; } +int sockinfo_tcp::update_xlio_socket(unsigned flags, uintptr_t userdata_sq) +{ + NOT_IN_USE(flags); // Currently unused. + m_xlio_socket_userdata = userdata_sq; + + return 0; +} + +int sockinfo_tcp::detach_xlio_group() +{ + // TODO check that socket is connected and has all the objects (to attach them unconditionally later) + // TODO replace lwip callbacks with drops + + remove_timer(); + + // Unregister this receiver from all the rings + for (auto rx_flow_iter = m_rx_flow_map.begin(); rx_flow_iter != m_rx_flow_map.end(); rx_flow_iter = m_rx_flow_map.begin()) { + flow_tuple_with_local_if flow = rx_flow_iter->first; + bool result = detach_receiver(flow); + if (!result) { + si_tcp_logwarn("Detach receiver failed, migration may be spoiled"); + } + } + // TODO SO_BINDTODEVICE support + + delete m_p_connected_dst_entry; + m_p_connected_dst_entry = nullptr; + + m_p_group->remove_socket(this); + m_p_group = nullptr; + + return 0; +} + +int sockinfo_tcp::attach_xlio_group(poll_group *group) +{ + struct xlio_socket_attr attr = { + .flags = 0, /* unused */ + .domain = (int)m_family, + .group = reinterpret_cast(group), + .userdata_sq = m_xlio_socket_userdata, + }; + + // TODO check that socket is detached + // TODO reinitialize lwip callbacks + + set_xlio_socket(&attr); + group->add_socket(this); + + create_dst_entry(); + if (!m_p_connected_dst_entry) { + si_tcp_logwarn("Couldn't create dst_enrty, migration failed"); + errno = ENOMEM; + return -1; + } + bool result = prepare_dst_to_send(is_incoming()); + if (!result) { + si_tcp_logwarn("Couldn't attach TX, migration failed"); + errno = ENOTCONN; + return -1; + } + + result = attach_as_uc_receiver(role_t(NULL), true); + if (!result) { + si_tcp_logwarn("Couldn't attach RX, migration failed"); + errno = ECONNABORTED; + return -1; + } + + register_timer(); + + return 0; +} + void sockinfo_tcp::add_tx_ring_to_group() { ring *rng = get_tx_ring(); @@ -2466,11 +2540,12 @@ ssize_t sockinfo_tcp::rx(const rx_call_t call_type, iovec *p_iov, ssize_t sz_iov void sockinfo_tcp::register_timer() { - // A reused time-wait socket wil try to add a timer although it is already registered. - // We should avoid calling register_socket_timer_event unnecessarily because it introduces - // internal-thread locks contention. + /* A reused time-wait socket will try to add a timer although it is already registered. + * We should avoid calling register_socket_timer_event unnecessarily because it introduces + * internal-thread locks contention. + */ if (!is_timer_registered()) { - si_tcp_logdbg("Registering TCP socket timer: socket: %p, thread-col: %p, global-col: %p", + si_tcp_logdbg("Registering TCP socket timer: socket: %p, timer-col: %p, global-col: %p", this, get_tcp_timer_collection(), g_tcp_timers_collection); set_timer_registered(true); @@ -2478,6 +2553,17 @@ void sockinfo_tcp::register_timer() } } +void sockinfo_tcp::remove_timer() +{ + if (is_timer_registered()) { + si_tcp_logdbg("Removing TCP socket timer: socket: %p, timer-col: %p, global-col: %p", + this, get_tcp_timer_collection(), g_tcp_timers_collection); + + set_timer_registered(false); + get_event_mgr()->unregister_socket_timer_event(this); + } +} + void sockinfo_tcp::queue_rx_ctl_packet(struct tcp_pcb *pcb, mem_buf_desc_t *p_desc) { /* in tcp_ctl_thread mode, always lock the child first*/ @@ -2744,7 +2830,7 @@ int sockinfo_tcp::connect(const sockaddr *__to, socklen_t __tolen) int rc = wait_for_conn_ready_blocking(); // Handle ret from blocking connect if (rc < 0) { - // Interuppted wait for blocking socket currently considered as failure. + // Interrupted wait for blocking socket currently considered as failure. if (errno == EINTR || errno == EAGAIN) { m_conn_state = TCP_CONN_FAILED; } @@ -3255,19 +3341,36 @@ sockinfo_tcp *sockinfo_tcp::accept_clone() // Clone is always called first when a SYN packet received by a listen socket. m_p_socket_stats->listen_counters.n_rx_syn++; - // Create the socket object. We skip shadow sockets for incoming connections. - fd = socket_internal(m_family, SOCK_STREAM, 0, false, false); - if (fd < 0) { - m_p_socket_stats->listen_counters.n_conn_dropped++; - return nullptr; - } + if (is_xlio_socket()) { + struct xlio_socket_attr attr = { + .flags = 0, /* unused */ + .domain = (int)m_family, + .group = reinterpret_cast(m_p_group), + .userdata_sq = 0, + }; + xlio_socket_t sock; + int rc = xlio_socket_create(&attr, &sock); + if (rc != 0) { + si_tcp_logdbg("Couldn't create XLIO socket (errno=%d)", errno); + m_p_socket_stats->listen_counters.n_conn_dropped++; + return nullptr; + } - si = dynamic_cast(fd_collection_get_sockfd(fd)); + si = reinterpret_cast(sock); + } else { + // Create the socket object. We skip shadow sockets for incoming connections. + fd = socket_internal(m_family, SOCK_STREAM, 0, false, false); + if (fd < 0) { + m_p_socket_stats->listen_counters.n_conn_dropped++; + return nullptr; + } - if (!si) { - si_tcp_logwarn("can not get accept socket from FD collection"); - XLIO_CALL(close, fd); - return nullptr; + si = dynamic_cast(fd_collection_get_sockfd(fd)); + if (!si) { + si_tcp_logwarn("Can not get accept socket from FD collection"); + XLIO_CALL(close, fd); + return nullptr; + } } // This method is called from a flow which assumes that the socket is locked @@ -3362,16 +3465,22 @@ err_t sockinfo_tcp::accept_lwip_cb(void *arg, struct tcp_pcb *child_pcb, err_t e return ERR_RST; } - tcp_ip_output(&(new_sock->m_pcb), sockinfo_tcp::ip_output); - tcp_arg(&(new_sock->m_pcb), new_sock); + tcp_ip_output(&new_sock->m_pcb, sockinfo_tcp::ip_output); + tcp_arg(&new_sock->m_pcb, new_sock); - if (safe_mce_sys().enable_socketxtreme) { + if (new_sock->is_xlio_socket()) { + tcp_recv(&new_sock->m_pcb, sockinfo_tcp::rx_lwip_cb_xlio_socket); + } else if (safe_mce_sys().enable_socketxtreme) { tcp_recv(&new_sock->m_pcb, sockinfo_tcp::rx_lwip_cb_socketxtreme); } else { tcp_recv(&new_sock->m_pcb, sockinfo_tcp::rx_lwip_cb); } - tcp_err(&(new_sock->m_pcb), sockinfo_tcp::err_lwip_cb); + if (new_sock->is_xlio_socket()) { + tcp_err(&new_sock->m_pcb, sockinfo_tcp::err_lwip_cb_xlio_socket); + } else { + tcp_err(&new_sock->m_pcb, sockinfo_tcp::err_lwip_cb); + } ASSERT_LOCKED(new_sock->m_tcp_con_lock); @@ -3439,7 +3548,11 @@ err_t sockinfo_tcp::accept_lwip_cb(void *arg, struct tcp_pcb *child_pcb, err_t e // todo check that listen socket was not closed by now ? (is_server()) conn->m_ready_pcbs.erase(&new_sock->m_pcb); - if (safe_mce_sys().enable_socketxtreme) { + if (conn->is_xlio_socket()) { + conn->m_p_group->m_socket_accept_cb(reinterpret_cast(new_sock), + reinterpret_cast(conn), + conn->m_xlio_socket_userdata); + } else if (safe_mce_sys().enable_socketxtreme) { accept_connection_socketxtreme(conn, new_sock); } else { conn->m_accepted_conns.push_back(new_sock); @@ -3644,34 +3757,32 @@ err_t sockinfo_tcp::syn_received_lwip_cb(void *arg, struct tcp_pcb *newpcb) ASSERT_LOCKED(listen_sock->m_tcp_con_lock); - /* Inherite properties from the parent */ + // Inherit properties from the parent. new_sock->set_conn_properties_from_pcb(); new_sock->m_rcvbuff_max = std::max(listen_sock->m_rcvbuff_max, 2 * new_sock->m_pcb.mss); new_sock->fit_rcv_wnd(true); - // Socket socket options listen_sock->set_sock_options(new_sock); listen_sock->m_tcp_con_lock.unlock(); new_sock->create_dst_entry(); + // Pass true for passive socket to skip the transport rules checking. bool is_new_offloaded = new_sock->m_p_connected_dst_entry && - new_sock->prepare_dst_to_send( - true); // pass true for passive socket to skip the transport rules checking + new_sock->prepare_dst_to_send(true); - /* this can happen if there is no route back to the syn sender. - * so we just need to ignore it. - * we set the state to close so we won't try to send fin when we don't - * have route. */ + /* This can happen if there is no route back to the syn sender. So we just need to ignore it. + * We set the state to close so we won't try to send fin when we don't have route. + */ if (!is_new_offloaded) { new_sock->setPassthrough(); set_tcp_state(&new_sock->m_pcb, CLOSED); - // This method is called from a flow (tcp_listen_input, L3_level_tcp_input) which - // priorly called clone_conn_cb which creates a locked new socket. Before we call to - // close() we need to unlock the socket, so close() can perform as a regular close() - // call. + /* This method is called from a flow (tcp_listen_input, L3_level_tcp_input) which priorly + * called clone_conn_cb which creates a locked new socket. Before we call to close() we + * need to unlock the socket, so close() can perform as a regular close() call. + */ new_sock->unlock_tcp_con(); close(new_sock->get_fd()); diff --git a/src/core/sock/sockinfo_tcp.h b/src/core/sock/sockinfo_tcp.h index 97e88623a..5f5371b74 100644 --- a/src/core/sock/sockinfo_tcp.h +++ b/src/core/sock/sockinfo_tcp.h @@ -321,9 +321,6 @@ class sockinfo_tcp : public sockinfo { } bool is_incoming() override { return m_b_incoming; } - bool is_timer_registered() const { return m_timer_registered; } - void set_timer_registered(bool v) { m_timer_registered = v; } - bool is_connected() { return m_sock_state == TCP_SOCK_CONNECTED_RDWR; } inline bool is_rtr() @@ -348,6 +345,8 @@ class sockinfo_tcp : public sockinfo { inline fd_type_t get_type() override { return FD_TYPE_SOCKET; } void handle_timer_expired(); + bool is_timer_registered() const { return m_timer_registered; } + void set_timer_registered(bool v) { m_timer_registered = v; } inline ib_ctx_handler *get_ctx() { @@ -416,9 +415,12 @@ class sockinfo_tcp : public sockinfo { void flush(); void set_xlio_socket(const struct xlio_socket_attr *attr); + int update_xlio_socket(unsigned flags, uintptr_t userdata_sq); + bool is_xlio_socket() const { return m_p_group != nullptr; } void add_tx_ring_to_group(); - bool is_xlio_socket() { return m_p_group != nullptr; } - poll_group *get_poll_group() { return m_p_group; } + poll_group *get_poll_group() const { return m_p_group; } + int detach_xlio_group(); + int attach_xlio_group(poll_group *group); void xlio_socket_event(int event, int value); static err_t rx_lwip_cb_xlio_socket(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); static void err_lwip_cb_xlio_socket(void *pcb_container, err_t err); @@ -499,8 +501,9 @@ class sockinfo_tcp : public sockinfo { void set_conn_properties_from_pcb(); void set_sock_options(sockinfo_tcp *new_sock); void passthrough_unlock(const char *dbg); - // Register to timer + void register_timer(); + void remove_timer(); void handle_socket_linger(); diff --git a/src/core/xlio.h b/src/core/xlio.h index f3daa80bb..0b53caba4 100644 --- a/src/core/xlio.h +++ b/src/core/xlio.h @@ -446,12 +446,20 @@ struct ibv_pd; int xlio_socket_create(const struct xlio_socket_attr *attr, xlio_socket_t *sock_out); int xlio_socket_destroy(xlio_socket_t sock); + int xlio_socket_setsockopt(xlio_socket_t sock, int level, int optname, const void *optval, socklen_t optlen); +int xlio_socket_getpeername(xlio_socket_t sock, struct sockaddr *addr, socklen_t *addrlen); + int xlio_socket_bind(xlio_socket_t sock, const struct sockaddr *addr, socklen_t addrlen); int xlio_socket_connect(xlio_socket_t sock, const struct sockaddr *to, socklen_t tolen); +int xlio_socket_listen(xlio_socket_t sock); struct ibv_pd *xlio_socket_get_pd(xlio_socket_t sock); +/* Socket migration */ +int xlio_socket_detach_group(xlio_socket_t sock); +int xlio_socket_attach_group(xlio_socket_t sock, xlio_poll_group_t group); + /* * TX flow. * diff --git a/src/core/xlio_extra.h b/src/core/xlio_extra.h index 3bd15b022..b3d41cc4b 100644 --- a/src/core/xlio_extra.h +++ b/src/core/xlio_extra.h @@ -331,7 +331,10 @@ struct __attribute__((packed)) xlio_api_t { socklen_t optlen); int (*xlio_socket_bind)(xlio_socket_t sock, const struct sockaddr *addr, socklen_t addrlen); int (*xlio_socket_connect)(xlio_socket_t sock, const struct sockaddr *to, socklen_t tolen); + int (*xlio_socket_listen)(xlio_socket_t sock); struct ibv_pd *(*xlio_socket_get_pd)(xlio_socket_t sock); + int (*xlio_socket_detach_group)(xlio_socket_t sock); + int (*xlio_socket_attach_group)(xlio_socket_t sock, xlio_poll_group_t group); int (*xlio_socket_send)(xlio_socket_t sock, const void *data, size_t len, const struct xlio_socket_send_attr *attr); int (*xlio_socket_sendv)(xlio_socket_t sock, const struct iovec *iov, unsigned iovcnt, diff --git a/src/core/xlio_types.h b/src/core/xlio_types.h index 3fa7d472c..43d2b1aea 100644 --- a/src/core/xlio_types.h +++ b/src/core/xlio_types.h @@ -417,6 +417,9 @@ typedef void (*xlio_socket_comp_cb_t)(xlio_socket_t, uintptr_t userdata_sq, uint typedef void (*xlio_socket_rx_cb_t)(xlio_socket_t, uintptr_t userdata_sq, void *data, size_t len, struct xlio_buf *buf); +typedef void (*xlio_socket_accept_cb_t)(xlio_socket_t sock, xlio_socket_t parent, + uintptr_t parent_userdata_sq); + /* * XLIO Socket API attribute structures */ @@ -441,6 +444,7 @@ struct xlio_poll_group_attr { xlio_socket_event_cb_t socket_event_cb; xlio_socket_comp_cb_t socket_comp_cb; xlio_socket_rx_cb_t socket_rx_cb; + xlio_socket_accept_cb_t socket_accept_cb; }; struct xlio_socket_attr {