mirror of https://github.com/F-Stack/f-stack.git
471 lines
12 KiB
C
471 lines
12 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2022 Corigine, Inc.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include "../nfpcore/nfp_nsp.h"
|
|
#include "../nfp_logs.h"
|
|
#include "../nfp_common.h"
|
|
#include "../nfp_flow.h"
|
|
#include "nfp_flower.h"
|
|
#include "nfp_flower_cmsg.h"
|
|
#include "nfp_flower_ctrl.h"
|
|
#include "nfp_flower_representor.h"
|
|
|
|
static void *
|
|
nfp_flower_cmsg_init(struct rte_mbuf *m,
|
|
enum nfp_flower_cmsg_type type,
|
|
uint32_t size)
|
|
{
|
|
char *pkt;
|
|
uint32_t data;
|
|
uint32_t new_size = size;
|
|
struct nfp_flower_cmsg_hdr *hdr;
|
|
|
|
pkt = rte_pktmbuf_mtod(m, char *);
|
|
PMD_DRV_LOG(DEBUG, "flower_cmsg_init using pkt at %p", pkt);
|
|
|
|
data = rte_cpu_to_be_32(NFP_NET_META_PORTID);
|
|
rte_memcpy(pkt, &data, 4);
|
|
pkt += 4;
|
|
new_size += 4;
|
|
|
|
/* First the metadata as flower requires it */
|
|
data = rte_cpu_to_be_32(NFP_META_PORT_ID_CTRL);
|
|
rte_memcpy(pkt, &data, 4);
|
|
pkt += 4;
|
|
new_size += 4;
|
|
|
|
/* Now the ctrl header */
|
|
hdr = (struct nfp_flower_cmsg_hdr *)pkt;
|
|
hdr->pad = 0;
|
|
hdr->type = type;
|
|
hdr->version = NFP_FLOWER_CMSG_VER1;
|
|
|
|
pkt = (char *)hdr + NFP_FLOWER_CMSG_HLEN;
|
|
new_size += NFP_FLOWER_CMSG_HLEN;
|
|
|
|
m->pkt_len = new_size;
|
|
m->data_len = m->pkt_len;
|
|
|
|
return pkt;
|
|
}
|
|
|
|
static void
|
|
nfp_flower_cmsg_mac_repr_init(struct rte_mbuf *mbuf, int num_ports)
|
|
{
|
|
uint32_t size;
|
|
struct nfp_flower_cmsg_mac_repr *msg;
|
|
enum nfp_flower_cmsg_type type = NFP_FLOWER_CMSG_TYPE_MAC_REPR;
|
|
|
|
size = sizeof(*msg) + (num_ports * sizeof(msg->ports[0]));
|
|
msg = nfp_flower_cmsg_init(mbuf, type, size);
|
|
memset(msg->reserved, 0, sizeof(msg->reserved));
|
|
msg->num_ports = num_ports;
|
|
}
|
|
|
|
static void
|
|
nfp_flower_cmsg_mac_repr_fill(struct rte_mbuf *m,
|
|
unsigned int idx,
|
|
unsigned int nbi,
|
|
unsigned int nbi_port,
|
|
unsigned int phys_port)
|
|
{
|
|
struct nfp_flower_cmsg_mac_repr *msg;
|
|
|
|
msg = (struct nfp_flower_cmsg_mac_repr *)nfp_flower_cmsg_get_data(m);
|
|
msg->ports[idx].idx = idx;
|
|
msg->ports[idx].info = nbi & NFP_FLOWER_CMSG_MAC_REPR_NBI;
|
|
msg->ports[idx].nbi_port = nbi_port;
|
|
msg->ports[idx].phys_port = phys_port;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_mac_repr(struct nfp_app_fw_flower *app_fw_flower)
|
|
{
|
|
int i;
|
|
uint16_t cnt;
|
|
unsigned int nbi;
|
|
unsigned int nbi_port;
|
|
unsigned int phys_port;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_eth_table *nfp_eth_table;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(ERR, "Could not allocate mac repr cmsg");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
nfp_flower_cmsg_mac_repr_init(mbuf, app_fw_flower->num_phyport_reprs);
|
|
|
|
/* Fill in the mac repr cmsg */
|
|
nfp_eth_table = app_fw_flower->pf_hw->pf_dev->nfp_eth_table;
|
|
for (i = 0; i < app_fw_flower->num_phyport_reprs; i++) {
|
|
nbi = nfp_eth_table->ports[i].nbi;
|
|
nbi_port = nfp_eth_table->ports[i].base;
|
|
phys_port = nfp_eth_table->ports[i].index;
|
|
|
|
nfp_flower_cmsg_mac_repr_fill(mbuf, i, nbi, nbi_port, phys_port);
|
|
}
|
|
|
|
/* Send the cmsg via the ctrl vNIC */
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_repr_reify(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct nfp_flower_representor *repr)
|
|
{
|
|
uint16_t cnt;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_cmsg_port_reify *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "alloc mbuf for repr reify failed");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PORT_REIFY, sizeof(*msg));
|
|
msg->portnum = rte_cpu_to_be_32(repr->port_id);
|
|
msg->reserved = 0;
|
|
msg->info = rte_cpu_to_be_16(1);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_port_mod(struct nfp_app_fw_flower *app_fw_flower,
|
|
uint32_t port_id, bool carrier_ok)
|
|
{
|
|
uint16_t cnt;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_cmsg_port_mod *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "alloc mbuf for repr portmod failed");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PORT_MOD, sizeof(*msg));
|
|
msg->portnum = rte_cpu_to_be_32(port_id);
|
|
msg->reserved = 0;
|
|
msg->info = carrier_ok;
|
|
msg->mtu = 9000;
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_flow_delete(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct rte_flow *flow)
|
|
{
|
|
char *msg;
|
|
uint16_t cnt;
|
|
uint32_t msg_len;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_fl_rule_metadata *nfp_flow_meta;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for flow delete.");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Copy the flow to mbuf */
|
|
nfp_flow_meta = flow->payload.meta;
|
|
msg_len = (nfp_flow_meta->key_len + nfp_flow_meta->mask_len +
|
|
nfp_flow_meta->act_len) << NFP_FL_LW_SIZ;
|
|
msg_len += sizeof(struct nfp_fl_rule_metadata);
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_FLOW_DEL, msg_len);
|
|
rte_memcpy(msg, flow->payload.meta, msg_len);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct rte_flow *flow)
|
|
{
|
|
char *msg;
|
|
uint16_t cnt;
|
|
uint32_t msg_len;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_fl_rule_metadata *nfp_flow_meta;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for flow add.");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* copy the flow to mbuf */
|
|
nfp_flow_meta = flow->payload.meta;
|
|
msg_len = (nfp_flow_meta->key_len + nfp_flow_meta->mask_len +
|
|
nfp_flow_meta->act_len) << NFP_FL_LW_SIZ;
|
|
msg_len += sizeof(struct nfp_fl_rule_metadata);
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_FLOW_ADD, msg_len);
|
|
rte_memcpy(msg, flow->payload.meta, msg_len);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct nfp_flower_cmsg_tun_neigh_v4 *payload)
|
|
{
|
|
uint16_t cnt;
|
|
size_t msg_len;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_cmsg_tun_neigh_v4 *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun neigh");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
|
|
if (!nfp_flower_support_decap_v2(app_fw_flower))
|
|
msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
|
|
memcpy(msg, payload, msg_len);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct nfp_flower_cmsg_tun_neigh_v6 *payload)
|
|
{
|
|
uint16_t cnt;
|
|
size_t msg_len;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_cmsg_tun_neigh_v6 *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun neigh");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
|
|
if (!nfp_flower_support_decap_v2(app_fw_flower))
|
|
msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
|
|
memcpy(msg, payload, msg_len);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower)
|
|
{
|
|
uint16_t cnt;
|
|
uint32_t count = 0;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flow_priv *priv;
|
|
struct nfp_ipv4_addr_entry *entry;
|
|
struct nfp_flower_cmsg_tun_ipv4_addr *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun addr");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(*msg));
|
|
|
|
priv = app_fw_flower->flow_priv;
|
|
rte_spinlock_lock(&priv->ipv4_off_lock);
|
|
LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
|
|
if (count >= NFP_FL_IPV4_ADDRS_MAX) {
|
|
rte_spinlock_unlock(&priv->ipv4_off_lock);
|
|
PMD_DRV_LOG(ERR, "IPv4 offload exceeds limit.");
|
|
return -ERANGE;
|
|
}
|
|
msg->ipv4_addr[count] = entry->ipv4_addr;
|
|
count++;
|
|
}
|
|
msg->count = rte_cpu_to_be_32(count);
|
|
rte_spinlock_unlock(&priv->ipv4_off_lock);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower)
|
|
{
|
|
uint16_t cnt;
|
|
uint32_t count = 0;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flow_priv *priv;
|
|
struct nfp_ipv6_addr_entry *entry;
|
|
struct nfp_flower_cmsg_tun_ipv6_addr *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun addr");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6, sizeof(*msg));
|
|
|
|
priv = app_fw_flower->flow_priv;
|
|
rte_spinlock_lock(&priv->ipv6_off_lock);
|
|
LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
|
|
if (count >= NFP_FL_IPV6_ADDRS_MAX) {
|
|
rte_spinlock_unlock(&priv->ipv6_off_lock);
|
|
PMD_DRV_LOG(ERR, "IPv6 offload exceeds limit.");
|
|
return -ERANGE;
|
|
}
|
|
memcpy(&msg->ipv6_addr[count * 16], entry->ipv6_addr, 16UL);
|
|
count++;
|
|
}
|
|
msg->count = rte_cpu_to_be_32(count);
|
|
rte_spinlock_unlock(&priv->ipv6_off_lock);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct nfp_fl_rule_metadata *nfp_flow_meta,
|
|
uint16_t mac_idx,
|
|
bool is_del)
|
|
{
|
|
uint16_t cnt;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_meta_tci *meta_tci;
|
|
struct nfp_flower_cmsg_pre_tun_rule *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for pre tunnel rule");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, sizeof(*msg));
|
|
|
|
meta_tci = (struct nfp_flower_meta_tci *)((char *)nfp_flow_meta +
|
|
sizeof(struct nfp_fl_rule_metadata));
|
|
if (meta_tci->tci)
|
|
msg->vlan_tci = meta_tci->tci;
|
|
else
|
|
msg->vlan_tci = 0xffff;
|
|
|
|
if (is_del)
|
|
msg->flags = rte_cpu_to_be_32(NFP_TUN_PRE_TUN_RULE_DEL);
|
|
|
|
msg->port_idx = rte_cpu_to_be_16(mac_idx);
|
|
msg->host_ctx_id = nfp_flow_meta->host_ctx_id;
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
|
|
struct rte_ether_addr *mac,
|
|
uint16_t mac_idx,
|
|
bool is_del)
|
|
{
|
|
uint16_t cnt;
|
|
struct rte_mbuf *mbuf;
|
|
struct nfp_flower_cmsg_tun_mac *msg;
|
|
|
|
mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
|
|
if (mbuf == NULL) {
|
|
PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for tunnel mac");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_MAC, sizeof(*msg));
|
|
|
|
msg->count = rte_cpu_to_be_16(1);
|
|
msg->index = rte_cpu_to_be_16(mac_idx);
|
|
rte_ether_addr_copy(mac, &msg->addr);
|
|
if (is_del)
|
|
msg->flags = rte_cpu_to_be_16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
|
|
|
|
cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
|
|
if (cnt == 0) {
|
|
PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
|
|
rte_pktmbuf_free(mbuf);
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|