Blame src/vma/sock/socket_fd_api.cpp

Packit 6d2c1b
/*
Packit 6d2c1b
 * Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
Packit 6d2c1b
 *
Packit 6d2c1b
 * This software is available to you under a choice of one of two
Packit 6d2c1b
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 6d2c1b
 * General Public License (GPL) Version 2, available from the file
Packit 6d2c1b
 * COPYING in the main directory of this source tree, or the
Packit 6d2c1b
 * BSD license below:
Packit 6d2c1b
 *
Packit 6d2c1b
 *     Redistribution and use in source and binary forms, with or
Packit 6d2c1b
 *     without modification, are permitted provided that the following
Packit 6d2c1b
 *     conditions are met:
Packit 6d2c1b
 *
Packit 6d2c1b
 *      - Redistributions of source code must retain the above
Packit 6d2c1b
 *        copyright notice, this list of conditions and the following
Packit 6d2c1b
 *        disclaimer.
Packit 6d2c1b
 *
Packit 6d2c1b
 *      - Redistributions in binary form must reproduce the above
Packit 6d2c1b
 *        copyright notice, this list of conditions and the following
Packit 6d2c1b
 *        disclaimer in the documentation and/or other materials
Packit 6d2c1b
 *        provided with the distribution.
Packit 6d2c1b
 *
Packit 6d2c1b
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 6d2c1b
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 6d2c1b
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 6d2c1b
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 6d2c1b
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 6d2c1b
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 6d2c1b
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 6d2c1b
 * SOFTWARE.
Packit 6d2c1b
 */
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
#include <sys/epoll.h>
Packit 6d2c1b
Packit 6d2c1b
#include <vma/iomux/epfd_info.h>
Packit 6d2c1b
#include <vlogger/vlogger.h>
Packit 6d2c1b
#include "utils/bullseye.h"
Packit 6d2c1b
#include "sock-redirect.h"
Packit 6d2c1b
Packit 6d2c1b
#include "socket_fd_api.h"
Packit 6d2c1b
Packit 6d2c1b
#define MODULE_NAME 		"sapi"
Packit 6d2c1b
#undef  MODULE_HDR_INFO
Packit 6d2c1b
#define MODULE_HDR_INFO 	MODULE_NAME "[fd=%d]:%d:%s() "
Packit 6d2c1b
#undef	__INFO__
Packit 6d2c1b
#define __INFO__		m_fd
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage off
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
socket_fd_api::socket_fd_api(int fd) : m_epoll_event_flags(0), m_fd(fd), m_n_sysvar_select_poll_os_ratio(safe_mce_sys().select_poll_os_ratio), m_econtext(NULL)
Packit 6d2c1b
{
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
socket_fd_api::~socket_fd_api()
Packit 6d2c1b
{
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::destructor_helper()
Packit 6d2c1b
{
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::shutdown(int __how)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.shutdown(m_fd, __how);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("shutdown failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::bind(const sockaddr *__addr, socklen_t __addrlen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.bind(m_fd, __addr, __addrlen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("bind failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::connect(const sockaddr *__to, socklen_t __tolen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.connect(m_fd, __to, __tolen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("connect failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::accept(struct sockaddr *__addr, socklen_t *__addrlen)
Packit 6d2c1b
{
Packit 6d2c1b
       __log_info_func("");
Packit 6d2c1b
       int ret = orig_os_api.accept(m_fd, __addr, __addrlen);
Packit 6d2c1b
       if (ret < 0) {
Packit 6d2c1b
               __log_info_dbg("accept failed (ret=%d %m)", ret);
Packit 6d2c1b
       }
Packit 6d2c1b
       return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::accept4(struct sockaddr *__addr, socklen_t *__addrlen, int __flags)
Packit 6d2c1b
{
Packit 6d2c1b
       __log_info_func("");
Packit 6d2c1b
       int ret = orig_os_api.accept4(m_fd, __addr, __addrlen, __flags);
Packit 6d2c1b
       if (ret < 0) {
Packit 6d2c1b
               __log_info_dbg("accept4 failed (ret=%d %m)", ret);
Packit 6d2c1b
       }
Packit 6d2c1b
       return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::listen(int backlog)
Packit 6d2c1b
{
Packit 6d2c1b
       __log_info_func("");
Packit 6d2c1b
       int ret = orig_os_api.listen(m_fd, backlog);
Packit 6d2c1b
       if (ret < 0) {
Packit 6d2c1b
               __log_info_dbg("listen failed (ret=%d %m)", ret);
Packit 6d2c1b
       }
Packit 6d2c1b
       return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::getsockname(sockaddr *__name, socklen_t *__namelen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.getsockname(m_fd, __name, __namelen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("getsockname failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::getpeername(sockaddr *__name, socklen_t *__namelen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.getpeername(m_fd, __name, __namelen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("getpeername failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::setsockopt(int __level, int __optname,
Packit 6d2c1b
			      __const void *__optval, socklen_t __optlen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.setsockopt(m_fd, __level, __optname, __optval, __optlen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("setsockopt failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::getsockopt(int __level, int __optname, void *__optval,
Packit 6d2c1b
			      socklen_t *__optlen)
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_func("");
Packit 6d2c1b
	int ret = orig_os_api.getsockopt(m_fd, __level, __optname, __optval, __optlen);
Packit 6d2c1b
	if (ret) {
Packit 6d2c1b
		__log_info_dbg("getsockopt failed (ret=%d %m)", ret);
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
bool socket_fd_api::is_readable(uint64_t *p_poll_sn, fd_array_t* p_fd_array)
Packit 6d2c1b
{
Packit 6d2c1b
	NOT_IN_USE(p_poll_sn);
Packit 6d2c1b
	NOT_IN_USE(p_fd_array);
Packit 6d2c1b
	__log_info_funcall("");
Packit 6d2c1b
	return false;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::set_immediate_os_sample()
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_funcall("");
Packit 6d2c1b
	return;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::unset_immediate_os_sample()
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_funcall("");
Packit 6d2c1b
	return;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool socket_fd_api::is_writeable()
Packit 6d2c1b
{
Packit 6d2c1b
	__log_info_funcall("");
Packit 6d2c1b
	return true;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool socket_fd_api::is_errorable(int *errors)
Packit 6d2c1b
{
Packit 6d2c1b
	NOT_IN_USE(errors);
Packit 6d2c1b
	__log_info_funcall("");
Packit 6d2c1b
	return false;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::statistics_print(vlog_levels_t log_level /* = VLOG_DEBUG */)
Packit 6d2c1b
{
Packit 6d2c1b
	int epoll_fd = get_epoll_context_fd();
Packit 6d2c1b
Packit 6d2c1b
	// Socket data
Packit 6d2c1b
	vlog_printf(log_level, "Fd number : %d\n", m_fd);
Packit 6d2c1b
	if (epoll_fd) {
Packit 6d2c1b
		vlog_printf(log_level, "Socket epoll Fd : %d\n", epoll_fd);
Packit 6d2c1b
		vlog_printf(log_level, "Socket epoll flags : 0x%x\n", m_fd_rec.events);
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
ssize_t socket_fd_api::rx_os(const rx_call_t call_type, iovec* p_iov,
Packit 6d2c1b
			     ssize_t sz_iov, const int flags, sockaddr *__from,
Packit 6d2c1b
			     socklen_t *__fromlen, struct msghdr *__msg)
Packit 6d2c1b
{
Packit 6d2c1b
	errno = 0;
Packit 6d2c1b
	switch (call_type) {
Packit 6d2c1b
	case RX_READ:
Packit 6d2c1b
		__log_info_func("calling os receive with orig read");
Packit 6d2c1b
		return orig_os_api.read(m_fd, p_iov[0].iov_base, p_iov[0].iov_len);
Packit 6d2c1b
Packit 6d2c1b
	case RX_READV:
Packit 6d2c1b
		__log_info_func("calling os receive with orig readv");
Packit 6d2c1b
		return orig_os_api.readv(m_fd, p_iov, sz_iov);
Packit 6d2c1b
Packit 6d2c1b
	case RX_RECV:
Packit 6d2c1b
		__log_info_func("calling os receive with orig recv");
Packit 6d2c1b
		return orig_os_api.recv(m_fd, p_iov[0].iov_base, p_iov[0].iov_len,
Packit 6d2c1b
		                        flags);
Packit 6d2c1b
Packit 6d2c1b
	case RX_RECVFROM:
Packit 6d2c1b
		__log_info_func("calling os receive with orig recvfrom");
Packit 6d2c1b
		return orig_os_api.recvfrom(m_fd, p_iov[0].iov_base, p_iov[0].iov_len,
Packit 6d2c1b
		                            flags, __from, __fromlen);
Packit 6d2c1b
Packit 6d2c1b
	case RX_RECVMSG: {
Packit 6d2c1b
		__log_info_func("calling os receive with orig recvmsg");
Packit 6d2c1b
		return orig_os_api.recvmsg(m_fd, __msg, flags);
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	return (ssize_t) -1;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
ssize_t socket_fd_api::tx_os(const tx_call_t call_type,
Packit 6d2c1b
			     const iovec* p_iov, const ssize_t sz_iov,
Packit 6d2c1b
			     const int __flags, const sockaddr *__to,
Packit 6d2c1b
			     const socklen_t __tolen)
Packit 6d2c1b
{
Packit 6d2c1b
	errno = 0;
Packit 6d2c1b
Packit 6d2c1b
	// Ignore dummy messages for OS
Packit 6d2c1b
	if (unlikely(IS_DUMMY_PACKET(__flags))) {
Packit 6d2c1b
		errno = EINVAL;
Packit 6d2c1b
		return -1;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	switch (call_type) {
Packit 6d2c1b
	case TX_WRITE:
Packit 6d2c1b
		__log_info_func("calling os transmit with orig write");
Packit 6d2c1b
		return orig_os_api.write(m_fd, p_iov[0].iov_base, p_iov[0].iov_len);
Packit 6d2c1b
Packit 6d2c1b
	case TX_WRITEV:
Packit 6d2c1b
		__log_info_func("calling os transmit with orig writev");
Packit 6d2c1b
		return orig_os_api.writev(m_fd, p_iov, sz_iov);
Packit 6d2c1b
Packit 6d2c1b
	case TX_SEND:
Packit 6d2c1b
		__log_info_func("calling os transmit with orig send");
Packit 6d2c1b
		return orig_os_api.send(m_fd, p_iov[0].iov_base, p_iov[0].iov_len,
Packit 6d2c1b
		                        __flags);
Packit 6d2c1b
Packit 6d2c1b
	case TX_SENDTO:
Packit 6d2c1b
		__log_info_func("calling os transmit with orig sendto");
Packit 6d2c1b
		return orig_os_api.sendto(m_fd, p_iov[0].iov_base, p_iov[0].iov_len,
Packit 6d2c1b
		                          __flags, __to, __tolen);
Packit 6d2c1b
Packit 6d2c1b
	case TX_SENDMSG: {
Packit 6d2c1b
		msghdr __message;
Packit 6d2c1b
		memset(&__message, 0, sizeof(__message));
Packit 6d2c1b
		__message.msg_iov = (iovec*) p_iov;
Packit 6d2c1b
		__message.msg_iovlen = sz_iov;
Packit 6d2c1b
		__message.msg_name = (void*) __to;
Packit 6d2c1b
		__message.msg_namelen = __tolen;
Packit 6d2c1b
Packit 6d2c1b
		__log_info_func("calling os transmit with orig sendmsg");
Packit 6d2c1b
		return orig_os_api.sendmsg(m_fd, &__message, __flags);
Packit 6d2c1b
		}
Packit 6d2c1b
	default:
Packit 6d2c1b
		__log_info_func("calling undefined os call type!");
Packit 6d2c1b
		break;
Packit 6d2c1b
	}
Packit 6d2c1b
	return (ssize_t) -1;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::register_callback(vma_recv_callback_t callback, void *context)
Packit 6d2c1b
{
Packit 6d2c1b
	NOT_IN_USE(callback);
Packit 6d2c1b
	NOT_IN_USE(context);
Packit 6d2c1b
	return -1;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::free_packets(struct vma_packet_t *pkts, size_t count)
Packit 6d2c1b
{
Packit 6d2c1b
	NOT_IN_USE(pkts);
Packit 6d2c1b
	NOT_IN_USE(count);
Packit 6d2c1b
	return -1;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::free_buffs(uint16_t len)
Packit 6d2c1b
{
Packit 6d2c1b
	NOT_IN_USE(len);
Packit 6d2c1b
	return -1;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::add_epoll_context(epfd_info *epfd)
Packit 6d2c1b
{
Packit 6d2c1b
	if (!m_econtext) {
Packit 6d2c1b
		// This socket is not registered to any epfd
Packit 6d2c1b
		m_econtext = epfd;
Packit 6d2c1b
		return 0;
Packit 6d2c1b
	} else {
Packit 6d2c1b
		// Currently VMA does not support more then 1 epfd listed
Packit 6d2c1b
		errno = (m_econtext == epfd) ? EEXIST : ENOMEM;
Packit 6d2c1b
		return -1;
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::remove_epoll_context(epfd_info *epfd)
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_econtext == epfd)
Packit 6d2c1b
		m_econtext = NULL;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::notify_epoll_context(uint32_t events)
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_econtext) {
Packit 6d2c1b
		m_econtext->insert_epoll_event_cb(this, events);
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::notify_epoll_context_add_ring(ring* ring)
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_econtext) {
Packit 6d2c1b
		m_econtext->increase_ring_ref_count(ring);
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::notify_epoll_context_remove_ring(ring* ring)
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_econtext){
Packit 6d2c1b
		m_econtext->decrease_ring_ref_count(ring);
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool socket_fd_api::notify_epoll_context_verify(epfd_info *epfd)
Packit 6d2c1b
{
Packit 6d2c1b
	return m_econtext == epfd;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void socket_fd_api::notify_epoll_context_fd_is_offloaded()
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_econtext) {
Packit 6d2c1b
		m_econtext->remove_fd_from_epoll_os(m_fd);
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int socket_fd_api::get_epoll_context_fd() {
Packit 6d2c1b
	if (m_econtext) {
Packit 6d2c1b
		return  m_econtext->get_epoll_fd();
Packit 6d2c1b
	}
Packit 6d2c1b
	return 0;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage on
Packit 6d2c1b
#endif