|
Packit Service |
aa3af4 |
/*
|
|
Packit Service |
aa3af4 |
* Copyright (c) 2001-2020 Mellanox Technologies, Ltd. All rights reserved.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* This software is available to you under a choice of one of two
|
|
Packit Service |
aa3af4 |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit Service |
aa3af4 |
* General Public License (GPL) Version 2, available from the file
|
|
Packit Service |
aa3af4 |
* COPYING in the main directory of this source tree, or the
|
|
Packit Service |
aa3af4 |
* BSD license below:
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* Redistribution and use in source and binary forms, with or
|
|
Packit Service |
aa3af4 |
* without modification, are permitted provided that the following
|
|
Packit Service |
aa3af4 |
* conditions are met:
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* - Redistributions of source code must retain the above
|
|
Packit Service |
aa3af4 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
aa3af4 |
* disclaimer.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* - Redistributions in binary form must reproduce the above
|
|
Packit Service |
aa3af4 |
* copyright notice, this list of conditions and the following
|
|
Packit Service |
aa3af4 |
* disclaimer in the documentation and/or other materials
|
|
Packit Service |
aa3af4 |
* provided with the distribution.
|
|
Packit Service |
aa3af4 |
*
|
|
Packit Service |
aa3af4 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit Service |
aa3af4 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit Service |
aa3af4 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit Service |
aa3af4 |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit Service |
aa3af4 |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit Service |
aa3af4 |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit Service |
aa3af4 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit Service |
aa3af4 |
* SOFTWARE.
|
|
Packit Service |
aa3af4 |
*/
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
#include "utils/bullseye.h"
|
|
Packit Service |
aa3af4 |
#include "vma/util/utils.h"
|
|
Packit Service |
aa3af4 |
#include "vma/dev/rfs_mc.h"
|
|
Packit Service |
aa3af4 |
#include "vma/dev/ring_simple.h"
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
#define MODULE_NAME "rfs_mc"
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
rfs_mc::rfs_mc(flow_tuple *flow_spec_5t, ring_slave *p_ring, rfs_rule_filter* rule_filter /*= NULL*/, int flow_tag_id /*=0*/):
|
|
Packit Service |
aa3af4 |
rfs (flow_spec_5t, p_ring, rule_filter, flow_tag_id)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
BULLSEYE_EXCLUDE_BLOCK_START
|
|
Packit Service |
aa3af4 |
if (!m_flow_tuple.is_udp_mc()) {
|
|
Packit Service |
aa3af4 |
throw_vma_exception("rfs_mc called with non mc destination ip");
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
BULLSEYE_EXCLUDE_BLOCK_END
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (m_p_ring->is_simple() && !prepare_flow_spec()) {
|
|
Packit Service |
aa3af4 |
throw_vma_exception("IB multicast offload is not supported");
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
bool rfs_mc::prepare_flow_spec()
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
ring_simple* p_ring = dynamic_cast<ring_simple*>(m_p_ring);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (!p_ring) {
|
|
Packit Service |
aa3af4 |
rfs_logpanic("Incompatible ring type");
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
transport_type_t type = p_ring->get_transport_type();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
/*
|
|
Packit Service |
aa3af4 |
* todo note that ring is not locked here.
|
|
Packit Service |
aa3af4 |
* we touch members that should not change during the ring life.
|
|
Packit Service |
aa3af4 |
* the ring will not be deleted as we increased refcnt.
|
|
Packit Service |
aa3af4 |
* if one of these assumptions change, we must lock.
|
|
Packit Service |
aa3af4 |
*/
|
|
Packit Service |
aa3af4 |
attach_flow_data_t* p_attach_flow_data = NULL;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
switch (type) {
|
|
Packit Service |
aa3af4 |
case VMA_TRANSPORT_IB:
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
attach_flow_data_ib_v2_t* attach_flow_data_ib_v2 = NULL;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (0 == p_ring->m_p_qp_mgr->get_underly_qpn()) {
|
|
Packit Service |
aa3af4 |
// IB MC flow steering is done only on L2 --> need to zero other fields to get correct behaviour
|
|
Packit Service |
aa3af4 |
// CX3 HW does not support L3+L4 MC flow steering rule
|
|
Packit Service |
aa3af4 |
#ifdef DEFINED_IBV_FLOW_SPEC_IB
|
|
Packit Service |
aa3af4 |
attach_flow_data_ib_v1_t* attach_flow_data_ib_v1 = NULL;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
attach_flow_data_ib_v1 = new attach_flow_data_ib_v1_t(p_ring->m_p_qp_mgr);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
uint8_t dst_gid[16];
|
|
Packit Service |
aa3af4 |
create_mgid_from_ipv4_mc_ip(dst_gid, p_ring->m_p_qp_mgr->get_partiton(), m_flow_tuple.get_dst_ip());
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_ib_set_by_dst_gid(&(attach_flow_data_ib_v1->ibv_flow_attr.ib),
|
|
Packit Service |
aa3af4 |
dst_gid);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
p_attach_flow_data = (attach_flow_data_t*)attach_flow_data_ib_v1;
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
#else
|
|
Packit Service |
aa3af4 |
return false;
|
|
Packit Service |
aa3af4 |
#endif
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
attach_flow_data_ib_v2 = new attach_flow_data_ib_v2_t(p_ring->m_p_qp_mgr);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_ipv4_set(&(attach_flow_data_ib_v2->ibv_flow_attr.ipv4),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_dst_ip(),
|
|
Packit Service |
aa3af4 |
0);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_tcp_udp_set(&(attach_flow_data_ib_v2->ibv_flow_attr.tcp_udp),
|
|
Packit Service |
aa3af4 |
(m_flow_tuple.get_protocol() == PROTO_TCP),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_dst_port(),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_src_port());
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
p_attach_flow_data = (attach_flow_data_t*)attach_flow_data_ib_v2;
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
case VMA_TRANSPORT_ETH:
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
attach_flow_data_eth_ipv4_tcp_udp_t* attach_flow_data_eth = NULL;
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
attach_flow_data_eth = new attach_flow_data_eth_ipv4_tcp_udp_t(p_ring->m_p_qp_mgr);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
uint8_t dst_mac[6];
|
|
Packit Service |
aa3af4 |
create_multicast_mac_from_ip(dst_mac, m_flow_tuple.get_dst_ip());
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_eth_set(&(attach_flow_data_eth->ibv_flow_attr.eth),
|
|
Packit Service |
aa3af4 |
dst_mac,
|
|
Packit Service |
aa3af4 |
htons(p_ring->m_p_qp_mgr->get_partiton()));
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (safe_mce_sys().eth_mc_l2_only_rules) {
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_ipv4_set(&(attach_flow_data_eth->ibv_flow_attr.ipv4), 0, 0);
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_tcp_udp_set(&(attach_flow_data_eth->ibv_flow_attr.tcp_udp), 0, 0, 0);
|
|
Packit Service |
aa3af4 |
p_attach_flow_data = (attach_flow_data_t*)attach_flow_data_eth;
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_ipv4_set(&(attach_flow_data_eth->ibv_flow_attr.ipv4),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_dst_ip(),
|
|
Packit Service |
aa3af4 |
0);
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_tcp_udp_set(&(attach_flow_data_eth->ibv_flow_attr.tcp_udp),
|
|
Packit Service |
aa3af4 |
(m_flow_tuple.get_protocol() == PROTO_TCP),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_dst_port(),
|
|
Packit Service |
aa3af4 |
m_flow_tuple.get_src_port());
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
if (m_flow_tag_id) { // Will not attach flow_tag spec to rule for tag_id==0
|
|
Packit Service |
aa3af4 |
ibv_flow_spec_flow_tag_set(&attach_flow_data_eth->ibv_flow_attr.flow_tag, m_flow_tag_id);
|
|
Packit Service |
aa3af4 |
attach_flow_data_eth->ibv_flow_attr.add_flow_tag_spec();
|
|
Packit Service |
aa3af4 |
rfs_logdbg("Adding flow_tag spec to MC rule, num_of_specs: %d flow_tag_id: %d",
|
|
Packit Service |
aa3af4 |
attach_flow_data_eth->ibv_flow_attr.attr.num_of_specs, m_flow_tag_id);
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
p_attach_flow_data = (attach_flow_data_t*)attach_flow_data_eth;
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
BULLSEYE_EXCLUDE_BLOCK_START
|
|
Packit Service |
aa3af4 |
default:
|
|
Packit Service |
aa3af4 |
rfs_logpanic("Incompatible transport type = %d", type);
|
|
Packit Service |
aa3af4 |
return false;
|
|
Packit Service |
aa3af4 |
break;
|
|
Packit Service |
aa3af4 |
BULLSEYE_EXCLUDE_BLOCK_END
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
m_attach_flow_data_vector.push_back(p_attach_flow_data);
|
|
Packit Service |
aa3af4 |
return true;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
bool rfs_mc::rx_dispatch_packet(mem_buf_desc_t* p_rx_wc_buf_desc, void* pv_fd_ready_array)
|
|
Packit Service |
aa3af4 |
{
|
|
Packit Service |
aa3af4 |
// Dispatching: Notify new packet to all registered receivers
|
|
Packit Service |
aa3af4 |
p_rx_wc_buf_desc->reset_ref_count();
|
|
Packit Service |
aa3af4 |
p_rx_wc_buf_desc->inc_ref_count();
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
for (uint32_t i=0; i < m_n_sinks_list_entries; ++i) {
|
|
Packit Service |
aa3af4 |
if (m_sinks_list[i]) {
|
|
Packit Service |
aa3af4 |
m_sinks_list[i]->rx_input_cb(p_rx_wc_buf_desc, pv_fd_ready_array);
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Check packet ref_count to see if any receivers are interested in this packet
|
|
Packit Service |
aa3af4 |
if (p_rx_wc_buf_desc->dec_ref_count() > 1) {
|
|
Packit Service |
aa3af4 |
// The sink will be responsible to return the buffer to CQ for reuse
|
|
Packit Service |
aa3af4 |
return true;
|
|
Packit Service |
aa3af4 |
}
|
|
Packit Service |
aa3af4 |
|
|
Packit Service |
aa3af4 |
// Reuse this data buffer & mem_buf_desc
|
|
Packit Service |
aa3af4 |
return false;
|
|
Packit Service |
aa3af4 |
}
|