Blame src/vma/dev/rfs.h

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 RFS_H
Packit 6d2c1b
#define RFS_H
Packit 6d2c1b
Packit 6d2c1b
#include <vector>
Packit 6d2c1b
Packit 6d2c1b
#include "vma/ib/base/verbs_extra.h"
Packit 6d2c1b
#include "vma/util/vtypes.h"
Packit 6d2c1b
#include "vma/dev/ring_simple.h"
Packit 6d2c1b
#include "vma/proto/mem_buf_desc.h"
Packit 6d2c1b
#include "vma/proto/flow_tuple.h"
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
#define rfs_logpanic 	__log_info_panic
Packit 6d2c1b
#define rfs_logerr	__log_info_err
Packit 6d2c1b
#define rfs_logwarn	__log_info_warn
Packit 6d2c1b
#define rfs_loginfo	__log_info_info
Packit 6d2c1b
#define rfs_logdbg	__log_info_dbg
Packit 6d2c1b
#define rfs_logfunc	__log_info_func
Packit 6d2c1b
#define rfs_logfuncall	__log_info_funcall
Packit 6d2c1b
Packit 6d2c1b
#define RFS_SINKS_LIST_DEFAULT_LEN 32
Packit 6d2c1b
Packit 6d2c1b
class qp_mgr;
Packit 6d2c1b
class pkt_rcvr_sink;
Packit 6d2c1b
Packit 6d2c1b
/* ETHERNET
Packit 6d2c1b
 */
Packit 6d2c1b
typedef struct attach_flow_data_eth_ipv4_tcp_udp_t {
Packit 6d2c1b
	struct ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	struct ibv_flow_attr_eth_ipv4_tcp_udp {
Packit 6d2c1b
		vma_ibv_flow_attr             attr;
Packit 6d2c1b
		vma_ibv_flow_spec_eth         eth;
Packit 6d2c1b
		vma_ibv_flow_spec_ipv4        ipv4;
Packit 6d2c1b
		vma_ibv_flow_spec_tcp_udp     tcp_udp;
Packit 6d2c1b
		vma_ibv_flow_spec_action_tag  flow_tag; // must be the last as struct can be used without it		
Packit 6d2c1b
Packit 6d2c1b
		ibv_flow_attr_eth_ipv4_tcp_udp(uint8_t port) {
Packit 6d2c1b
			memset(this, 0, sizeof(*this));
Packit 6d2c1b
			attr.size = sizeof(struct ibv_flow_attr_eth_ipv4_tcp_udp) - sizeof(flow_tag);			
Packit 6d2c1b
			attr.num_of_specs = 3;
Packit 6d2c1b
			attr.type = VMA_IBV_FLOW_ATTR_NORMAL;
Packit 6d2c1b
			attr.priority = 1; // almost highest priority, 0 is used for 5-tuple later
Packit 6d2c1b
			attr.port = port;
Packit 6d2c1b
		}
Packit 6d2c1b
		inline void add_flow_tag_spec(void) {
Packit 6d2c1b
			attr.num_of_specs++;
Packit 6d2c1b
			attr.size += sizeof(flow_tag);
Packit 6d2c1b
		}
Packit 6d2c1b
	} ibv_flow_attr;
Packit 6d2c1b
	attach_flow_data_eth_ipv4_tcp_udp_t(qp_mgr* qp_mgr) :
Packit 6d2c1b
		ibv_flow(NULL),
Packit 6d2c1b
		p_qp_mgr(qp_mgr),
Packit 6d2c1b
		ibv_flow_attr(qp_mgr->get_port_num()) {}
Packit 6d2c1b
} attach_flow_data_eth_ipv4_tcp_udp_t;
Packit 6d2c1b
Packit 6d2c1b
/* IPOIB (MC)
Packit 6d2c1b
 */
