|
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 |
}
|