Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce IPv6 overlay support for non-offloading path #462

Merged
merged 14 commits into from
Dec 22, 2023
Merged
1 change: 1 addition & 0 deletions docs/deployment/help_dpservice-bin.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
| --vf-pattern | PATTERN | virtual interface name pattern (e.g. 'eth1vf') | |
| --dhcp-mtu | SIZE | set the mtu field in DHCP responses (68 - 1500) | |
| --dhcp-dns | IPv4 | set the domain name server field in DHCP responses (can be used multiple times) | |
| --dhcpv6-dns | ADDR6 | set the domain name server field in DHCPv6 responses (can be used multiple times) | |
| --udp-virtsvc | IPv4,port,IPv6,port | map a VM-accessible IPv4 endpoint to an outside IPv6 UDP service | |
| --tcp-virtsvc | IPv4,port,IPv6,port | map a VM-accessible IPv4 endpoint to an outside IPv6 TCP service | |
| --wcmp | PERCENTAGE | weighted-cost-multipath percentage for pf0 (0 - 100) | |
Expand Down
5 changes: 5 additions & 0 deletions hack/dp_conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
"arg": "IPv4",
"help": "set the domain name server field in DHCP responses (can be used multiple times)"
},
{
"lgopt": "dhcpv6-dns",
"arg": "ADDR6",
"help": "set the domain name server field in DHCPv6 responses (can be used multiple times)"
},
{
"lgopt": "udp-virtsvc",
"arg": "IPv4,port,IPv6,port",
Expand Down
1 change: 1 addition & 0 deletions include/dp_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const char *dp_conf_get_eal_a_pf0(void);
const char *dp_conf_get_eal_a_pf1(void);
const uint8_t *dp_conf_get_underlay_ip(void);
const struct dp_conf_dhcp_dns *dp_conf_get_dhcp_dns(void);
const struct dp_conf_dhcp_dns *dp_conf_get_dhcpv6_dns(void);
#ifdef ENABLE_VIRTSVC
const struct dp_conf_virtual_services *dp_conf_get_virtual_services(void);
#endif
Expand Down
21 changes: 14 additions & 7 deletions include/dp_firewall.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,21 @@ struct dp_port_filter {
struct dp_port_range dst_port;
};

struct dp_ip_mask {
union {
uint32_t ip4;
uint8_t ip6[DP_IPV6_ADDR_SIZE];
};
};

struct dp_fwall_rule {
char rule_id[DP_FIREWALL_ID_MAX_LEN];
uint32_t src_ip;
uint32_t src_ip_mask;
uint32_t dest_ip;
uint32_t dest_ip_mask;
uint16_t priority;
uint8_t protocol;
char rule_id[DP_FIREWALL_ID_MAX_LEN];
struct dp_ip_address src_ip;
struct dp_ip_address dest_ip;
struct dp_ip_mask src_mask;
struct dp_ip_mask dest_mask;
uint16_t priority;
uint8_t protocol;
union {
struct dp_icmp_filter icmp;
struct dp_port_filter tcp_udp;
Expand Down
32 changes: 21 additions & 11 deletions include/dp_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <rte_malloc.h>
#include "dpdk_layer.h"
#include "dp_firewall.h"
#include "dp_util.h"
#include "dp_mbuf_dyn.h"
#include "dp_refcount.h"
#include "dp_timers.h"
Expand All @@ -32,16 +33,18 @@ extern "C" {
#define DP_FLOW_FLAG_DST_NAT 0x02
#define DP_FLOW_FLAG_DST_LB 0x04
#define DP_FLOW_FLAG_FIREWALL 0x08
#define DP_FLOW_FLAG_DEFAULT 0x10
#define DP_FLOW_FLAG_SRC_NAT64 0x10
#define DP_FLOW_FLAG_DEFAULT 0x20

#define DP_FLOW_FLAG_NF (DP_FLOW_FLAG_SRC_NAT | DP_FLOW_FLAG_DST_NAT | DP_FLOW_FLAG_DST_LB)
#define DP_FLOW_FLAG_NF (DP_FLOW_FLAG_SRC_NAT64 | DP_FLOW_FLAG_SRC_NAT | DP_FLOW_FLAG_DST_NAT | DP_FLOW_FLAG_DST_LB)

#define DP_FLOW_HAS_NO_FLAGS(flag) (!(flag))
#define DP_FLOW_HAS_FLAG_SRC_NAT(flag) ((flag) & DP_FLOW_FLAG_SRC_NAT)
#define DP_FLOW_HAS_FLAG_DST_NAT(flag) ((flag) & DP_FLOW_FLAG_DST_NAT)
#define DP_FLOW_HAS_FLAG_DST_LB(flag) ((flag) & DP_FLOW_FLAG_DST_LB)
#define DP_FLOW_HAS_FLAG_FIREWALL(flag) ((flag) & DP_FLOW_FLAG_FIREWALL)
#define DP_FLOW_HAS_FLAG_DEFAULT(flag) ((flag) & DP_FLOW_FLAG_DEFAULT)
#define DP_FLOW_HAS_NO_FLAGS(flag) (!(flag))
#define DP_FLOW_HAS_FLAG_SRC_NAT(flag) ((flag) & DP_FLOW_FLAG_SRC_NAT)
#define DP_FLOW_HAS_FLAG_DST_NAT(flag) ((flag) & DP_FLOW_FLAG_DST_NAT)
#define DP_FLOW_HAS_FLAG_DST_LB(flag) ((flag) & DP_FLOW_FLAG_DST_LB)
#define DP_FLOW_HAS_FLAG_FIREWALL(flag) ((flag) & DP_FLOW_FLAG_FIREWALL)
#define DP_FLOW_HAS_FLAG_SRC_NAT64(flag) ((flag) & DP_FLOW_FLAG_SRC_NAT64)
#define DP_FLOW_HAS_FLAG_DEFAULT(flag) ((flag) & DP_FLOW_FLAG_DEFAULT)

#define DP_FLOW_HAS_FLAG_NF(flag) ((flag) & DP_FLOW_FLAG_NF)

Expand All @@ -66,14 +69,21 @@ enum dp_flow_tcp_state {
};

struct flow_key {
uint32_t ip_dst;
uint32_t ip_src;
union {
uint32_t ip4;
uint8_t ip6[DP_IPV6_ADDR_SIZE];
} l3_dst;
union {
uint32_t ip4;
uint8_t ip6[DP_IPV6_ADDR_SIZE];
} l3_src;
uint16_t port_dst;
union {
uint16_t port_src;
uint16_t type_src; /* ICMP */
} src;
uint32_t vni;
uint16_t l3_type;
uint8_t proto;
enum dp_vnf_type vnf_type;
} __rte_packed;
Expand Down Expand Up @@ -127,7 +137,7 @@ int dp_get_flow(const struct flow_key *key, struct flow_value **p_flow_val);
int dp_add_flow(const struct flow_key *key, struct flow_value *flow_val);
void dp_delete_flow(const struct flow_key *key);
int dp_build_flow_key(struct flow_key *key /* out */, struct rte_mbuf *m /* in */);
void dp_invert_flow_key(const struct flow_key *key /* in */, struct flow_key *inv_key /* out */);
void dp_invert_flow_key(const struct flow_key *key /* in */, uint16_t l3_type /* in */, struct flow_key *inv_key /* out */);
int dp_flow_init(int socket_id);
void dp_flow_free(void);
void dp_process_aged_flows(uint16_t port_id);
Expand Down
12 changes: 8 additions & 4 deletions include/dp_lb.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
extern "C" {
#endif

#include "dp_flow.h"
#include "grpc/dp_grpc_responder.h"

#define DP_LB_TABLE_MAX 256
Expand All @@ -19,7 +20,11 @@ extern "C" {
#define DP_LB_DLB 3

struct lb_key {
uint32_t ip;
union {
uint32_t v4;
uint8_t v6[DP_IPV6_ADDR_SIZE];
} ip;
uint16_t ip_type;
uint32_t vni;
} __rte_packed;

Expand All @@ -39,9 +44,8 @@ struct lb_value {

int dp_lb_init(int socket_id);
void dp_lb_free(void);
bool dp_is_ip_lb(uint32_t ol_ip, uint32_t vni);
uint32_t dp_get_lb_ip(uint32_t ol_ip, uint32_t vni);
uint8_t *dp_lb_get_backend_ip(uint32_t ol_ip, uint32_t vni, rte_be16_t port, uint8_t proto);
bool dp_is_ip_lb(struct dp_flow *df, uint32_t vni);
uint8_t *dp_lb_get_backend_ip(struct flow_key *flow_key, uint32_t vni);
bool dp_is_lb_enabled(void);
int dp_del_lb_back_ip(const void *id_key, const uint8_t *back_ip);
int dp_add_lb_back_ip(const void *id_key, const uint8_t *back_ip, uint8_t ip_size);
Expand Down
2 changes: 2 additions & 0 deletions include/dp_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ extern "C" {
#define DP_LOG_IPV6(VALUE) _DP_LOG_IPV6("ipv6", VALUE)
#define DP_LOG_SRC_IPV4(VALUE) _DP_LOG_IPV4("src_ipv4", VALUE)
#define DP_LOG_DST_IPV4(VALUE) _DP_LOG_IPV4("dst_ipv4", VALUE)
#define DP_LOG_SRC_IPV6(VALUE) _DP_LOG_IPV6("src_ipv6", VALUE)
#define DP_LOG_DST_IPV6(VALUE) _DP_LOG_IPV6("dst_ipv6", VALUE)
#define DP_LOG_L4PORT(VALUE) _DP_LOG_UINT("port", VALUE)
#define DP_LOG_SRC_PORT(VALUE) _DP_LOG_UINT("src_port", VALUE)
#define DP_LOG_DST_PORT(VALUE) _DP_LOG_UINT("dst_port", VALUE)
Expand Down
6 changes: 3 additions & 3 deletions include/dp_lpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ const struct dp_port *dp_get_ip4_out_port(const struct dp_port *in_port,

const struct dp_port *dp_get_ip6_out_port(const struct dp_port *in_port,
uint32_t t_vni,
const struct rte_ipv6_hdr *ipv6_hdr,
struct dp_iface_route *route);

const struct dp_flow *df,
struct dp_iface_route *route,
uint8_t route_key[DP_IPV6_ADDR_SIZE]);
uint32_t dp_get_gw_ip4(void);
const uint8_t *dp_get_gw_ip6(void);

Expand Down
7 changes: 3 additions & 4 deletions include/dp_mbuf_dyn.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ enum dp_nat_type {
DP_NAT_CHG_DST_IP,
DP_CHG_UL_DST_IP,
DP_LB_RECIRC,
DP_NAT_64_CHG_SRC_IP,
DP_NAT_64_CHG_DST_IP,
} __rte_packed;

struct dp_flow {
Expand Down Expand Up @@ -166,14 +168,11 @@ static __rte_always_inline int dp_extract_l4_header(struct dp_flow *df, const vo
df->l4_info.trans_port.dst_port = ((const struct rte_udp_hdr *)l4_hdr)->dst_port;
df->l4_info.trans_port.src_port = ((const struct rte_udp_hdr *)l4_hdr)->src_port;
return DP_OK;
} else if (df->l4_type == IPPROTO_ICMP) {
} else if (df->l4_type == IPPROTO_ICMP || df->l4_type == IPPROTO_ICMPV6) {
df->l4_info.icmp_field.icmp_type = ((const struct rte_icmp_hdr *)l4_hdr)->icmp_type;
df->l4_info.icmp_field.icmp_code = ((const struct rte_icmp_hdr *)l4_hdr)->icmp_code;
df->l4_info.icmp_field.icmp_identifier = ((const struct rte_icmp_hdr *)l4_hdr)->icmp_ident;
return DP_OK;
} else if (df->l4_type == IPPROTO_ICMPV6) {
df->l4_info.icmp_field.icmp_type = ((const struct rte_icmp_hdr *)l4_hdr)->icmp_type;
return DP_OK;
}

return DP_ERROR;
Expand Down
25 changes: 17 additions & 8 deletions include/dp_nat.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
#include <rte_common.h>
#include <rte_mbuf.h>
#include "dp_flow.h"
#include "dp_util.h"
#include "grpc/dp_grpc_responder.h"

#ifdef __cplusplus
extern "C" {
#endif

#define DP_NAT64_PREFIX "\x00\x64\xff\x9b\x00\x00\x00\x00\x00\x00\x00\x00"

#define DP_NETWORK_NAT_ALL_VNI 0

struct nat_key {
Expand All @@ -25,20 +28,20 @@ struct nat_key {
typedef struct network_nat_entry {
union {
uint32_t nat_ip4;
uint8_t nat_ip6[16];
uint8_t nat_ip6[DP_IPV6_ADDR_SIZE];
} nat_ip;
uint16_t port_range[2];
uint32_t vni;
uint8_t dst_ipv6[16];
uint8_t dst_ipv6[DP_IPV6_ADDR_SIZE];
TAILQ_ENTRY(network_nat_entry) entries;
} network_nat_entry;

struct snat_data {
uint32_t vip_ip;
uint32_t nat_ip;
uint16_t nat_port_range[2];
uint8_t ul_vip_ip6[16]; /* VIP underlay */
uint8_t ul_nat_ip6[16]; /* NAT Gateway underlay */
uint8_t ul_vip_ip6[DP_IPV6_ADDR_SIZE]; /* VIP underlay */
uint8_t ul_nat_ip6[DP_IPV6_ADDR_SIZE]; /* NAT Gateway underlay */
uint64_t log_timestamp;
};

Expand All @@ -47,9 +50,9 @@ struct dnat_data {
};

struct netnat_portmap_key {
uint32_t iface_src_ip;
uint32_t vni;
uint16_t iface_src_port;
struct dp_ip_address src_ip;
uint32_t vni;
uint16_t iface_src_port;
} __rte_packed;

struct netnat_portmap_data {
Expand All @@ -74,7 +77,6 @@ struct nat_check_result {
int dp_nat_init(int socket_id);
void dp_nat_free(void);

uint32_t dp_get_iface_vip_ip(uint32_t iface_ip, uint32_t vni);
int dp_set_iface_vip_ip(uint32_t iface_ip, uint32_t vip_ip, uint32_t vni,
const uint8_t ul_ipv6[DP_VNF_IPV6_ADDR_SIZE]);
int dp_del_iface_vip_ip(uint32_t iface_ip, uint32_t vni);
Expand All @@ -91,6 +93,9 @@ int dp_set_dnat_ip(uint32_t d_ip, uint32_t dnat_ip, uint32_t vni);
void dp_nat_chg_ip(struct dp_flow *df, struct rte_ipv4_hdr *ipv4_hdr,
struct rte_mbuf *m);

int dp_nat_chg_ipv6_to_ipv4_hdr(struct dp_flow *df, struct rte_mbuf *m, uint32_t nat_ip, rte_be32_t *dest_ip /* out */);
int dp_nat_chg_ipv4_to_ipv6_hdr(struct dp_flow *df, struct rte_mbuf *m, uint8_t *ipv6_addr);

void dp_del_vip_from_dnat(uint32_t d_ip, uint32_t vni);

int dp_add_network_nat_entry(uint32_t nat_ipv4, const uint8_t nat_ipv6[DP_VNF_IPV6_ADDR_SIZE],
Expand All @@ -112,6 +117,10 @@ int dp_list_nat_neigh_entries(uint32_t nat_ip, struct dp_grpc_responder *respond
struct snat_data *dp_get_iface_snat_data(uint32_t iface_ip, uint32_t vni);
void dp_del_all_neigh_nat_entries_in_vni(uint32_t vni);

static __rte_always_inline bool dp_is_ip6_in_nat64_range(const uint8_t *ipv6_addr)
{
return memcmp(ipv6_addr, DP_NAT64_PREFIX, 12) == 0;
}

#ifdef __cplusplus
}
Expand Down
9 changes: 6 additions & 3 deletions include/dp_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <net/if.h>
#include <rte_pci.h>
#include "dp_conf.h"
#include "dp_util.h"
#include "dp_firewall.h"
#include "dp_internal_stats.h"
#include "dpdk_layer.h"
Expand All @@ -23,8 +24,8 @@ struct dp_iface_cfg {
uint32_t own_ip;
uint32_t neigh_ip;
uint8_t ip_depth;
uint8_t dhcp_ipv6[16];
uint8_t own_ipv6[16];
uint8_t dhcp_ipv6[DP_IPV6_ADDR_SIZE];
uint8_t own_ipv6[DP_IPV6_ADDR_SIZE];
uint8_t ip6_depth;
uint32_t pxe_ip;
char pxe_str[DP_IFACE_PXE_MAX_LEN];
Expand All @@ -35,7 +36,9 @@ struct dp_port_iface {
struct dp_iface_cfg cfg;
uint32_t vni;
char id[DP_IFACE_ID_MAX_LEN];
uint8_t ul_ipv6[16];
uint8_t ul_ipv6[DP_IPV6_ADDR_SIZE];
uint32_t nat_ip;
uint16_t nat_port_range[2];
bool ready;
};

Expand Down
8 changes: 8 additions & 0 deletions include/dp_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extern "C" {
#define DP_IFACE_PXE_MAX_LEN 32
#define DP_LB_ID_MAX_LEN 64
#define DP_LB_MAX_PORTS 16
#define DP_IPV6_ADDR_SIZE 16

#define DP_MAC_EQUAL(mac1, mac2) (((mac1)->addr_bytes[0] == (mac2)->addr_bytes[0]) && \
((mac1)->addr_bytes[1] == (mac2)->addr_bytes[1]) && \
Expand All @@ -38,6 +39,13 @@ extern "C" {
#define DP_TCP_PKT_FLAG_SYNACK(FLAGS) \
(((FLAGS) & (RTE_TCP_SYN_FLAG|RTE_TCP_ACK_FLAG)) == (RTE_TCP_SYN_FLAG|RTE_TCP_ACK_FLAG))

struct dp_ip_address {
uint16_t ip_type;
union {
uint32_t ipv4;
uint8_t ipv6[DP_IPV6_ADDR_SIZE];
};
};

int dp_get_dev_info(uint16_t port_id, struct rte_eth_dev_info *dev_info, char ifname[IF_NAMESIZE]);

Expand Down
11 changes: 6 additions & 5 deletions include/dp_vnf.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <rte_common.h>
#include "dp_util.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -30,8 +31,8 @@ enum dp_vnf_type {
} __rte_packed; // for 'struct dp_flow' and 'struct flow_key'

struct dp_vnf_prefix {
uint32_t ip;
uint8_t length;
struct dp_ip_address ol;
uint8_t length;
};

struct dp_vnf {
Expand All @@ -45,13 +46,13 @@ int dp_vnf_init(int socket_id);
void dp_vnf_free(void);

int dp_add_vnf(const uint8_t ul_addr6[DP_VNF_IPV6_ADDR_SIZE], enum dp_vnf_type type,
uint16_t port_id, uint32_t vni, uint32_t prefix_ip, uint8_t prefix_len);
uint16_t port_id, uint32_t vni, struct dp_ip_address *pfx_ip, uint8_t prefix_len);
const struct dp_vnf *dp_get_vnf(const uint8_t ul_addr6[DP_VNF_IPV6_ADDR_SIZE]);
int dp_del_vnf(const uint8_t ul_addr6[DP_VNF_IPV6_ADDR_SIZE]);

bool dp_vnf_lbprefix_exists(uint16_t port_id, uint32_t vni, uint32_t prefix_ip, uint8_t prefix_len);
bool dp_vnf_lbprefix_exists(uint16_t port_id, uint32_t vni, struct dp_ip_address *prefix_ip, uint8_t prefix_len);

int dp_del_vnf_by_value(enum dp_vnf_type type, uint16_t port_id, uint32_t vni, uint32_t prefix_ip, uint8_t prefix_len);
int dp_del_vnf_by_value(enum dp_vnf_type type, uint16_t port_id, uint32_t vni, struct dp_ip_address *prefix_ip, uint8_t prefix_len);

int dp_list_vnf_alias_prefixes(uint16_t port_id, enum dp_vnf_type type, struct dp_grpc_responder *responder);

Expand Down
Loading