Packit 6d2c1b
typedef struct attach_flow_data_ib_v2_t {
Packit 6d2c1b
	struct ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	struct ibv_flow_attr_ib_v2 {
Packit 6d2c1b
		vma_ibv_flow_attr             attr;
Packit 6d2c1b
		vma_ibv_flow_spec_ipv4        ipv4;
Packit 6d2c1b
		vma_ibv_flow_spec_tcp_udp     tcp_udp;
Packit 6d2c1b
Packit 6d2c1b
		ibv_flow_attr_ib_v2(uint8_t port) {
Packit 6d2c1b
			memset(this, 0, sizeof(*this));
Packit 6d2c1b
			attr.size = sizeof(struct ibv_flow_attr_ib_v2);
Packit 6d2c1b
			attr.num_of_specs = 2;
Packit 6d2c1b
			attr.type = VMA_IBV_FLOW_ATTR_NORMAL;
Packit 6d2c1b
			attr.priority = 1; // almost highest priority, 0 is used for 5-tuple later
Packit 6d2c1b
			attr.port = port;
Packit 6d2c1b
		}
Packit 6d2c1b
	} ibv_flow_attr;
Packit 6d2c1b
	attach_flow_data_ib_v2_t(qp_mgr* qp_mgr) :
Packit 6d2c1b
		ibv_flow(NULL),
Packit 6d2c1b
		p_qp_mgr(qp_mgr),
Packit 6d2c1b
		ibv_flow_attr(qp_mgr->get_port_num()) {}
Packit 6d2c1b
Packit 6d2c1b
} attach_flow_data_ib_v2_t;
Packit 6d2c1b
Packit 6d2c1b
#ifdef DEFINED_IBV_FLOW_SPEC_IB
Packit 6d2c1b
typedef struct attach_flow_data_ib_v1_t {
Packit 6d2c1b
	struct ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	struct ibv_flow_attr_ib_v1 {
Packit 6d2c1b
		vma_ibv_flow_attr             attr;
Packit 6d2c1b
		vma_ibv_flow_spec_ib          ib;
Packit 6d2c1b
Packit 6d2c1b
		ibv_flow_attr_ib_v1(uint8_t port) {
Packit 6d2c1b
			memset(this, 0, sizeof(*this));
Packit 6d2c1b
			attr.size = sizeof(struct ibv_flow_attr_ib_v1);
Packit 6d2c1b
			attr.num_of_specs = 1;
Packit 6d2c1b
			attr.type = VMA_IBV_FLOW_ATTR_NORMAL;
Packit 6d2c1b
			attr.priority = 1; // almost highest priority, 0 is used for 5-tuple later
Packit 6d2c1b
			attr.port = port;
Packit 6d2c1b
		}
Packit 6d2c1b
	} ibv_flow_attr;
Packit 6d2c1b
	attach_flow_data_ib_v1_t(qp_mgr* qp_mgr) :
Packit 6d2c1b
		ibv_flow(NULL),
Packit 6d2c1b
		p_qp_mgr(qp_mgr),
Packit 6d2c1b
		ibv_flow_attr(qp_mgr->get_port_num()) {}
Packit 6d2c1b
Packit 6d2c1b
} attach_flow_data_ib_v1_t;
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
/* IPOIB (UC)
Packit 6d2c1b
 */
