|
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 |
#ifndef FD_COLLECTION_H
|
|
Packit |
6d2c1b |
#define FD_COLLECTION_H
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#include <map>
|
|
Packit |
6d2c1b |
#include <rdma/rdma_cma.h>
|
|
Packit |
6d2c1b |
#include "vlogger/vlogger.h"
|
|
Packit |
6d2c1b |
#include "utils/lock_wrapper.h"
|
|
Packit |
6d2c1b |
#include "vma/iomux/epfd_info.h"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#include "vma/sock/socket_fd_api.h"
|
|
Packit |
6d2c1b |
#include "vma/event/timer_handler.h"
|
|
Packit |
6d2c1b |
#include "vma/event/event_handler_manager.h"
|
|
Packit |
6d2c1b |
#include <vma/sock/cleanable_obj.h>
|
|
Packit |
6d2c1b |
#include "vma/dev/ring_tap.h"
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
typedef vma_list_t<socket_fd_api, socket_fd_api::pendig_to_remove_node_offset> sock_fd_api_list_t;
|
|
Packit |
6d2c1b |
typedef vma_list_t<epfd_info, epfd_info::epfd_info_node_offset> epfd_info_list_t;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
typedef std::tr1::unordered_map<pthread_t, int> offload_thread_rule_t;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#if (VMA_MAX_DEFINED_LOG_LEVEL < DEFINED_VLOG_FINER)
|
|
Packit |
6d2c1b |
#define fdcoll_logfuncall(log_fmt, log_args...) ((void)0)
|
|
Packit |
6d2c1b |
#else
|
|
Packit |
6d2c1b |
#define fdcoll_logfuncall(log_fmt, log_args...) do { if (g_vlogger_level >= VLOG_FUNC_ALL) vlog_printf(VLOG_FUNC_ALL, "fdc:%d:%s() " log_fmt "\n", __LINE__, __FUNCTION__, ##log_args); } while (0)
|
|
Packit |
6d2c1b |
#endif /* VMA_MAX_DEFINED_LOG_LEVEL */
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
class cq_channel_info: public cleanable_obj
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
public:
|
|
Packit |
6d2c1b |
cq_channel_info(ring* p_ring) : m_p_ring(p_ring) {};
|
|
Packit |
6d2c1b |
~cq_channel_info() {};
|
|
Packit |
6d2c1b |
ring* get_ring() const { return m_p_ring; };
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
protected:
|
|
Packit |
6d2c1b |
ring* m_p_ring;
|
|
Packit |
6d2c1b |
};
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
class fd_collection : private lock_mutex_recursive, public timer_handler
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
public:
|
|
Packit |
6d2c1b |
fd_collection();
|
|
Packit |
6d2c1b |
~fd_collection();
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Create and add a sockinfo. Use get_sock() to get it.
|
|
Packit |
6d2c1b |
* @param domain e.g AF_INET.
|
|
Packit |
6d2c1b |
* @param type e.g SOCK_DGRAM.
|
|
Packit |
6d2c1b |
* @return socket fd or -1 on failure.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int addsocket(int fd, int domain, int type, bool check_offload = false);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Create pipeinfo. Use get_sock() to get it.
|
|
Packit |
6d2c1b |
* @param fdrd Read fd.
|
|
Packit |
6d2c1b |
* @param fdwr Write fd.
|
|
Packit |
6d2c1b |
* @return 0 on success, -1 on failure.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int addpipe(int fdrd, int fdwr);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Create epfd_info. Use get_epfd() to get it.
|
|
Packit |
6d2c1b |
* @param epfd epoll fd.
|
|
Packit |
6d2c1b |
* @param size epoll fd size (as passed to epoll_create).
|
|
Packit |
6d2c1b |
* @return 0 on success, -1 on failure.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int addepfd(int epfd, int size);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Create cq_channel_info. Use get_cq_channel_info() to get it.
|
|
Packit |
6d2c1b |
* @param cq_ch_fd: cq channel fd.
|
|
Packit |
6d2c1b |
* @param p_ring: pointer to ring which is the relevant rx_cq owner.
|
|
Packit |
6d2c1b |
* @return 0 on success, -1 on failure.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int add_cq_channel_fd(int cq_ch_fd, ring* p_ring);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Add tap fd index to tap_map.
|
|
Packit |
6d2c1b |
* @param tapfd: tap fd.
|
|
Packit |
6d2c1b |
* @param p_ring: pointer to ring owner of the tap.
|
|
Packit |
6d2c1b |
* @return 0 on success, -1 on failure.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int addtapfd(int tapfd, ring_tap* p_ring);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove pipeinfo/sockinfo.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int del_sockfd(int fd, bool b_cleanup = false);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove epfd_info.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int del_epfd(int fd, bool b_cleanup = false);
|
|
Packit |
6d2c1b |
void remove_epfd_from_list(epfd_info* epfd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove cq_channel_info.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
int del_cq_channel_fd(int fd, bool b_cleanup = false);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove tap_fd from tap_map.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void del_tapfd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Call set_immediate_os_sample of the input fd.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline bool set_immediate_os_sample(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Get sock_fd_api (sockinfo or pipeinfo) by fd.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline socket_fd_api* get_sockfd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Get epfd_info by fd.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline epfd_info* get_epfd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Get cq_channel_info by fd.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline cq_channel_info* get_cq_channel_fd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Get rint_tap by tap fd.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline ring_tap* get_tapfd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Get the fd_map size.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
inline int get_fd_map_size();
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove fd from the collection of all epfd's
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void remove_from_all_epfds(int fd, bool passthrough);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Remove everything from the collection.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void clear();
|
|
Packit |
6d2c1b |
void prepare_to_close();
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void offloading_rule_change_thread(bool offloaded, pthread_t tid);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
/**
|
|
Packit |
6d2c1b |
* Dump fd statistics using VMA logger.
|
|
Packit |
6d2c1b |
*/
|
|
Packit |
6d2c1b |
void statistics_print(int fd, vlog_levels_t log_level);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
private:
|
|
Packit |
6d2c1b |
template <typename cls> int del(int fd, bool b_cleanup, cls **map_type);
|
|
Packit |
6d2c1b |
template <typename cls> inline cls* get(int fd, cls **map_type);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
int m_n_fd_map_size;
|
|
Packit |
6d2c1b |
socket_fd_api** m_p_sockfd_map;
|
|
Packit |
6d2c1b |
epfd_info** m_p_epfd_map;
|
|
Packit |
6d2c1b |
cq_channel_info** m_p_cq_channel_map;
|
|
Packit |
6d2c1b |
ring_tap** m_p_tap_map;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
epfd_info_list_t m_epfd_lst;
|
|
Packit |
6d2c1b |
//Contains fds which are in closing process
|
|
Packit |
6d2c1b |
sock_fd_api_list_t m_pendig_to_remove_lst;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void* m_timer_handle;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
const bool m_b_sysvar_offloaded_sockets;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
//if (m_b_sysvar_offloaded_sockets is true) contain all threads that need not be offloaded.
|
|
Packit |
6d2c1b |
//else contain all threads that need to be offloaded.
|
|
Packit |
6d2c1b |
offload_thread_rule_t m_offload_thread_rule;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline bool is_valid_fd(int fd);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline bool create_offloaded_sockets();
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
//Fd collection timer implementation
|
|
Packit |
6d2c1b |
//This gives context to handle pending to remove fds.
|
|
Packit |
6d2c1b |
//In case of TCP we recheck if TCP socket is closable and delete
|
|
Packit |
6d2c1b |
//it if it does otherwise we run handle_timer of the socket to
|
|
Packit |
6d2c1b |
//progress the TCP connection.
|
|
Packit |
6d2c1b |
void handle_timer_expired(void* user_data);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
void statistics_print_helper(int fd, vlog_levels_t log_level);
|
|
Packit |
6d2c1b |
};
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline bool fd_collection::is_valid_fd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
if (fd < 0 || fd >= m_n_fd_map_size)
|
|
Packit |
6d2c1b |
return false;
|
|
Packit |
6d2c1b |
return true;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
template <typename cls>
|
|
Packit |
6d2c1b |
inline cls* fd_collection::get(int fd, cls **map_type)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
if (!is_valid_fd(fd))
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
cls* obj = map_type[fd];
|
|
Packit |
6d2c1b |
return obj;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline bool fd_collection::set_immediate_os_sample(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
epfd_info* epfd_fd;
|
|
Packit |
6d2c1b |
ring_tap* p_ring;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
auto_unlocker locker(*this);
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
if ((p_ring = get_tapfd(fd))) {
|
|
Packit |
6d2c1b |
p_ring->set_tap_data_available();
|
|
Packit |
6d2c1b |
return true;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
if ((epfd_fd = get_epfd(fd))){
|
|
Packit |
6d2c1b |
epfd_fd->set_os_data_available();
|
|
Packit |
6d2c1b |
return true;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
return false;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline socket_fd_api* fd_collection::get_sockfd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
return get(fd, m_p_sockfd_map);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline epfd_info* fd_collection::get_epfd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
return get(fd, m_p_epfd_map);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline cq_channel_info* fd_collection::get_cq_channel_fd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
return get(fd, m_p_cq_channel_map);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline ring_tap* fd_collection::get_tapfd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
return get(fd, m_p_tap_map);
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline int fd_collection::get_fd_map_size()
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
return m_n_fd_map_size;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
extern fd_collection* g_p_fd_collection;
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline socket_fd_api* fd_collection_get_sockfd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
if (g_p_fd_collection)
|
|
Packit |
6d2c1b |
return g_p_fd_collection->get_sockfd(fd);
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
inline epfd_info* fd_collection_get_epfd(int fd)
|
|
Packit |
6d2c1b |
{
|
|
Packit |
6d2c1b |
if (g_p_fd_collection)
|
|
Packit |
6d2c1b |
return g_p_fd_collection->get_epfd(fd);
|
|
Packit |
6d2c1b |
return NULL;
|
|
Packit |
6d2c1b |
}
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#endif
|