NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
psp_gw_utils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024-2025 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 
29 #include <rte_ether.h>
30 
31 #include "psp_gw_utils.h"
32 
33 std::string mac_to_string(const rte_ether_addr &mac_addr)
34 {
35  std::string addr_str(RTE_ETHER_ADDR_FMT_SIZE, '\0');
36  rte_ether_format_addr(addr_str.data(), RTE_ETHER_ADDR_FMT_SIZE, &mac_addr);
37  addr_str.resize(strlen(addr_str.c_str()));
38  return addr_str;
39 }
40 
41 bool is_empty_mac_addr(const rte_ether_addr &addr)
42 {
43  rte_ether_addr empty_ether_addr = {};
44  return !memcmp(empty_ether_addr.addr_bytes, addr.addr_bytes, RTE_ETHER_ADDR_LEN);
45 }
46 
47 std::string ipv4_to_string(rte_be32_t ipv4_addr)
48 {
49  std::string addr_str(INET_ADDRSTRLEN, '\0');
50  inet_ntop(AF_INET, &ipv4_addr, addr_str.data(), INET_ADDRSTRLEN);
51  addr_str.resize(strlen(addr_str.c_str()));
52  return addr_str;
53 }
54 
55 std::string ipv6_to_string(const uint32_t ipv6_addr[])
56 {
57  std::string addr_str(INET6_ADDRSTRLEN, '\0');
58  inet_ntop(AF_INET6, ipv6_addr, addr_str.data(), INET6_ADDRSTRLEN);
59  addr_str.resize(strlen(addr_str.c_str()));
60  return addr_str;
61 }
62 
63 std::string ip_to_string(const struct doca_flow_ip_addr &ip_addr)
64 {
65  if (ip_addr.type == DOCA_FLOW_L3_TYPE_IP4)
66  return ipv4_to_string(ip_addr.ipv4_addr);
67  else if (ip_addr.type == DOCA_FLOW_L3_TYPE_IP6)
68  return ipv6_to_string(ip_addr.ipv6_addr);
69  return "Invalid IP type";
70 }
71 
72 bool is_ip_equal(struct doca_flow_ip_addr *ip_a, struct doca_flow_ip_addr *ip_b)
73 {
74  if (ip_a->type != ip_b->type)
75  return false;
76  if (ip_a->type == DOCA_FLOW_L3_TYPE_IP4)
77  return ip_a->ipv4_addr == ip_b->ipv4_addr;
78  for (int i = 0; i < 4; i++) {
79  if (ip_a->ipv6_addr[i] != ip_b->ipv6_addr[i])
80  return false;
81  }
82  return true;
83 }
84 
85 doca_error_t parse_ip_addr(const std::string &ip_str,
86  doca_flow_l3_type enforce_l3_type,
87  struct doca_flow_ip_addr *ip_addr)
88 {
89  memset(ip_addr, 0, sizeof(struct doca_flow_ip_addr));
90  if (enforce_l3_type == DOCA_FLOW_L3_TYPE_IP4) {
91  ip_addr->type = DOCA_FLOW_L3_TYPE_IP4;
92  if (inet_pton(AF_INET, ip_str.c_str(), &ip_addr->ipv4_addr) != 1)
94  } else if (enforce_l3_type == DOCA_FLOW_L3_TYPE_IP6) {
95  ip_addr->type = DOCA_FLOW_L3_TYPE_IP6;
96  if (inet_pton(AF_INET6, ip_str.c_str(), ip_addr->ipv6_addr) != 1)
98  } else {
99  if (inet_pton(AF_INET, ip_str.c_str(), &ip_addr->ipv4_addr) == 1) {
100  ip_addr->type = DOCA_FLOW_L3_TYPE_IP4;
101  } else if (inet_pton(AF_INET6, ip_str.c_str(), ip_addr->ipv6_addr) == 1) {
102  ip_addr->type = DOCA_FLOW_L3_TYPE_IP6;
103  } else {
105  }
106  }
107  return DOCA_SUCCESS;
108 }
109 
110 void copy_ip_addr(const struct doca_flow_ip_addr &src, struct doca_flow_ip_addr &dst)
111 {
112  memset(&dst, 0, sizeof(struct doca_flow_ip_addr));
113  if (src.type == DOCA_FLOW_L3_TYPE_IP4) {
115  dst.ipv4_addr = src.ipv4_addr;
116  } else if (src.type == DOCA_FLOW_L3_TYPE_IP6) {
118  memcpy(dst.ipv6_addr, src.ipv6_addr, sizeof(src.ipv6_addr));
119  } // else dst.type is already 0 == DOCA_FLOW_L3_TYPE_NONE
120 }
121 
122 psp_gw_peer *lookup_vip_pair(std::vector<psp_gw_peer> *peers, ip_pair &vip_pair)
123 {
124  for (auto &peer : *peers) {
125  for (auto peer_vip_pair : peer.vip_pairs) {
126  if (is_ip_equal(&peer_vip_pair.dst_vip, &vip_pair.dst_vip) &&
127  is_ip_equal(&peer_vip_pair.src_vip, &vip_pair.src_vip))
128  return &peer;
129  }
130  }
131  return nullptr;
132 }
uintptr_t addr
static uint64_t *restrict src
Definition: dpaintrin.h:230
enum doca_error doca_error_t
DOCA API return codes.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
doca_flow_l3_type
doca flow layer 3 packet type
@ DOCA_FLOW_L3_TYPE_IP6
@ DOCA_FLOW_L3_TYPE_IP4
bool is_ip_equal(struct doca_flow_ip_addr *ip_a, struct doca_flow_ip_addr *ip_b)
Compare DOCA Flow IP address struct, return true if addresses are equal.
doca_error_t parse_ip_addr(const std::string &ip_str, doca_flow_l3_type enforce_l3_type, struct doca_flow_ip_addr *ip_addr)
Parse an IP address string into a DOCA Flow IP address struct.
std::string ipv4_to_string(rte_be32_t ipv4_addr)
Converts an IPv4 address to a C++ string.
psp_gw_peer * lookup_vip_pair(std::vector< psp_gw_peer > *peers, ip_pair &vip_pair)
Search for a peer in a vector of peers that holds the same IP pair.
bool is_empty_mac_addr(const rte_ether_addr &addr)
Tests whether a MAC address has been set (is non-zero)
std::string mac_to_string(const rte_ether_addr &mac_addr)
Converts a MAC/ethernet address to a C++ string.
void copy_ip_addr(const struct doca_flow_ip_addr &src, struct doca_flow_ip_addr &dst)
Copy an IP address struct.
std::string ip_to_string(const struct doca_flow_ip_addr &ip_addr)
Converts a DOCA Flow IP address struct to a C++ string.
std::string ipv6_to_string(const uint32_t ipv6_addr[])
Converts an IPv6 address to a C++ string.
doca flow ip address
doca_be32_t ipv4_addr
doca_be32_t ipv6_addr[4]
enum doca_flow_l3_type type
doca_flow_ip_addr dst_vip
Definition: psp_gw_config.h:83
doca_flow_ip_addr src_vip
Definition: psp_gw_config.h:82
Describes a peer which is capable of exchanging traffic flows over a PSP tunnel.
Definition: psp_gw_config.h:98