28 #include <sys/ioctl.h>
34 #include <json-c/json.h>
36 #include <rte_hash_crc.h>
55 const std::string
key;
64 std::vector<void *>
params = {})
85 struct rte_hash_parameters table_params = {0};
87 table_params.name =
"IPv6 table";
88 table_params.entries =
app_config->max_tunnels;
89 table_params.key_len =
sizeof(uint32_t) * 4;
90 table_params.hash_func = rte_hash_crc;
91 table_params.hash_func_init_val = 0;
93 app_config->ip6_table = rte_hash_create(&table_params);
110 const char *pci_addr = (
const char *)param;
112 int pci_addr_len = strlen(pci_addr);
114 DOCA_LOG_ERR(
"Expected PCI addr in DDDD:BB:DD.F or BB:DD.F formats, instead received: %s", pci_addr);
171 char *mac_addr = (
char *)param;
174 DOCA_LOG_ERR(
"Cannot specify both --decap-dmac and --vf-name");
178 if (rte_ether_unformat_addr(mac_addr, &
app_config->dcap_dmac) != 0) {
197 char *mac_addr = (
char *)param;
199 if (rte_ether_unformat_addr(mac_addr, &
app_config->nexthop_dmac) != 0) {
220 size_t slash =
ip.find(
'/');
221 if (slash == std::string::npos) {
225 std::string mask_len_str =
ip.substr(slash + 1);
226 mask_len = std::atoi(mask_len_str.c_str());
228 if (mask_len == 0 || mask_len > 32) {
229 DOCA_LOG_ERR(
"Invalid IP addr mask string found: %s",
ip.c_str());
233 ip =
ip.substr(0, slash);
244 uint32_t ip_native = RTE_BE32(ip_parsed.
ipv4_addr);
245 uint32_t mask = (1 << (32 - mask_len)) - 1;
263 bool *bool_param = (
bool *)param;
264 app_config->net_config.vc_enabled = *bool_param;
265 DOCA_LOG_INFO(
"PSP VCs %s", *bool_param ?
"Enabled" :
"Disabled");
279 bool *bool_param = (
bool *)param;
280 app_config->disable_ingress_acl = *bool_param;
281 DOCA_LOG_INFO(
"Ingress ACLs %s", *bool_param ?
"Disabled" :
"Enabled");
295 int32_t *int_param = (int32_t *)param;
296 app_config->log2_sample_rate = (uint16_t)*int_param;
311 app_config->create_tunnels_at_startup = (
bool *)param;
314 app_config->create_tunnels_at_startup ?
"Enabled" :
"Disabled");
329 int *int_param = (
int *)param;
330 if (*int_param < 1) {
332 "The maximal number of tunnel (max-tunnels) must be greater than zero, instead received: %d",
356 int *int_param = (
int *)param;
357 if (*int_param < 0 || 0x3f < *int_param) {
358 DOCA_LOG_ERR(
"PSP crypt-offset must be a 6-bit non-negative integer, instead received: %d", *int_param);
362 app_config->net_config.crypt_offset = *int_param;
378 int *int_param = (
int *)param;
380 DOCA_LOG_ERR(
"Unsupported PSP version: %d", *int_param);
384 app_config->net_config.default_psp_proto_ver = *int_param;
400 bool *bool_param = (
bool *)param;
403 DOCA_LOG_INFO(
"NOTE: debug_keys is enabled; crypto keys will be written to logs.");
420 std::string vf_iface_name = (
const char *)param;
423 DOCA_LOG_ERR(
"Cannot specify both --vf-name and --decap-dmac");
428 DOCA_LOG_ERR(
"Cannot specify both --vf-name and --inner ipv6");
432 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
438 struct ifreq ifr = {};
439 strncpy(ifr.ifr_name, vf_iface_name.c_str(), IFNAMSIZ - 1);
441 if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
442 DOCA_LOG_ERR(
"Failed ioctl(sockfd, SIOCGIFADDR, &ifr)");
447 rte_be32_t vf_ip_addr = ((
struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
451 if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) {
452 DOCA_LOG_ERR(
"Failed ioctl(sockfd, SIOCGIFHWADDR, &ifr)");
457 app_config->dcap_dmac = *(rte_ether_addr *)ifr.ifr_hwaddr.sa_data;
460 DOCA_LOG_INFO(
"For VF device %s, detected IP addr %s, MAC addr %s",
461 vf_iface_name.c_str(),
478 bool *bool_param = (
bool *)param;
480 DOCA_LOG_INFO(
"Stats %s", *bool_param ?
"Enabled" :
"Disabled");
493 supported_types += (
first ?
"" :
", ") +
type.first;
509 std::string perf_types = (
const char *)param;
510 std::istringstream perf_types_stream(perf_types);
511 for (std::string perf_type; std::getline(perf_types_stream, perf_type,
',');) {
513 std::string supported_types;
515 DOCA_LOG_ERR(
"Unsupported perf type: %s, supported types are: %s",
517 supported_types.c_str());
522 DOCA_LOG_INFO(
"Enabled perf print for %s", perf_types.c_str());
536 bool *bool_param = (
bool *)param;
537 app_config->show_rss_rx_packets = *bool_param;
540 "NOTE: show_rss_rx_packets is enabled; rx packets received to RSS will be written to logs");
555 bool *bool_param = (
bool *)param;
558 DOCA_LOG_INFO(
"The original order of the packets will be maintained");
573 std::string outer_type = (
const char *)param;
575 if (outer_type ==
"ipv4") {
577 }
else if (outer_type ==
"ipv6") {
580 DOCA_LOG_ERR(
"Unsupported outer type: %s, supported types are: ipv4, ipv6", outer_type.c_str());
598 std::string inner_type = (
const char *)param;
600 if (inner_type ==
"ipv4") {
602 }
else if (inner_type ==
"ipv6") {
604 DOCA_LOG_ERR(
"Cannot specify both --inner ipv6 and --vf-name");
609 DOCA_LOG_ERR(
"Unsupported inner type: %s, supported types are: ipv4, ipv6", inner_type.c_str());
627 std::string
mode = (
const char *)param;
629 if (
mode ==
"tunnel") {
631 }
else if (
mode ==
"transport") {
634 DOCA_LOG_ERR(
"Unsupported mode: %s, supported modes are: tunnel, transport",
mode.c_str());
658 if (access(
json_path.c_str(), F_OK) == -1) {
678 if (!json_object_is_type(json_obj, json_type_string)) {
679 DOCA_LOG_ERR(
"Invalid JSON object type: %d, expected string", json_object_get_type(json_obj));
682 value = json_object_get_string(json_obj);
697 if (!json_object_is_type(json_obj, json_type_array)) {
698 DOCA_LOG_ERR(
"Invalid JSON object type: %d, expected array", json_object_get_type(json_obj));
701 length = json_object_array_length(json_obj);
714 json_object *json_obj,
720 if (!json_object_is_type(json_obj, json_type_object)) {
721 DOCA_LOG_ERR(
"Invalid JSON object type: %d, expected object", json_object_get_type(json_obj));
726 json_object_object_foreach(json_obj, key, val)
729 for (
auto &handler : handlers) {
730 if (strcmp(key, handler.key.c_str()) == 0) {
736 handler.found =
true;
747 for (
auto &handler : handlers) {
748 if (handler.required && !handler.found) {
749 DOCA_LOG_ERR(
"Missing required key in JSON file: %s", handler.key.c_str());
767 std::vector<void *> ¶ms)
772 DOCA_LOG_ERR(
"Invalid local-grpc-address, expected string");
775 std::string server =
app_config->local_svc_addr;
778 size_t sep =
app_config->local_svc_addr.find(
':');
779 if (sep != 0 && sep != std::string::npos) {
780 std::string port = server.substr(sep + 1);
781 server = server.substr(0, sep);
783 DOCA_LOG_ERR(
"Invalid port in local-grpc-address: %s", server.c_str());
786 if (port.find_first_not_of(
"0123456789") != std::string::npos) {
787 DOCA_LOG_ERR(
"Invalid port in local-grpc-address: %s", port.c_str());
790 int port_num = std::stoi(port);
791 if (port_num < 0 || 65535 < port_num) {
792 DOCA_LOG_ERR(
"Invalid port in local-grpc-address: %s", port.c_str());
812 std::vector<void *> ¶ms)
837 std::vector<void *> ¶ms)
844 DOCA_LOG_ERR(
"Invalid remote-grpc-address, expected string");
863 std::vector<void *> ¶ms)
866 std::string local_vip_str;
874 DOCA_LOG_ERR(
"Invalid local VIP addr: %s", local_vip_str.c_str());
892 std::vector<void *> ¶ms)
896 std::vector<ip_pair> *
vip_pairs = (std::vector<ip_pair> *)params[0];
899 DOCA_LOG_ERR(
"Local VIP not set - must specify 'local-vip' or '--vf-name'");
909 if (nb_remote_vips == 0) {
914 for (
int i = 0; i < nb_remote_vips; i++) {
915 json_object *json_obj_vip = json_object_array_get_idx(json_obj_remote_vips, i);
923 uint32_t mask_len = 0;
931 DOCA_LOG_ERR(
"Remote VIP subnet mask length < 16 not supported; found %d", mask_len);
936 DOCA_LOG_ERR(
"Invalid remote VIP addr: %s", vip_str.c_str());
952 n_peers = 1 << (32 - mask_len);
955 for (uint32_t i = 0; i < n_peers; i++) {
956 std::string peer_virt_ip;
960 }
else if (i == 16) {
965 struct ip_pair vip_pair = {*local_vip, remote_vip};
967 if (peer !=
nullptr) {
969 DOCA_LOG_ERR(
"Duplicate VIP pair found in JSON file: (%s -> %s)",
970 local_vip_str.c_str(),
971 peer_virt_ip.c_str());
974 vip_pairs->push_back(vip_pair);
995 std::vector<void *> ¶ms)
1004 if (nb_sessions == 0) {
1010 DOCA_LOG_ERR(
"Too many sessions in JSON file for peer %s: %d, max allowed: %d",
1017 for (
int i = 0; i < nb_sessions; i++) {
1020 json_object *json_obj_session = json_object_array_get_idx(json_obj_sessions, i);
1053 std::vector<void *> ¶ms)
1063 if (nb_peers == 0) {
1073 for (
int i = 0; i < nb_peers; i++) {
1075 json_object *json_obj_peer = json_object_array_get_idx(json_obj_peers, i);
1088 app_config->net_config.peers.push_back(peer);
1109 std::string json_content((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
1114 enum json_tokener_error json_err = json_tokener_success;
1115 json_object *parsed_json = json_tokener_parse_verbose(json_content.c_str(), &json_err);
1116 if (parsed_json ==
nullptr || json_err != json_tokener_success) {
1117 DOCA_LOG_ERR(
"Failed to parse JSON file(: %s)", json_tokener_error_desc(json_err));
1129 json_object_put(parsed_json);
1134 DOCA_LOG_ERR(
"REQUIRED: One of (--vf-name) or (--decap-dmac) to set the MAC address for decap");
1135 json_object_put(parsed_json);
1138 json_object_put(parsed_json);
1157 const char *long_name,
1162 bool accept_multiple)
1164 struct doca_argp_param *param =
NULL;
1180 if (accept_multiple)
1186 DOCA_LOG_ERR(
"Failed to register program param %s: %s",
1187 long_name ? long_name : short_name,
1206 "PCI BDF of the device in BB:DD.F format (required)",
1216 "Device representor list in vf[x-y]pf[x-y] format (required)",
1236 "mac_dst addr of the decapped packets",
1246 "Name of the virtual function device / unsecured port",
1256 "next-hop mac_dst addr of the encapped packets",
1266 "Enable use of PSP virtualization cookies",
1275 "disable-ingress-acl",
1276 "Allows any ingress packet that successfully decrypts",
1286 "Sets the log2 sample rate: 0: disabled, 1: 50%, ... 16: 1.5e-3%",
1296 "Specify the max number of PSP tunnels",
1306 "Specify the PSP crypt offset",
1316 "Specify the PSP version for outgoing connections (0 or 1)",
1326 "Create tunnels at startup",
1336 "Enable debug keys",
1346 "Enable printing statistics",
1356 "Enable printing performance metrics (key-gen, insertion, all)",
1365 "show-rss-rx-packets",
1366 "Show RSS rx packets",
1396 "Path to the JSON file with application configuration",
1406 "maintain original packet ordering",
1416 "tunnel or transport mode",
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
doca_argp_type
Flag input type.
DOCA_EXPERIMENTAL doca_error_t doca_argp_start(int argc, char **argv)
Parse incoming arguments (cmd line/json).
DOCA_EXPERIMENTAL doca_error_t doca_argp_init(const char *program_name, void *program_config)
Initialize the parser interface.
doca_error_t(* doca_argp_param_cb_t)(void *, void *)
Flag callback function type.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_destroy(void)
ARG Parser destroy.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
DOCA_EXPERIMENTAL void doca_argp_param_set_multiplicity(struct doca_argp_param *param)
Mark the program param as supporting multiple appearances.
#define DOCA_DEVINFO_PCI_BDF_SIZE
Buffer size to hold PCI BDF format: "XX:XX.X". Including a null terminator.
#define DOCA_DEVINFO_PCI_ADDR_SIZE
Buffer size to hold PCI BDF format: "XXXX:XX:XX.X". Including a null terminator.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
static const uint32_t PSP_MAX_SESSIONS
static const std::map< std::string, uint16_t > PSP_PERF_MAP
const std::set< uint32_t > SUPPORTED_PSP_VERSIONS
static const uint32_t PSP_MAX_PEERS
static doca_error_t psp_gw_register_params(void)
Registers command-line arguments to the application.
DOCA_LOG_REGISTER(PSP_Gateway_Params)
doca_flow_ip_addr interface_vf_addr
static doca_error_t handle_nexthop_dmac_param(void *param, void *config)
Configures the next-hop dst-mac to apply on encap.
static void get_supported_perf_types(std::string &supported_types)
Returns supported perf types as a string.
static doca_error_t handle_psp_version_param(void *param, void *config)
Configures the PSP version to use for outgoing connections.
static doca_error_t handle_config_file_param(void *param, void *config)
Configures the JSON config file path.
static doca_error_t handle_sample_param(void *param, void *config)
Configures the sampling rate of packets.
static doca_error_t handle_perf_print_param(void *param, void *config)
Indicates what performance printing should be enabled.
static doca_error_t parse_json_peers(json_object *json_obj_peers, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the peers.
static doca_error_t handle_mode_param(void *param, void *config)
Handle the mode param.
static doca_error_t handle_debug_keys_param(void *param, void *config)
Indicates the application should log all encryption keys.
static doca_error_t handle_outer_param(void *param, void *config)
Handle outer IP type param.
static doca_error_t handle_json_level_fields(psp_json_field_handlers &handlers, json_object *json_obj, psp_gw_app_config *app_config)
Handles a JSON object with all of its keys.
static doca_error_t parse_subnet_mask(std::string &ip, uint32_t &mask_len)
Parses a host string with optional subnet mask suffix (i.e. /24).
static doca_error_t handle_pci_addr_param(void *param, void *config)
Configures the dst-mac to apply on decap.
static doca_error_t handle_inner_param(void *param, void *config)
Handle inner IP type param.
static doca_error_t parse_json_config(json_object *json_obj_config, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the remote gRPC address.
static doca_error_t handle_show_rss_rx_packets_param(void *param, void *config)
Indicates the application should log all received packets to RSS.
static doca_error_t handle_vf_name_param(void *param, void *config)
Indicates the name of the netdev used as the unsecured port.
static doca_error_t json_object_ver_array_length(json_object *json_obj, int &length)
Verifies and extracts the array length from the json object.
static doca_error_t handle_maintain_order_param(void *param, void *config)
Indicates if the application should maintain the order of original packets.
static doca_error_t parse_local_grpc_address(json_object *json_obj_local_addr, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parse the local gRPC address.
static doca_error_t handle_stats_print_param(void *param, void *config)
Indicates whether statistics should be printed.
static doca_error_t handle_static_tunnels_param(void *param, void *config)
Indicates the application should create all PSP tunnels at startup.
static doca_error_t parse_local_vip(json_object *json_obj_local_vip, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the local VIP.
static doca_error_t json_object_ver_get_string(json_object *json_obj, std::string &value)
Verifies and extracts the string from the json object.
static doca_error_t parse_remote_vips(json_object *json_obj_remote_vips, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the remote VIPs.
static doca_error_t handle_core_mask_param(void *param, void *config)
Configures the DPDK eal_init core mask parameter.
static doca_error_t psp_gw_register_single_param(const char *short_name, const char *long_name, const char *description, doca_argp_param_cb_t cb, enum doca_argp_type arg_type, bool required, bool accept_multiple)
Utility function to create a single argp parameter.
doca_error_t psp_gw_parse_config_file(psp_gw_app_config *app_config)
Parses the configuration JSON file that was passed to the application.
static doca_error_t handle_psp_crypt_offset_param(void *param, void *config)
Configures the PSP crypt-offset.
static doca_error_t handle_repr_param(void *param, void *config)
Configures the device representors parameter.
static doca_error_t create_ip6_table(psp_gw_app_config *app_config)
std::vector< psp_json_field_handler > psp_json_field_handlers
static doca_error_t handle_ingress_acl_param(void *param, void *config)
Indicates the application should skip ACL checks on ingress.
doca_error_t psp_gw_argp_exec(int &argc, char *argv[], psp_gw_app_config *app_config)
Parses command-line arguments to the application.
static doca_error_t parse_sessions(json_object *json_obj_sessions, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the sessions.
static doca_error_t handle_vc_param(void *param, void *config)
Indicates the application should include the VC in the PSP tunnel header.
std::function< doca_error_t(json_object *, psp_gw_app_config *, std::vector< void * > &)> psp_parse_json_object_cb
static doca_error_t handle_max_tunnels_param(void *param, void *config)
Configures the max number of tunnels to be supported.
static doca_error_t parse_remote_grpc_address(json_object *json_obj_remote_addr, psp_gw_app_config *app_config, std::vector< void * > ¶ms)
Parses the remote gRPC address.
static doca_error_t handle_decap_dmac_param(void *param, void *config)
Configures the dst-mac to apply on decap.
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.
enum doca_flow_l3_type type
describes the configuration of the PSP networking service on the local host.
Describes a peer which is capable of exchanging traffic flows over a PSP tunnel.
std::vector< ip_pair > vip_pairs
psp_parse_json_object_cb parser_cb
std::vector< void * > params
psp_json_field_handler(const std::string &key, psp_parse_json_object_cb parser_cb, bool required, std::vector< void * > params={})