Blame src/vma/proto/dst_entry.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 "utils/bullseye.h"
Packit 6d2c1b
#include "dst_entry.h"
Packit 6d2c1b
#include "vma/proto/rule_table_mgr.h"
Packit 6d2c1b
#include "vma/proto/route_table_mgr.h"
Packit 6d2c1b
#include "vma/util/utils.h"
Packit 6d2c1b
Packit 6d2c1b
#define MODULE_NAME             "dst"
Packit 6d2c1b
Packit 6d2c1b
#define dst_logpanic           __log_panic
Packit 6d2c1b
#define dst_logerr             __log_err
Packit 6d2c1b
#define dst_logwarn            __log_warn
Packit 6d2c1b
#define dst_loginfo            __log_info
Packit 6d2c1b
#define dst_logdbg             __log_info_dbg
Packit 6d2c1b
#define dst_logfunc            __log_info_func
Packit 6d2c1b
#define dst_logfuncall         __log_info_funcall
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
dst_entry::dst_entry(in_addr_t dst_ip, uint16_t dst_port, uint16_t src_port, socket_data &sock_data, resource_allocation_key &ring_alloc_logic):
Packit 6d2c1b
	m_dst_ip(dst_ip), m_dst_port(dst_port), m_src_port(src_port), m_bound_ip(0),
Packit 6d2c1b
	m_so_bindtodevice_ip(0), m_route_src_ip(0), m_pkt_src_ip(0),
Packit 6d2c1b
	m_ring_alloc_logic(sock_data.fd, ring_alloc_logic, this),
Packit 6d2c1b
	m_p_tx_mem_buf_desc_list(NULL), m_b_tx_mem_buf_desc_list_pending(false),
