diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index 89f5feeee..1a758c93f 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -76,7 +76,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push - timeout-minutes: 60 + timeout-minutes: 95 uses: docker/build-push-action@v5 with: context: . diff --git a/docs/deployment/README.md b/docs/deployment/README.md index a84ecbeed..9ced0bff4 100644 --- a/docs/deployment/README.md +++ b/docs/deployment/README.md @@ -5,6 +5,28 @@ All command-line arguments and configuration files are already handled by the Do For development, direct use of dp-service is covered by the [development section](../development/). +## Host machine setup +For dpservice to work properly, host IPv6 address needs to set up on `lo` instead of separately on the NIC ports, this way the address is shared. + +This address must be in the form of a network prefix `/64`, i.e. the last 64 bits of the host address must be zero. This way the 64 bit suffix can be used for containers or VMs running on the host. + +It is suggested that `:0000::/65` is used for host itself and `:8000::/65` is then assigned special role, e.g. `:f000::/68` for PodIPs, `:d000::/68` for dpservice, etc. + +Dpservice will generate addresses in the range from `:d000::` to `:dfff::`. + +If meson option `-Denable_address_type=true` is used, addresses are generated based on the usage type: + +| Use | Range | +|-|-| +| `:d000::/80` | unused | +| `:d001::/80` | NICs | +| `:d002::/80` | VIPs | +| `:d003::/80` | NATGateways | +| `:d004::/80` | LoadBalancers | +| `:d005::/80` | LoadBalancer targets | +| `:d006::/80` | Prefixes | +| `:d0ff::/80` | Virtual services | + ## Command-line tools All tool binaries are designed to be prefixed with `dpservice-` to enable the operator to simply type `dps` for list of possible tools. diff --git a/include/dp_ipaddr.h b/include/dp_ipaddr.h index e13b2ff21..728bf57d7 100644 --- a/include/dp_ipaddr.h +++ b/include/dp_ipaddr.h @@ -21,6 +21,7 @@ static_assert(sizeof(rte_be64_t) * 2 == DP_IPV6_ADDR_SIZE, "DP_IPV6_ADDR_SIZE is #define DP_UNDERLAY_FLAG_EXTERNALLY_GENERATED 0x80 #define DP_UNDERLAY_FLAG_SECONDARY_POOL 0x40 +#define DP_UNDERLAY_ADDRESS_TYPE 0xd0 // structure for holding IPv6 addresses // this way sizeof(dp_ipv6 *) is a meaningful value and passing the pointer only is safe @@ -36,7 +37,8 @@ union dp_ipv6 { } _nat64; struct __rte_packed { rte_be64_t prefix; - rte_be16_t kernel; + uint8_t type; + uint8_t subtype; uint8_t flags; uint8_t random; rte_be32_t local; @@ -166,7 +168,7 @@ int dp_ipv4_to_str(uint32_t ipv4, char *dest, int dest_len); int dp_str_to_ipv4(const char *src, uint32_t *dest); int dp_str_to_ipv6(const char *src, union dp_ipv6 *dest); -void dp_generate_ul_ipv6(union dp_ipv6 *dest); +void dp_generate_ul_ipv6(union dp_ipv6 *dest, uint8_t addr_type); // structure for holding dual IP addresses diff --git a/include/dp_port.h b/include/dp_port.h index 468f4a42a..27fc25721 100644 --- a/include/dp_port.h +++ b/include/dp_port.h @@ -62,15 +62,11 @@ struct dp_port_async_template { enum dp_port_async_template_type { DP_PORT_ASYNC_TEMPLATE_PF_ISOLATION, -#ifdef ENABLE_VIRTSVC - DP_PORT_ASYNC_TEMPLATE_VIRTSVC_ISOLATION, -#endif DP_PORT_ASYNC_TEMPLATE_COUNT, }; enum dp_port_async_flow_type { - DP_PORT_ASYNC_FLOW_ISOLATE_IPIP, - DP_PORT_ASYNC_FLOW_ISOLATE_IPV6, + DP_PORT_ASYNC_FLOW_ISOLATE_PREFIX, DP_PORT_ASYNC_FLOW_COUNT, }; diff --git a/include/dp_virtsvc.h b/include/dp_virtsvc.h index 2b8face71..20709a68a 100644 --- a/include/dp_virtsvc.h +++ b/include/dp_virtsvc.h @@ -49,7 +49,6 @@ struct dp_virtsvc { union dp_ipv6 ul_addr; struct rte_hash *open_ports; struct dp_virtsvc_conn connections[DP_VIRTSVC_PORTCOUNT]; - struct rte_flow *isolation_rules[DP_MAX_PF_PORTS]; }; struct dp_virtsvc_lookup_entry { @@ -105,11 +104,6 @@ void dp_virtsvc_free(void); size_t dp_virtsvc_get_count(void); -int dp_install_virtsvc_sync_isolation_rules(uint16_t port_id); -uint16_t dp_create_virtsvc_async_isolation_rules(uint16_t port_id, - struct rte_flow_template_table *template_table); -void dp_destroy_virtsvc_async_isolation_rules(uint16_t port_id); - int dp_virtsvc_get_pf_route(struct dp_virtsvc *virtsvc, uint16_t vf_port_id, rte_be32_t vf_ip, diff --git a/include/dp_vnf.h b/include/dp_vnf.h index 5f195ca9d..ada27b5eb 100644 --- a/include/dp_vnf.h +++ b/include/dp_vnf.h @@ -23,12 +23,12 @@ struct dp_grpc_responder; enum dp_vnf_type { DP_VNF_TYPE_UNDEFINED, - DP_VNF_TYPE_LB_ALIAS_PFX, - DP_VNF_TYPE_ALIAS_PFX, - DP_VNF_TYPE_LB, + DP_VNF_TYPE_INTERFACE_IP, DP_VNF_TYPE_VIP, DP_VNF_TYPE_NAT, - DP_VNF_TYPE_INTERFACE_IP, + DP_VNF_TYPE_LB, + DP_VNF_TYPE_LB_ALIAS_PFX, + DP_VNF_TYPE_ALIAS_PFX, } __rte_packed; // for 'struct dp_flow' and 'struct flow_key' struct dp_vnf_prefix { diff --git a/include/rte_flow/dp_rte_async_flow_isolation.h b/include/rte_flow/dp_rte_async_flow_isolation.h index 7fb54484d..ff7e413b5 100644 --- a/include/rte_flow/dp_rte_async_flow_isolation.h +++ b/include/rte_flow/dp_rte_async_flow_isolation.h @@ -8,23 +8,12 @@ extern "C" { #endif -#include -#include -#include "dp_ipaddr.h" #include "dp_port.h" int dp_create_pf_async_isolation_templates(struct dp_port *port); int dp_create_pf_async_isolation_rules(struct dp_port *port); -#ifdef ENABLE_VIRTSVC -int dp_create_virtsvc_async_isolation_templates(struct dp_port *port); - -struct rte_flow *dp_create_virtsvc_async_isolation_rule(uint16_t port_id, - struct rte_flow_template_table *template_table, - const union dp_ipv6 *ul_addr); -#endif - #ifdef __cplusplus } #endif diff --git a/include/rte_flow/dp_rte_flow_helpers.h b/include/rte_flow/dp_rte_flow_helpers.h index e77119219..edbe7d873 100644 --- a/include/rte_flow/dp_rte_flow_helpers.h +++ b/include/rte_flow/dp_rte_flow_helpers.h @@ -62,6 +62,9 @@ static const struct rte_flow_item_ipv6 dp_flow_item_ipv6_dst_mask = { .hdr.dst_addr.a = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", .hdr.proto = 0xff, }; +static const struct rte_flow_item_ipv6 dp_flow_item_ipv6_dst_pfx68_mask = { + .hdr.dst_addr.a = "\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00", +}; #ifdef ENABLE_VIRTSVC static const struct rte_flow_item_ipv6 dp_flow_item_ipv6_dst_only_mask = { .hdr.dst_addr.a = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", @@ -201,6 +204,18 @@ void dp_set_ipv6_dst_flow_item(struct rte_flow_item *item, item->last = NULL; } +static __rte_always_inline +void dp_set_ipv6_dst_pfx68_flow_item(struct rte_flow_item *item, + struct rte_flow_item_ipv6 *ipv6_spec, + const union dp_ipv6 *dst) +{ + dp_set_dst_ipv6(&ipv6_spec->hdr, dst); + item->type = RTE_FLOW_ITEM_TYPE_IPV6; + item->spec = ipv6_spec; + item->mask = &dp_flow_item_ipv6_dst_pfx68_mask; + item->last = NULL; +} + static __rte_always_inline void dp_set_ipv4_dst_flow_item(struct rte_flow_item *item, struct rte_flow_item_ipv4 *ipv4_spec, diff --git a/include/rte_flow/dp_rte_flow_init.h b/include/rte_flow/dp_rte_flow_init.h deleted file mode 100644 index 79b905659..000000000 --- a/include/rte_flow/dp_rte_flow_init.h +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -#ifndef __INCLUDE_DP_RTE_FLOW_INIT_H__ -#define __INCLUDE_DP_RTE_FLOW_INIT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "dp_port.h" - -int dp_install_isolated_mode_ipip(uint16_t port_id, uint8_t proto_id); - -#ifdef ENABLE_VIRTSVC -int dp_install_isolated_mode_virtsvc(uint16_t port_id, uint8_t proto_id, const union dp_ipv6 *svc_ipv6, uint16_t svc_port); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/rte_flow/dp_rte_flow_isolation.h b/include/rte_flow/dp_rte_flow_isolation.h new file mode 100644 index 000000000..2354c3c07 --- /dev/null +++ b/include/rte_flow/dp_rte_flow_isolation.h @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef __INCLUDE_DP_RTE_FLOW_ISOLATION_H__ +#define __INCLUDE_DP_RTE_FLOW_ISOLATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int dp_install_isolated_mode(uint16_t port_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/meson.build b/meson.build index ed92177cc..9c2a13ad4 100644 --- a/meson.build +++ b/meson.build @@ -56,6 +56,9 @@ endif if get_option('enable_tests') add_global_arguments('-DENABLE_PYTEST', language: ['c', 'cpp']) endif +if get_option('enable_underlay_type') + add_global_arguments('-DENABLE_UNDERLAY_TYPE', language: ['c', 'cpp']) +endif dpdk_dep = dependency('libdpdk', version: '>=21.11.0') proto_dep = dependency('protobuf') diff --git a/meson_options.txt b/meson_options.txt index c8f35c1c3..a24002b50 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,3 +10,5 @@ option('compiler_suggestions', type: 'boolean', value: false, description: 'Show various compiler suggestions (warnings)') option('build_dpservice_cli', type: 'boolean', value: false, description: 'Enable building of dpservice-cli golang gRPC client') +option('enable_underlay_type', type: 'boolean', value: false, description: + 'Generate underlay address with vnf_type field') diff --git a/src/dp_ipaddr.c b/src/dp_ipaddr.c index 1a9ac347c..ae5dfd991 100644 --- a/src/dp_ipaddr.c +++ b/src/dp_ipaddr.c @@ -70,12 +70,19 @@ int dp_ipaddr_to_str(const struct dp_ip_address *addr, char *dest, int dest_len) } -void dp_generate_ul_ipv6(union dp_ipv6 *dest) +void dp_generate_ul_ipv6(union dp_ipv6 *dest, uint8_t addr_type) { static uint32_t ul_counter = 0; dest->_ul.prefix = dp_conf_get_underlay_ip()->_prefix; // Use the same prefix as the host - dest->_ul.kernel = dest->_ul.flags = 0; + dest->_ul.type = DP_UNDERLAY_ADDRESS_TYPE; +#ifdef ENABLE_UNDERLAY_TYPE + dest->_ul.subtype = addr_type; +#else + (void)addr_type; + dest->_ul.subtype = 0; +#endif + dest->_ul.flags = 0; #ifdef ENABLE_STATIC_UNDERLAY_IP dest->_ul.random = 1; #else diff --git a/src/dp_port.c b/src/dp_port.c index 0b0eacb40..72f5c71e4 100644 --- a/src/dp_port.c +++ b/src/dp_port.c @@ -20,7 +20,7 @@ #include "rte_flow/dp_rte_async_flow_template.h" #include "rte_flow/dp_rte_flow.h" #include "rte_flow/dp_rte_flow_capture.h" -#include "rte_flow/dp_rte_flow_init.h" +#include "rte_flow/dp_rte_flow_isolation.h" #define DP_PORT_INIT_PF true #define DP_PORT_INIT_VF false @@ -388,10 +388,6 @@ static int dp_stop_eth_port(struct dp_port *port) DPS_LOG_INFO("Stopping port", DP_LOG_PORT(port)); if (dp_conf_is_multiport_eswitch()) { -#ifdef ENABLE_VIRTSVC - if (port->is_pf) - dp_destroy_virtsvc_async_isolation_rules(port->port_id); -#endif dp_destroy_async_rules(port->port_id, port->default_async_rules.default_flows, RTE_DIM(port->default_async_rules.default_flows)); @@ -425,19 +421,6 @@ void dp_ports_free(void) } -static int dp_port_install_sync_isolated_mode(uint16_t port_id) -{ - DPS_LOG_INFO("Init isolation flow rules"); - if (DP_FAILED(dp_install_isolated_mode_ipip(port_id, IPPROTO_IPIP)) - || DP_FAILED(dp_install_isolated_mode_ipip(port_id, IPPROTO_IPV6))) - return DP_ERROR; -#ifdef ENABLE_VIRTSVC - return dp_install_virtsvc_sync_isolation_rules(port_id); -#else - return DP_OK; -#endif -} - static int dp_port_bind_port_hairpins(const struct dp_port *port) { // two pf port's hairpins are bound when processing the second port @@ -463,30 +446,6 @@ static int dp_install_vf_init_rte_rules(struct dp_port *port) return DP_OK; } -static int dp_port_install_async_isolated_mode(struct dp_port *port) -{ - DPS_LOG_INFO("Init async isolation flow rules"); - if (DP_FAILED(dp_create_pf_async_isolation_rules(port))) - return DP_ERROR; - return DP_OK; -} - -static int dp_port_create_default_pf_async_templates(struct dp_port *port) -{ - DPS_LOG_INFO("Installing PF async templates", DP_LOG_PORT(port)); - if (DP_FAILED(dp_create_pf_async_isolation_templates(port))) { - DPS_LOG_ERR("Failed to create pf async isolation templates", DP_LOG_PORT(port)); - return DP_ERROR; - } -#ifdef ENABLE_VIRTSVC - if (DP_FAILED(dp_create_virtsvc_async_isolation_templates(port))) { - DPS_LOG_ERR("Failed to create virtsvc async isolation templates", DP_LOG_PORT(port)); - return DP_ERROR; - } -#endif - return DP_OK; -} - static void dp_acquire_neigh_mac(struct dp_port *port); @@ -560,12 +519,15 @@ static int dp_init_port(struct dp_port *port) if (port->is_pf) { if (dp_conf_is_multiport_eswitch()) { - if (DP_FAILED(dp_port_create_default_pf_async_templates(port)) - || DP_FAILED(dp_port_install_async_isolated_mode(port))) + DPS_LOG_INFO("Init async isolation flow rules"); + if (DP_FAILED(dp_create_pf_async_isolation_templates(port)) + || DP_FAILED(dp_create_pf_async_isolation_rules(port))) return DP_ERROR; - } else - if (DP_FAILED(dp_port_install_sync_isolated_mode(port->port_id))) + } else { + DPS_LOG_INFO("Init isolation flow rules"); + if (DP_FAILED(dp_install_isolated_mode(port->port_id))) return DP_ERROR; + } } if (dp_conf_is_offload_enabled()) { diff --git a/src/dp_virtsvc.c b/src/dp_virtsvc.c index 8cb822395..e912c0b0d 100644 --- a/src/dp_virtsvc.c +++ b/src/dp_virtsvc.c @@ -13,9 +13,6 @@ #include "dp_log.h" #include "dp_multi_path.h" #include "dp_util.h" -#include "rte_flow/dp_rte_flow_init.h" -#include "rte_flow/dp_rte_async_flow.h" -#include "rte_flow/dp_rte_async_flow_isolation.h" // WARNING: This module is not designed to be thread-safe (even though it could work) // It is assumed that thread-unsafe code will only ever be called from one node @@ -169,7 +166,8 @@ int dp_virtsvc_init(int socket_id) dp_virtservices_end->virtual_port = rule->virtual_port; dp_virtservices_end->service_port = rule->service_port; dp_copy_ipv6(&dp_virtservices_end->service_addr, &rule->service_addr); - dp_generate_ul_ipv6(&dp_virtservices_end->ul_addr); + // TODO temporary, already made better in a branch (including ifdef ENABLE_UNDERLAY_TYPE) + dp_generate_ul_ipv6(&dp_virtservices_end->ul_addr, 0xff); // last_assigned_port is 0 due to zmalloc() snprintf(hashtable_name, sizeof(hashtable_name), "virtsvc_table_%u", i); dp_virtservices_end->open_ports = dp_create_jhash_table(DP_VIRTSVC_PORTCOUNT, @@ -224,72 +222,6 @@ size_t dp_virtsvc_get_count(void) } -int dp_install_virtsvc_sync_isolation_rules(uint16_t port_id) -{ - int ret; - - DP_FOREACH_VIRTSVC(&dp_virtservices, service) { - ret = dp_install_isolated_mode_virtsvc(port_id, - service->proto, - &service->service_addr, - service->service_port); - if (DP_FAILED(ret)) { - DPS_LOG_ERR("Cannot create isolation rule", DP_LOG_VIRTSVC(service), DP_LOG_RET(ret)); - return DP_ERROR; - } - } - return DP_OK; -} - -uint16_t dp_create_virtsvc_async_isolation_rules(uint16_t port_id, - struct rte_flow_template_table *template_table) -{ - struct rte_flow *flow; - uint16_t rule_count = 0; - uint16_t pf_idx; - - if (port_id == dp_get_pf0()->port_id) - pf_idx = 0; - else if (port_id == dp_get_pf1()->port_id) - pf_idx = 1; - else { - DPS_LOG_ERR("Invalid port for virtual service isolation", DP_LOG_PORTID(port_id)); - return 0; - } - - DP_FOREACH_VIRTSVC(&dp_virtservices, service) { - flow = dp_create_virtsvc_async_isolation_rule(port_id, template_table, &service->ul_addr); - if (!flow) { - DPS_LOG_ERR("Cannot create async virtsvc isolation rule", DP_LOG_VIRTSVC(service)); - break; - } - service->isolation_rules[pf_idx] = flow; - rule_count++; - } - - return rule_count; -} - -void dp_destroy_virtsvc_async_isolation_rules(uint16_t port_id) -{ - uint16_t pf_idx; - - if (port_id == dp_get_pf0()->port_id) - pf_idx = 0; - else if (port_id == dp_get_pf1()->port_id) - pf_idx = 1; - else { - DPS_LOG_ERR("Invalid port for virtual service isolation", DP_LOG_PORTID(port_id)); - return; - } - - DP_FOREACH_VIRTSVC(&dp_virtservices, service) { - if (DP_FAILED(dp_destroy_async_rules(port_id, &service->isolation_rules[pf_idx], 1))) - DPS_LOG_ERR("Cannot destroy async virtual service isolation rule", DP_LOG_VIRTSVC(service)); - } -} - - static __rte_always_inline bool dp_virtsvc_is_connection_old(struct dp_virtsvc_conn *conn, uint64_t current_tsc) { uint64_t timeout = conn->last_pkt_timestamp + (conn->state == DP_VIRTSVC_CONN_ESTABLISHED diff --git a/src/grpc/dp_grpc_impl.c b/src/grpc/dp_grpc_impl.c index 2205f4924..de7f005e5 100644 --- a/src/grpc/dp_grpc_impl.c +++ b/src/grpc/dp_grpc_impl.c @@ -30,7 +30,7 @@ static int dp_create_vnf_route(union dp_ipv6 *ul_addr6 /* out */, { // if ul_addr6 already provided, try to use that one, otherwise generate it here if (dp_ipv6_match(ul_addr6, &dp_empty_ipv6)) - dp_generate_ul_ipv6(ul_addr6); + dp_generate_ul_ipv6(ul_addr6, type); return dp_add_vnf(ul_addr6, type, port->port_id, vni, pfx_ip, prefix_len); } diff --git a/src/meson.build b/src/meson.build index 06fae0447..6ff00e97b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -32,13 +32,13 @@ dp_sources = [ 'nodes/rx_periodic_node.c', 'nodes/snat_node.c', 'nodes/tx_node.c', - 'rte_flow/dp_rte_flow.c', - 'rte_flow/dp_rte_flow_capture.c', - 'rte_flow/dp_rte_flow_init.c', - 'rte_flow/dp_rte_flow_traffic_forward.c', 'rte_flow/dp_rte_async_flow.c', 'rte_flow/dp_rte_async_flow_isolation.c', 'rte_flow/dp_rte_async_flow_template.c', + 'rte_flow/dp_rte_flow.c', + 'rte_flow/dp_rte_flow_capture.c', + 'rte_flow/dp_rte_flow_isolation.c', + 'rte_flow/dp_rte_flow_traffic_forward.c', 'dp_argparse.c', 'dp_cntrack.c', 'dp_conf.c', diff --git a/src/monitoring/dp_event.c b/src/monitoring/dp_event.c index a2d1c66ee..0fff5f4b7 100644 --- a/src/monitoring/dp_event.c +++ b/src/monitoring/dp_event.c @@ -8,7 +8,6 @@ #include "dp_log.h" #include "dp_port.h" #include "monitoring/dp_monitoring.h" -#include "rte_flow/dp_rte_flow_init.h" static int dp_send_event_msg(const struct dp_event_msg *msg) diff --git a/src/monitoring/dp_graphtrace.c b/src/monitoring/dp_graphtrace.c index 79b7b74ad..63e2b02a1 100644 --- a/src/monitoring/dp_graphtrace.c +++ b/src/monitoring/dp_graphtrace.c @@ -12,7 +12,6 @@ #include "dpdk_layer.h" #include "monitoring/dp_graphtrace_shared.h" #include "monitoring/dp_pcap.h" -#include "rte_flow/dp_rte_flow_init.h" #include "rte_flow/dp_rte_flow.h" #include "monitoring/dp_event.h" diff --git a/src/rte_flow/dp_rte_async_flow_isolation.c b/src/rte_flow/dp_rte_async_flow_isolation.c index 59c1e066f..f8609ba81 100644 --- a/src/rte_flow/dp_rte_async_flow_isolation.c +++ b/src/rte_flow/dp_rte_async_flow_isolation.c @@ -4,9 +4,6 @@ #include "rte_flow/dp_rte_async_flow_isolation.h" #include "dp_error.h" -#ifdef ENABLE_VIRTSVC -#include "dp_virtsvc.h" -#endif #include "rte_flow/dp_rte_async_flow.h" #include "rte_flow/dp_rte_async_flow_template.h" #include "rte_flow/dp_rte_flow_helpers.h" @@ -57,7 +54,7 @@ int dp_create_pf_async_isolation_templates(struct dp_port *port) .mask = &dp_flow_item_eth_mask, }, { .type = RTE_FLOW_ITEM_TYPE_IPV6, - .mask = &dp_flow_item_ipv6_mask, + .mask = &dp_flow_item_ipv6_dst_pfx68_mask, }, { .type = RTE_FLOW_ITEM_TYPE_END }, }; @@ -76,50 +73,14 @@ int dp_create_pf_async_isolation_templates(struct dp_port *port) return dp_init_async_template(port->port_id, tmpl); } -#ifdef ENABLE_VIRTSVC -int dp_create_virtsvc_async_isolation_templates(struct dp_port *port) -{ - struct dp_port_async_template *tmpl; - - tmpl = dp_alloc_async_template(DP_ISOLATION_PATTERN_COUNT, DP_ISOLATION_ACTIONS_COUNT); - if (!tmpl) - return DP_ERROR; - - port->default_async_rules.default_templates[DP_PORT_ASYNC_TEMPLATE_VIRTSVC_ISOLATION] = tmpl; - - const struct rte_flow_item tcp_src_pattern[] = { - { .type = RTE_FLOW_ITEM_TYPE_ETH, - .mask = &dp_flow_item_eth_mask, - }, - { .type = RTE_FLOW_ITEM_TYPE_IPV6, - .mask = &dp_flow_item_ipv6_dst_only_mask, - }, - { .type = RTE_FLOW_ITEM_TYPE_END }, - }; - tmpl->pattern_templates[DP_ISOLATION_PATTERN_IPV6_PROTO] - = dp_create_async_pattern_template(port->port_id, &ingress_pattern_template_attr, tcp_src_pattern); - - static const struct rte_flow_action actions[] = { - { .type = RTE_FLOW_ACTION_TYPE_QUEUE, }, - { .type = RTE_FLOW_ACTION_TYPE_END, }, - }; - tmpl->actions_templates[DP_ISOLATION_ACTIONS_QUEUE] - = dp_create_async_actions_template(port->port_id, &ingress_actions_template_attr, actions, actions); - tmpl->table_attr = &pf_ingress_template_table_attr; - - return dp_init_async_template(port->port_id, tmpl); -} -#endif - - -static struct rte_flow *dp_create_pf_async_isolation_rule(uint16_t port_id, uint8_t proto, struct rte_flow_template_table *template_table) +static struct rte_flow *dp_create_pf_async_isolation_rule(uint16_t port_id, struct rte_flow_template_table *template_table) { const struct rte_flow_item_eth eth_spec = { .hdr.ether_type = htons(RTE_ETHER_TYPE_IPV6), }; - const struct rte_flow_item_ipv6 ipv6_spec = { - .hdr.proto = proto, + struct rte_flow_item_ipv6 ipv6_spec = { + 0, }; const struct rte_flow_item pattern[] = { { .type = RTE_FLOW_ITEM_TYPE_ETH, @@ -141,81 +102,38 @@ static struct rte_flow *dp_create_pf_async_isolation_rule(uint16_t port_id, uint { .type = RTE_FLOW_ACTION_TYPE_END }, }; - return dp_create_async_rule(port_id, template_table, - pattern, DP_ISOLATION_PATTERN_IPV6_PROTO, - actions, DP_ISOLATION_ACTIONS_QUEUE); -} - -#ifdef ENABLE_VIRTSVC -struct rte_flow *dp_create_virtsvc_async_isolation_rule(uint16_t port_id, - struct rte_flow_template_table *template_table, - const union dp_ipv6 *ul_addr) -{ - const struct rte_flow_item_eth eth_spec = { - .hdr.ether_type = htons(RTE_ETHER_TYPE_IPV6), - }; - const struct rte_flow_item_ipv6 ipv6_spec = { - .hdr.dst_addr = ul_addr->addr, - }; - const struct rte_flow_item pattern[] = { - { .type = RTE_FLOW_ITEM_TYPE_ETH, - .spec = ð_spec, - }, - { .type = RTE_FLOW_ITEM_TYPE_IPV6, - .spec = &ipv6_spec, - }, - { .type = RTE_FLOW_ITEM_TYPE_END }, + // Only allow the right IPv6 underlay prefix + const union dp_ipv6 ul_addr6 = { + ._ul.prefix = dp_conf_get_underlay_ip()->_prefix, + ._ul.type = DP_UNDERLAY_ADDRESS_TYPE, }; - static const struct rte_flow_action_queue queue_action = { - .index = 0, - }; - const struct rte_flow_action actions[] = { - { .type = RTE_FLOW_ACTION_TYPE_QUEUE, - .conf = &queue_action, - }, - { .type = RTE_FLOW_ACTION_TYPE_END }, - }; + dp_set_dst_ipv6(&ipv6_spec.hdr, &ul_addr6); return dp_create_async_rule(port_id, template_table, pattern, DP_ISOLATION_PATTERN_IPV6_PROTO, actions, DP_ISOLATION_ACTIONS_QUEUE); } -#endif int dp_create_pf_async_isolation_rules(struct dp_port *port) { struct rte_flow *flow; uint16_t rule_count = 0; - size_t rules_required = 2; + size_t rules_required = 1; struct dp_port_async_template **templates = port->default_async_rules.default_templates; - flow = dp_create_pf_async_isolation_rule(port->port_id, IPPROTO_IPIP, + flow = dp_create_pf_async_isolation_rule(port->port_id, templates[DP_PORT_ASYNC_TEMPLATE_PF_ISOLATION]->template_table); if (!flow) { DPS_LOG_ERR("Failed to install PF async IPIP isolation rule", DP_LOG_PORT(port)); return DP_ERROR; } else { - port->default_async_rules.default_flows[DP_PORT_ASYNC_FLOW_ISOLATE_IPIP] = flow; + port->default_async_rules.default_flows[DP_PORT_ASYNC_FLOW_ISOLATE_PREFIX] = flow; rule_count++; } - flow = dp_create_pf_async_isolation_rule(port->port_id, IPPROTO_IPV6, - templates[DP_PORT_ASYNC_TEMPLATE_PF_ISOLATION]->template_table); - if (!flow) { - DPS_LOG_ERR("Failed to install PF async IPV6 isolation rule", DP_LOG_PORT(port)); - // cannot return, need to push all previous rules and then return error - } else { - port->default_async_rules.default_flows[DP_PORT_ASYNC_FLOW_ISOLATE_IPV6] = flow; - rule_count++; - } + // add more rules here and increase rules_required appropriately -#ifdef ENABLE_VIRTSVC - rules_required += dp_virtsvc_get_count(); - rule_count += dp_create_virtsvc_async_isolation_rules(port->port_id, - templates[DP_PORT_ASYNC_TEMPLATE_VIRTSVC_ISOLATION]->template_table); - // cannot return, need to push all previous rules and then return error -#endif if (dp_blocking_commit_async_rules(port->port_id, rule_count)) { DPS_LOG_ERR("Failed to commit PF async isolation rules", DP_LOG_PORT(port)); diff --git a/src/rte_flow/dp_rte_flow_init.c b/src/rte_flow/dp_rte_flow_init.c deleted file mode 100644 index fcc861c44..000000000 --- a/src/rte_flow/dp_rte_flow_init.c +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors -// SPDX-License-Identifier: Apache-2.0 - -#include "rte_flow/dp_rte_flow_init.h" - -#include "dp_error.h" -#include "dp_log.h" -#include "rte_flow/dp_rte_flow_helpers.h" -#include "dp_conf.h" -#include "monitoring/dp_monitoring.h" - -static const struct rte_flow_attr dp_flow_attr_prio_ingress = { - .group = 0, - .priority = 1, - .ingress = 1, - .egress = 0, - .transfer = 0, -}; - - -int dp_install_isolated_mode_ipip(uint16_t port_id, uint8_t proto_id) -{ - struct rte_flow_item_eth eth_spec; // #1 - struct rte_flow_item_ipv6 ipv6_spec; // #2 - struct rte_flow_item pattern[3]; // + end - int pattern_cnt = 0; - struct rte_flow_action_queue queue_action; // #1 - struct rte_flow_action action[2]; // + end - int action_cnt = 0; - - // create match pattern: IP in IPv6 tunnel packets - dp_set_eth_flow_item(&pattern[pattern_cnt++], ð_spec, htons(RTE_ETHER_TYPE_IPV6)); - dp_set_ipv6_flow_item(&pattern[pattern_cnt++], &ipv6_spec, proto_id); - dp_set_end_flow_item(&pattern[pattern_cnt++]); - - // create flow action: allow packets to enter dp-service packet queue - dp_set_redirect_queue_action(&action[action_cnt++], &queue_action, 0); - dp_set_end_action(&action[action_cnt++]); - - if (!dp_install_rte_flow(port_id, &dp_flow_attr_prio_ingress, pattern, action)) - return DP_ERROR; - - DPS_LOG_DEBUG("Installed IPIP isolation flow rule", DP_LOG_PORTID(port_id)); - return DP_OK; -} - -#ifdef ENABLE_VIRTSVC -int dp_install_isolated_mode_virtsvc(uint16_t port_id, uint8_t proto_id, const union dp_ipv6 *svc_ipv6, rte_be16_t svc_port) -{ - struct rte_flow_item_eth eth_spec; // #1 - struct rte_flow_item_ipv6 ipv6_spec; // #2 - struct rte_flow_item_tcp tcp_spec; // #3 (choose one) - struct rte_flow_item_udp udp_spec; // #3 (choose one) - struct rte_flow_item pattern[4]; // + end - int pattern_cnt = 0; - struct rte_flow_action_queue queue_action; // #1 - struct rte_flow_action actions[2]; // + end - int action_cnt = 0; - - // create match pattern: IPv6 packets from selected addresses - dp_set_eth_flow_item(&pattern[pattern_cnt++], ð_spec, htons(RTE_ETHER_TYPE_IPV6)); - dp_set_ipv6_src_flow_item(&pattern[pattern_cnt++], &ipv6_spec, svc_ipv6, proto_id); - if (proto_id == IPPROTO_TCP) { - dp_set_tcp_src_flow_item(&pattern[pattern_cnt++], &tcp_spec, svc_port); - } else if (proto_id == IPPROTO_UDP) { - dp_set_udp_src_flow_item(&pattern[pattern_cnt++], &udp_spec, svc_port); - } else { - DPS_LOG_ERR("Invalid virtsvc protocol for isolation", DP_LOG_PROTO(proto_id)); - return DP_ERROR; - } - dp_set_end_flow_item(&pattern[pattern_cnt++]); - - // create flow action: allow packets to enter dp-service packet queue - dp_set_redirect_queue_action(&actions[action_cnt++], &queue_action, 0); - dp_set_end_action(&actions[action_cnt++]); - - if (!dp_install_rte_flow(port_id, &dp_flow_attr_prio_ingress, pattern, actions)) - return DP_ERROR; - - DPS_LOG_DEBUG("Installed virtsvc isolation flow rule", DP_LOG_PORTID(port_id)); - return DP_OK; -} -#endif diff --git a/src/rte_flow/dp_rte_flow_isolation.c b/src/rte_flow/dp_rte_flow_isolation.c new file mode 100644 index 000000000..ecbfeb84f --- /dev/null +++ b/src/rte_flow/dp_rte_flow_isolation.c @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 + +#include "rte_flow/dp_rte_flow_isolation.h" + +#include "dp_error.h" +#include "dp_log.h" +#include "rte_flow/dp_rte_flow_helpers.h" +#include "dp_conf.h" +#include "monitoring/dp_monitoring.h" + +static const struct rte_flow_attr dp_flow_attr_prio_ingress = { + .group = 0, + .priority = 1, + .ingress = 1, + .egress = 0, + .transfer = 0, +}; + + +int dp_install_isolated_mode(uint16_t port_id) +{ + struct rte_flow_item_eth eth_spec; // #1 + struct rte_flow_item_ipv6 ipv6_spec; // #2 + struct rte_flow_item pattern[3]; // + end + int pattern_cnt = 0; + struct rte_flow_action_queue queue_action; // #1 + struct rte_flow_action action[2]; // + end + int action_cnt = 0; + union dp_ipv6 ul_addr6; + + ul_addr6._ul.prefix = dp_conf_get_underlay_ip()->_prefix; + ul_addr6._ul.type = DP_UNDERLAY_ADDRESS_TYPE; + + // create match pattern: IP in IPv6 tunnel packets + dp_set_eth_flow_item(&pattern[pattern_cnt++], ð_spec, htons(RTE_ETHER_TYPE_IPV6)); + dp_set_ipv6_dst_pfx68_flow_item(&pattern[pattern_cnt++], &ipv6_spec, &ul_addr6); + dp_set_end_flow_item(&pattern[pattern_cnt++]); + + // create flow action: allow packets to enter dp-service packet queue + dp_set_redirect_queue_action(&action[action_cnt++], &queue_action, 0); + dp_set_end_action(&action[action_cnt++]); + + if (!dp_install_rte_flow(port_id, &dp_flow_attr_prio_ingress, pattern, action)) + return DP_ERROR; + + DPS_LOG_DEBUG("Installed IPIP isolation flow rule", DP_LOG_PORTID(port_id)); + return DP_OK; +} + diff --git a/test/local/test_vf_to_pf.py b/test/local/test_vf_to_pf.py index 7beed0330..93ecf4141 100644 --- a/test/local/test_vf_to_pf.py +++ b/test/local/test_vf_to_pf.py @@ -57,7 +57,7 @@ def test_vf_to_pf_network_nat_icmp(prepare_ipv4, grpc_client, port_redundancy): icmp_pkt = (Ether(dst=PF0.mac, src=VM1.mac, type=0x0800) / IP(dst=public_ip3, src=VM1.ip) / - ICMP(type=8, id=0x0040)) + ICMP(type=8, id=0x0050)) delayed_sendp(icmp_pkt, VM1.tap) pkt = sniff_packet(VM1.tap, is_icmp_pkt)