Packit 6d2c1b
typedef struct attach_flow_data_ib_ipv4_tcp_udp_v2_t {
Packit 6d2c1b
	struct ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	struct ibv_flow_attr_ib_ipv4_tcp_udp_v2 {
Packit 6d2c1b
Packit 6d2c1b
		vma_ibv_flow_attr             attr;
Packit 6d2c1b
		vma_ibv_flow_spec_ipv4        ipv4;
Packit 6d2c1b
		vma_ibv_flow_spec_tcp_udp     tcp_udp;
Packit 6d2c1b
Packit 6d2c1b
		ibv_flow_attr_ib_ipv4_tcp_udp_v2(uint8_t port) {
Packit 6d2c1b
			memset(this, 0, sizeof(*this));
Packit 6d2c1b
			attr.size = sizeof(struct ibv_flow_attr_ib_ipv4_tcp_udp_v2);
Packit 6d2c1b
			attr.num_of_specs = 2;
Packit 6d2c1b
			attr.type = VMA_IBV_FLOW_ATTR_NORMAL;
Packit 6d2c1b
			attr.priority = 1; // almost highest priority, 0 is used for 5-tuple later
Packit 6d2c1b
			attr.port = port;
Packit 6d2c1b
		}
Packit 6d2c1b
	} ibv_flow_attr;
Packit 6d2c1b
	attach_flow_data_ib_ipv4_tcp_udp_v2_t(qp_mgr* qp_mgr) :
Packit 6d2c1b
		ibv_flow(NULL),
Packit 6d2c1b
		p_qp_mgr(qp_mgr),
Packit 6d2c1b
		ibv_flow_attr(qp_mgr->get_port_num()) {}
Packit 6d2c1b
} attach_flow_data_ib_ipv4_tcp_udp_v2_t;
Packit 6d2c1b
Packit 6d2c1b
#ifdef DEFINED_IBV_FLOW_SPEC_IB
Packit 6d2c1b
typedef struct attach_flow_data_ib_ipv4_tcp_udp_v1_t {
Packit 6d2c1b
	struct ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	struct ibv_flow_attr_ib_ipv4_tcp_udp_v1 {
Packit 6d2c1b
Packit 6d2c1b
		vma_ibv_flow_attr             attr;
Packit 6d2c1b
		vma_ibv_flow_spec_ib          ib;
Packit 6d2c1b
		vma_ibv_flow_spec_ipv4        ipv4;
Packit 6d2c1b
		vma_ibv_flow_spec_tcp_udp     tcp_udp;
Packit 6d2c1b
Packit 6d2c1b
		ibv_flow_attr_ib_ipv4_tcp_udp_v1(uint8_t port) {
Packit 6d2c1b
			memset(this, 0, sizeof(*this));
Packit 6d2c1b
			attr.size = sizeof(struct ibv_flow_attr_ib_ipv4_tcp_udp_v1);
Packit 6d2c1b
			attr.num_of_specs = 3;
Packit 6d2c1b
			attr.type = VMA_IBV_FLOW_ATTR_NORMAL;
Packit 6d2c1b
			attr.priority = 1; // almost highest priority, 0 is used for 5-tuple later
Packit 6d2c1b
			attr.port = port;
Packit 6d2c1b
		}
Packit 6d2c1b
	} ibv_flow_attr;
Packit 6d2c1b
	attach_flow_data_ib_ipv4_tcp_udp_v1_t(qp_mgr* qp_mgr) :
Packit 6d2c1b
		ibv_flow(NULL),
Packit 6d2c1b
		p_qp_mgr(qp_mgr),
Packit 6d2c1b
		ibv_flow_attr(qp_mgr->get_port_num()) {}
Packit 6d2c1b
} attach_flow_data_ib_ipv4_tcp_udp_v1_t;
Packit 6d2c1b
#endif /* DEFINED_IBV_FLOW_SPEC_IB */
Packit 6d2c1b
Packit 6d2c1b
typedef struct attach_flow_data_t {
Packit 6d2c1b
	vma_ibv_flow *                       ibv_flow;
Packit 6d2c1b
	qp_mgr*                                 p_qp_mgr;
Packit 6d2c1b
	vma_ibv_flow_attr                    ibv_flow_attr;
Packit 6d2c1b
} attach_flow_data_t;
Packit 6d2c1b
Packit 6d2c1b
typedef std::vector<attach_flow_data_t*> attach_flow_data_vector_t;
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
class rfs_rule_filter
Packit 6d2c1b
{
Packit 6d2c1b
public:
Packit 6d2c1b
	rfs_rule_filter(rule_filter_map_t& map, uint64_t key, flow_tuple& flow_tuple) : m_map(map), m_key(key), m_flow_tuple(flow_tuple) {}
Packit 6d2c1b
	rule_filter_map_t& m_map;
Packit 6d2c1b
	uint64_t m_key;
Packit 6d2c1b
	flow_tuple m_flow_tuple;
Packit 6d2c1b
};
Packit 6d2c1b
Packit 6d2c1b
/**
Packit 6d2c1b
 * @class rfs
Packit 6d2c1b
 *
Packit 6d2c1b
 * Object to manages the sink list
Packit 6d2c1b
 * This object is used for maintaining the sink list and dispatching packets
Packit 6d2c1b
 *
Packit 6d2c1b
 */
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
class rfs
Packit 6d2c1b
{
Packit 6d2c1b
public:
Packit 6d2c1b
	rfs(flow_tuple *flow_spec_5t, ring_slave *p_ring,
Packit 6d2c1b
	    rfs_rule_filter* rule_filter = NULL, uint32_t flow_tag_id = 0);
Packit 6d2c1b
	virtual ~rfs();
Packit 6d2c1b
Packit 6d2c1b
	/**
Packit 6d2c1b
	 * Register/Unregister a sink with this rfs object
Packit 6d2c1b
	 * Get notifications about incoming packets using the pkt_rcvr_sink callback api
Packit 6d2c1b
	 * The rfs will call ibv_attach on the QP once when at least one receiver sink is registered
Packit 6d2c1b
	 * An ibv_detach is called when the last receiver sink is deleted from the registered list
Packit 6d2c1b
	 *
Packit 6d2c1b
	 */
Packit 6d2c1b
	bool 			attach_flow(pkt_rcvr_sink *sink); // Add a sink. If this is the first sink --> map the sink and attach flow to QP
Packit 6d2c1b
	bool 			detach_flow(pkt_rcvr_sink *sink); // Delete a sink. If this is the last sink --> delete it and detach flow from QP
Packit 6d2c1b
Packit 6d2c1b
	uint32_t 		get_num_of_sinks() const { return m_n_sinks_list_entries; }
Packit 6d2c1b
	virtual bool 		rx_dispatch_packet(mem_buf_desc_t* p_rx_wc_buf_desc, void* pv_fd_ready_array) = 0;
Packit 6d2c1b
Packit 6d2c1b
protected:
Packit 6d2c1b
	flow_tuple		m_flow_tuple;
Packit 6d2c1b
	ring_slave*		m_p_ring;
Packit 6d2c1b
	rfs_rule_filter*	m_p_rule_filter;
Packit 6d2c1b
	attach_flow_data_vector_t m_attach_flow_data_vector;
Packit 6d2c1b
	pkt_rcvr_sink**		m_sinks_list;
Packit 6d2c1b
	uint32_t 		m_n_sinks_list_entries; // Number of actual sinks in the array (we shrink the array if a sink is removed)
Packit 6d2c1b
	uint32_t		m_n_sinks_list_max_length;
Packit 6d2c1b
	uint32_t		m_flow_tag_id; // Associated with this rule, set by attach_flow()
Packit 6d2c1b
	bool 			m_b_tmp_is_attached; // Only temporary, while ibcm calls attach_flow with no sinks...
Packit 6d2c1b
Packit 6d2c1b
	bool 			create_ibv_flow(); // Attach flow to all qps
Packit 6d2c1b
	bool 			destroy_ibv_flow(); // Detach flow from all qps
Packit 6d2c1b
	bool 			add_sink(pkt_rcvr_sink* p_sink);
Packit 6d2c1b
	bool 			del_sink(pkt_rcvr_sink* p_sink);
Packit 6d2c1b
	virtual bool 		prepare_flow_spec() = 0;
Packit 6d2c1b
Packit 6d2c1b
private:
Packit 6d2c1b
	rfs();		// I don't want anyone to use the default constructor
Packit 6d2c1b
	inline void 		prepare_filter_attach(int& filter_counter, rule_filter_map_t::iterator& filter_iter);
Packit 6d2c1b
	inline void 		filter_keep_attached(rule_filter_map_t::iterator& filter_iter);
Packit 6d2c1b
	inline void 		prepare_filter_detach(int& filter_counter, bool decrease_counter);
Packit 6d2c1b
Packit 6d2c1b
};
Packit 6d2c1b
Packit 6d2c1b
#endif /* RFS_H */