Packit 6d2c1b
	m_ttl(sock_data.ttl), m_tos(sock_data.tos), m_pcp(sock_data.pcp), m_id(0)
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("dst:%s:%d src: %d", m_dst_ip.to_str().c_str(), ntohs(m_dst_port), ntohs(m_src_port));
Packit 6d2c1b
	init_members();
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
dst_entry::~dst_entry()
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("%s", to_str().c_str());
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_neigh_entry) {
Packit 6d2c1b
		ip_address dst_addr = m_dst_ip;
Packit 6d2c1b
		if (m_p_rt_val && m_p_rt_val->get_gw_addr() != INADDR_ANY && !dst_addr.is_mc()) {
Packit 6d2c1b
			dst_addr = m_p_rt_val->get_gw_addr();
Packit 6d2c1b
		}
Packit 6d2c1b
		g_p_neigh_table_mgr->unregister_observer(neigh_key(dst_addr, m_p_net_dev_val),this);
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_rt_entry) {
Packit 6d2c1b
		g_p_route_table_mgr->unregister_observer(route_rule_table_key(m_dst_ip.get_in_addr(), m_route_src_ip, m_tos), this);
Packit 6d2c1b
		m_p_rt_entry = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_ring) {
Packit 6d2c1b
		if (m_sge) {
Packit 6d2c1b
			delete[] m_sge;
Packit 6d2c1b
			m_sge = NULL;
Packit 6d2c1b
		}
Packit 6d2c1b
Packit 6d2c1b
		if (m_p_tx_mem_buf_desc_list) {
Packit 6d2c1b
			m_p_ring->mem_buf_tx_release(m_p_tx_mem_buf_desc_list, true);
Packit 6d2c1b
			m_p_tx_mem_buf_desc_list = NULL;
Packit 6d2c1b
		}
Packit 6d2c1b
Packit 6d2c1b
		m_p_net_dev_val->release_ring(m_ring_alloc_logic.get_key());
Packit 6d2c1b
		m_p_ring = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_net_dev_entry && m_p_net_dev_val) {
Packit 6d2c1b
		g_p_net_device_table_mgr->unregister_observer(m_p_net_dev_val->get_local_addr(), this);
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_send_wqe_handler) {
Packit 6d2c1b
		delete m_p_send_wqe_handler;
Packit 6d2c1b
		m_p_send_wqe_handler = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_neigh_val) {
Packit 6d2c1b
		delete m_p_neigh_val;
Packit 6d2c1b
		m_p_neigh_val = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	dst_logdbg("Done %s", to_str().c_str());
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::init_members()
Packit 6d2c1b
{
Packit 6d2c1b
	set_state(false);
Packit 6d2c1b
	m_p_rt_val = NULL;
Packit 6d2c1b
	m_p_net_dev_val = NULL;
Packit 6d2c1b
	m_p_ring = NULL;
Packit 6d2c1b
	m_p_net_dev_entry = NULL;
Packit 6d2c1b
	m_p_neigh_entry = NULL;
Packit 6d2c1b
	m_p_neigh_val = NULL;
Packit 6d2c1b
	m_p_rt_entry = NULL;
Packit 6d2c1b
	memset(&m_inline_send_wqe, 0, sizeof(m_inline_send_wqe));
Packit 6d2c1b
	memset(&m_not_inline_send_wqe, 0, sizeof(m_not_inline_send_wqe));
Packit 6d2c1b
	memset(&m_fragmented_send_wqe, 0, sizeof(m_not_inline_send_wqe));
Packit 6d2c1b
	m_p_send_wqe_handler = NULL;
Packit 6d2c1b
	m_sge = NULL;
Packit 6d2c1b
	m_b_is_offloaded = true;
Packit 6d2c1b
	m_b_is_initialized = false;
Packit 6d2c1b
	m_p_send_wqe = NULL;
Packit 6d2c1b
	m_max_inline = 0;
Packit 6d2c1b
	m_max_ip_payload_size = 0;
Packit 6d2c1b
	m_max_udp_payload_size = 0;
Packit 6d2c1b
	m_b_force_os = false;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::set_src_addr()
Packit 6d2c1b
{
Packit 6d2c1b
	m_pkt_src_ip = INADDR_ANY;
Packit 6d2c1b
	if (m_route_src_ip) {
Packit 6d2c1b
		m_pkt_src_ip = m_route_src_ip;
Packit 6d2c1b
	}
Packit 6d2c1b
	else if (m_p_rt_val && m_p_rt_val->get_src_addr()) {
Packit 6d2c1b
		m_pkt_src_ip = m_p_rt_val->get_src_addr();
Packit 6d2c1b
	}
Packit 6d2c1b
	else if (m_p_net_dev_val && m_p_net_dev_val->get_local_addr()) {
Packit 6d2c1b
		m_pkt_src_ip = m_p_net_dev_val->get_local_addr();
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::update_net_dev_val()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	net_device_val* new_nd_val = m_p_net_dev_val;
Packit 6d2c1b
	if (m_so_bindtodevice_ip && g_p_net_device_table_mgr) {
Packit 6d2c1b
		new_nd_val = g_p_net_device_table_mgr->get_net_device_val(m_so_bindtodevice_ip);
Packit 6d2c1b
		// TODO should we register to g_p_net_device_table_mgr  with m_p_net_dev_entry?
Packit 6d2c1b
		// what should we do with an old one?
Packit 6d2c1b
		dst_logdbg("getting net_dev_val by bindtodevice ip");
Packit 6d2c1b
	} else if (m_p_rt_entry) {
Packit 6d2c1b
		new_nd_val = m_p_rt_entry->get_net_dev_val();
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_net_dev_val != new_nd_val) {
Packit 6d2c1b
		dst_logdbg("updating net_device");
Packit 6d2c1b
Packit 6d2c1b
		if (m_p_neigh_entry) {
Packit 6d2c1b
			ip_address dst_addr = m_dst_ip;
Packit 6d2c1b
			if (m_p_rt_val && m_p_rt_val->get_gw_addr() != INADDR_ANY && !dst_addr.is_mc()) {
Packit 6d2c1b
				dst_addr = m_p_rt_val->get_gw_addr();
Packit 6d2c1b
			}
Packit 6d2c1b
			g_p_neigh_table_mgr->unregister_observer(neigh_key(dst_addr, m_p_net_dev_val),this);
Packit 6d2c1b
			m_p_neigh_entry = NULL;
Packit 6d2c1b
		}
Packit 6d2c1b
Packit 6d2c1b
		// Change the net_device, clean old resources...
Packit 6d2c1b
		release_ring();
Packit 6d2c1b
Packit 6d2c1b
		// Save the new net_device
Packit 6d2c1b
		m_p_net_dev_val = new_nd_val;
Packit 6d2c1b
Packit 6d2c1b
		if (m_p_net_dev_val) {
Packit 6d2c1b
			// more resource clean and alloc...
Packit 6d2c1b
			ret_val = alloc_transport_dep_res();
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logdbg("Netdev is not offloaded fallback to OS");
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		if (m_p_net_dev_val) {
Packit 6d2c1b
			// Only if we already had a valid net_device_val which did not change
Packit 6d2c1b
			dst_logdbg("no change in net_device");
Packit 6d2c1b
			ret_val = true;
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logdbg("Netdev is not offloaded fallback to OS");
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::update_rt_val()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = true;
Packit 6d2c1b
	route_val* p_rt_val = NULL;
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_rt_entry && m_p_rt_entry->get_val(p_rt_val)) {
Packit 6d2c1b
		if (m_p_rt_val == p_rt_val) {
Packit 6d2c1b
			dst_logdbg("no change in route_val");
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logdbg("updating route val");
Packit 6d2c1b
			m_p_rt_val = p_rt_val;
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		dst_logdbg("Route entry is not valid");
Packit 6d2c1b
		ret_val = false;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::resolve_net_dev(bool is_connect)
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	cache_entry_subject<route_rule_table_key, route_val*>* p_ces = NULL;
Packit 6d2c1b
	
Packit 6d2c1b
	if (ZERONET_N(m_dst_ip.get_in_addr())) {
Packit 6d2c1b
		dst_logdbg("VMA does not offload zero net IP address");
Packit 6d2c1b
		return ret_val;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (LOOPBACK_N(m_dst_ip.get_in_addr())) {
Packit 6d2c1b
		dst_logdbg("VMA does not offload local loopback IP address");
Packit 6d2c1b
		return ret_val;
Packit 6d2c1b
	}
Packit 6d2c1b
	
Packit 6d2c1b
	//When VMA will support routing with OIF, we need to check changing in outgoing interface
Packit 6d2c1b
	//Source address changes is not checked since multiple bind is not allowed on the same socket
Packit 6d2c1b
	if (!m_p_rt_entry) {
Packit 6d2c1b
		m_route_src_ip = m_bound_ip;
Packit 6d2c1b
		route_rule_table_key rtk(m_dst_ip.get_in_addr(), m_route_src_ip, m_tos);
Packit 6d2c1b
		if (g_p_route_table_mgr->register_observer(rtk, this, &p_ces)) {
Packit 6d2c1b
			// In case this is the first time we trying to resolve route entry,
Packit 6d2c1b
			// means that register_observer was run
Packit 6d2c1b
			m_p_rt_entry = dynamic_cast<route_entry*>(p_ces);
Packit 6d2c1b
			if (is_connect && !m_route_src_ip) {
Packit 6d2c1b
				route_val* p_rt_val = NULL;
Packit 6d2c1b
				if (m_p_rt_entry && m_p_rt_entry->get_val(p_rt_val) && p_rt_val->get_src_addr()) {
Packit 6d2c1b
					g_p_route_table_mgr->unregister_observer(rtk, this);
Packit 6d2c1b
					m_route_src_ip = p_rt_val->get_src_addr();
Packit 6d2c1b
					route_rule_table_key new_rtk(m_dst_ip.get_in_addr(), m_route_src_ip, m_tos);
Packit 6d2c1b
					if (g_p_route_table_mgr->register_observer(new_rtk, this, &p_ces)) {
Packit 6d2c1b
						m_p_rt_entry = dynamic_cast<route_entry*>(p_ces);
Packit 6d2c1b
					}
Packit 6d2c1b
					else {
Packit 6d2c1b
						dst_logdbg("Error in route resolving logic");
Packit 6d2c1b
						return ret_val;
Packit 6d2c1b
					}
Packit 6d2c1b
				}
Packit 6d2c1b
			}
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logdbg("Error in registering route entry");
Packit 6d2c1b
			return ret_val;
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (update_rt_val()) {
Packit 6d2c1b
		ret_val = update_net_dev_val();
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::resolve_neigh()
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("");
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
	ip_address dst_addr = m_dst_ip;
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_rt_val && m_p_rt_val->get_gw_addr() != INADDR_ANY && !dst_addr.is_mc()) {
Packit 6d2c1b
		dst_addr = m_p_rt_val->get_gw_addr();
Packit 6d2c1b
	}
Packit 6d2c1b
	cache_entry_subject<neigh_key, neigh_val*>* p_ces = NULL;
Packit 6d2c1b
	if (m_p_neigh_entry || g_p_neigh_table_mgr->register_observer(neigh_key(dst_addr, m_p_net_dev_val), this, &p_ces)) {
Packit 6d2c1b
		if(m_p_neigh_entry == NULL)
Packit 6d2c1b
			m_p_neigh_entry = dynamic_cast<neigh_entry*>(p_ces);
Packit 6d2c1b
		if (m_p_neigh_entry) {
Packit 6d2c1b
			if (m_p_neigh_entry->get_peer_info(m_p_neigh_val)) {
Packit 6d2c1b
				dst_logdbg("neigh is valid");
Packit 6d2c1b
				ret_val = true;
Packit 6d2c1b
			}
Packit 6d2c1b
			else {
Packit 6d2c1b
				dst_logdbg("neigh is not valid");
Packit 6d2c1b
			}
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::resolve_ring()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_net_dev_val) {
Packit 6d2c1b
		if (!m_p_ring) {
Packit 6d2c1b
			dst_logdbg("getting a ring");
Packit 6d2c1b
			m_p_ring = m_p_net_dev_val->reserve_ring(m_ring_alloc_logic.create_new_key(m_pkt_src_ip));
Packit 6d2c1b
		}
Packit 6d2c1b
		if (m_p_ring) {
Packit 6d2c1b
			if (m_sge) {
Packit 6d2c1b
				delete[] m_sge;
Packit 6d2c1b
				m_sge = NULL;
Packit 6d2c1b
			}
Packit 6d2c1b
#ifdef DEFINED_TSO
Packit 6d2c1b
			m_sge = new (nothrow) struct ibv_sge [m_p_ring->get_max_send_sge()];
Packit 6d2c1b
#else
Packit 6d2c1b
			m_sge = new (nothrow) struct ibv_sge [2];
Packit 6d2c1b
#endif /* DEFINED_TSO */
Packit 6d2c1b
			if (!m_sge) {
Packit 6d2c1b
				dst_logpanic("%s Failed to allocate send SGE", to_str().c_str());
Packit 6d2c1b
			}
Packit 6d2c1b
			m_max_inline = m_p_ring->get_max_inline_data();
Packit 6d2c1b
			m_max_inline = std::min<uint32_t>(m_max_inline, get_route_mtu() + (uint32_t)m_header.m_transport_header_len);
Packit 6d2c1b
			ret_val = true;
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::release_ring()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
	if (m_p_net_dev_val) {
Packit 6d2c1b
		if (m_p_ring) {
Packit 6d2c1b
			if (m_p_tx_mem_buf_desc_list) {
Packit 6d2c1b
				m_p_ring->mem_buf_tx_release(m_p_tx_mem_buf_desc_list, true);
Packit 6d2c1b
				m_p_tx_mem_buf_desc_list = NULL;
Packit 6d2c1b
			}
Packit 6d2c1b
			dst_logdbg("releasing a ring");
Packit 6d2c1b
			if (m_p_net_dev_val->release_ring(m_ring_alloc_logic.get_key())) {
Packit 6d2c1b
				dst_logerr("Failed to release ring for allocation key %s",
Packit 6d2c1b
					   m_ring_alloc_logic.get_key()->to_str());
Packit 6d2c1b
			}
Packit 6d2c1b
			m_p_ring = NULL;
Packit 6d2c1b
		}
Packit 6d2c1b
		ret_val = true;
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::notify_cb()
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("");
Packit 6d2c1b
	set_state(false);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::configure_ip_header(header *h, uint16_t packet_id)
Packit 6d2c1b
{
Packit 6d2c1b
	h->configure_ip_header(get_protocol_type(), m_pkt_src_ip, m_dst_ip.get_in_addr(), m_ttl, m_tos, packet_id);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::conf_l2_hdr_and_snd_wqe_eth()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	//Maybe we after invalidation so we free the wqe_handler since we are going to build it from scratch
Packit 6d2c1b
	if (m_p_send_wqe_handler) {
Packit 6d2c1b
		delete m_p_send_wqe_handler;
Packit 6d2c1b
		m_p_send_wqe_handler = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	m_p_send_wqe_handler = new wqe_send_handler();
Packit 6d2c1b
	if (!m_p_send_wqe_handler) {
Packit 6d2c1b
		dst_logpanic("%s Failed to allocate send WQE handler", to_str().c_str());
Packit 6d2c1b
	}
Packit 6d2c1b
	m_p_send_wqe_handler->init_inline_wqe(m_inline_send_wqe, get_sge_lst_4_inline_send(), get_inline_sge_num());
Packit 6d2c1b
	m_p_send_wqe_handler->init_not_inline_wqe(m_not_inline_send_wqe, get_sge_lst_4_not_inline_send(), 1);
Packit 6d2c1b
	m_p_send_wqe_handler->init_wqe(m_fragmented_send_wqe, get_sge_lst_4_not_inline_send(), 1);
Packit 6d2c1b
Packit 6d2c1b
	net_device_val_eth *netdevice_eth = dynamic_cast<net_device_val_eth*>(m_p_net_dev_val);
Packit 6d2c1b
	BULLSEYE_EXCLUDE_BLOCK_START
Packit 6d2c1b
	if (netdevice_eth) {
Packit 6d2c1b
	BULLSEYE_EXCLUDE_BLOCK_END
Packit 6d2c1b
		const L2_address *src = m_p_net_dev_val->get_l2_address();
Packit 6d2c1b
		const L2_address *dst = m_p_neigh_val->get_l2_address();
Packit 6d2c1b
Packit 6d2c1b
		BULLSEYE_EXCLUDE_BLOCK_START
Packit 6d2c1b
		if (src && dst) {
Packit 6d2c1b
		BULLSEYE_EXCLUDE_BLOCK_END
Packit 6d2c1b
			if (netdevice_eth->get_vlan()) { //vlan interface
Packit 6d2c1b
				uint32_t prio = get_priority_by_tc_class(m_pcp);
Packit 6d2c1b
				uint16_t vlan_tci = (prio << NET_ETH_VLAN_PCP_OFFSET) |
Packit 6d2c1b
						netdevice_eth->get_vlan();
Packit 6d2c1b
				m_header.configure_vlan_eth_headers(*src, *dst, vlan_tci);
Packit 6d2c1b
			}
Packit 6d2c1b
			else {
Packit 6d2c1b
				m_header.configure_eth_headers(*src, *dst);
Packit 6d2c1b
			}
Packit 6d2c1b
			init_sge();
Packit 6d2c1b
			ret_val = true;
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logerr("Can't build proper L2 header, L2 address is not available");
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		dst_logerr("Dynamic cast failed, can't build proper L2 header");
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
bool  dst_entry::conf_l2_hdr_and_snd_wqe_ib()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
	neigh_ib_val *neigh_ib = dynamic_cast<neigh_ib_val*>(m_p_neigh_val);
Packit 6d2c1b
Packit 6d2c1b
	BULLSEYE_EXCLUDE_BLOCK_START
Packit 6d2c1b
	if (!neigh_ib) {
Packit 6d2c1b
		dst_logerr("Dynamic cast to neigh_ib failed, can't build proper ibv_send_wqe: header");
Packit 6d2c1b
	BULLSEYE_EXCLUDE_BLOCK_END
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		uint32_t qpn = neigh_ib->get_qpn();
Packit 6d2c1b
		uint32_t qkey = neigh_ib->get_qkey();
Packit 6d2c1b
		struct ibv_ah *ah = (struct ibv_ah *)neigh_ib->get_ah();
Packit 6d2c1b
Packit 6d2c1b
		//Maybe we after invalidation so we free the wqe_handler since we are going to build it from scratch
Packit 6d2c1b
		if (m_p_send_wqe_handler) {
Packit 6d2c1b
			delete m_p_send_wqe_handler;
Packit 6d2c1b
			m_p_send_wqe_handler = NULL;
Packit 6d2c1b
		}
Packit 6d2c1b
		m_p_send_wqe_handler = new wqe_send_ib_handler();
Packit 6d2c1b
Packit 6d2c1b
		BULLSEYE_EXCLUDE_BLOCK_START
Packit 6d2c1b
		if (!m_p_send_wqe_handler) {
Packit 6d2c1b
			dst_logpanic("%s Failed to allocate send WQE handler", to_str().c_str());
Packit 6d2c1b
		}
Packit 6d2c1b
		BULLSEYE_EXCLUDE_BLOCK_END
Packit 6d2c1b
		((wqe_send_ib_handler *)(m_p_send_wqe_handler))->init_inline_ib_wqe(m_inline_send_wqe, get_sge_lst_4_inline_send(), get_inline_sge_num(), ah, qpn, qkey);
Packit 6d2c1b
		((wqe_send_ib_handler*)(m_p_send_wqe_handler))->init_not_inline_ib_wqe(m_not_inline_send_wqe, get_sge_lst_4_not_inline_send(), 1, ah, qpn, qkey);
Packit 6d2c1b
		((wqe_send_ib_handler*)(m_p_send_wqe_handler))->init_ib_wqe(m_fragmented_send_wqe, get_sge_lst_4_not_inline_send(), 1, ah, qpn, qkey);
Packit 6d2c1b
		m_header.configure_ipoib_headers();
Packit 6d2c1b
		init_sge();
Packit 6d2c1b
Packit 6d2c1b
		ret_val = true;
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::conf_hdrs_and_snd_wqe()
Packit 6d2c1b
{
Packit 6d2c1b
	transport_type_t tranposrt = VMA_TRANSPORT_IB;
Packit 6d2c1b
	bool ret_val = true;
Packit 6d2c1b
Packit 6d2c1b
	dst_logdbg("dst_entry %s configuring the header template", to_str().c_str());
Packit 6d2c1b
Packit 6d2c1b
	configure_ip_header(&m_header);
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_net_dev_val) {
Packit 6d2c1b
		tranposrt = m_p_net_dev_val->get_transport_type();
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	switch (tranposrt) {
Packit 6d2c1b
	case VMA_TRANSPORT_ETH:
Packit 6d2c1b
		ret_val = conf_l2_hdr_and_snd_wqe_eth();
Packit 6d2c1b
		break;
Packit 6d2c1b
	case VMA_TRANSPORT_IB:
Packit 6d2c1b
	default:
Packit 6d2c1b
		ret_val = conf_l2_hdr_and_snd_wqe_ib();
Packit 6d2c1b
		break;
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage off
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::get_net_dev_val()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_rt_entry) {
Packit 6d2c1b
		m_p_rt_entry->get_val(m_p_rt_val);
Packit 6d2c1b
		ret_val = true;
Packit 6d2c1b
	}
Packit 6d2c1b
	else {
Packit 6d2c1b
		dst_logdbg("%s doesn't use route table to resolve netdev", to_str().c_str());
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage on
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
//Implementation of pure virtual function of neigh_observer
Packit 6d2c1b
transport_type_t dst_entry::get_obs_transport_type() const
Packit 6d2c1b
{
Packit 6d2c1b
	if(m_p_net_dev_val)
Packit 6d2c1b
		return(m_p_net_dev_val->get_transport_type());
Packit 6d2c1b
	return VMA_TRANSPORT_UNKNOWN;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage off
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
flow_tuple dst_entry::get_flow_tuple() const
Packit 6d2c1b
{
Packit 6d2c1b
	in_addr_t dst_ip = 0;
Packit 6d2c1b
	in_protocol_t protocol = PROTO_UNDEFINED;
Packit 6d2c1b
Packit 6d2c1b
	dst_ip = m_dst_ip.get_in_addr();
Packit 6d2c1b
	protocol = (in_protocol_t)get_protocol_type();
Packit 6d2c1b
Packit 6d2c1b
	return flow_tuple(dst_ip, m_dst_port, m_pkt_src_ip, m_src_port, protocol);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
#if _BullseyeCoverage
Packit 6d2c1b
    #pragma BullseyeCoverage on
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::offloaded_according_to_rules()
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = true;
Packit 6d2c1b
	transport_t target_transport;
Packit 6d2c1b
Packit 6d2c1b
	sockaddr_in to;
Packit 6d2c1b
	memset(&to, 0, sizeof(to));
Packit 6d2c1b
	to.sin_family = AF_INET;
Packit 6d2c1b
	to.sin_addr.s_addr = m_dst_ip.get_in_addr();
Packit 6d2c1b
	to.sin_port = m_dst_port;
Packit 6d2c1b
Packit 6d2c1b
Packit 6d2c1b
	target_transport = get_transport(to);
Packit 6d2c1b
Packit 6d2c1b
	if (target_transport == TRANS_OS) {
Packit 6d2c1b
		ret_val = false;
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::prepare_to_send(struct vma_rate_limit_t &rate_limit, bool skip_rules, bool is_connect)
Packit 6d2c1b
{
Packit 6d2c1b
	bool resolved = false;
Packit 6d2c1b
	m_slow_path_lock.lock();
Packit 6d2c1b
	if (!m_b_is_initialized) {
Packit 6d2c1b
		if((!skip_rules) && (!offloaded_according_to_rules())) {
Packit 6d2c1b
			dst_logdbg("dst_entry in BLACK LIST!");
Packit 6d2c1b
			m_b_is_offloaded = false;
Packit 6d2c1b
			m_b_force_os = true;
Packit 6d2c1b
		}
Packit 6d2c1b
		m_b_is_initialized = true;
Packit 6d2c1b
	}
Packit 6d2c1b
	dst_logdbg("%s", to_str().c_str());
Packit 6d2c1b
	if (!m_b_force_os && !is_valid()) {
Packit 6d2c1b
		bool is_ofloaded = false;
Packit 6d2c1b
		set_state(true);
Packit 6d2c1b
		if (resolve_net_dev(is_connect)) {
Packit 6d2c1b
			set_src_addr();
Packit 6d2c1b
			// overwrite mtu from route if exists
Packit 6d2c1b
			m_max_udp_payload_size = get_route_mtu() - sizeof(struct iphdr);
Packit 6d2c1b
			m_max_ip_payload_size = m_max_udp_payload_size & ~0x7;
Packit 6d2c1b
			if (resolve_ring()) {
Packit 6d2c1b
				is_ofloaded = true;
Packit 6d2c1b
				modify_ratelimit(rate_limit);
Packit 6d2c1b
				if (resolve_neigh()) {
Packit 6d2c1b
					if (get_obs_transport_type() == VMA_TRANSPORT_ETH) {
Packit 6d2c1b
						dst_logdbg("local mac: %s peer mac: %s", m_p_net_dev_val->get_l2_address()->to_str().c_str(), m_p_neigh_val->get_l2_address()->to_str().c_str());
Packit 6d2c1b
					} else {
Packit 6d2c1b
						dst_logdbg("peer L2 address: %s", m_p_neigh_val->get_l2_address()->to_str().c_str());
Packit 6d2c1b
					}
Packit 6d2c1b
					configure_headers();
Packit 6d2c1b
					m_id = m_p_ring->generate_id(m_p_net_dev_val->get_l2_address()->get_address(),
Packit 6d2c1b
								     m_p_neigh_val->get_l2_address()->get_address(),
Packit 6d2c1b
								     ((ethhdr*)(m_header.m_actual_hdr_addr))->h_proto /* if vlan, use vlan proto */,
Packit 6d2c1b
								     htons(ETH_P_IP),
Packit 6d2c1b
								     m_pkt_src_ip,
Packit 6d2c1b
								     m_dst_ip.get_in_addr(),
Packit 6d2c1b
								     m_src_port,
Packit 6d2c1b
								     m_dst_port);
Packit 6d2c1b
					if (m_p_tx_mem_buf_desc_list) {
Packit 6d2c1b
						m_p_ring->mem_buf_tx_release(m_p_tx_mem_buf_desc_list, true);
Packit 6d2c1b
						m_p_tx_mem_buf_desc_list = NULL;
Packit 6d2c1b
					}
Packit 6d2c1b
					resolved = true;
Packit 6d2c1b
				}
Packit 6d2c1b
			}
Packit 6d2c1b
		}
Packit 6d2c1b
		m_b_is_offloaded = is_ofloaded;
Packit 6d2c1b
		if (m_b_is_offloaded) {
Packit 6d2c1b
			dst_logdbg("dst_entry is offloaded!");
Packit 6d2c1b
		}
Packit 6d2c1b
		else {
Packit 6d2c1b
			dst_logdbg("dst_entry is NOT offloaded!");
Packit 6d2c1b
		}
Packit 6d2c1b
		if (!resolved) {
Packit 6d2c1b
			set_state(false);
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	m_slow_path_lock.unlock();
Packit 6d2c1b
Packit 6d2c1b
	return m_b_is_offloaded;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::try_migrate_ring(lock_base& socket_lock)
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret = false;
Packit 6d2c1b
	if (m_ring_alloc_logic.is_logic_support_migration()) {
Packit 6d2c1b
		if (!m_tx_migration_lock.trylock()) {
Packit 6d2c1b
			if (m_ring_alloc_logic.should_migrate_ring()) {
Packit 6d2c1b
				resource_allocation_key old_key(*m_ring_alloc_logic.get_key());
Packit 6d2c1b
				do_ring_migration(socket_lock, old_key);
Packit 6d2c1b
				ret = true;
Packit 6d2c1b
			}
Packit 6d2c1b
			m_tx_migration_lock.unlock();
Packit 6d2c1b
		}
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int dst_entry::get_route_mtu()
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_p_rt_val && m_p_rt_val->get_mtu() > 0 ) {
Packit 6d2c1b
		return m_p_rt_val->get_mtu();
Packit 6d2c1b
	}
Packit 6d2c1b
	return m_p_net_dev_val->get_mtu();
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::do_ring_migration(lock_base& socket_lock, resource_allocation_key &old_key)
Packit 6d2c1b
{
Packit 6d2c1b
	m_slow_path_lock.lock();
Packit 6d2c1b
Packit 6d2c1b
	if (!m_p_net_dev_val || !m_p_ring) {
Packit 6d2c1b
		m_slow_path_lock.unlock();
Packit 6d2c1b
		return;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	uint64_t new_calc_id = m_ring_alloc_logic.calc_res_key_by_logic();
Packit 6d2c1b
	resource_allocation_key *new_key = m_ring_alloc_logic.get_key();
Packit 6d2c1b
	// Check again if migration is needed before migration
Packit 6d2c1b
	if (old_key.get_user_id_key() == new_calc_id &&
Packit 6d2c1b
	    old_key.get_ring_alloc_logic() == new_key->get_ring_alloc_logic()) {
Packit 6d2c1b
		m_slow_path_lock.unlock();
Packit 6d2c1b
		return;
Packit 6d2c1b
	}
Packit 6d2c1b
	// Update key to new ID
Packit 6d2c1b
	new_key->set_user_id_key(new_calc_id);
Packit 6d2c1b
	m_slow_path_lock.unlock();
Packit 6d2c1b
	socket_lock.unlock();
Packit 6d2c1b
Packit 6d2c1b
	ring* new_ring = m_p_net_dev_val->reserve_ring(new_key);
Packit 6d2c1b
	if (!new_ring) {
Packit 6d2c1b
		socket_lock.lock();
Packit 6d2c1b
		return;
Packit 6d2c1b
	}
Packit 6d2c1b
	if (new_ring == m_p_ring) {
Packit 6d2c1b
		if (!m_p_net_dev_val->release_ring(&old_key)) {
Packit 6d2c1b
			dst_logerr("Failed to release ring for allocation key %s",
Packit 6d2c1b
				  old_key.to_str());
Packit 6d2c1b
		}
Packit 6d2c1b
		socket_lock.lock();
Packit 6d2c1b
		return;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	dst_logdbg("migrating from key=%s and ring=%p to key=%s and ring=%p",
Packit 6d2c1b
		   old_key.to_str(), m_p_ring, new_key->to_str(), new_ring);
Packit 6d2c1b
Packit 6d2c1b
	socket_lock.lock();
Packit 6d2c1b
	m_slow_path_lock.lock();
Packit 6d2c1b
Packit 6d2c1b
	set_state(false);
Packit 6d2c1b
Packit 6d2c1b
	ring* old_ring = m_p_ring;
Packit 6d2c1b
	m_p_ring = new_ring;
Packit 6d2c1b
	if (m_sge) {
Packit 6d2c1b
		delete[] m_sge;
Packit 6d2c1b
		m_sge = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
#ifdef DEFINED_TSO
Packit 6d2c1b
	m_sge = new (nothrow) struct ibv_sge [m_p_ring->get_max_send_sge()];
Packit 6d2c1b
#else
Packit 6d2c1b
	m_sge = new (nothrow) struct ibv_sge [2];
Packit 6d2c1b
#endif /* DEFINED_TSO */
Packit 6d2c1b
	if (!m_sge) {
Packit 6d2c1b
		dst_logpanic("%s Failed to allocate send SGE", to_str().c_str());
Packit 6d2c1b
	}
Packit 6d2c1b
	m_max_inline = m_p_ring->get_max_inline_data();
Packit 6d2c1b
	m_max_inline = std::min<uint32_t>(m_max_inline, get_route_mtu() + (uint32_t)m_header.m_transport_header_len);
Packit 6d2c1b
Packit 6d2c1b
	mem_buf_desc_t* tmp_list = m_p_tx_mem_buf_desc_list;
Packit 6d2c1b
	m_p_tx_mem_buf_desc_list = NULL;
Packit 6d2c1b
Packit 6d2c1b
	m_slow_path_lock.unlock();
Packit 6d2c1b
	socket_lock.unlock();
Packit 6d2c1b
Packit 6d2c1b
	if (tmp_list) {
Packit 6d2c1b
		old_ring->mem_buf_tx_release(tmp_list, true);
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	m_p_net_dev_val->release_ring(&old_key);
Packit 6d2c1b
Packit 6d2c1b
	socket_lock.lock();
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::set_bound_addr(in_addr_t addr)
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("");
Packit 6d2c1b
	m_bound_ip = addr;
Packit 6d2c1b
	set_state(false);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::set_so_bindtodevice_addr(in_addr_t addr)
Packit 6d2c1b
{
Packit 6d2c1b
	dst_logdbg("");
Packit 6d2c1b
	m_so_bindtodevice_ip = addr;
Packit 6d2c1b
	set_state(false);
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
in_addr_t dst_entry::get_dst_addr()
Packit 6d2c1b
{
Packit 6d2c1b
	return m_dst_ip.get_in_addr();
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
uint16_t dst_entry::get_dst_port()
Packit 6d2c1b
{
Packit 6d2c1b
	return m_dst_port;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
ssize_t dst_entry::pass_buff_to_neigh(const iovec * p_iov, size_t sz_iov, uint16_t packet_id)
Packit 6d2c1b
{
Packit 6d2c1b
	ssize_t ret_val = 0;
Packit 6d2c1b
Packit 6d2c1b
	dst_logdbg("");
Packit 6d2c1b
Packit 6d2c1b
	configure_ip_header(&m_header_neigh, packet_id);
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_neigh_entry) {
Packit 6d2c1b
		neigh_send_info n_send_info(const_cast<iovec *>(p_iov),
Packit 6d2c1b
				sz_iov, &m_header_neigh,
Packit 6d2c1b
				get_protocol_type(), get_route_mtu(),
Packit 6d2c1b
				m_tos);
Packit 6d2c1b
		ret_val = m_p_neigh_entry->send(n_send_info);
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::alloc_transport_dep_res()
Packit 6d2c1b
{
Packit 6d2c1b
	return alloc_neigh_val(get_obs_transport_type());
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::alloc_neigh_val(transport_type_t tranport)
Packit 6d2c1b
{
Packit 6d2c1b
	bool ret_val = false;
Packit 6d2c1b
Packit 6d2c1b
	if (m_p_neigh_val) {
Packit 6d2c1b
		delete m_p_neigh_val;
Packit 6d2c1b
		m_p_neigh_val = NULL;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	switch (tranport) {
Packit 6d2c1b
		case VMA_TRANSPORT_IB:
Packit 6d2c1b
			m_p_neigh_val = new neigh_ib_val;
Packit 6d2c1b
			break;
Packit 6d2c1b
		case VMA_TRANSPORT_ETH:
Packit 6d2c1b
		default:
Packit 6d2c1b
			m_p_neigh_val = new neigh_eth_val;
Packit 6d2c1b
			break;
Packit 6d2c1b
	}
Packit 6d2c1b
	if (m_p_neigh_val) {
Packit 6d2c1b
		ret_val = true;
Packit 6d2c1b
	}
Packit 6d2c1b
	return ret_val;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
void dst_entry::return_buffers_pool()
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_p_tx_mem_buf_desc_list == NULL) {
Packit 6d2c1b
		return;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	if (m_b_tx_mem_buf_desc_list_pending && m_p_ring &&
Packit 6d2c1b
		m_p_ring->mem_buf_tx_release(m_p_tx_mem_buf_desc_list, true, true)) {
Packit 6d2c1b
		m_p_tx_mem_buf_desc_list = NULL;
Packit 6d2c1b
		set_tx_buff_list_pending(false);
Packit 6d2c1b
	} else {
Packit 6d2c1b
		set_tx_buff_list_pending(true);
Packit 6d2c1b
	}
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int dst_entry::modify_ratelimit(struct vma_rate_limit_t &rate_limit)
Packit 6d2c1b
{
Packit 6d2c1b
	if (m_p_ring) {
Packit 6d2c1b
		return m_p_ring->modify_ratelimit(rate_limit);
Packit 6d2c1b
	}
Packit 6d2c1b
	return 0;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
int dst_entry::get_priority_by_tc_class(uint32_t pcp)
Packit 6d2c1b
{
Packit 6d2c1b
	// translate class to priority
Packit 6d2c1b
	if (m_p_net_dev_val) {
Packit 6d2c1b
		return m_p_net_dev_val->get_priority_by_tc_class(pcp);
Packit 6d2c1b
	}
Packit 6d2c1b
	return VMA_DEFAULT_ENGRESS_MAP_PRIO;
Packit 6d2c1b
}
Packit 6d2c1b
Packit 6d2c1b
bool dst_entry::update_ring_alloc_logic(int fd, lock_base& socket_lock, resource_allocation_key &ring_alloc_logic)
Packit 6d2c1b
{
Packit 6d2c1b
	resource_allocation_key old_key(*m_ring_alloc_logic.get_key());
Packit 6d2c1b
Packit 6d2c1b
	m_ring_alloc_logic = ring_allocation_logic_tx(fd, ring_alloc_logic, this);
Packit 6d2c1b
Packit 6d2c1b
	if (*m_ring_alloc_logic.get_key() != old_key) {
Packit 6d2c1b
		auto_unlocker locker(m_tx_migration_lock);
Packit 6d2c1b
		do_ring_migration(socket_lock, old_key);
Packit 6d2c1b
		return true;
Packit 6d2c1b
	}
Packit 6d2c1b
Packit 6d2c1b
	return false;
Packit 6d2c1b
}