summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VNFs/DPPD-PROX/Makefile2
-rw-r--r--VNFs/DPPD-PROX/cmd_parser.c26
-rw-r--r--VNFs/DPPD-PROX/commands.c4
-rw-r--r--VNFs/DPPD-PROX/config/ipv6.cfg85
-rw-r--r--VNFs/DPPD-PROX/defaults.c12
-rw-r--r--VNFs/DPPD-PROX/defines.h9
-rw-r--r--VNFs/DPPD-PROX/handle_gen.c158
-rw-r--r--VNFs/DPPD-PROX/handle_master.c590
-rw-r--r--VNFs/DPPD-PROX/handle_master.h91
-rw-r--r--VNFs/DPPD-PROX/handle_routing.c1
-rw-r--r--VNFs/DPPD-PROX/handle_swap.c70
-rw-r--r--VNFs/DPPD-PROX/ip6_addr.h4
-rw-r--r--VNFs/DPPD-PROX/lconf.c16
-rw-r--r--VNFs/DPPD-PROX/main.c52
-rw-r--r--VNFs/DPPD-PROX/packet_utils.c461
-rw-r--r--VNFs/DPPD-PROX/packet_utils.h31
-rw-r--r--VNFs/DPPD-PROX/parse_utils.c6
-rw-r--r--VNFs/DPPD-PROX/prox_args.c59
-rw-r--r--VNFs/DPPD-PROX/prox_cfg.h14
-rw-r--r--VNFs/DPPD-PROX/prox_cksum.h10
-rw-r--r--VNFs/DPPD-PROX/prox_compat.c30
-rw-r--r--VNFs/DPPD-PROX/prox_compat.h13
-rw-r--r--VNFs/DPPD-PROX/prox_ipv6.c302
-rw-r--r--VNFs/DPPD-PROX/prox_ipv6.h140
-rw-r--r--VNFs/DPPD-PROX/prox_port_cfg.c2
-rw-r--r--VNFs/DPPD-PROX/prox_shared.c6
-rw-r--r--VNFs/DPPD-PROX/rx_pkt.c97
-rw-r--r--VNFs/DPPD-PROX/rx_pkt.h8
-rw-r--r--VNFs/DPPD-PROX/task_base.h4
-rw-r--r--VNFs/DPPD-PROX/task_init.c23
-rw-r--r--VNFs/DPPD-PROX/task_init.h11
-rw-r--r--VNFs/DPPD-PROX/tx_pkt.c177
-rw-r--r--VNFs/DPPD-PROX/tx_pkt.h121
33 files changed, 2215 insertions, 420 deletions
diff --git a/VNFs/DPPD-PROX/Makefile b/VNFs/DPPD-PROX/Makefile
index f8bde42..ff75c17 100644
--- a/VNFs/DPPD-PROX/Makefile
+++ b/VNFs/DPPD-PROX/Makefile
@@ -213,7 +213,7 @@ SRCS-y += stats_port.c stats_mempool.c stats_ring.c stats_l4gen.c
SRCS-y += stats_latency.c stats_global.c stats_core.c stats_task.c stats_prio.c stats_irq.c
SRCS-y += cmd_parser.c input.c prox_shared.c prox_lua_types.c
SRCS-y += genl4_bundle.c heap.c genl4_stream_tcp.c genl4_stream_udp.c cdf.c
-SRCS-y += stats.c stats_cons_log.c stats_cons_cli.c stats_parser.c hash_set.c prox_lua.c prox_malloc.c
+SRCS-y += stats.c stats_cons_log.c stats_cons_cli.c stats_parser.c hash_set.c prox_lua.c prox_malloc.c prox_ipv6.c prox_compat.c
ifeq ($(FIRST_PROX_MAKE),)
MAKEFLAGS += --no-print-directory
diff --git a/VNFs/DPPD-PROX/cmd_parser.c b/VNFs/DPPD-PROX/cmd_parser.c
index 8c72f7b..2d3b570 100644
--- a/VNFs/DPPD-PROX/cmd_parser.c
+++ b/VNFs/DPPD-PROX/cmd_parser.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2019 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -384,7 +384,7 @@ static int parse_cmd_count(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
else {
@@ -413,7 +413,7 @@ static int parse_cmd_set_probability(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "impair", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "impair", "l3"))){
+ if (!task_is_mode(lcore_id, task_id, "impair")) {
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
} else {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
@@ -438,7 +438,7 @@ static int parse_cmd_delay_us(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "impair", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "impair", "l3"))){
+ if (!task_is_mode(lcore_id, task_id, "impair")) {
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
} else {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
@@ -463,7 +463,7 @@ static int parse_cmd_random_delay_us(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "impair", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "impair", "l3"))){
+ if (!task_is_mode(lcore_id, task_id, "impair")) {
plog_err("Core %u task %u is not impairing packets\n", lcore_id, task_id);
} else {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
@@ -525,7 +525,7 @@ static int parse_cmd_pkt_size(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
} else {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
@@ -597,7 +597,7 @@ static int parse_cmd_speed(const char *str, struct input *input)
for (i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
else if (speed > 1000.0f || speed < 0.0f) { // Up to 100 Gbps
@@ -631,7 +631,7 @@ static int parse_cmd_speed_byte(const char *str, struct input *input)
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
else if (bps > 12500000000) { // Up to 100Gbps
@@ -657,7 +657,7 @@ static int parse_cmd_reset_randoms_all(const char *str, struct input *input)
unsigned task_id, lcore_id = -1;
while (prox_core_next(&lcore_id, 0) == 0) {
for (task_id = 0; task_id < lcore_cfg[lcore_id].n_tasks_all; task_id++) {
- if ((task_is_mode_and_submode(lcore_id, task_id, "gen", "")) || (task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
uint32_t n_rands = task_gen_get_n_randoms(tbase);
@@ -678,7 +678,7 @@ static int parse_cmd_reset_values_all(const char *str, struct input *input)
unsigned task_id, lcore_id = -1;
while (prox_core_next(&lcore_id, 0) == 0) {
for (task_id = 0; task_id < lcore_cfg[lcore_id].n_tasks_all; task_id++) {
- if ((task_is_mode_and_submode(lcore_id, task_id, "gen", "")) || (task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
plog_info("Resetting values on core %d task %d\n", lcore_id, task_id);
@@ -699,7 +699,7 @@ static int parse_cmd_reset_values(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
else {
@@ -730,7 +730,7 @@ static int parse_cmd_set_value(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
// do not check offset here - gen knows better than us the maximum frame size
@@ -769,7 +769,7 @@ static int parse_cmd_set_random(const char *str, struct input *input)
if (cores_task_are_valid(lcores, task_id, nb_cores)) {
for (unsigned int i = 0; i < nb_cores; i++) {
lcore_id = lcores[i];
- if ((!task_is_mode_and_submode(lcore_id, task_id, "gen", "")) && (!task_is_mode_and_submode(lcore_id, task_id, "gen", "l3"))) {
+ if (!task_is_mode(lcore_id, task_id, "gen")) {
plog_err("Core %u task %u is not generating packets\n", lcore_id, task_id);
}
else if (offset > PROX_RTE_ETHER_MAX_LEN) {
diff --git a/VNFs/DPPD-PROX/commands.c b/VNFs/DPPD-PROX/commands.c
index df5e69c..32b974c 100644
--- a/VNFs/DPPD-PROX/commands.c
+++ b/VNFs/DPPD-PROX/commands.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -114,7 +114,7 @@ static inline void start_l3(struct task_args *targ)
{
if (!task_is_master(targ)) {
if ((targ->nb_txrings != 0) || (targ->nb_txports != 0)) {
- if (targ->flags & TASK_ARG_L3)
+ if (targ->flags & (TASK_ARG_L3|TASK_ARG_NDP))
task_start_l3(targ->tbase, targ);
}
}
diff --git a/VNFs/DPPD-PROX/config/ipv6.cfg b/VNFs/DPPD-PROX/config/ipv6.cfg
new file mode 100644
index 0000000..6ad4725
--- /dev/null
+++ b/VNFs/DPPD-PROX/config/ipv6.cfg
@@ -0,0 +1,85 @@
+;;
+;; Copyright (c) 2020 Intel Corporation
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+
+[eal options]
+-n=6 ; force number of memory channels
+no-output=no ; disable DPDK debug output
+
+[port 0]
+name=p0
+
+[port 2]
+name=p1
+
+[defaults]
+mempool size=8K
+
+[global]
+start time=5
+name=Basic IPv6
+
+[variables]
+$loc_gen_hex_ip1=fe 80 00 00 00 00 00 00 00 00 00 00 00 00 00 01
+$loc_swp_hex_ip1=fe 80 00 00 00 00 00 00 00 00 00 00 00 00 00 02
+$glob_gen_hex_ip1=20 01 db 80 00 00 00 00 00 00 00 00 00 00 00 01
+$glob_swp_hex_ip1=20 01 db 80 00 00 00 00 00 00 00 00 00 00 00 02
+$loc_gen_ip1=fe80::0001
+$glob_gen_ip1=2001:db80::0001
+$loc_swp_ip1=fe80::0002
+$glob_swp_ip1=2001:db80::0002
+
+[core 0s0]
+mode=master
+
+; 84 bytes packet to include latency related data.
+; for 64 bytes packets, comment out lat pos, packet id pos, signature pos, accuracy pos; set pkt size to 60 and
+; set payload & udp length to 8 (bytes 19 and 59 changed from 1a to 08)
+[core 1s0]
+name=TX0
+task=0
+mode=gen
+sub mode=ndp
+local ipv6=${loc_gen_ip1}
+global ipv6=${glob_gen_ip1}
+tx port=p0
+bps=1000
+pkt inline=00 00 01 00 00 01 00 00 02 00 00 02 86 dd 60 00 00 00 00 1a 11 40 ${glob_gen_hex_ip1} ${glob_swp_hex_ip1} 13 88 13 88 00 1a 55 7b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+lat pos=62
+packet id pos=66
+signature pos=72
+accuracy pos=76
+pkt size=80
+
+task=1
+mode=lat
+sub mode=ndp
+rx port=p0
+local ipv6=${loc_gen_ip1}
+global ipv6=${glob_gen_ip1}
+lat pos=62
+packet id pos=66
+signature pos=72
+accuracy pos=76
+
+[core 2s0]
+name=SWAP
+task=0
+mode=swap
+sub mode=ndp
+rx port=p1
+tx port=p1
+local ipv6=${loc_swp_ip1}
+global ipv6=${glob_swp_ip1}
diff --git a/VNFs/DPPD-PROX/defaults.c b/VNFs/DPPD-PROX/defaults.c
index bb359cf..ac611d0 100644
--- a/VNFs/DPPD-PROX/defaults.c
+++ b/VNFs/DPPD-PROX/defaults.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <libgen.h>
#include <rte_sched.h>
+#include <rte_ether.h>
#include <rte_version.h>
#include "lconf.h"
@@ -28,6 +29,7 @@
#include "toeplitz.h"
#include "handle_master.h"
#include "prox_compat.h"
+#include "prox_ipv6.h"
#define TEN_GIGABIT 1250000000
#define QUEUE_SIZES 128
@@ -115,8 +117,16 @@ static struct rte_sched_subport_params subport_params_default = {
#endif
};
-void set_global_defaults(__attribute__((unused)) struct prox_cfg *prox_cfg)
+void set_global_defaults(struct prox_cfg *prox_cfg)
{
+ if (parse_ip6(&prox_cfg->all_routers_ipv6_mcast_addr, ALL_ROUTERS_IPV6_MCAST_ADDR) != 0)
+ plog_err("Failed to parse %s\n", ALL_ROUTERS_IPV6_MCAST_ADDR);
+ if (parse_ip6(&prox_cfg->all_nodes_ipv6_mcast_addr, ALL_NODES_IPV6_MCAST_ADDR) != 0)
+ plog_err("Failed to parse %s\n", ALL_NODES_IPV6_MCAST_ADDR);
+ if (parse_ip6(&prox_cfg->random_ip, RANDOM_IPV6) != 0)
+ plog_err("Failed to parse %s\n", RANDOM_IPV6);
+ set_mcast_mac_from_ipv6(&prox_cfg->all_routers_mac_addr, &prox_cfg->all_routers_ipv6_mcast_addr);
+ set_mcast_mac_from_ipv6(&prox_cfg->all_nodes_mac_addr, &prox_cfg->all_nodes_ipv6_mcast_addr);
}
void set_task_defaults(struct prox_cfg* prox_cfg, struct lcore_cfg* lcore_cfg_init)
diff --git a/VNFs/DPPD-PROX/defines.h b/VNFs/DPPD-PROX/defines.h
index c2309be..3be1a96 100644
--- a/VNFs/DPPD-PROX/defines.h
+++ b/VNFs/DPPD-PROX/defines.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -42,6 +42,13 @@
addr[12], addr[13], addr[14], addr[15]
#endif
+#ifndef IPv6_PREFIX
+#define IPv6_PREFIX_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+#define IPv6_PREFIX(addr) \
+ addr[0], addr[1], addr[2], addr[3], \
+ addr[4], addr[5], addr[6], addr[7]
+#endif
+
#ifndef MAC_BYTES
#define MAC_BYTES_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
diff --git a/VNFs/DPPD-PROX/handle_gen.c b/VNFs/DPPD-PROX/handle_gen.c
index 1546dce..ac75f22 100644
--- a/VNFs/DPPD-PROX/handle_gen.c
+++ b/VNFs/DPPD-PROX/handle_gen.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -47,6 +47,8 @@
#include "arp.h"
#include "tx_pkt.h"
#include "handle_master.h"
+#include "defines.h"
+#include "prox_ipv6.h"
struct pkt_template {
uint16_t len;
@@ -172,11 +174,11 @@ static void parse_l2_l3_len(uint8_t *pkt, uint16_t *l2_len, uint16_t *l3_len, ui
case ETYPE_MPLSM:
*l2_len +=4;
break;
+ case ETYPE_IPv6:
case ETYPE_IPv4:
break;
case ETYPE_EoGRE:
case ETYPE_ARP:
- case ETYPE_IPv6:
*l2_len = 0;
break;
default:
@@ -187,7 +189,8 @@ static void parse_l2_l3_len(uint8_t *pkt, uint16_t *l2_len, uint16_t *l3_len, ui
if (*l2_len) {
prox_rte_ipv4_hdr *ip = (prox_rte_ipv4_hdr *)(pkt + *l2_len);
- *l3_len = ipv4_get_hdr_len(ip);
+ if (ip->version_ihl >> 4 == 4)
+ *l3_len = ipv4_get_hdr_len(ip);
}
}
@@ -196,9 +199,20 @@ static void checksum_packet(uint8_t *hdr, struct rte_mbuf *mbuf, struct pkt_temp
uint16_t l2_len = pkt_template->l2_len;
uint16_t l3_len = pkt_template->l3_len;
- if (l2_len) {
- prox_rte_ipv4_hdr *ip = (prox_rte_ipv4_hdr*)(hdr + l2_len);
+ prox_rte_ipv4_hdr *ip = (prox_rte_ipv4_hdr*)(hdr + l2_len);
+ if (l3_len) {
prox_ip_udp_cksum(mbuf, ip, l2_len, l3_len, cksum_offload);
+ } else if (ip->version_ihl >> 4 == 6) {
+ prox_rte_ipv6_hdr *ip6 = (prox_rte_ipv6_hdr *)(hdr + l2_len);
+ if (ip6->proto == IPPROTO_UDP) {
+ prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(ip6 + 1);
+ udp->dgram_cksum = 0;
+ udp->dgram_cksum = rte_ipv6_udptcp_cksum(ip6, udp);
+ } else if (ip6->proto == IPPROTO_TCP) {
+ prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(ip6 + 1);
+ tcp->cksum = 0;
+ tcp->cksum = rte_ipv6_udptcp_cksum(ip6, tcp);
+ }
}
}
@@ -758,23 +772,45 @@ static inline void build_value(struct task_gen *task, uint32_t mask, int bit_pos
register_ip_to_ctrl_plane(tbase->l3.tmaster, rte_cpu_to_be_32(val | fixed_bits), tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
}
}
+
+static inline void build_value_ipv6(struct task_gen *task, uint32_t mask, int var_bit_pos, int init_var_bit_pos, struct ipv6_addr val, struct ipv6_addr fixed_bits)
+{
+ struct task_base *tbase = (struct task_base *)task;
+ if (var_bit_pos < 32) {
+ build_value_ipv6(task, mask >> 1, var_bit_pos + 1, init_var_bit_pos, val, fixed_bits);
+ if (mask & 1) {
+ int byte_pos = (var_bit_pos + init_var_bit_pos) / 8;
+ int bit_pos = (var_bit_pos + init_var_bit_pos) % 8;
+ val.bytes[byte_pos] = val.bytes[byte_pos] | (1 << bit_pos);
+ build_value_ipv6(task, mask >> 1, var_bit_pos + 1, init_var_bit_pos, val, fixed_bits);
+ }
+ } else {
+ for (uint i = 0; i < sizeof(struct ipv6_addr) / 8; i++)
+ val.bytes[i] = val.bytes[i] | fixed_bits.bytes[i];
+ register_node_to_ctrl_plane(tbase->l3.tmaster, &null_addr, &val, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
+ }
+}
+
static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
{
struct task_base *tbase = (struct task_base *)task;
int i, len, fixed;
unsigned int offset;
- uint32_t mask;
+ uint32_t mask, ip_len;
+ struct ipv6_addr *ip6_src = NULL;
+ uint32_t *ip_src;
for (uint32_t i = 0; i < task->n_pkts; ++i) {
struct pkt_template *pktpl = &task->pkt_template[i];
unsigned int ip_src_pos = 0;
- int maybe_ipv4 = 0;
+ int ipv4 = 0;
unsigned int l2_len = sizeof(prox_rte_ether_hdr);
uint8_t *pkt = pktpl->buf;
prox_rte_ether_hdr *eth_hdr = (prox_rte_ether_hdr*)pkt;
uint16_t ether_type = eth_hdr->ether_type;
prox_rte_vlan_hdr *vlan_hdr;
+ prox_rte_ipv4_hdr *ip;
// Unstack VLAN tags
while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(prox_rte_vlan_hdr) < pktpl->len)) {
@@ -784,19 +820,38 @@ static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
}
if ((ether_type == ETYPE_MPLSU) || (ether_type == ETYPE_MPLSM)) {
l2_len +=4;
- maybe_ipv4 = 1;
- }
- if ((ether_type != ETYPE_IPv4) && !maybe_ipv4)
+ ip = (prox_rte_ipv4_hdr *)(pkt + l2_len);
+ if (ip->version_ihl >> 4 == 4)
+ ipv4 = 1;
+ else if (ip->version_ihl >> 4 != 6) // Version field at same location for IPv4 and IPv6
+ continue;
+ } else if (ether_type == ETYPE_IPv4) {
+ ip = (prox_rte_ipv4_hdr *)(pkt + l2_len);
+ PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4); // Invalid Packet
+ ipv4 = 1;
+ } else if (ether_type == ETYPE_IPv6) {
+ ip = (prox_rte_ipv4_hdr *)(pkt + l2_len);
+ PROX_PANIC(ip->version_ihl >> 4 != 6, "IPv6 ether_type but IP version = %d != 6", ip->version_ihl >> 4); // Invalid Packet
+ } else {
continue;
+ }
- prox_rte_ipv4_hdr *ip = (prox_rte_ipv4_hdr *)(pkt + l2_len);
- PROX_PANIC(ip->version_ihl >> 4 != 4, "IPv4 ether_type but IP version = %d != 4", ip->version_ihl >> 4);
-
- // Even if IPv4 header contains options, options are after ip src and dst
- ip_src_pos = l2_len + sizeof(prox_rte_ipv4_hdr) - 2 * sizeof(uint32_t);
- uint32_t *ip_src = ((uint32_t *)(pktpl->buf + ip_src_pos));
- plog_info("\tip_src_pos = %d, ip_src = %x\n", ip_src_pos, *ip_src);
- register_ip_to_ctrl_plane(tbase->l3.tmaster, *ip_src, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
+ PROX_PANIC(ipv4 && ((prox_cfg.flags & DSF_L3_ENABLED) == 0), "Trying to generate an IPv4 packet in NDP mode => not supported\n");
+ PROX_PANIC((ipv4 == 0) && ((prox_cfg.flags & DSF_NDP_ENABLED) == 0), "Trying to generate an IPv6 packet in L3 (IPv4) mode => not supported\n");
+ if (ipv4) {
+ // Even if IPv4 header contains options, options are after ip src and dst
+ ip_src_pos = l2_len + sizeof(prox_rte_ipv4_hdr) - 2 * sizeof(uint32_t);
+ ip_src = ((uint32_t *)(pktpl->buf + ip_src_pos));
+ plog_info("\tip_src_pos = %d, ip_src = %x\n", ip_src_pos, *ip_src);
+ register_ip_to_ctrl_plane(tbase->l3.tmaster, *ip_src, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
+ ip_len = sizeof(uint32_t);
+ } else {
+ ip_src_pos = l2_len + sizeof(prox_rte_ipv6_hdr) - 2 * sizeof(struct ipv6_addr);
+ ip6_src = ((struct ipv6_addr *)(pktpl->buf + ip_src_pos));
+ plog_info("\tip_src_pos = %d, ip6_src = "IPv6_BYTES_FMT"\n", ip_src_pos, IPv6_BYTES(ip6_src->bytes));
+ register_node_to_ctrl_plane(tbase->l3.tmaster, ip6_src, &null_addr, tbase->l3.reachable_port_id, tbase->l3.core_id, tbase->l3.task_id);
+ ip_len = sizeof(struct ipv6_addr);
+ }
for (int j = 0; j < task->n_rands; j++) {
offset = task->rand[j].rand_offset;
@@ -804,7 +859,12 @@ static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
mask = task->rand[j].rand_mask;
fixed = task->rand[j].fixed_bits;
plog_info("offset = %d, len = %d, mask = %x, fixed = %x\n", offset, len, mask, fixed);
- if ((offset < ip_src_pos + 4) && (offset + len >= ip_src_pos)) {
+ if (offset >= ip_src_pos + ip_len) // First random bit after IP
+ continue;
+ if (offset + len < ip_src_pos) // Last random bit before IP
+ continue;
+
+ if (ipv4) {
if (offset >= ip_src_pos) {
int32_t ip_src_mask = (1 << (4 + ip_src_pos - offset) * 8) - 1;
mask = mask & ip_src_mask;
@@ -816,6 +876,28 @@ static inline void register_all_ip_to_ctrl_plane(struct task_gen *task)
fixed = (fixed << bits) | (rte_be_to_cpu_32(*ip_src) & ((1 << bits) - 1));
build_value(task, mask, 0, 0, fixed);
}
+ } else {
+ // We do not support when random partially covers IP - either starting before or finishing after
+ if (offset + len >= ip_src_pos + ip_len) { // len over the ip
+ plog_err("Not supported: random_offset = %d, random_len = %d, ip_src_pos = %d, ip_len = %d\n", offset, len, ip_src_pos, ip_len);
+ continue;
+ }
+ if (offset < ip_src_pos) {
+ plog_err("Not supported: random_offset = %d, random_len = %d, ip_src_pos = %d, ip_len = %d\n", offset, len, ip_src_pos, ip_len);
+ continue;
+ }
+ // Even for IPv6 the random mask supported by PROX are 32 bits only
+ struct ipv6_addr fixed_ipv6;
+ uint init_var_byte_pos = (offset - ip_src_pos);
+ for (uint i = 0; i < sizeof(struct ipv6_addr); i++) {
+ if (i < init_var_byte_pos)
+ fixed_ipv6.bytes[i] = ip6_src->bytes[i];
+ else if (i < init_var_byte_pos + len)
+ fixed_ipv6.bytes[i] = (fixed >> (i - init_var_byte_pos)) & 0xFF;
+ else
+ fixed_ipv6.bytes[i] = ip6_src->bytes[i];
+ }
+ build_value_ipv6(task, mask, 0, init_var_byte_pos * 8, null_addr, fixed_ipv6);
}
}
}
@@ -999,17 +1081,29 @@ static void task_gen_pkt_template_recalc_checksum(struct task_gen *task)
if (template->l2_len == 0)
continue;
ip = (prox_rte_ipv4_hdr *)(template->buf + template->l2_len);
-
- ip->hdr_checksum = 0;
- prox_ip_cksum_sw(ip);
- uint32_t l4_len = rte_bswap16(ip->total_length) - template->l3_len;
-
- if (ip->next_proto_id == IPPROTO_UDP) {
- prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(((uint8_t *)ip) + template->l3_len);
- prox_udp_cksum_sw(udp, l4_len, ip->src_addr, ip->dst_addr);
- } else if (ip->next_proto_id == IPPROTO_TCP) {
- prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(((uint8_t *)ip) + template->l3_len);
- prox_tcp_cksum_sw(tcp, l4_len, ip->src_addr, ip->dst_addr);
+ if (ip->version_ihl >> 4 == 4) {
+ ip->hdr_checksum = 0;
+ prox_ip_cksum_sw(ip);
+ uint32_t l4_len = rte_bswap16(ip->total_length) - template->l3_len;
+ if (ip->next_proto_id == IPPROTO_UDP) {
+ prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(((uint8_t *)ip) + template->l3_len);
+ prox_udp_cksum_sw(udp, l4_len, ip->src_addr, ip->dst_addr);
+ } else if (ip->next_proto_id == IPPROTO_TCP) {
+ prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(((uint8_t *)ip) + template->l3_len);
+ prox_tcp_cksum_sw(tcp, l4_len, ip->src_addr, ip->dst_addr);
+ }
+ } else if (ip->version_ihl >> 4 == 6) {
+ prox_rte_ipv6_hdr *ip6;
+ ip6 = (prox_rte_ipv6_hdr *)(template->buf + template->l2_len);
+ if (ip6->proto == IPPROTO_UDP) {
+ prox_rte_udp_hdr *udp = (prox_rte_udp_hdr *)(ip6 + 1);
+ udp->dgram_cksum = 0;
+ udp->dgram_cksum = rte_ipv6_udptcp_cksum(ip6, udp);
+ } else if (ip6->proto == IPPROTO_TCP) {
+ prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(ip6 + 1);
+ tcp->cksum = 0;
+ tcp->cksum = rte_ipv6_udptcp_cksum(ip6, tcp);
+ }
}
/* The current implementation avoids checksum
@@ -1130,7 +1224,7 @@ static struct rte_mempool *task_gen_create_mempool(struct task_args *targ, uint1
uint32_t mbuf_size = TX_MBUF_SIZE;
if (max_frame_size + (unsigned)sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM > mbuf_size)
mbuf_size = max_frame_size + (unsigned)sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
- plog_info("\t\tCreating mempool with name '%s'\n", name);
+ plog_info("\tCreating mempool with name '%s'\n", name);
ret = rte_mempool_create(name, targ->nb_mbuf - 1, mbuf_size,
targ->nb_cache_mbuf, sizeof(struct rte_pktmbuf_pool_private),
rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, 0,
@@ -1138,7 +1232,7 @@ static struct rte_mempool *task_gen_create_mempool(struct task_args *targ, uint1
PROX_PANIC(ret == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
sock_id, targ->nb_mbuf - 1);
- plog_info("\t\tMempool %p size = %u * %u cache %u, socket %d\n", ret,
+ plog_info("\tMempool %p size = %u * %u cache %u, socket %d\n", ret,
targ->nb_mbuf - 1, mbuf_size, targ->nb_cache_mbuf, sock_id);
return ret;
diff --git a/VNFs/DPPD-PROX/handle_master.c b/VNFs/DPPD-PROX/handle_master.c
index ce5c0bc..a528a68 100644
--- a/VNFs/DPPD-PROX/handle_master.c
+++ b/VNFs/DPPD-PROX/handle_master.c
@@ -19,7 +19,6 @@
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
-#include <poll.h>
#include <net/if.h>
#include <rte_hash.h>
@@ -44,6 +43,8 @@
#include "input.h"
#include "tx_pkt.h"
#include "defines.h"
+#include "prox_ipv6.h"
+#include "packet_utils.h"
#define PROX_MAX_ARP_REQUESTS 32 // Maximum number of tasks requesting the same MAC address
#define NETLINK_BUF_SIZE 16384
@@ -51,18 +52,24 @@
static char netlink_buf[NETLINK_BUF_SIZE];
const char *actions_string[] = {
- "UPDATE_FROM_CTRL", // Controlplane sending a MAC update to dataplane
- "ROUTE_ADD_FROM_CTRL", // Controlplane sending a new route to dataplane
- "ROUTE_DEL_FROM_CTRL", // Controlplane deleting a new route from dataplane
- "SEND_ARP_REQUEST_FROM_CTRL", // Controlplane requesting dataplane to send ARP request
- "SEND_ARP_REPLY_FROM_CTRL", // Controlplane requesting dataplane to send ARP reply
- "SEND_ICMP_FROM_CTRL", // Controlplane requesting dataplane to send ICMP message
- "SEND_BGP_FROM_CTRL", // Controlplane requesting dataplane to send BGP message
- "ARP_TO_CTRL", // ARP sent by datplane to Controlpane for handling
- "ICMP_TO_CTRL", // ICMP sent by datplane to Controlpane for handling
- "BGP_TO_CTRL", // BGP sent by datplane to Controlpane for handling
- "REQ_MAC_TO_CTRL", // Dataplane requesting MAC resolution to Controlplane
+ "MAC_INFO_FROM_MASTER", // Controlplane sending a MAC update to dataplane
+ "MAC_INFO_FROM_MASTER_FOR_IPV6",// Controlplane sending a MAC update to dataplane
+ "IPV6_INFO_FROM_MASTER", // Controlplane IPv6 Global IP info to dataplane
+ "ROUTE_ADD_FROM_MASTER", // Controlplane sending a new route to dataplane
+ "ROUTE_DEL_FROM_MASTER", // Controlplane deleting a new route from dataplane
+ "SEND_ARP_REQUEST_FROM_MASTER", // Controlplane requesting dataplane to send ARP request
+ "SEND_ARP_REPLY_FROM_MASTER", // Controlplane requesting dataplane to send ARP reply
+ "SEND_NDP_FROM_MASTER", // Controlplane requesting dataplane to send NDP
+ "SEND_ICMP_FROM_MASTER", // Controlplane requesting dataplane to send ICMP message
+ "SEND_BGP_FROM_MASTER", // Controlplane requesting dataplane to send BGP message
+ "ARP_PKT_FROM_NET_TO_MASTER", // ARP sent by datplane to Controlpane for handling
+ "NDP_PKT_FROM_NET_TO_MASTER," // NDP sent by datplane to Controlpane for handling
+ "ICMP_TO_MASTER", // ICMP sent by datplane to Controlpane for handling
+ "BGP_TO_MASTER" // BGP sent by datplane to Controlpane for handling
+ "IP4_REQ_MAC_TO_MASTER", // Dataplane requesting MAC resolution to Controlplane
+ "IP6_REQ_MAC_TO_MASTER", // Dataplane requesting MAC resolution to Controlplane
"PKT_FROM_TAP" // Packet received by Controlplane from kernel and forwarded to dataplane for sending
+
};
static struct my_arp_t arp_reply = {
@@ -80,68 +87,64 @@ static struct my_arp_t arp_request = {
.oper = 0x100
};
-struct ip_table {
- prox_rte_ether_addr mac;
- struct rte_ring *ring;
-};
-
-struct external_ip_table {
- prox_rte_ether_addr mac;
- struct rte_ring *rings[PROX_MAX_ARP_REQUESTS];
- uint16_t nb_requests;
-};
-
-struct port_table {
- prox_rte_ether_addr mac;
- struct rte_ring *ring;
- uint32_t ip;
- uint8_t port;
- uint8_t flags;
- uint64_t last_echo_req_rcvd_tsc;
- uint64_t last_echo_rep_rcvd_tsc;
- uint32_t n_echo_req;
- uint32_t n_echo_rep;
-};
-
-struct task_master {
- struct task_base base;
- struct rte_ring *ctrl_rx_ring;
- struct rte_ring **ctrl_tx_rings;
- struct ip_table *internal_ip_table;
- struct external_ip_table *external_ip_table;
- struct rte_hash *external_ip_hash;
- struct rte_hash *internal_ip_hash;
- struct port_table internal_port_table[PROX_MAX_PORTS];
- struct vdev all_vdev[PROX_MAX_PORTS];
- int max_vdev_id;
- struct pollfd arp_fds;
- struct pollfd route_fds;
-};
-
struct ip_port {
uint32_t ip;
uint8_t port;
} __attribute__((packed));
-static inline uint8_t get_command(struct rte_mbuf *mbuf)
-{
- return mbuf->udata64 & 0xFF;
-}
-static inline uint8_t get_task(struct rte_mbuf *mbuf)
-{
- return (mbuf->udata64 >> 8) & 0xFF;
-}
-static inline uint8_t get_core(struct rte_mbuf *mbuf)
-{
- return (mbuf->udata64 >> 16) & 0xFF;
-}
-static inline uint8_t get_port(struct rte_mbuf *mbuf)
+struct ip6_port {
+ struct ipv6_addr ip6;
+ uint8_t port;
+} __attribute__((packed));
+
+void register_router_to_ctrl_plane(struct task_base *tbase, uint8_t port_id, uint8_t core_id, uint8_t task_id, struct ipv6_addr *local_ipv6_addr, struct ipv6_addr *global_ipv6_addr, struct ipv6_addr *router_prefix)
{
- return mbuf->port;
+ struct task_master *task = (struct task_master *)tbase;
+ task->internal_port_table[port_id].flags |= IPV6_ROUTER;
+ memcpy(&task->internal_port_table[port_id].router_prefix, router_prefix, sizeof(struct ipv6_addr));
+ register_node_to_ctrl_plane(tbase, local_ipv6_addr, global_ipv6_addr, port_id, core_id, task_id);
}
-static inline uint32_t get_ip(struct rte_mbuf *mbuf)
+
+void register_node_to_ctrl_plane(struct task_base *tbase, struct ipv6_addr *local_ipv6_addr, struct ipv6_addr *global_ipv6_addr, uint8_t port_id, uint8_t core_id, uint8_t task_id)
{
- return (mbuf->udata64 >> 32) & 0xFFFFFFFF;
+ struct task_master *task = (struct task_master *)tbase;
+ if (task->internal_port_table[port_id].flags & IPV6_ROUTER)
+ plogx_dbg("\tregistering router with port %d core %d and task %d\n", port_id, core_id, task_id);
+ else
+ plogx_dbg("\tregistering node with port %d core %d and task %d\n", port_id, core_id, task_id);
+
+ if (port_id >= PROX_MAX_PORTS) {
+ plog_err("Unable to register router, port %d\n", port_id);
+ return;
+ }
+ task->internal_port_table[port_id].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
+ memcpy(&task->internal_port_table[port_id].mac, &prox_port_cfg[port_id].eth_addr, sizeof(prox_rte_ether_addr));
+ memcpy(&task->internal_port_table[port_id].local_ipv6_addr, local_ipv6_addr, sizeof(struct ipv6_addr));
+ if (memcmp(local_ipv6_addr, &prox_cfg.random_ip, sizeof(struct ipv6_addr)) == 0) {
+ task->internal_port_table[port_id].flags |= HANDLE_RANDOM_LOCAL_IP_FLAG;
+ return;
+ }
+ memcpy(&task->internal_port_table[port_id].global_ipv6_addr, global_ipv6_addr, sizeof(struct ipv6_addr));
+ if (memcmp(global_ipv6_addr, &prox_cfg.random_ip, sizeof(struct ipv6_addr)) == 0) {
+ task->internal_port_table[port_id].flags |= HANDLE_RANDOM_GLOBAL_IP_FLAG;
+ return;
+ }
+ struct ip6_port key;
+ memcpy(&key.ip6, local_ipv6_addr, sizeof(struct ipv6_addr));
+ key.port = port_id;
+ int ret = rte_hash_add_key(task->internal_ip6_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ plog_err("Unable to register ip "IPv6_BYTES_FMT"\n", IPv6_BYTES(local_ipv6_addr->bytes));
+ return;
+ }
+ memcpy(&key.ip6, global_ipv6_addr, sizeof(struct ipv6_addr));
+ ret = rte_hash_add_key(task->internal_ip6_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ plog_err("Unable to register ip "IPv6_BYTES_FMT"\n", IPv6_BYTES(global_ipv6_addr->bytes));
+ return;
+ }
+ memcpy(&task->internal_ip6_table[ret].mac, &prox_port_cfg[port_id].eth_addr, sizeof(prox_rte_ether_addr));
+ task->internal_ip6_table[ret].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
}
void master_init_vdev(struct task_base *tbase, uint8_t port_id, uint8_t core_id, uint8_t task_id)
@@ -188,7 +191,7 @@ void register_ip_to_ctrl_plane(struct task_base *tbase, uint32_t ip, uint8_t por
return;
}
- /* TODO - stoe multiple rings if multiple cores able to handle IP
+ /* TODO - store multiple rings if multiple cores able to handle IP
Remove them when such cores are stopped and de-register IP
*/
task->internal_port_table[port_id].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
@@ -209,7 +212,6 @@ void register_ip_to_ctrl_plane(struct task_base *tbase, uint32_t ip, uint8_t por
}
memcpy(&task->internal_ip_table[ret].mac, &prox_port_cfg[port_id].eth_addr, sizeof(prox_rte_ether_addr));
task->internal_ip_table[ret].ring = task->ctrl_tx_rings[core_id * MAX_TASKS_PER_CORE + task_id];
-
}
static inline void handle_arp_reply(struct task_base *tbase, struct rte_mbuf *mbuf)
@@ -232,7 +234,7 @@ static inline void handle_arp_reply(struct task_base *tbase, struct rte_mbuf *mb
rte_mbuf_refcnt_set(mbuf, nb_requests);
for (int i = 0; i < nb_requests; i++) {
struct rte_ring *ring = task->external_ip_table[ret].rings[i];
- tx_ring_ip(tbase, ring, UPDATE_FROM_CTRL, mbuf, key);
+ tx_ring_ip(tbase, ring, MAC_INFO_FROM_MASTER, mbuf, key);
}
task->external_ip_table[ret].nb_requests = 0;
} else {
@@ -258,7 +260,7 @@ static inline void handle_arp_request(struct task_base *tbase, struct rte_mbuf *
create_mac(hdr_arp, &mac);
mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
build_arp_reply(hdr_arp, &mac);
- tx_ring(tbase, ring, ARP_REPLY_FROM_CTRL, mbuf);
+ tx_ring(tbase, ring, SEND_ARP_REPLY_FROM_MASTER, mbuf);
return;
}
@@ -273,7 +275,7 @@ static inline void handle_arp_request(struct task_base *tbase, struct rte_mbuf *
struct rte_ring *ring = task->internal_ip_table[ret].ring;
mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
build_arp_reply(hdr_arp, &task->internal_ip_table[ret].mac);
- tx_ring(tbase, ring, ARP_REPLY_FROM_CTRL, mbuf);
+ tx_ring(tbase, ring, SEND_ARP_REPLY_FROM_MASTER, mbuf);
}
}
@@ -337,7 +339,7 @@ static inline void handle_unknown_ip(struct task_base *tbase, struct rte_mbuf *m
// We send an ARP request even if one was just sent (and not yet answered) by another task
mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
build_arp_request(mbuf, &task->internal_port_table[port].mac, ip_dst, ip_src);
- tx_ring(tbase, ring, ARP_REQ_FROM_CTRL, mbuf);
+ tx_ring(tbase, ring, SEND_ARP_REQUEST_FROM_MASTER, mbuf);
}
static inline void build_icmp_reply_message(struct task_base *tbase, struct rte_mbuf *mbuf)
@@ -365,7 +367,7 @@ static inline void build_icmp_reply_message(struct task_base *tbase, struct rte_
} else {
struct rte_ring *ring = task->internal_ip_table[ret].ring;
mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM);
- tx_ring(tbase, ring, ICMP_FROM_CTRL, mbuf);
+ tx_ring(tbase, ring, SEND_ICMP_FROM_MASTER, mbuf);
}
}
@@ -411,10 +413,306 @@ static inline void handle_icmp(struct task_base *tbase, struct rte_mbuf *mbuf)
return;
}
-static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf, int ring_id)
+static inline void handle_unknown_ip6(struct task_base *tbase, struct rte_mbuf *mbuf)
{
struct task_master *task = (struct task_master *)tbase;
struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ uint8_t port = get_port(mbuf);
+ struct ipv6_addr *ip_dst = ctrl_ring_get_ipv6_addr(mbuf);
+ int ret1, ret2, i;
+
+ plogx_dbg("\tMaster trying to find MAC of external IP "IPv6_BYTES_FMT" for port %d\n", IPv6_BYTES(ip_dst->bytes), port);
+ if (unlikely(port >= PROX_MAX_PORTS)) {
+ plogx_dbg("Port %d not found", port);
+ tx_drop(mbuf);
+ return;
+ }
+ struct ipv6_addr *local_ip_src = &task->internal_port_table[port].local_ipv6_addr;
+ struct ipv6_addr *global_ip_src = &task->internal_port_table[port].global_ipv6_addr;
+ struct ipv6_addr *ip_src;
+ if (memcmp(local_ip_src, ip_dst, 8) == 0)
+ ip_src = local_ip_src;
+ else if (memcmp(global_ip_src, &null_addr, 16))
+ ip_src = global_ip_src;
+ else {
+ plogx_dbg("Unable to find a src ip for dst ip "IPv6_BYTES_FMT"\n", IPv6_BYTES(ip_dst->bytes));
+ tx_drop(mbuf);
+ return;
+ }
+ struct rte_ring *ring = task->ctrl_tx_rings[get_core(mbuf) * MAX_TASKS_PER_CORE + get_task(mbuf)];
+
+ if (ring == NULL) {
+ plogx_dbg("Port %d not registered", port);
+ tx_drop(mbuf);
+ return;
+ }
+
+ ret2 = rte_hash_add_key(task->external_ip6_hash, (const void *)ip_dst);
+ if (unlikely(ret2 < 0)) {
+ plogx_dbg("Unable to add IP "IPv6_BYTES_FMT" in external_ip6_hash\n", IPv6_BYTES(ip_dst->bytes));
+ tx_drop(mbuf);
+ return;
+ }
+
+ // If multiple tasks requesting the same info, we will need to send a reply to all of them
+ // However if one task sends multiple requests to the same IP (e.g. because it is not answering)
+ // then we should not send multiple replies to the same task
+ if (task->external_ip6_table[ret2].nb_requests >= PROX_MAX_ARP_REQUESTS) {
+ // This can only happen if really many tasks requests the same IP
+ plogx_dbg("Unable to add request for IP "IPv6_BYTES_FMT" in external_ip6_table\n", IPv6_BYTES(ip_dst->bytes));
+ tx_drop(mbuf);
+ return;
+ }
+ for (i = 0; i < task->external_ip6_table[ret2].nb_requests; i++) {
+ if (task->external_ip6_table[ret2].rings[i] == ring)
+ break;
+ }
+ if (i >= task->external_ip6_table[ret2].nb_requests) {
+ // If this is a new request i.e. a new task requesting a new IP
+ task->external_ip6_table[ret2].rings[task->external_ip6_table[ret2].nb_requests] = ring;
+ task->external_ip6_table[ret2].nb_requests++;
+ // Only needed for first request - but avoid test and copy the same 6 bytes
+ // In most cases we will only have one request per IP.
+ //memcpy(&task->external_ip6_table[ret2].mac, &task->internal_port_table[port].mac, sizeof(prox_rte_ether_addr));
+ }
+
+ // As timers are not handled by master, we might send an NS request even if one was just sent
+ // (and not yet answered) by another task
+ build_neighbour_sollicitation(mbuf, &task->internal_port_table[port].mac, ip_dst, ip_src);
+ tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
+}
+
+static inline void handle_rs(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ int i, ret;
+ uint8_t port = get_port(mbuf);
+
+ if (task->internal_port_table[port].flags & IPV6_ROUTER) {
+ plogx_dbg("\tMaster handling Router Solicitation from ip "IPv6_BYTES_FMT" on port %d\n", IPv6_BYTES(ipv6_hdr->src_addr), port);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+ build_router_advertisement(mbuf, &prox_port_cfg[port].eth_addr, &task->internal_port_table[port].local_ipv6_addr, &task->internal_port_table[port].router_prefix);
+ tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
+ return;
+ }
+}
+
+static inline void handle_ra(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ int i, ret, send = 0;
+ uint8_t port = get_port(mbuf);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+
+ plog_dbg("Master handling Router Advertisement from ip "IPv6_BYTES_FMT" on port %d - len = %d; payload_len = %d\n", IPv6_BYTES(ipv6_hdr->src_addr), port, rte_pktmbuf_pkt_len(mbuf), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ if (rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr) > rte_pktmbuf_pkt_len(mbuf)) {
+ plog_err("Unexpected length received: pkt_len = %d, ipv6 hdr length = %ld, ipv6 payload len = %d\n", rte_pktmbuf_pkt_len(mbuf), sizeof(prox_rte_ipv6_hdr), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ tx_drop(mbuf);
+ return;
+ }
+ if (ring == NULL) {
+ plog_info("TX side not initialized yet => dropping\n");
+ tx_drop(mbuf);
+ return;
+ }
+ int16_t option_len = rte_be_to_cpu_16(ipv6_hdr->payload_len) - sizeof(struct icmpv6_RA) + sizeof(struct icmpv6_option);
+ struct icmpv6_RA *router_advertisement = (struct icmpv6_RA *)(ipv6_hdr + 1);
+ struct icmpv6_option *option = (struct icmpv6_option *)&router_advertisement->options;
+ struct icmpv6_prefix_option *prefix_option;
+ while(option_len > 0) {
+ uint8_t type = option->type;
+ switch(type) {
+ case ICMPv6_source_link_layer_address:
+ plog_dbg("\tOption %d = Source Link Layer Address\n", type);
+ break;
+ case ICMPv6_prefix_information:
+ prefix_option = (struct icmpv6_prefix_option *)option;
+ plog_dbg("\tOption %d = Prefix Information = %s\n", type, IP6_Canonical(&prefix_option->prefix));
+ send = 1;
+ break;
+ case ICMPv6_mtu:
+ plog_dbg("\tOption %d = MTU\n", type);
+ break;
+ default:
+ plog_dbg("\tOption %d = Unknown Option\n", type);
+ break;
+ }
+ if ((option->length == 0) || (option->length *8 > option_len)) {
+ plog_err("Unexpected option length (%d) received in option %d: %d\n", option->length, option->type, option->length);
+ send = 0;
+ break;
+ }
+ option_len -=option->length * 8;
+ option = (struct icmpv6_option *)(((uint8_t *)option) + option->length * 8);
+ }
+ if (send) {
+ struct ipv6_addr global_ipv6;
+ memcpy(&global_ipv6, &prefix_option->prefix, sizeof(struct ipv6_addr));
+ set_EUI(&global_ipv6, &task->internal_port_table[port].mac);
+ tx_ring_ip6(tbase, ring, IPV6_INFO_FROM_MASTER, mbuf, &global_ipv6);
+ } else
+ tx_drop(mbuf);
+}
+
+static inline void handle_ns(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ struct icmpv6_NS *neighbour_sollicitation = (struct icmpv6_NS *)(ipv6_hdr + 1);
+ int i, ret;
+ uint8_t port = get_port(mbuf);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+
+ plog_dbg("Master handling Neighbour Sollicitation for ip "IPv6_BYTES_FMT" on port %d - len = %d; payload_len = %d\n", IPv6_BYTES(neighbour_sollicitation->target_address.bytes), port, rte_pktmbuf_pkt_len(mbuf), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ if (rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr) > rte_pktmbuf_pkt_len(mbuf)) {
+ plog_err("Unexpected length received: pkt_len = %d, ipv6 hdr length = %ld, ipv6 payload len = %d\n", rte_pktmbuf_pkt_len(mbuf), sizeof(prox_rte_ipv6_hdr), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ tx_drop(mbuf);
+ return;
+ }
+ int16_t option_len = rte_be_to_cpu_16(ipv6_hdr->payload_len) - sizeof(struct icmpv6_NS) + sizeof(struct icmpv6_option);
+ struct icmpv6_option *option = (struct icmpv6_option *)&neighbour_sollicitation->options;
+ while(option_len > 0) {
+ uint8_t type = option->type;
+ switch(type) {
+ case ICMPv6_source_link_layer_address:
+ plog_dbg("Option %d = Source Link Layer Address\n", type);
+ break;
+ default:
+ plog_dbg("Option %d = Unknown Option\n", type);
+ break;
+ }
+ if ((option->length == 0) || (option->length *8 > option_len)) {
+ plog_err("Unexpected option length (%d) received in option %d: %d\n", option->length, option->type, option->length);
+ tx_drop(mbuf);
+ return;
+ }
+ option_len -=option->length * 8;
+ option = (struct icmpv6_option *)(((uint8_t *)option) + option->length * 8);
+ }
+ struct ip6_port key;
+ memcpy(&key.ip6, &neighbour_sollicitation->target_address, sizeof(struct ipv6_addr));
+ key.port = port;
+
+ if (memcmp(&neighbour_sollicitation->target_address, &task->internal_port_table[port].local_ipv6_addr, 8) == 0) {
+ // Local IP
+ if (task->internal_port_table[port].flags & HANDLE_RANDOM_LOCAL_IP_FLAG) {
+ prox_rte_ether_addr mac;
+ plogx_dbg("\tMaster handling NS request for ip "IPv6_BYTES_FMT" on port %d which supports random ip\n", IPv6_BYTES(key.ip6.bytes), key.port);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+ create_mac_from_EUI(&key.ip6, &mac);
+ build_neighbour_advertisement(tbase, mbuf, &mac, &task->internal_port_table[port].local_ipv6_addr, PROX_SOLLICITED);
+ tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
+ return;
+ }
+ } else {
+ if (task->internal_port_table[port].flags & HANDLE_RANDOM_GLOBAL_IP_FLAG) {
+ prox_rte_ether_addr mac;
+ plogx_dbg("\tMaster handling NS request for ip "IPv6_BYTES_FMT" on port %d which supports random ip\n", IPv6_BYTES(key.ip6.bytes), key.port);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+ create_mac_from_EUI(&key.ip6, &mac);
+ build_neighbour_advertisement(tbase, mbuf, &mac, &task->internal_port_table[port].global_ipv6_addr, PROX_SOLLICITED);
+ tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
+ return;
+ }
+ }
+
+ ret = rte_hash_lookup(task->internal_ip6_hash, (const void *)&key);
+ if (unlikely(ret < 0)) {
+ // entry not found for this IP.
+ plogx_dbg("Master ignoring Neighbour Sollicitation received on un-registered IP "IPv6_BYTES_FMT" on port %d\n", IPv6_BYTES(key.ip6.bytes), port);
+ tx_drop(mbuf);
+ } else {
+ struct rte_ring *ring = task->internal_ip6_table[ret].ring;
+ build_neighbour_advertisement(tbase, mbuf, &task->internal_ip6_table[ret].mac, &key.ip6, PROX_SOLLICITED);
+ tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
+ }
+}
+
+static inline void handle_na(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ struct icmpv6_NA *neighbour_advertisement = (struct icmpv6_NA *)(ipv6_hdr + 1);
+ int i, ret;
+ uint8_t port = get_port(mbuf);
+ struct rte_ring *ring = task->internal_port_table[port].ring;
+
+ plog_dbg("Master handling Neighbour Advertisement for ip "IPv6_BYTES_FMT" on port %d - len = %d; payload_len = %d\n", IPv6_BYTES(neighbour_advertisement->destination_address.bytes), port, rte_pktmbuf_pkt_len(mbuf), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ if (rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr) > rte_pktmbuf_pkt_len(mbuf)) {
+ plog_err("Unexpected length received: pkt_len = %d, ipv6 hdr length = %ld, ipv6 payload len = %d\n", rte_pktmbuf_pkt_len(mbuf), sizeof(prox_rte_ipv6_hdr), rte_be_to_cpu_16(ipv6_hdr->payload_len));
+ tx_drop(mbuf);
+ return;
+ }
+ int16_t option_len = rte_be_to_cpu_16(ipv6_hdr->payload_len) - sizeof(struct icmpv6_NA) + sizeof(struct icmpv6_option);
+ struct icmpv6_option *option = (struct icmpv6_option *)&neighbour_advertisement->options;
+ uint8_t *target_address = NULL;
+ while(option_len > 0) {
+ uint8_t type = option->type;
+ switch(type) {
+ case ICMPv6_source_link_layer_address:
+ plog_dbg("Option %d = Source Link Layer Address\n", type);
+ break;
+ case ICMPv6_target_link_layer_address:
+ if (option->length != 1) {
+ plog_err("Unexpected option length = %u for Target Link Layer Address\n", option->length);
+ break;
+ }
+ target_address = option->data;
+ plog_dbg("Option %d = Target Link Layer Address = "MAC_BYTES_FMT"\n", type, MAC_BYTES(target_address));
+ break;
+ default:
+ plog_dbg("Option %d = Unknown Option\n", type);
+ break;
+ }
+ if ((option->length == 0) || (option->length *8 > option_len)) {
+ plog_err("Unexpected option length (%d) received in option %d: %d\n", option->length, option->type, option->length);
+ tx_drop(mbuf);
+ return;
+ }
+ option_len -=option->length * 8;
+ option = (struct icmpv6_option *)(((uint8_t *)option) + option->length * 8);
+ }
+
+ if (target_address == NULL) {
+ tx_drop(mbuf);
+ }
+ struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
+ struct ipv6_addr *key = &neighbour_advertisement->destination_address;
+
+ ret = rte_hash_lookup(task->external_ip6_hash, (const void *)key);
+ if (unlikely(ret < 0)) {
+ // entry not found for this IP: we did not ask a request, delete the reply
+ tx_drop(mbuf);
+ } else {
+ // entry found for this IP
+ uint16_t nb_requests = task->external_ip6_table[ret].nb_requests;
+ //memcpy(&hdr->d_addr.addr_bytes, &task->external_ip6_table[ret].mac, sizeof(prox_rte_ether_addr));
+ // If we receive a request from multiple task for the same IP, then we update all tasks
+ if (task->external_ip6_table[ret].nb_requests) {
+ rte_mbuf_refcnt_set(mbuf, nb_requests);
+ for (int i = 0; i < nb_requests; i++) {
+ struct rte_ring *ring = task->external_ip6_table[ret].rings[i];
+ tx_ring_ip6_data(tbase, ring, MAC_INFO_FROM_MASTER_FOR_IPV6, mbuf, &neighbour_advertisement->destination_address, *(uint64_t *)target_address);
+ }
+ task->external_ip6_table[ret].nb_requests = 0;
+ } else {
+ tx_drop(mbuf);
+ }
+ }
+}
+
+static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf, int ring_id)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ struct ether_hdr_arp *hdr_arp;
+ prox_rte_ether_hdr *hdr;
+ struct icmpv6 *icmpv6;
int command = get_command(mbuf);
uint8_t port = get_port(mbuf);
uint32_t ip;
@@ -422,7 +720,7 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
plogx_dbg("\tMaster received %s (%x) from mbuf %p\n", actions_string[command], command, mbuf);
switch(command) {
- case BGP_TO_CTRL:
+ case BGP_TO_MASTER:
if (vdev_port != NO_VDEV_PORT) {
// If a virtual (net_tap) device is attached, send the (BGP) packet to this device
// The kernel will receive and handle it.
@@ -432,7 +730,7 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
}
tx_drop(mbuf);
break;
- case ICMP_TO_CTRL:
+ case ICMP_TO_MASTER:
if (vdev_port != NO_VDEV_PORT) {
// If a virtual (net_tap) device is attached, send the (PING) packet to this device
// The kernel will receive and handle it.
@@ -442,7 +740,7 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
}
handle_icmp(tbase, mbuf);
break;
- case ARP_TO_CTRL:
+ case ARP_PKT_FROM_NET_TO_MASTER:
if (vdev_port != NO_VDEV_PORT) {
// If a virtual (net_tap) device is attached, send the (ARP) packet to this device
// The kernel will receive and handle it.
@@ -450,8 +748,9 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
int n = rte_eth_tx_burst(prox_port_cfg[port].dpdk_mapping, 0, &mbuf, 1);
return;
}
+ hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
if (hdr_arp->ether_hdr.ether_type != ETYPE_ARP) {
- plog_err("\tUnexpected message received: ARP_TO_CTRL with ether_type %x\n", hdr_arp->ether_hdr.ether_type);
+ plog_err("\tUnexpected message received: ARP_PKT_FROM_NET_TO_MASTER with ether_type %x\n", hdr_arp->ether_hdr.ether_type);
tx_drop(mbuf);
return;
} else if (arp_is_gratuitous(hdr_arp)) {
@@ -469,7 +768,7 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
return;
}
break;
- case REQ_MAC_TO_CTRL:
+ case IP4_REQ_MAC_TO_MASTER:
if (vdev_port != NO_VDEV_PORT) {
// We send a packet to the kernel with the proper destnation IP address and our src IP address
// This means that if a generator sends packets from many sources all ARP will still
@@ -489,9 +788,9 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
int ret = rte_hash_lookup(task->external_ip_hash, (const void *)&ip);
if ((ret >= 0) && (!prox_rte_is_zero_ether_addr(&task->external_ip_table[ret].mac))) {
memcpy(&hdr_arp->arp.data.sha, &task->external_ip_table[ret].mac, sizeof(prox_rte_ether_addr));
- plogx_dbg("\tMaster ready to send UPDATE_FROM_CTRL ip "IPv4_BYTES_FMT" with mac "MAC_BYTES_FMT"\n",
+ plogx_dbg("\tMaster ready to send MAC_INFO_FROM_MASTER ip "IPv4_BYTES_FMT" with mac "MAC_BYTES_FMT"\n",
IP4(ip), MAC_BYTES(hdr_arp->arp.data.sha.addr_bytes));
- tx_ring_ip(tbase, ring, UPDATE_FROM_CTRL, mbuf, ip);
+ tx_ring_ip(tbase, ring, MAC_INFO_FROM_MASTER, mbuf, ip);
return;
}
@@ -508,6 +807,61 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
}
handle_unknown_ip(tbase, mbuf);
break;
+ case IP6_REQ_MAC_TO_MASTER:
+ handle_unknown_ip6(tbase, mbuf);
+ break;
+ case NDP_PKT_FROM_NET_TO_MASTER:
+ hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ if (unlikely((hdr->ether_type != ETYPE_IPv6) || (ipv6_hdr->proto != ICMPv6))) {
+ // Should not happen
+ if (hdr->ether_type != ETYPE_IPv6)
+ plog_err("\tUnexpected message received: NDP_PKT_FROM_NET_TO_MASTER with ether_type %x\n", hdr->ether_type);
+ else
+ plog_err("\tUnexpected message received: NDP_PKT_FROM_NET_TO_MASTER with ether_type %x and proto %x\n", hdr->ether_type, ipv6_hdr->proto);
+ tx_drop(mbuf);
+ return;
+ }
+ icmpv6 = (struct icmpv6 *)(ipv6_hdr + 1);
+ switch (icmpv6->type) {
+ case ICMPv6_DU:
+ plog_err("IPV6 ICMPV6 Destination Unreachable\n");
+ tx_drop(mbuf);
+ break;
+ case ICMPv6_PTB:
+ plog_err("IPV6 ICMPV6 packet too big\n");
+ tx_drop(mbuf);
+ break;
+ case ICMPv6_TE:
+ plog_err("IPV6 ICMPV6 Time Exceeded\n");
+ tx_drop(mbuf);
+ break;
+ case ICMPv6_PaPr:
+ plog_err("IPV6 ICMPV6 Parameter Problem\n");
+ tx_drop(mbuf);
+ break;
+ case ICMPv6_RS:
+ handle_rs(tbase, mbuf);
+ break;
+ case ICMPv6_RA:
+ handle_ra(tbase, mbuf);
+ break;
+ case ICMPv6_NS:
+ handle_ns(tbase, mbuf);
+ break;
+ case ICMPv6_NA:
+ handle_na(tbase, mbuf);
+ break;
+ case ICMPv6_RE:
+ plog_err("IPV6 ICMPV6 Redirect not handled\n");
+ tx_drop(mbuf);
+ break;
+ default:
+ plog_err("Unexpected type %d in IPV6 ICMPV6\n", icmpv6->type);
+ tx_drop(mbuf);
+ break;
+ }
+ break;
default:
plogx_dbg("\tMaster received unexpected message\n");
tx_drop(mbuf);
@@ -517,7 +871,6 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
void init_ctrl_plane(struct task_base *tbase)
{
- prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
struct task_master *task = (struct task_master *)tbase;
int socket_id = rte_lcore_to_socket_id(prox_cfg.master);
uint32_t n_entries = MAX_ARP_ENTRIES * 4;
@@ -527,25 +880,52 @@ void init_ctrl_plane(struct task_base *tbase)
struct rte_hash_parameters hash_params = {
.name = hash_name,
.entries = n_entries,
- .key_len = sizeof(uint32_t),
.hash_func = rte_hash_crc,
.hash_func_init_val = 0,
};
- task->external_ip_hash = rte_hash_create(&hash_params);
- PROX_PANIC(task->external_ip_hash == NULL, "Failed to set up external ip hash\n");
- plog_info("\texternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
- task->external_ip_table = (struct external_ip_table *)prox_zmalloc(n_entries * sizeof(struct external_ip_table), socket_id);
- PROX_PANIC(task->external_ip_table == NULL, "Failed to allocate memory for %u entries in external ip table\n", n_entries);
- plog_info("\texternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct external_ip_table));
-
- hash_name[0]++;
- hash_params.key_len = sizeof(struct ip_port);
- task->internal_ip_hash = rte_hash_create(&hash_params);
- PROX_PANIC(task->internal_ip_hash == NULL, "Failed to set up internal ip hash\n");
- plog_info("\tinternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
- task->internal_ip_table = (struct ip_table *)prox_zmalloc(n_entries * sizeof(struct ip_table), socket_id);
- PROX_PANIC(task->internal_ip_table == NULL, "Failed to allocate memory for %u entries in internal ip table\n", n_entries);
- plog_info("\tinternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct ip_table));
+ if (prox_cfg.flags & DSF_L3_ENABLED) {
+ hash_params.key_len = sizeof(uint32_t);
+ task->external_ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->external_ip_hash == NULL, "Failed to set up external ip hash\n");
+ plog_info("\texternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ hash_name[0]++;
+
+ task->external_ip_table = (struct external_ip_table *)prox_zmalloc(n_entries * sizeof(struct external_ip_table), socket_id);
+ PROX_PANIC(task->external_ip_table == NULL, "Failed to allocate memory for %u entries in external ip table\n", n_entries);
+ plog_info("\texternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct external_ip_table));
+
+ hash_params.key_len = sizeof(struct ip_port);
+ task->internal_ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->internal_ip_hash == NULL, "Failed to set up internal ip hash\n");
+ plog_info("\tinternal ip hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ hash_name[0]++;
+
+ task->internal_ip_table = (struct ip_table *)prox_zmalloc(n_entries * sizeof(struct ip_table), socket_id);
+ PROX_PANIC(task->internal_ip_table == NULL, "Failed to allocate memory for %u entries in internal ip table\n", n_entries);
+ plog_info("\tinternal ip table, with %d entries of size %ld\n", n_entries, sizeof(struct ip_table));
+ }
+
+ if (prox_cfg.flags & DSF_NDP_ENABLED) {
+ hash_params.key_len = sizeof(struct ipv6_addr);
+ task->external_ip6_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->external_ip6_hash == NULL, "Failed to set up external ip6 hash\n");
+ plog_info("\texternal ip6 hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ hash_name[0]++;
+
+ task->external_ip6_table = (struct external_ip_table *)prox_zmalloc(n_entries * sizeof(struct external_ip_table), socket_id);
+ PROX_PANIC(task->external_ip6_table == NULL, "Failed to allocate memory for %u entries in external ip6 table\n", n_entries);
+ plog_info("\texternal ip6_table, with %d entries of size %ld\n", n_entries, sizeof(struct external_ip_table));
+
+ hash_params.key_len = sizeof(struct ip6_port);
+ task->internal_ip6_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(task->internal_ip6_hash == NULL, "Failed to set up internal ip6 hash\n");
+ plog_info("\tinternal ip6 hash table allocated, with %d entries of size %d\n", hash_params.entries, hash_params.key_len);
+ hash_name[0]++;
+
+ task->internal_ip6_table = (struct ip_table *)prox_zmalloc(n_entries * sizeof(struct ip_table), socket_id);
+ PROX_PANIC(task->internal_ip6_table == NULL, "Failed to allocate memory for %u entries in internal ip6 table\n", n_entries);
+ plog_info("\tinternal ip6 table, with %d entries of size %ld\n", n_entries, sizeof(struct ip_table));
+ }
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
PROX_PANIC(fd < 0, "Failed to open netlink socket: %d\n", errno);
@@ -574,7 +954,7 @@ void init_ctrl_plane(struct task_base *tbase)
task->route_fds.events = POLL_IN;
plog_info("\tRTMGRP_IPV4_ROUTE netlink group bound; fd = %d\n", fd);
- static char name[] = "master_arp_pool";
+ static char name[] = "master_arp_nd_pool";
const int NB_ARP_MBUF = 1024;
const int ARP_MBUF_SIZE = 2048;
const int NB_CACHE_ARP_MBUF = 256;
@@ -585,7 +965,7 @@ void init_ctrl_plane(struct task_base *tbase)
rte_socket_id(), NB_ARP_MBUF);
plog_info("\t\tMempool %p (%s) size = %u * %u cache %u, socket %d\n", ret, name, NB_ARP_MBUF,
ARP_MBUF_SIZE, NB_CACHE_ARP_MBUF, rte_socket_id());
- tbase->l3.arp_pool = ret;
+ tbase->l3.arp_nd_pool = ret;
}
static void handle_route_event(struct task_base *tbase)
@@ -638,13 +1018,13 @@ static void handle_route_event(struct task_base *tbase)
}
}
int dpdk_vdev_port = -1;
- for (int i = 0; i< rte_eth_dev_count(); i++) {
+ for (int i = 0; i< prox_rte_eth_dev_count_avail(); i++) {
if (strcmp(prox_port_cfg[i].name, interface_name) == 0)
dpdk_vdev_port = i;
}
if (dpdk_vdev_port != -1) {
plogx_info("Received netlink message on tap interface %s for IP "IPv4_BYTES_FMT"/%d, Gateway "IPv4_BYTES_FMT"\n", interface_name, IP4(ip), dst_len, IP4(gw_ip));
- int ret1 = rte_mempool_get(tbase->l3.arp_pool, (void **)mbufs);
+ int ret1 = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)mbufs);
if (unlikely(ret1 != 0)) {
plog_err("Unable to allocate a mbuf for master to core communication\n");
return;
@@ -726,7 +1106,7 @@ static void handle_arp_event(struct task_base *tbase)
memcpy(&task->external_ip_table[ret].mac, &mac, sizeof(prox_rte_ether_addr));
// If we receive a request from multiple task for the same IP, then we update all tasks
- int ret1 = rte_mempool_get(tbase->l3.arp_pool, (void **)mbufs);
+ int ret1 = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)mbufs);
if (unlikely(ret1 != 0)) {
plog_err("Unable to allocate a mbuf for master to core communication\n");
return;
@@ -736,8 +1116,8 @@ static void handle_arp_event(struct task_base *tbase)
struct rte_ring *ring = task->external_ip_table[ret].rings[i];
struct ether_hdr_arp *hdr = rte_pktmbuf_mtod(mbufs[0], struct ether_hdr_arp *);
memcpy(&hdr->arp.data.sha, &mac, sizeof(prox_rte_ether_addr));
- tx_ring_ip(tbase, ring, UPDATE_FROM_CTRL, mbufs[0], ip);
- plog_dbg("UPDATE_FROM_CTRL ip "IPv4_BYTES_FMT" with mac "MAC_BYTES_FMT"\n", IP4(ip), MAC_BYTES(mac.addr_bytes));
+ tx_ring_ip(tbase, ring, MAC_INFO_FROM_MASTER, mbufs[0], ip);
+ plog_dbg("MAC_INFO_FROM_MASTER ip "IPv4_BYTES_FMT" with mac "MAC_BYTES_FMT"\n", IP4(ip), MAC_BYTES(mac.addr_bytes));
}
task->external_ip_table[ret].nb_requests = 0;
return;
diff --git a/VNFs/DPPD-PROX/handle_master.h b/VNFs/DPPD-PROX/handle_master.h
index fc8706a..518906e 100644
--- a/VNFs/DPPD-PROX/handle_master.h
+++ b/VNFs/DPPD-PROX/handle_master.h
@@ -14,30 +14,91 @@
// limitations under the License.
*/
+#include <poll.h>
#include "task_base.h"
#include "task_init.h"
enum arp_actions {
- UPDATE_FROM_CTRL,
- ROUTE_ADD_FROM_CTRL,
- ROUTE_DEL_FROM_CTRL,
- ARP_REQ_FROM_CTRL,
- ARP_REPLY_FROM_CTRL,
- ICMP_FROM_CTRL,
- BGP_FROM_CTRL,
- ARP_TO_CTRL,
- ICMP_TO_CTRL,
- BGP_TO_CTRL,
- REQ_MAC_TO_CTRL,
+ MAC_INFO_FROM_MASTER,
+ MAC_INFO_FROM_MASTER_FOR_IPV6,
+ IPV6_INFO_FROM_MASTER,
+ ROUTE_ADD_FROM_MASTER,
+ ROUTE_DEL_FROM_MASTER,
+ SEND_ARP_REQUEST_FROM_MASTER,
+ SEND_ARP_REPLY_FROM_MASTER,
+ SEND_NDP_FROM_MASTER,
+ SEND_ICMP_FROM_MASTER,
+ SEND_BGP_FROM_MASTER,
+ ARP_PKT_FROM_NET_TO_MASTER,
+ NDP_PKT_FROM_NET_TO_MASTER,
+ ICMP_TO_MASTER,
+ BGP_TO_MASTER,
+ IP4_REQ_MAC_TO_MASTER,
+ IP6_REQ_MAC_TO_MASTER,
PKT_FROM_TAP,
MAX_ACTIONS
};
-#define HANDLE_RANDOM_IP_FLAG 1
+#define PROX_MAX_ARP_REQUESTS 32 // Maximum number of tasks requesting the same MAC address
+
+#define HANDLE_RANDOM_IP_FLAG 1
+#define HANDLE_RANDOM_LOCAL_IP_FLAG 2
+#define HANDLE_RANDOM_GLOBAL_IP_FLAG 4
+#define IPV6_ROUTER 8
#define RANDOM_IP 0xffffffff
#define PROX_PSEUDO_PKT_PORT 0xdead
+struct port_table {
+ prox_rte_ether_addr mac;
+ struct rte_ring *ring;
+ uint32_t ip;
+ uint8_t port;
+ uint8_t flags;
+ struct ipv6_addr local_ipv6_addr;
+ struct ipv6_addr global_ipv6_addr;
+ struct ipv6_addr router_prefix;
+ uint64_t last_echo_req_rcvd_tsc;
+ uint64_t last_echo_rep_rcvd_tsc;
+ uint32_t n_echo_req;
+ uint32_t n_echo_rep;
+};
+
+struct ip_table {
+ prox_rte_ether_addr mac;
+ struct rte_ring *ring;
+};
+
+struct external_ip_table {
+ prox_rte_ether_addr mac;
+ struct rte_ring *rings[PROX_MAX_ARP_REQUESTS];
+ uint16_t nb_requests;
+};
+
+struct vdev {
+ int port_id;
+ struct rte_ring *ring;
+};
+
+struct task_master {
+ struct task_base base;
+ struct rte_ring *ctrl_rx_ring;
+ struct rte_ring **ctrl_tx_rings;
+ struct ip_table *internal_ip_table; // Store mac address from our IP
+ struct external_ip_table *external_ip_table; // Store mac address from external systems
+ struct ip_table *internal_ip6_table; // Store mac address from our IP
+ struct external_ip_table *external_ip6_table; // Store mac address from external systems
+ struct rte_hash *external_ip_hash;
+ struct rte_hash *external_ip6_hash;
+ struct rte_hash *internal_ip_hash;
+ struct rte_hash *internal_ip6_hash;
+ struct port_table internal_port_table[PROX_MAX_PORTS];
+ struct vdev all_vdev[PROX_MAX_PORTS];
+ int max_vdev_id;
+ struct pollfd arp_fds;
+ struct pollfd route_fds;
+};
+
const char *actions_string[MAX_ACTIONS];
void init_ctrl_plane(struct task_base *tbase);
@@ -49,9 +110,7 @@ static inline void tx_drop(struct rte_mbuf *mbuf)
rte_pktmbuf_free(mbuf);
}
-struct vdev {
- int port_id;
- struct rte_ring *ring;
-};
void register_ip_to_ctrl_plane(struct task_base *task, uint32_t ip, uint8_t port_id, uint8_t core_id, uint8_t task_id);
void master_init_vdev(struct task_base *task, uint8_t port_id, uint8_t core_id, uint8_t task_id);
+void register_router_to_ctrl_plane(struct task_base *tbase, uint8_t port_id, uint8_t core_id, uint8_t task_id, struct ipv6_addr *local_ipv6_addr, struct ipv6_addr *global_ipv6_addr, struct ipv6_addr *router_prefix);
+void register_node_to_ctrl_plane(struct task_base *tbase, struct ipv6_addr *local_ipv6_addr, struct ipv6_addr *global_ipv6_addr, uint8_t port_id, uint8_t core_id, uint8_t task_id);
diff --git a/VNFs/DPPD-PROX/handle_routing.c b/VNFs/DPPD-PROX/handle_routing.c
index 29b8438..4683ede 100644
--- a/VNFs/DPPD-PROX/handle_routing.c
+++ b/VNFs/DPPD-PROX/handle_routing.c
@@ -37,7 +37,6 @@
#include "mpls.h"
#include "qinq.h"
#include "prox_cfg.h"
-#include "ip6_addr.h"
#include "prox_shared.h"
#include "prox_cksum.h"
#include "mbuf_utils.h"
diff --git a/VNFs/DPPD-PROX/handle_swap.c b/VNFs/DPPD-PROX/handle_swap.c
index b9029b6..a5abd89 100644
--- a/VNFs/DPPD-PROX/handle_swap.c
+++ b/VNFs/DPPD-PROX/handle_swap.c
@@ -142,6 +142,38 @@ static void stop_swap(struct task_base *tbase)
}
}
+static void handle_ipv6(struct task_swap *task, struct rte_mbuf *mbufs, prox_rte_ipv6_hdr *ipv6_hdr, uint8_t *out)
+{
+ __m128i ip = _mm_loadu_si128((__m128i*)&(ipv6_hdr->src_addr));
+ uint16_t port;
+ uint16_t payload_len;
+ prox_rte_udp_hdr *udp_hdr;
+
+ rte_mov16((uint8_t *)&(ipv6_hdr->src_addr), (uint8_t *)&(ipv6_hdr->dst_addr)); // Copy dst into src
+ rte_mov16((uint8_t *)&(ipv6_hdr->dst_addr), (uint8_t *)&ip); // Copy src into dst
+ switch(ipv6_hdr->proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ payload_len = ipv6_hdr->payload_len;
+ udp_hdr = (prox_rte_udp_hdr *)(ipv6_hdr + 1);
+ if (unlikely(udp_hdr->dgram_len < payload_len)) {
+ plog_warn("Unexpected L4 len (%u) versus L3 payload len (%u) in IPv6 packet\n", udp_hdr->dgram_len, payload_len);
+ *out = OUT_DISCARD;
+ break;
+ }
+ port = udp_hdr->dst_port;
+ udp_hdr->dst_port = udp_hdr->src_port;
+ udp_hdr->src_port = port;
+ write_src_and_dst_mac(task, mbufs);
+ *out = 0;
+ break;
+ default:
+ plog_warn("Unsupported next hop %u in IPv6 packet\n", ipv6_hdr->proto);
+ *out = OUT_DISCARD;
+ break;
+ }
+}
+
static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
{
struct task_swap *task = (struct task_swap *)tbase;
@@ -149,6 +181,7 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
prox_rte_ether_addr mac;
prox_rte_ipv4_hdr *ip_hdr;
prox_rte_udp_hdr *udp_hdr;
+ prox_rte_ipv6_hdr *ipv6_hdr;
struct gre_hdr *pgre;
prox_rte_ipv4_hdr *inner_ip_hdr;
uint32_t ip;
@@ -183,6 +216,11 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
}
mpls_len += sizeof(struct mpls_hdr);
ip_hdr = (prox_rte_ipv4_hdr *)(mpls + 1);
+ if (unlikely((ip_hdr->version_ihl >> 4) == 6)) {
+ ipv6_hdr = (prox_rte_ipv6_hdr *)(ip_hdr);
+ handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]);
+ continue;
+ }
break;
case ETYPE_8021ad:
qinq = (struct qinq_hdr *)hdr;
@@ -191,20 +229,34 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
out[j] = OUT_DISCARD;
continue;
}
- ip_hdr = (prox_rte_ipv4_hdr *)(qinq + 1);
+ if (qinq->ether_type == ETYPE_IPv4) {
+ ip_hdr = (prox_rte_ipv4_hdr *)(qinq + 1);
+ } else if (qinq->ether_type == ETYPE_IPv6) {
+ ipv6_hdr = (prox_rte_ipv6_hdr *)(qinq + 1);
+ handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]);
+ continue;
+ } else {
+ plog_warn("Unsupported packet type\n");
+ out[j] = OUT_DISCARD;
+ continue;
+ }
break;
case ETYPE_VLAN:
vlan = (prox_rte_vlan_hdr *)(hdr + 1);
if (vlan->eth_proto == ETYPE_IPv4) {
ip_hdr = (prox_rte_ipv4_hdr *)(vlan + 1);
+ } else if (vlan->eth_proto == ETYPE_IPv6) {
+ ipv6_hdr = (prox_rte_ipv6_hdr *)(vlan + 1);
+ handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]);
+ continue;
} else if (vlan->eth_proto == ETYPE_VLAN) {
vlan = (prox_rte_vlan_hdr *)(vlan + 1);
if (vlan->eth_proto == ETYPE_IPv4) {
ip_hdr = (prox_rte_ipv4_hdr *)(vlan + 1);
}
else if (vlan->eth_proto == ETYPE_IPv6) {
- plog_warn("Unsupported IPv6\n");
- out[j] = OUT_DISCARD;
+ ipv6_hdr = (prox_rte_ipv6_hdr *)(vlan + 1);
+ handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]);
continue;
}
else {
@@ -222,8 +274,8 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
ip_hdr = (prox_rte_ipv4_hdr *)(hdr + 1);
break;
case ETYPE_IPv6:
- plog_warn("Unsupported IPv6\n");
- out[j] = OUT_DISCARD;
+ ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr + 1);
+ handle_ipv6(task, mbufs[j], ipv6_hdr, &out[j]);
continue;
case ETYPE_LLDP:
out[j] = OUT_DISCARD;
@@ -234,7 +286,13 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
continue;
}
// TODO 2 : check packet is long enough for Ethernet + IP + UDP + extra header (VLAN, MPLS, ...)
+ // IPv4 packet
+
ip = ip_hdr->dst_addr;
+ if (unlikely((ip_hdr->version_ihl >> 4) != 4)) {
+ out[j] = OUT_DISCARD;
+ continue;
+ }
switch (ip_hdr->next_proto_id) {
case IPPROTO_GRE:
@@ -256,7 +314,7 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui
break;
case IPPROTO_UDP:
case IPPROTO_TCP:
- if (task->igmp_address && PROX_RTE_IS_IPV4_MCAST(rte_be_to_cpu_32(ip))) {
+ if (unlikely(task->igmp_address && PROX_RTE_IS_IPV4_MCAST(rte_be_to_cpu_32(ip)))) {
out[j] = OUT_DISCARD;
continue;
}
diff --git a/VNFs/DPPD-PROX/ip6_addr.h b/VNFs/DPPD-PROX/ip6_addr.h
index f9b56c1..3279ded 100644
--- a/VNFs/DPPD-PROX/ip6_addr.h
+++ b/VNFs/DPPD-PROX/ip6_addr.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
#ifndef _IP6_ADDR_H_
#define _IP6_ADDR_H_
-#include <inttypes.h>
-
struct ipv6_addr {
uint8_t bytes[16];
};
diff --git a/VNFs/DPPD-PROX/lconf.c b/VNFs/DPPD-PROX/lconf.c
index 63e4763..be2486e 100644
--- a/VNFs/DPPD-PROX/lconf.c
+++ b/VNFs/DPPD-PROX/lconf.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -246,7 +246,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
if (lconf->msg.type == LCONF_MSG_DUMP ||
lconf->msg.type == LCONF_MSG_DUMP_TX) {
t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
if (t->aux->tx_pkt_orig)
t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
@@ -267,7 +267,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
if (task_base_get_original_rx_pkt_function(t) != rx_pkt_dummy) {
t->aux->task_rt_dump.n_trace = lconf->msg.val;
task_base_add_rx_pkt_function(t, rx_pkt_trace);
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
if (t->aux->tx_pkt_orig)
t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
@@ -280,7 +280,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
}
} else {
t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
if (t->aux->tx_pkt_orig)
t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
@@ -306,7 +306,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
t->aux->tx_pkt_l2 = tx_pkt_distr;
} else {
@@ -328,7 +328,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
if (t->aux->tx_pkt_orig) {
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
t->aux->tx_pkt_orig = NULL;
} else {
@@ -371,7 +371,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
t->aux->tx_pkt_orig = t->aux->tx_pkt_l2;
t->aux->tx_pkt_l2 = tx_pkt_bw;
} else {
@@ -385,7 +385,7 @@ int lconf_do_flags(struct lcore_cfg *lconf)
for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
t = lconf->tasks_all[task_id];
if (t->aux->tx_pkt_orig) {
- if (t->tx_pkt == tx_pkt_l3) {
+ if ((t->tx_pkt == tx_pkt_l3) || (t->tx_pkt == tx_pkt_ndp)) {
t->aux->tx_pkt_l2 = t->aux->tx_pkt_orig;
t->aux->tx_pkt_orig = NULL;
} else {
diff --git a/VNFs/DPPD-PROX/main.c b/VNFs/DPPD-PROX/main.c
index 1af49b7..f6fa3e8 100644
--- a/VNFs/DPPD-PROX/main.c
+++ b/VNFs/DPPD-PROX/main.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -155,7 +155,7 @@ static void check_missing_rx(void)
{
struct lcore_cfg *lconf = NULL, *rx_lconf = NULL, *tx_lconf = NULL;
struct task_args *targ, *rx_targ = NULL, *tx_targ = NULL;
- uint8_t port_id, rx_port_id, ok;
+ uint8_t port_id, rx_port_id, ok, l3, ndp;
while (core_targ_next(&lconf, &targ, 0) == 0) {
PROX_PANIC((targ->flags & TASK_ARG_RX_RING) && targ->rx_rings[0] == 0 && !targ->tx_opt_ring_task,
@@ -168,12 +168,17 @@ static void check_missing_rx(void)
lconf = NULL;
while (core_targ_next(&lconf, &targ, 0) == 0) {
- if (strcmp(targ->sub_mode_str, "l3") != 0)
+ l3 = ndp = 0;
+ if (strcmp(targ->sub_mode_str, "l3") == 0)
+ l3 = 1;
+ else if (strcmp(targ->sub_mode_str, "ndp") == 0)
+ ndp = 1;
+ else
continue;
- PROX_PANIC((targ->nb_rxports == 0) && (targ->nb_txports == 0), "L3 task must have a RX or a TX port\n");
- // If the L3 sub_mode receives from a port, check that there is at least one core/task
- // transmitting to this port in L3 sub_mode
+ PROX_PANIC((targ->nb_rxports == 0) && (targ->nb_txports == 0), "L3/NDP task must have a RX or a TX port\n");
+ // If the L3/NDP sub_mode receives from a port, check that there is at least one core/task
+ // transmitting to this port in L3/NDP sub_mode
for (uint8_t i = 0; i < targ->nb_rxports; ++i) {
rx_port_id = targ->rx_port_queue[i].port;
ok = 0;
@@ -181,35 +186,40 @@ static void check_missing_rx(void)
while (core_targ_next(&tx_lconf, &tx_targ, 0) == 0) {
if ((port_id = tx_targ->tx_port_queue[0].port) == OUT_DISCARD)
continue;
- if ((rx_port_id == port_id) && (tx_targ->flags & TASK_ARG_L3)){
+ if ((rx_port_id == port_id) &&
+ ( ((tx_targ->flags & TASK_ARG_L3) && l3) ||
+ ((tx_targ->flags & TASK_ARG_NDP) && ndp) ) ) {
ok = 1;
break;
}
}
- PROX_PANIC(ok == 0, "RX L3 sub mode for port %d on core %d task %d, but no core/task transmitting on that port\n", rx_port_id, lconf->id, targ->id);
+ PROX_PANIC(ok == 0, "RX %s sub mode for port %d on core %d task %d, but no core/task transmitting on that port\n", l3 ? "l3":"ndp", rx_port_id, lconf->id, targ->id);
}
- // If the L3 sub_mode transmits to a port, check that there is at least one core/task
- // receiving from that port in L3 sub_mode.
+ // If the L3/NDP sub_mode transmits to a port, check that there is at least one core/task
+ // receiving from that port in L3/NDP sub_mode.
if ((port_id = targ->tx_port_queue[0].port) == OUT_DISCARD)
continue;
rx_lconf = NULL;
ok = 0;
- plog_info("\tCore %d task %d transmitting to port %d in L3 mode\n", lconf->id, targ->id, port_id);
+ plog_info("\tCore %d task %d transmitting to port %d in %s submode\n", lconf->id, targ->id, port_id, l3 ? "l3":"ndp");
while (core_targ_next(&rx_lconf, &rx_targ, 0) == 0) {
for (uint8_t i = 0; i < rx_targ->nb_rxports; ++i) {
rx_port_id = rx_targ->rx_port_queue[i].port;
- if ((rx_port_id == port_id) && (rx_targ->flags & TASK_ARG_L3)){
+ if ((rx_port_id == port_id) &&
+ ( ((rx_targ->flags & TASK_ARG_L3) && l3) ||
+ ((rx_targ->flags & TASK_ARG_NDP) && ndp) ) ){
ok = 1;
break;
}
}
if (ok == 1) {
- plog_info("\tCore %d task %d has found core %d task %d receiving from port %d\n", lconf->id, targ->id, rx_lconf->id, rx_targ->id, port_id);
+ plog_info("\tCore %d task %d has found core %d task %d receiving from port %d in %s submode\n", lconf->id, targ->id, rx_lconf->id, rx_targ->id, port_id,
+ ((rx_targ->flags & TASK_ARG_L3) && l3) ? "l3":"ndp");
break;
}
}
- PROX_PANIC(ok == 0, "L3 sub mode for port %d on core %d task %d, but no core/task receiving on that port\n", port_id, lconf->id, targ->id);
+ PROX_PANIC(ok == 0, "%s sub mode for port %d on core %d task %d, but no core/task receiving on that port\n", l3 ? "l3":"ndp", port_id, lconf->id, targ->id);
}
}
@@ -629,7 +639,7 @@ static void init_rings(void)
lconf = NULL;
struct prox_port_cfg *port;
while (core_targ_next(&lconf, &starg, 1) == 0) {
- if ((starg->task_init) && (starg->flags & TASK_ARG_L3)) {
+ if ((starg->task_init) && (starg->flags & (TASK_ARG_L3|TASK_ARG_NDP))) {
struct core_task ct;
ct.core = prox_cfg.master;
ct.task = 0;
@@ -750,12 +760,12 @@ static void setup_mempools_unique_per_socket(void)
sprintf(name, "socket_%u_pool", i);
if ((pool[i] = rte_mempool_lookup(name)) == NULL) {
pool[i] = rte_mempool_create(name,
- mbuf_count[i] - 1, mbuf_size[i],
- nb_cache_mbuf[i],
- sizeof(struct rte_pktmbuf_pool_private),
- rte_pktmbuf_pool_init, NULL,
- prox_pktmbuf_init, NULL,
- i, flags);
+ mbuf_count[i] - 1, mbuf_size[i],
+ nb_cache_mbuf[i],
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ prox_pktmbuf_init, NULL,
+ i, flags);
PROX_PANIC(pool[i] == NULL, "\t\tError: cannot create mempool for socket %u\n", i);
plog_info("\tMempool %p size = %u * %u cache %u, socket %d\n", pool[i],
mbuf_count[i], mbuf_size[i], nb_cache_mbuf[i], i);
diff --git a/VNFs/DPPD-PROX/packet_utils.c b/VNFs/DPPD-PROX/packet_utils.c
index 08178d8..466dd48 100644
--- a/VNFs/DPPD-PROX/packet_utils.c
+++ b/VNFs/DPPD-PROX/packet_utils.c
@@ -31,6 +31,9 @@
#include "prox_lua.h"
#include "hash_entry_types.h"
#include "prox_compat.h"
+#include "prox_cfg.h"
+#include "defines.h"
+#include "prox_ipv6.h"
#include "tx_pkt.h"
static inline int find_ip(struct ether_hdr_arp *pkt, uint16_t len, uint32_t *ip_dst)
@@ -76,15 +79,91 @@ static inline int find_ip(struct ether_hdr_arp *pkt, uint16_t len, uint32_t *ip_
return -1;
}
+static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len, struct ipv6_addr *ip_dst)
+{
+ prox_rte_vlan_hdr *vlan_hdr;
+ prox_rte_ipv6_hdr *ip;
+ uint16_t ether_type = pkt->ether_type;
+ uint16_t l2_len = sizeof(prox_rte_ether_hdr);
+
+ // Unstack VLAN tags
+ while (((ether_type == ETYPE_8021ad) || (ether_type == ETYPE_VLAN)) && (l2_len + sizeof(prox_rte_vlan_hdr) < len)) {
+ vlan_hdr = (prox_rte_vlan_hdr *)((uint8_t *)pkt + l2_len);
+ l2_len +=4;
+ ether_type = vlan_hdr->eth_proto;
+ }
+
+ switch (ether_type) {
+ case ETYPE_MPLSU:
+ case ETYPE_MPLSM:
+ // In case of MPLS, next hop MAC is based on MPLS, not destination IP
+ l2_len = 0;
+ break;
+ case ETYPE_IPv4:
+ case ETYPE_EoGRE:
+ case ETYPE_ARP:
+ l2_len = 0;
+ break;
+ case ETYPE_IPv6:
+ break;
+ default:
+ l2_len = 0;
+ plog_warn("Unsupported packet type %x - CRC might be wrong\n", ether_type);
+ break;
+ }
+
+ if (l2_len && (l2_len + sizeof(prox_rte_ipv6_hdr) <= len)) {
+ prox_rte_ipv6_hdr *ip = (prox_rte_ipv6_hdr *)((uint8_t *)pkt + l2_len);
+ // TODO: implement LPM => replace ip_dst by next hop IP DST
+ memcpy(ip_dst, &ip->dst_addr, sizeof(struct ipv6_addr));
+ return (struct ipv6_addr *)&ip->src_addr;
+ }
+ return NULL;
+}
+
+static void send_unsollicited_neighbour_advertisement(struct task_base *tbase, struct task_args *targ)
+{
+ int ret;
+ uint8_t out = 0, port_id = tbase->l3.reachable_port_id;
+ struct rte_mbuf *mbuf;
+
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ mbuf->port = port_id;
+ build_neighbour_advertisement(tbase->l3.tmaster, mbuf, &prox_port_cfg[port_id].eth_addr, &targ->local_ipv6, PROX_UNSOLLICITED);
+ tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out);
+ TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
+ } else {
+ plog_err("Failed to get a mbuf from arp/ndp mempool\n");
+ }
+}
+
+static void send_router_sollicitation(struct task_base *tbase, struct task_args *targ)
+{
+ int ret;
+ uint8_t out = 0, port_id = tbase->l3.reachable_port_id;
+ struct rte_mbuf *mbuf;
+
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ mbuf->port = port_id;
+ build_router_sollicitation(mbuf, &prox_port_cfg[port_id].eth_addr, &targ->local_ipv6);
+ tbase->aux->tx_ctrlplane_pkt(tbase, &mbuf, 1, &out);
+ TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
+ } else {
+ plog_err("Failed to get a mbuf from arp/ndp mempool\n");
+ }
+}
+
/* This implementation could be improved: instead of checking each time we send a packet whether we need also
to send an ARP, we should only check whether the MAC is valid.
- We should check arp_update_time in the master process. This would also require the generating task to clear its arp ring
+ We should check arp_ndp_retransmit_timeout in the master process. This would also require the generating task to clear its arp ring
to avoid sending many ARP while starting after a long stop.
- We could also check for arp_timeout in the master so that dataplane has only to check whether MAC is available
- but this would require either thread safety, or the exchange of information between master and generating core.
-*/
+ We could also check for reachable_timeout in the master so that dataplane has only to check whether MAC is available
+ but this would require either thread safety, or the the exchange of information between master and generating core.
+ */
-static inline int add_key_and_send_arp(struct rte_hash *ip_hash, uint32_t *ip_dst, struct arp_table *entries, uint64_t tsc, uint64_t hz, uint32_t arp_update_time, prox_next_hop_index_type nh, uint64_t **time)
+static inline int add_key_and_send_arp(struct rte_hash *ip_hash, uint32_t *ip_dst, struct arp_table *entries, uint64_t tsc, uint64_t hz, uint32_t arp_ndp_retransmit_timeout, prox_next_hop_index_type nh, uint64_t **time)
{
int ret = rte_hash_add_key(ip_hash, (const void *)ip_dst);
if (unlikely(ret < 0)) {
@@ -94,26 +173,26 @@ static inline int add_key_and_send_arp(struct rte_hash *ip_hash, uint32_t *ip_ds
} else {
entries[ret].ip = *ip_dst;
entries[ret].nh = nh;
- *time = &entries[ret].arp_update_time;
+ *time = &entries[ret].arp_ndp_retransmit_timeout;
}
- return SEND_ARP;
+ return SEND_ARP_ND;
}
-static inline int update_mac_and_send_mbuf(struct arp_table *entry, prox_rte_ether_addr *mac, uint64_t tsc, uint64_t hz, uint32_t arp_update_time, uint64_t **time)
+static inline int update_mac_and_send_mbuf(struct arp_table *entry, prox_rte_ether_addr *mac, uint64_t tsc, uint64_t hz, uint32_t arp_ndp_retransmit_timeout, uint64_t **time)
{
- if (likely((tsc < entry->arp_update_time) && (tsc < entry->arp_timeout))) {
+ if (likely((tsc < entry->arp_ndp_retransmit_timeout) && (tsc < entry->reachable_timeout))) {
memcpy(mac, &entry->mac, sizeof(prox_rte_ether_addr));
return SEND_MBUF;
- } else if (tsc > entry->arp_update_time) {
+ } else if (tsc > entry->arp_ndp_retransmit_timeout) {
// long time since we have sent an arp, send arp
- *time = &entry->arp_update_time;
- if (tsc < entry->arp_timeout){
+ *time = &entry->arp_ndp_retransmit_timeout;
+ if (tsc < entry->reachable_timeout){
// MAC is valid in the table => send also the mbuf
memcpy(mac, &entry->mac, sizeof(prox_rte_ether_addr));
- return SEND_MBUF_AND_ARP;
+ return SEND_MBUF_AND_ARP_ND;
} else {
// MAC still unknown, or timed out => only send ARP
- return SEND_ARP;
+ return SEND_ARP_ND;
}
}
// MAC is unknown and we already sent an ARP recently, drop mbuf and wait for ARP reply
@@ -154,7 +233,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
if (entry->ip) {
*ip_dst = entry->ip;
- return update_mac_and_send_mbuf(entry, mac, tsc, hz, l3->arp_update_time, time);
+ return update_mac_and_send_mbuf(entry, mac, tsc, hz, l3->arp_ndp_retransmit_timeout, time);
}
// no next ip: this is a local route
@@ -162,30 +241,32 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
int ret = rte_hash_lookup(l3->ip_hash, (const void *)ip_dst);
if (unlikely(ret < 0)) {
// IP not found, try to send an ARP
- return add_key_and_send_arp(l3->ip_hash, ip_dst, l3->arp_table, tsc, hz, l3->arp_update_time, MAX_HOP_INDEX, time);
+ return add_key_and_send_arp(l3->ip_hash, ip_dst, l3->arp_table, tsc, hz, l3->arp_ndp_retransmit_timeout, MAX_HOP_INDEX, time);
} else {
- return update_mac_and_send_mbuf(&l3->arp_table[ret], mac, tsc, hz, l3->arp_update_time, time);
+ return update_mac_and_send_mbuf(&l3->arp_table[ret], mac, tsc, hz, l3->arp_ndp_retransmit_timeout, time);
}
return 0;
}
// No Routing table specified: only a local ip and maybe a gateway
// Old default behavior: if a gw is specified, ALL packets go to this gateway (even those we could send w/o the gw
if (l3->gw.ip) {
- if (likely((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_update_time) && (tsc < l3->gw.arp_timeout))) {
+ if (likely((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_ndp_retransmit_timeout) && (tsc < l3->gw.reachable_timeout))) {
memcpy(mac, &l3->gw.mac, sizeof(prox_rte_ether_addr));
return SEND_MBUF;
- } else if (tsc > l3->gw.arp_update_time) {
+ } else if (tsc > l3->gw.arp_ndp_retransmit_timeout) {
// long time since we have successfully sent an arp, send arp
- // If sending ARP failed (ring full) then arp_update_time is not updated to avoid having to wait 1 sec to send ARP REQ again
- *time = &l3->gw.arp_update_time;
+ // If sending ARP failed (ring full) then arp_ndp_retransmit_timeout is not updated to avoid having to wait 1 sec to send ARP REQ again
+ *time = &l3->gw.arp_ndp_retransmit_timeout;
+ l3->gw.arp_ndp_retransmit_timeout = tsc + l3->arp_ndp_retransmit_timeout * hz / 1000;
+
*ip_dst = l3->gw.ip;
- if ((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_timeout)){
+ if ((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.reachable_timeout)){
// MAC is valid in the table => send also the mbuf
memcpy(mac, &l3->gw.mac, sizeof(prox_rte_ether_addr));
- return SEND_MBUF_AND_ARP;
+ return SEND_MBUF_AND_ARP_ND;
} else {
// MAC still unknown, or timed out => only send ARP
- return SEND_ARP;
+ return SEND_ARP_ND;
}
} else {
// MAC is unknown and we already sent an ARP recently, drop mbuf and wait for ARP reply
@@ -201,17 +282,16 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
if (likely(l3->n_pkts < 4)) {
for (unsigned int idx = 0; idx < l3->n_pkts; idx++) {
if (*ip_dst == l3->optimized_arp_table[idx].ip) {
- // IP address already in table
- return update_mac_and_send_mbuf(&l3->optimized_arp_table[idx], mac, tsc, hz, l3->arp_update_time, time);
+ return update_mac_and_send_mbuf(&l3->optimized_arp_table[idx], mac, tsc, hz, l3->arp_ndp_retransmit_timeout, time);
}
}
// IP address not found in table
l3->optimized_arp_table[l3->n_pkts].ip = *ip_dst;
- *time = &l3->optimized_arp_table[l3->n_pkts].arp_update_time;
+ *time = &l3->optimized_arp_table[l3->n_pkts].arp_ndp_retransmit_timeout;
l3->n_pkts++;
if (l3->n_pkts < 4) {
- return SEND_ARP;
+ return SEND_ARP_ND;
}
// We have too many IP addresses to search linearly; lets use hash table instead => copy all entries in hash table
@@ -228,16 +308,137 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
memcpy(&l3->arp_table[ret], &l3->optimized_arp_table[idx], sizeof(struct arp_table));
}
}
- return SEND_ARP;
+ return SEND_ARP_ND;
} else {
// Find IP in lookup table. Send ARP if not found
int ret = rte_hash_lookup(l3->ip_hash, (const void *)ip_dst);
if (unlikely(ret < 0)) {
// IP not found, try to send an ARP
- return add_key_and_send_arp(l3->ip_hash, ip_dst, &l3->arp_table[ret], tsc, hz, l3->arp_update_time, MAX_HOP_INDEX, time);
+ return add_key_and_send_arp(l3->ip_hash, ip_dst, &l3->arp_table[ret], tsc, hz, l3->arp_ndp_retransmit_timeout, MAX_HOP_INDEX, time);
+ } else {
+ // IP has been found
+ return update_mac_and_send_mbuf(&l3->arp_table[ret], mac, tsc, hz, l3->arp_ndp_retransmit_timeout, time);
+ }
+ }
+ // Should not happen
+ return DROP_MBUF;
+}
+
+int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv6_addr *ip_dst)
+{
+ const uint64_t hz = rte_get_tsc_hz();
+ prox_rte_ether_hdr *packet = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ether_addr *mac = &packet->d_addr;
+ struct ipv6_addr *used_ip_src;
+
+ uint64_t tsc = rte_rdtsc();
+ uint16_t len = rte_pktmbuf_pkt_len(mbuf);
+
+ struct ipv6_addr *pkt_src_ip6;
+ if ((pkt_src_ip6 = find_ip6(packet, len, ip_dst)) == NULL) {
+ // Unable to find IP address => non IP packet => send it as it
+ return SEND_MBUF;
+ }
+ struct l3_base *l3 = &(tbase->l3);
+ if (memcmp(&l3->local_ipv6, ip_dst, 8) == 0) {
+ // Same prefix as local -> use local
+ used_ip_src = &l3->local_ipv6;
+ } else if (memcmp(&l3->global_ipv6 , &null_addr, 16) != 0) {
+ // Global IP is defined -> use it
+ used_ip_src = &l3->global_ipv6;
+ } else {
+ plog_info("Error as trying to send a packet to "IPv6_BYTES_FMT" using "IPv6_BYTES_FMT" (local)\n", IPv6_BYTES(ip_dst->bytes), IPv6_BYTES(l3->local_ipv6.bytes));
+ return DROP_MBUF;
+ }
+
+ memcpy(pkt_src_ip6, used_ip_src, sizeof(struct ipv6_addr));
+ if (likely(l3->n_pkts < 4)) {
+ for (unsigned int idx = 0; idx < l3->n_pkts; idx++) {
+ if (memcmp(ip_dst, &l3->optimized_arp_table[idx].ip6, sizeof(struct ipv6_addr)) == 0) {
+ // IP address already in table
+ if ((tsc < l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout) && (tsc < l3->optimized_arp_table[idx].reachable_timeout)) {
+ // MAC address was recently updated in table, use it
+ // plog_dbg("Valid MAC address found => send packet\n");
+ memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(prox_rte_ether_addr));
+ return SEND_MBUF;
+ } else if (tsc > l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout) {
+ // NDP not sent since a long time, send NDP
+ l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout = tsc + l3->arp_ndp_retransmit_timeout * hz / 1000;
+ if (tsc < l3->optimized_arp_table[idx].reachable_timeout) {
+ // MAC still valid => also send mbuf
+ plog_dbg("Valid MAC found but NDP retransmit timeout => send packet and NDP\n");
+ memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(prox_rte_ether_addr));
+ return SEND_MBUF_AND_ARP_ND;
+ } else {
+ plog_dbg("Unknown MAC => send NDP but cannot send packet\n");
+ // MAC unvalid => only send NDP
+ return SEND_ARP_ND;
+ }
+ } else {
+ // NDP timeout elapsed, MAC not valid anymore but waiting for NDP reply
+ // plog_dbg("NDP reachable timeout elapsed - waiting for NDP reply\n");
+ return DROP_MBUF;
+ }
+ }
+ }
+ // IP address not found in table
+ memcpy(&l3->optimized_arp_table[l3->n_pkts].ip6, ip_dst, sizeof(struct ipv6_addr));
+ l3->optimized_arp_table[l3->n_pkts].arp_ndp_retransmit_timeout = tsc + l3->arp_ndp_retransmit_timeout * hz / 1000;
+ l3->n_pkts++;
+
+ if (l3->n_pkts < 4) {
+ return SEND_ARP_ND;
+ }
+
+ // We have too many IP addresses to search linearly; lets use hash table instead => copy all entries in hash table
+ for (uint32_t idx = 0; idx < l3->n_pkts; idx++) {
+ struct ipv6_addr *ip6 = &l3->optimized_arp_table[idx].ip6;
+ int ret = rte_hash_add_key(l3->ip6_hash, (const void *)ip6);
+ if (ret < 0) {
+ // This should not happen as few entries so far.
+ // If it happens, we still send the NDP as easier:
+ // If the NDP corresponds to this error, the NDP reply will be ignored
+ // If NDP does not correspond to this error/ip, then NDP reply will be handled.
+ plogx_err("Unable add ip "IPv6_BYTES_FMT" in mac_hash (already %d entries)\n", IPv6_BYTES(ip6->bytes), idx);
+ } else {
+ memcpy(&l3->arp_table[ret], &l3->optimized_arp_table[idx], sizeof(struct arp_table));
+ }
+ }
+ return SEND_ARP_ND;
+ } else {
+ // Find IP in lookup table. Send ND if not found
+ int ret = rte_hash_lookup(l3->ip6_hash, (const void *)ip_dst);
+ if (unlikely(ret < 0)) {
+ // IP not found, try to send an ND
+ int ret = rte_hash_add_key(l3->ip6_hash, (const void *)ip_dst);
+ if (ret < 0) {
+ // No reason to send NDP, as reply would be anyhow ignored
+ plogx_err("Unable to add ip "IPv6_BYTES_FMT" in mac_hash\n", IPv6_BYTES(ip_dst->bytes));
+ return DROP_MBUF;
+ } else {
+ memcpy(&l3->arp_table[ret].ip6, ip_dst, sizeof(struct ipv6_addr));
+ l3->arp_table[ret].arp_ndp_retransmit_timeout = tsc + l3->arp_ndp_retransmit_timeout * hz / 1000;
+ }
+ return SEND_ARP_ND;
} else {
// IP has been found
- return update_mac_and_send_mbuf(&l3->arp_table[ret], mac, tsc, hz, l3->arp_update_time, time);
+ if (likely((tsc < l3->arp_table[ret].arp_ndp_retransmit_timeout) && (tsc < l3->arp_table[ret].reachable_timeout))) {
+ // MAC still valid and NDP sent recently
+ memcpy(mac, &l3->arp_table[ret].mac, sizeof(prox_rte_ether_addr));
+ return SEND_MBUF;
+ } else if (tsc > l3->arp_table[ret].arp_ndp_retransmit_timeout) {
+ // NDP not sent since a long time, send NDP
+ l3->arp_table[ret].arp_ndp_retransmit_timeout = tsc + l3->arp_ndp_retransmit_timeout * hz / 1000;
+ if (tsc < l3->arp_table[ret].reachable_timeout) {
+ // MAC still valid => send also MBUF
+ memcpy(mac, &l3->arp_table[ret].mac, sizeof(prox_rte_ether_addr));
+ return SEND_MBUF_AND_ARP_ND;
+ } else {
+ return SEND_ARP_ND;
+ }
+ } else {
+ return DROP_MBUF;
+ }
}
}
// Should not happen
@@ -260,12 +461,22 @@ void task_init_l3(struct task_base *tbase, struct task_args *targ)
.hash_func = rte_hash_crc,
.hash_func_init_val = 0,
};
- tbase->l3.ip_hash = rte_hash_create(&hash_params);
- PROX_PANIC(tbase->l3.ip_hash == NULL, "Failed to set up ip hash table\n");
+ if (targ->flags & TASK_ARG_L3) {
+ plog_info("\tInitializing L3 (IPv4)\n");
+ tbase->l3.ip_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(tbase->l3.ip_hash == NULL, "Failed to set up ip hash table\n");
+ hash_name[0]++;
+ }
+ if (targ->flags & TASK_ARG_NDP) {
+ plog_info("\tInitializing NDP (IPv6)\n");
+ hash_params.key_len = sizeof(struct ipv6_addr);
+ tbase->l3.ip6_hash = rte_hash_create(&hash_params);
+ PROX_PANIC(tbase->l3.ip6_hash == NULL, "Failed to set up ip hash table\n");
+ }
tbase->l3.arp_table = (struct arp_table *)prox_zmalloc(n_entries * sizeof(struct arp_table), socket_id);
- PROX_PANIC(tbase->l3.arp_table == NULL, "Failed to allocate memory for %u entries in arp table\n", n_entries);
- plog_info("\tarp table, with %d entries of size %ld\n", n_entries, sizeof(struct l3_base));
+ PROX_PANIC(tbase->l3.arp_table == NULL, "Failed to allocate memory for %u entries in arp/ndp table\n", n_entries);
+ plog_info("\tarp/ndp table, with %d entries of size %ld\n", n_entries, sizeof(struct l3_base));
targ->lconf->ctrl_func_p[targ->task] = handle_ctrl_plane_pkts;
targ->lconf->ctrl_timeout = freq_to_tsc(targ->ctrl_freq);
@@ -275,36 +486,36 @@ void task_init_l3(struct task_base *tbase, struct task_args *targ)
tbase->l3.task_id = targ->id;
tbase->l3.tmaster = targ->tmaster;
tbase->l3.seed = (uint)rte_rdtsc();
- if (targ->arp_timeout != 0)
- tbase->l3.arp_timeout = targ->arp_timeout;
+ if (targ->reachable_timeout != 0)
+ tbase->l3.reachable_timeout = targ->reachable_timeout;
else
- tbase->l3.arp_timeout = DEFAULT_ARP_TIMEOUT;
- if (targ->arp_update_time != 0)
- tbase->l3.arp_update_time = targ->arp_update_time;
+ tbase->l3.reachable_timeout = DEFAULT_ARP_TIMEOUT;
+ if (targ->arp_ndp_retransmit_timeout != 0)
+ tbase->l3.arp_ndp_retransmit_timeout = targ->arp_ndp_retransmit_timeout;
else
- tbase->l3.arp_update_time = DEFAULT_ARP_UPDATE_TIME;
+ tbase->l3.arp_ndp_retransmit_timeout = DEFAULT_ARP_UPDATE_TIME;
}
void task_start_l3(struct task_base *tbase, struct task_args *targ)
{
- const int NB_ARP_MBUF = 1024;
- const int ARP_MBUF_SIZE = 2048;
- const int NB_CACHE_ARP_MBUF = 256;
const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);
+ const int NB_ARP_ND_MBUF = 1024;
+ const int ARP_ND_MBUF_SIZE = 2048;
+ const int NB_CACHE_ARP_ND_MBUF = 256;
struct prox_port_cfg *port = find_reachable_port(targ);
- if (port && (tbase->l3.arp_pool == NULL)) {
+ if (port && (tbase->l3.arp_nd_pool == NULL)) {
static char name[] = "arp0_pool";
tbase->l3.reachable_port_id = port - prox_port_cfg;
if (targ->local_ipv4) {
- tbase->local_ipv4 = rte_be_to_cpu_32(targ->local_ipv4);
- register_ip_to_ctrl_plane(tbase->l3.tmaster, tbase->local_ipv4, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
+ tbase->l3.local_ipv4 = rte_be_to_cpu_32(targ->local_ipv4);
+ register_ip_to_ctrl_plane(tbase->l3.tmaster, tbase->l3.local_ipv4, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
}
if (strcmp(targ->route_table, "") != 0) {
struct lpm4 *lpm;
int ret;
- PROX_PANIC(tbase->local_ipv4 == 0, "missing local_ipv4 will route table is specified in L3 mode\n");
+ PROX_PANIC(tbase->l3.local_ipv4 == 0, "missing local_ipv4 will route table is specified in L3 mode\n");
// LPM might be modified runtime => do not share with other cores
ret = lua_to_lpm4(prox_lua(), GLOBAL, targ->route_table, socket_id, &lpm);
@@ -330,7 +541,7 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ)
// Last but one "next_hop_index" is not a gateway but direct routes
tbase->l3.next_hops[tbase->l3.nb_gws].ip = 0;
ret = rte_lpm_add(tbase->l3.ipv4_lpm, targ->local_ipv4, targ->local_prefix, tbase->l3.nb_gws++);
- PROX_PANIC(ret, "Failed to add local_ipv4 "IPv4_BYTES_FMT"/%d to lpm\n", IP4(tbase->local_ipv4), targ->local_prefix);
+ PROX_PANIC(ret, "Failed to add local_ipv4 "IPv4_BYTES_FMT"/%d to lpm\n", IP4(tbase->l3.local_ipv4), targ->local_prefix);
// Last "next_hop_index" is default gw
tbase->l3.next_hops[tbase->l3.nb_gws].ip = rte_bswap32(targ->gateway_ipv4);
if (targ->gateway_ipv4) {
@@ -340,15 +551,50 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ)
}
master_init_vdev(tbase->l3.tmaster, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
+
+ // Create IPv6 addr if none were configured
+ if (targ->flags & TASK_ARG_NDP) {
+ if (!memcmp(&targ->local_ipv6, &null_addr, 16)) {
+ set_link_local(&targ->local_ipv6);
+ set_EUI(&targ->local_ipv6, &port->eth_addr);
+ }
+ plog_info("\tCore %d, task %d, local IPv6 addr is "IPv6_BYTES_FMT" (%s)\n",
+ targ->lconf->id, targ->id,
+ IPv6_BYTES(targ->local_ipv6.bytes),
+ IP6_Canonical(&targ->local_ipv6));
+ memcpy(&tbase->l3.local_ipv6, &targ->local_ipv6, sizeof(struct ipv6_addr));
+
+ if (memcmp(&targ->global_ipv6, &null_addr, sizeof(struct ipv6_addr))) {
+ memcpy(&tbase->l3.global_ipv6, &targ->global_ipv6, sizeof(struct ipv6_addr));
+ plog_info("\tCore %d, task %d, global IPv6 addr is "IPv6_BYTES_FMT" (%s)\n",
+ targ->lconf->id, targ->id,
+ IPv6_BYTES(targ->global_ipv6.bytes),
+ IP6_Canonical(&targ->global_ipv6));
+ }
+ if (targ->ipv6_router)
+ register_router_to_ctrl_plane(tbase->l3.tmaster, tbase->l3.reachable_port_id, targ->lconf->id, targ->id, &targ->local_ipv6, &targ->global_ipv6, &targ->router_prefix);
+ else
+ register_node_to_ctrl_plane(tbase->l3.tmaster, &targ->local_ipv6, &targ->global_ipv6, tbase->l3.reachable_port_id, targ->lconf->id, targ->id);
+ }
+
name[3]++;
- struct rte_mempool *ret = rte_mempool_create(name, NB_ARP_MBUF, ARP_MBUF_SIZE, NB_CACHE_ARP_MBUF,
+ struct rte_mempool *ret = rte_mempool_create(name, NB_ARP_ND_MBUF, ARP_ND_MBUF_SIZE, NB_CACHE_ARP_ND_MBUF,
sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, 0,
rte_socket_id(), 0);
- PROX_PANIC(ret == NULL, "Failed to allocate ARP memory pool on socket %u with %u elements\n",
- rte_socket_id(), NB_ARP_MBUF);
- plog_info("\t\tMempool %p (%s) size = %u * %u cache %u, socket %d\n", ret, name, NB_ARP_MBUF,
- ARP_MBUF_SIZE, NB_CACHE_ARP_MBUF, rte_socket_id());
- tbase->l3.arp_pool = ret;
+ PROX_PANIC(ret == NULL, "Failed to allocate ARP/ND memory pool on socket %u with %u elements\n",
+ rte_socket_id(), NB_ARP_ND_MBUF);
+ plog_info("\tMempool %p (%s) size = %u * %u cache %u, socket %d (for ARP/ND)\n", ret, name, NB_ARP_ND_MBUF,
+ ARP_ND_MBUF_SIZE, NB_CACHE_ARP_ND_MBUF, rte_socket_id());
+ tbase->l3.arp_nd_pool = ret;
+ if ((targ->flags & TASK_ARG_NDP) && (!targ->ipv6_router)) {
+ plog_info("Sending Router Sollicitation\n");
+ send_router_sollicitation(tbase, targ);
+ }
+ if ((targ->flags & TASK_ARG_NDP) && (targ->flags & TASK_ARG_SEND_NA_AT_STARTUP)) {
+ plog_info("Sending unsollicited Neighbour Advertisement\n");
+ send_unsollicited_neighbour_advertisement(tbase, targ);
+
+ }
}
}
@@ -360,10 +606,10 @@ void task_set_gateway_ip(struct task_base *tbase, uint32_t ip)
void task_set_local_ip(struct task_base *tbase, uint32_t ip)
{
- tbase->local_ipv4 = ip;
+ tbase->l3.local_ipv4 = ip;
}
-static void reset_arp_update_time(struct l3_base *l3, uint32_t ip)
+static void reset_arp_ndp_retransmit_timeout(struct l3_base *l3, uint32_t ip)
{
uint32_t idx;
plogx_dbg("MAC entry for IP "IPv4_BYTES_FMT" timeout in kernel\n", IP4(ip));
@@ -371,9 +617,9 @@ static void reset_arp_update_time(struct l3_base *l3, uint32_t ip)
if (l3->ipv4_lpm) {
int ret = rte_hash_lookup(l3->ip_hash, (const void *)&ip);
if (ret >= 0)
- l3->arp_table[ret].arp_update_time = 0;
+ l3->arp_table[ret].arp_ndp_retransmit_timeout = 0;
} else if (ip == l3->gw.ip) {
- l3->gw.arp_update_time = 0;
+ l3->gw.arp_ndp_retransmit_timeout = 0;
} else if (l3->n_pkts < 4) {
for (idx = 0; idx < l3->n_pkts; idx++) {
uint32_t ip_dst = l3->optimized_arp_table[idx].ip;
@@ -381,12 +627,12 @@ static void reset_arp_update_time(struct l3_base *l3, uint32_t ip)
break;
}
if (idx < l3->n_pkts) {
- l3->optimized_arp_table[idx].arp_update_time = 0;
+ l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout = 0;
}
} else {
int ret = rte_hash_lookup(l3->ip_hash, (const void *)&ip);
if (ret >= 0)
- l3->arp_table[ret].arp_update_time = 0;
+ l3->arp_table[ret].arp_ndp_retransmit_timeout = 0;
}
return;
}
@@ -413,15 +659,18 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
uint32_t ip, ip_dst, idx, gateway_ip, prefix;
prox_next_hop_index_type gateway_index;
int j, ret, modified_route;
+ uint64_t addr;
+ struct ipv6_addr *ip6, *ip6_dst;
uint16_t command;
prox_rte_ether_hdr *hdr;
struct ether_hdr_arp *hdr_arp;
struct l3_base *l3 = &tbase->l3;
uint64_t tsc= rte_rdtsc();
- uint64_t arp_timeout = l3->arp_timeout * hz / 1000;
+ uint64_t reachable_timeout = l3->reachable_timeout * hz / 1000;
uint32_t nh;
prox_rte_ipv4_hdr *pip;
prox_rte_udp_hdr *udp_hdr;
+ uint8_t port = tbase->l3.reachable_port_id;
for (j = 0; j < n_pkts; ++j) {
PREFETCH0(mbufs[j]);
@@ -434,10 +683,10 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
pip = NULL;
udp_hdr = NULL;
out[0] = OUT_HANDLED;
- command = mbufs[j]->udata64 & 0xFFFF;
+ command = get_command(mbufs[j]);
plogx_dbg("\tReceived %s mbuf %p\n", actions_string[command], mbufs[j]);
switch(command) {
- case ROUTE_ADD_FROM_CTRL:
+ case ROUTE_ADD_FROM_MASTER:
ip = ctrl_ring_get_ip(mbufs[j]);
gateway_ip = ctrl_ring_get_gateway_ip(mbufs[j]);
prefix = ctrl_ring_get_prefix(mbufs[j]);
@@ -457,7 +706,7 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
}
tx_drop(mbufs[j]);
break;
- case ROUTE_DEL_FROM_CTRL:
+ case ROUTE_DEL_FROM_MASTER:
ip = ctrl_ring_get_ip(mbufs[j]);
prefix = ctrl_ring_get_prefix(mbufs[j]);
@@ -471,15 +720,15 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
}
tx_drop(mbufs[j]);
break;
- case UPDATE_FROM_CTRL:
+ case MAC_INFO_FROM_MASTER:
hdr_arp = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr_arp *);
- ip = (mbufs[j]->udata64 >> 32) & 0xFFFFFFFF;
+ ip = get_ip(mbufs[j]);
if (prox_rte_is_zero_ether_addr(&hdr_arp->arp.data.sha)) {
// MAC timeout or deleted from kernel table => reset update_time
// This will cause us to send new ARP request
- // However, as arp_timeout not touched, we should continue sending our regular IP packets
- reset_arp_update_time(l3, ip);
+ // However, as reachable_timeout not touched, we should continue sending our regular IP packets
+ reset_arp_ndp_retransmit_timeout(l3, ip);
return;
} else
plogx_dbg("\tUpdating MAC entry for IP "IPv4_BYTES_FMT" with MAC "MAC_BYTES_FMT"\n",
@@ -494,20 +743,20 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
} else if ((nh = l3->arp_table[ret].nh) != MAX_HOP_INDEX) {
entry = &l3->next_hops[nh];
memcpy(&entry->mac, &(hdr_arp->arp.data.sha), sizeof(prox_rte_ether_addr));
- entry->arp_timeout = tsc + arp_timeout;
- update_arp_update_time(l3, &entry->arp_update_time, l3->arp_update_time);
+ entry->reachable_timeout = tsc + reachable_timeout;
+ update_arp_ndp_retransmit_timeout(l3, &entry->arp_ndp_retransmit_timeout, l3->arp_ndp_retransmit_timeout);
} else {
memcpy(&l3->arp_table[ret].mac, &(hdr_arp->arp.data.sha), sizeof(prox_rte_ether_addr));
- l3->arp_table[ret].arp_timeout = tsc + arp_timeout;
- update_arp_update_time(l3, &l3->arp_table[ret].arp_update_time, l3->arp_update_time);
+ l3->arp_table[ret].reachable_timeout = tsc + reachable_timeout;
+ update_arp_ndp_retransmit_timeout(l3, &l3->arp_table[ret].arp_ndp_retransmit_timeout, l3->arp_ndp_retransmit_timeout);
}
}
else if (ip == l3->gw.ip) {
// MAC address of the gateway
memcpy(&l3->gw.mac, &hdr_arp->arp.data.sha, 6);
l3->flags |= FLAG_DST_MAC_KNOWN;
- l3->gw.arp_timeout = tsc + arp_timeout;
- update_arp_update_time(l3, &l3->gw.arp_update_time, l3->arp_update_time);
+ l3->gw.reachable_timeout = tsc + reachable_timeout;
+ update_arp_ndp_retransmit_timeout(l3, &l3->gw.arp_ndp_retransmit_timeout, l3->arp_ndp_retransmit_timeout);
} else if (l3->n_pkts < 4) {
// Few packets tracked - should be faster to loop through them thean using a hash table
for (idx = 0; idx < l3->n_pkts; idx++) {
@@ -517,8 +766,8 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
}
if (idx < l3->n_pkts) {
memcpy(&l3->optimized_arp_table[idx].mac, &(hdr_arp->arp.data.sha), sizeof(prox_rte_ether_addr));
- l3->optimized_arp_table[idx].arp_timeout = tsc + arp_timeout;
- update_arp_update_time(l3, &l3->optimized_arp_table[idx].arp_update_time, l3->arp_update_time);
+ l3->optimized_arp_table[idx].reachable_timeout = tsc + reachable_timeout;
+ update_arp_ndp_retransmit_timeout(l3, &l3->optimized_arp_table[idx].arp_ndp_retransmit_timeout, l3->arp_ndp_retransmit_timeout);
}
} else {
ret = rte_hash_add_key(l3->ip_hash, (const void *)&ip);
@@ -526,21 +775,49 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
plogx_info("Unable add ip "IPv4_BYTES_FMT" in mac_hash\n", IP4(ip));
} else {
memcpy(&l3->arp_table[ret].mac, &(hdr_arp->arp.data.sha), sizeof(prox_rte_ether_addr));
- l3->arp_table[ret].arp_timeout = tsc + arp_timeout;
- update_arp_update_time(l3, &l3->arp_table[ret].arp_update_time, l3->arp_update_time);
+ l3->arp_table[ret].reachable_timeout = tsc + reachable_timeout;
+ update_arp_ndp_retransmit_timeout(l3, &l3->arp_table[ret].arp_ndp_retransmit_timeout, l3->arp_ndp_retransmit_timeout);
+ }
+ }
+ tx_drop(mbufs[j]);
+ break;
+ case MAC_INFO_FROM_MASTER_FOR_IPV6:
+ ip6 = ctrl_ring_get_ipv6_addr(mbufs[j]);
+ uint64_t data = ctrl_ring_get_data(mbufs[j]);
+
+ if (l3->n_pkts < 4) {
+ // Few packets tracked - should be faster to loop through them thean using a hash table
+ for (idx = 0; idx < l3->n_pkts; idx++) {
+ ip6_dst = &l3->optimized_arp_table[idx].ip6;
+ if (memcmp(ip6_dst, ip6, sizeof(struct ipv6_addr)) == 0)
+ break;
+ }
+ if (idx < l3->n_pkts) {
+ // IP found; this is a reply for one of our requests!
+ memcpy(&l3->optimized_arp_table[idx].mac, &data, sizeof(prox_rte_ether_addr));
+ l3->optimized_arp_table[idx].reachable_timeout = tsc + l3->reachable_timeout * hz / 1000;
+ }
+ } else {
+ int ret = rte_hash_add_key(l3->ip6_hash, (const void *)ip6);
+ if (ret < 0) {
+ plogx_info("Unable add ip "IPv6_BYTES_FMT" in mac_hash\n", IPv6_BYTES(ip6->bytes));
+ } else {
+ memcpy(&l3->arp_table[ret].mac, &data, sizeof(prox_rte_ether_addr));
+ l3->arp_table[ret].reachable_timeout = tsc + l3->reachable_timeout * hz / 1000;
}
}
tx_drop(mbufs[j]);
break;
- case ARP_REPLY_FROM_CTRL:
- case ARP_REQ_FROM_CTRL:
+ case SEND_NDP_FROM_MASTER:
+ case SEND_ARP_REQUEST_FROM_MASTER:
+ case SEND_ARP_REPLY_FROM_MASTER:
out[0] = 0;
// tx_ctrlplane_pkt does not drop packets
plogx_dbg("\tForwarding (ARP) packet from master\n");
tbase->aux->tx_ctrlplane_pkt(tbase, &mbufs[j], 1, out);
TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
break;
- case ICMP_FROM_CTRL:
+ case SEND_ICMP_FROM_MASTER:
out[0] = 0;
// tx_ctrlplane_pkt does not drop packets
plogx_dbg("\tForwarding (PING) packet from master\n");
@@ -584,6 +861,26 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
tbase->aux->tx_ctrlplane_pkt(tbase, &mbufs[j], 1, out);
TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
break;
+ case IPV6_INFO_FROM_MASTER:
+ // addr = ctrl_ring_get_data(mbufs[j]);
+ ip6 = ctrl_ring_get_ipv6_addr(mbufs[j]);
+ if (memcmp(&l3->global_ipv6 , &null_addr, 16) == 0) {
+ memcpy(&l3->global_ipv6, ip6, sizeof(struct ipv6_addr));
+ plog_info("Core %d task %d received global IP "IPv6_BYTES_FMT"\n", l3->core_id, l3->task_id, IPv6_BYTES(ip6->bytes));
+ } else if (memcmp(&l3->global_ipv6, ip6, 8) == 0) {
+ if (l3->prefix_printed == 0) {
+ plog_info("Core %d task %d received expected prefix "IPv6_PREFIX_FMT"\n", l3->core_id, l3->task_id, IPv6_PREFIX(ip6->bytes));
+ l3->prefix_printed = 1;
+ }
+ } else {
+ plog_warn("Core %d task %d received unexpected prefix "IPv6_PREFIX_FMT", IP = "IPv6_PREFIX_FMT"\n", l3->core_id, l3->task_id, IPv6_PREFIX(ip6->bytes), IPv6_PREFIX(l3->global_ipv6.bytes));
+ }
+ tx_drop(mbufs[j]);
+ break;
+ default:
+ plog_err("Unexpected message received: %d\n", command);
+ tx_drop(mbufs[j]);
+ break;
}
}
}
diff --git a/VNFs/DPPD-PROX/packet_utils.h b/VNFs/DPPD-PROX/packet_utils.h
index 0a1ef9d..ca4d449 100644
--- a/VNFs/DPPD-PROX/packet_utils.h
+++ b/VNFs/DPPD-PROX/packet_utils.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -29,9 +29,9 @@
#define IP4(x) x & 0xff, (x >> 8) & 0xff, (x >> 16) & 0xff, x >> 24 // From Network (BE)
enum {
- SEND_MBUF_AND_ARP,
+ SEND_MBUF_AND_ARP_ND,
SEND_MBUF,
- SEND_ARP,
+ SEND_ARP_ND,
DROP_MBUF
};
#define DEFAULT_ARP_TIMEOUT (1000 * 3600 * 24 * 15) // ~15 days = disabled by default
@@ -39,42 +39,50 @@ enum {
struct task_base;
struct task_args;
+struct task_master;
struct arp_table {
- uint64_t arp_update_time;
- uint64_t arp_timeout;
+ uint64_t arp_ndp_retransmit_timeout;
+ uint64_t reachable_timeout;
uint32_t ip;
uint32_t nh;
prox_rte_ether_addr mac;
+ struct ipv6_addr ip6;
};
struct l3_base {
struct rte_ring *ctrl_plane_ring;
struct task_base *tmaster;
uint32_t flags;
uint32_t n_pkts;
+ uint32_t local_ipv4;
uint8_t reachable_port_id;
uint8_t core_id;
uint8_t task_id;
- uint32_t arp_timeout;
- uint32_t arp_update_time;
uint seed;
prox_next_hop_index_type nb_gws;
+ uint32_t arp_ndp_retransmit_timeout;
+ uint32_t reachable_timeout;
struct arp_table gw;
struct arp_table optimized_arp_table[4];
struct rte_hash *ip_hash;
+ struct rte_hash *ip6_hash;
struct arp_table *arp_table;
- struct rte_mempool *arp_pool;
struct rte_lpm *ipv4_lpm;
struct arp_table *next_hops;
+ struct rte_mempool *arp_nd_pool;
+ struct ipv6_addr local_ipv6;
+ struct ipv6_addr global_ipv6;
+ uint8_t prefix_printed;
};
void task_init_l3(struct task_base *tbase, struct task_args *targ);
void task_start_l3(struct task_base *tbase, struct task_args *targ);
int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_dst, uint64_t **time, uint64_t tsc);
+int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv6_addr *ip_dst);
void task_set_gateway_ip(struct task_base *tbase, uint32_t ip);
void task_set_local_ip(struct task_base *tbase, uint32_t ip);
void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts);
-static inline void update_arp_update_time(struct l3_base *l3, uint64_t *ptr, uint32_t base)
+static inline void update_arp_ndp_retransmit_timeout(struct l3_base *l3, uint64_t *ptr, uint32_t base)
{
// randomize timers - from 0.5 to 1.5 * configured time
const uint64_t hz = rte_get_tsc_hz();
@@ -82,4 +90,9 @@ static inline void update_arp_update_time(struct l3_base *l3, uint64_t *ptr, uin
uint64_t rand = 500 + (1000L * rand_r(&l3->seed)) / RAND_MAX;
*ptr = tsc + (base * rand / 1000) * hz / 1000;
}
+static inline uint8_t get_port(struct rte_mbuf *mbuf)
+{
+ return mbuf->port;
+}
+
#endif /* _PACKET_UTILS_H_ */
diff --git a/VNFs/DPPD-PROX/parse_utils.c b/VNFs/DPPD-PROX/parse_utils.c
index 887de80..ab0e03b 100644
--- a/VNFs/DPPD-PROX/parse_utils.c
+++ b/VNFs/DPPD-PROX/parse_utils.c
@@ -27,13 +27,13 @@
#include "quit.h"
#include "cfgfile.h"
-#include "ip6_addr.h"
#include "parse_utils.h"
#include "prox_globals.h"
#include "prox_cfg.h"
#include "log.h"
#include "prox_lua.h"
#include "prox_lua_types.h"
+#include "prox_ipv6.h"
#include "prox_compat.h"
#define MAX_NB_PORT_NAMES PROX_MAX_PORTS
@@ -406,12 +406,12 @@ int parse_ip6(struct ipv6_addr *addr, const char *str2)
for (uint8_t i = 0, j = 0; i < ret; ++i, ++j) {
if (*addr_parts[i] == 0) {
- if (omitted == 0) {
+ if (omitted) {
set_errf("Can only omit zeros once");
return -1;
}
omitted = 1;
- j += 8 - ret;
+ j += 2 * (8 - ret) + 1;
}
else {
uint16_t w = strtoll(addr_parts[i], NULL, 16);
diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c
index cc8b3b2..25599cb 100644
--- a/VNFs/DPPD-PROX/prox_args.c
+++ b/VNFs/DPPD-PROX/prox_args.c
@@ -35,6 +35,8 @@
#include "defaults.h"
#include "prox_lua.h"
#include "cqm.h"
+#include "defines.h"
+#include "prox_ipv6.h"
#include "prox_compat.h"
#define MAX_RTE_ARGV 64
@@ -976,6 +978,9 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
if (STR_EQ(str, "streams")) {
return parse_str(targ->streams, pkey, sizeof(targ->streams));
}
+ if (STR_EQ(str, "Unsollicited NA")) {
+ return parse_flag(&targ->flags, TASK_ARG_SEND_NA_AT_STARTUP, pkey);
+ }
if (STR_EQ(str, "local lpm")) {
return parse_flag(&targ->flags, TASK_ARG_LOCAL_LPM, pkey);
}
@@ -1381,7 +1386,7 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
targ->task_init = to_task_init(mode_str, sub_mode_str);
if (!targ->task_init) {
- if (strcmp(sub_mode_str, "l3") != 0) {
+ if ((strcmp(sub_mode_str, "l3") != 0) && (strcmp(sub_mode_str, "ndp") != 0)) {
set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
return -1;
}
@@ -1392,9 +1397,13 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
}
}
if (strcmp(sub_mode_str, "l3") == 0) {
- prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
+ prox_cfg.flags |= DSF_L3_ENABLED;
targ->flags |= TASK_ARG_L3;
strcpy(targ->sub_mode_str, "l3");
+ } else if (strcmp(sub_mode_str, "ndp") == 0) {
+ prox_cfg.flags |= DSF_NDP_ENABLED;
+ targ->flags |= TASK_ARG_NDP;
+ strcpy(targ->sub_mode_str, "ndp");
} else {
strcpy(targ->sub_mode_str, targ->task_init->sub_mode_str);
}
@@ -1453,6 +1462,16 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
targ->local_prefix = 32;
return parse_ip(&targ->gateway_ipv4, pkey);
}
+ if (STR_EQ(str, "ipv6 router")) { /* we simulate an IPV6 router */
+ int rc = parse_flag(&targ->ipv6_router, 1, pkey);
+ if (!rc && targ->ipv6_router) {
+ plog_info("\tipv6 router configured => NDP enabled\n");
+ prox_cfg.flags |= DSF_NDP_ENABLED;
+ targ->flags |= TASK_ARG_NDP;
+ strcpy(targ->sub_mode_str, "ndp");
+ }
+ return 0;
+ }
if (STR_EQ(str, "local ipv4")) { /* source IP address to be used for packets */
struct ip4_subnet cidr;
if (parse_ip4_cidr(&cidr, pkey) != 0) {
@@ -1470,13 +1489,43 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
if (STR_EQ(str, "remote ipv4")) { /* source IP address to be used for packets */
return parse_ip(&targ->remote_ipv4, pkey);
}
+ if (STR_EQ(str, "global ipv6")) {
+ if (parse_ip6(&targ->global_ipv6, pkey) == 0) {
+ plog_info("\tglobal ipv6 configured => NDP enabled\n");
+ targ->flags |= TASK_ARG_NDP;
+ prox_cfg.flags |= DSF_NDP_ENABLED;
+ strcpy(targ->sub_mode_str, "ndp");
+ } else {
+ plog_err("Unable to parse content of local ipv6: %s\n", pkey);
+ return -1;
+ }
+ return 0;
+ }
if (STR_EQ(str, "local ipv6")) { /* source IPv6 address to be used for packets */
- return parse_ip6(&targ->local_ipv6, pkey);
+ if (parse_ip6(&targ->local_ipv6, pkey) == 0) {
+ plog_info("\tlocal ipv6 configured => NDP enabled\n");
+ targ->flags |= TASK_ARG_NDP;
+ prox_cfg.flags |= DSF_NDP_ENABLED;
+ strcpy(targ->sub_mode_str, "ndp");
+ } else {
+ plog_err("Unable to parse content of local ipv6: %s\n", pkey);
+ return -1;
+ }
+ return 0;
}
+ if (STR_EQ(str, "router prefix")) {
+ if (parse_ip6(&targ->router_prefix, pkey) == 0) {
+ plog_info("\trouter prefix set to "IPv6_BYTES_FMT" (%s)\n", IPv6_BYTES(targ->router_prefix.bytes), IP6_Canonical(&targ->router_prefix));
+ } else {
+ plog_err("Unable to parse content of router prefix: %s\n", pkey);
+ return -1;
+ }
+ return 0;
+ }
if (STR_EQ(str, "arp timeout"))
- return parse_int(&targ->arp_timeout, pkey);
+ return parse_int(&targ->reachable_timeout, pkey);
if (STR_EQ(str, "arp update time"))
- return parse_int(&targ->arp_update_time, pkey);
+ return parse_int(&targ->arp_ndp_retransmit_timeout, pkey);
if (STR_EQ(str, "number of packets"))
return parse_int(&targ->n_pkts, pkey);
if (STR_EQ(str, "pipes")) {
diff --git a/VNFs/DPPD-PROX/prox_cfg.h b/VNFs/DPPD-PROX/prox_cfg.h
index 8c4bd6c..e23c8ed 100644
--- a/VNFs/DPPD-PROX/prox_cfg.h
+++ b/VNFs/DPPD-PROX/prox_cfg.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,8 +18,11 @@
#define _PROX_CFG_H
#include <inttypes.h>
+#include <rte_ether.h>
#include "prox_globals.h"
+#include "ip6_addr.h"
+#include "prox_compat.h"
#define PROX_CM_STR_LEN (2 + 2 * sizeof(prox_cfg.core_mask) + 1)
#define PROX_CM_DIM (RTE_MAX_LCORE/(sizeof(uint64_t) * 8))
@@ -40,7 +43,9 @@
#define DSF_DISABLE_CMT 0x00002000 /* CMT disabled */
#define DSF_LIST_TASK_MODES 0x00004000 /* list supported task modes and exit */
#define DSF_ENABLE_BYPASS 0x00008000 /* Use Multi Producer rings to enable ring bypass */
-#define DSF_CTRL_PLANE_ENABLED 0x00010000 /* ctrl plane enabled */
+#define DSF_L3_ENABLED 0x00010000 /* ctrl plane enabled for IPv4 */
+#define DSF_NDP_ENABLED 0x00020000 /* ctrl plane enabled for IPv6 */
+#define DSF_CTRL_PLANE_ENABLED (DSF_L3_ENABLED|DSF_NDP_ENABLED) /* ctrl plane enabled */
#define MAX_PATH_LEN 1024
@@ -69,6 +74,11 @@ struct prox_cfg {
uint32_t heartbeat_timeout;
uint32_t poll_timeout;
uint64_t heartbeat_tsc;
+ struct ipv6_addr all_routers_ipv6_mcast_addr;
+ struct ipv6_addr all_nodes_ipv6_mcast_addr;
+ struct ipv6_addr random_ip;
+ prox_rte_ether_addr all_routers_mac_addr;
+ prox_rte_ether_addr all_nodes_mac_addr;
};
extern struct prox_cfg prox_cfg;
diff --git a/VNFs/DPPD-PROX/prox_cksum.h b/VNFs/DPPD-PROX/prox_cksum.h
index 6ba5026..03be595 100644
--- a/VNFs/DPPD-PROX/prox_cksum.h
+++ b/VNFs/DPPD-PROX/prox_cksum.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
#include <rte_mbuf.h>
#include "igmp.h"
#include "prox_compat.h"
+#include "prox_ipv6.h"
#if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
#define CALC_TX_OL(l2_len, l3_len) ((uint64_t)(l2_len) | (uint64_t)(l3_len) << 7)
@@ -68,4 +69,11 @@ void prox_udp_cksum_sw(prox_rte_udp_hdr *udp, uint16_t len, uint32_t src_ip_addr
void prox_tcp_cksum_sw(prox_rte_tcp_hdr *tcp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr);
void prox_igmp_cksum_sw(struct igmpv2_hdr *igmp, uint16_t len);
+struct ipv6_pseudo_hdr {
+ struct ipv6_addr src;
+ struct ipv6_addr dst;
+ uint32_t length;
+ uint32_t protocl:8;
+ uint32_t reserved:24;
+} __attribute__((__packed__));
#endif /* _PROX_CKSUM_H_ */
diff --git a/VNFs/DPPD-PROX/prox_compat.c b/VNFs/DPPD-PROX/prox_compat.c
new file mode 100644
index 0000000..572872e
--- /dev/null
+++ b/VNFs/DPPD-PROX/prox_compat.c
@@ -0,0 +1,30 @@
+/*
+// Copyright (c) 2010-2017 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <stddef.h>
+#include "quit.h"
+#include "prox_compat.h"
+
+char *prox_strncpy(char * dest, const char * src, size_t count)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wstringop-truncation"
+ strncpy(dest, src, count);
+#pragma GCC diagnostic pop
+ PROX_PANIC(dest[count - 1] != 0, "\t\tError in strncpy: buffer overrun (%lu bytes)", count);
+ return dest;
+}
diff --git a/VNFs/DPPD-PROX/prox_compat.h b/VNFs/DPPD-PROX/prox_compat.h
index bd059a6..091c2cc 100644
--- a/VNFs/DPPD-PROX/prox_compat.h
+++ b/VNFs/DPPD-PROX/prox_compat.h
@@ -20,7 +20,6 @@
#include <rte_hash_crc.h>
#include <rte_cryptodev.h>
#include "hash_utils.h"
-#include "quit.h"
/* This is a copy of the rte_table_hash_params from DPDK 17.11 *
* So if DPDK decides to change the structure the modifications *
@@ -221,16 +220,8 @@ typedef struct rte_icmp_hdr prox_rte_icmp_hdr;
#endif
-static inline char *prox_strncpy(char * dest, const char * src, size_t count)
-{
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic ignored "-Wstringop-truncation"
- strncpy(dest, src, count);
-#pragma GCC diagnostic pop
- PROX_PANIC(dest[count - 1] != 0, "\t\tError in strncpy: buffer overrun (%lu bytes)", count);
- return dest;
-}
+char *prox_strncpy(char * dest, const char * src, size_t count);
+
#ifdef RTE_LIBRTE_PMD_AESNI_MB
#if RTE_VERSION < RTE_VERSION_NUM(19,5,0,0)
//RFC4303
diff --git a/VNFs/DPPD-PROX/prox_ipv6.c b/VNFs/DPPD-PROX/prox_ipv6.c
new file mode 100644
index 0000000..9425f4a
--- /dev/null
+++ b/VNFs/DPPD-PROX/prox_ipv6.c
@@ -0,0 +1,302 @@
+/*
+// Copyright (c) 2020 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "task_base.h"
+#include "handle_master.h"
+#include "prox_cfg.h"
+#include "prox_ipv6.h"
+
+struct ipv6_addr null_addr = {{0}};
+char ip6_str[40]; // 8 blocks of 2 bytes (4 char) + 1x ":" between blocks
+
+void set_mcast_mac_from_ipv6(prox_rte_ether_addr *mac, struct ipv6_addr *ipv6_addr)
+{
+ mac->addr_bytes[0] = 0x33;
+ mac->addr_bytes[1] = 0x33;
+ memcpy(((uint32_t *)&mac->addr_bytes[2]), (uint32_t *)(&ipv6_addr->bytes[12]), sizeof(uint32_t));
+}
+
+// Note that this function is not Mthread safe and would result in garbage if called simultaneously from multiple threads
+// This function is however only used for debugging, printing errors...
+char *IP6_Canonical(struct ipv6_addr *addr)
+{
+ uint8_t *a = (uint8_t *)addr;
+ char *ptr = ip6_str;
+ int field = -1, len = 0, stored_field = 0, stored_len = 0;
+
+ // Find longest run of consecutive 16-bit 0 fields
+ for (int i = 0; i < 8; i++) {
+ if (((int)a[i * 2] == 0) && ((int)a[i * 2 + 1] == 0)) {
+ len++;
+ if (field == -1)
+ field = i; // Store where the first 0 field started
+ } else {
+ if (len > stored_len) {
+ // the longest run of consecutive 16-bit 0 fields MUST be shortened
+ stored_len = len;
+ stored_field = field;
+ }
+ len = 0;
+ field = -1;
+ }
+ }
+ if (len > stored_len) {
+ // the longest run of consecutive 16-bit 0 fields MUST be shortened
+ stored_len = len;
+ stored_field = field;
+ }
+ if (stored_len <= 1) {
+ // The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
+ stored_len = 0;
+ stored_field = -1;
+ }
+ for (int i = 0; i < 8; i++) {
+ if (i == stored_field) {
+ sprintf(ptr, ":");
+ ptr++;
+ if (i == 0) {
+ sprintf(ptr, ":");
+ ptr++;
+ }
+ i +=stored_len - 1; // ++ done in for loop
+ continue;
+ }
+ if ((int)a[i * 2] & 0xF0) {
+ sprintf(ptr, "%02x%02x", (int)a[i * 2], (int)a[i * 2 + 1]);
+ ptr+=4;
+ } else if ((int)a[i * 2] & 0x0F) {
+ sprintf(ptr, "%x%02x", (int)a[i * 2] >> 4, (int)a[i * 2] + 1);
+ ptr+=3;
+ } else if ((int)a[i * 2 + 1] & 0xF0) {
+ sprintf(ptr, "%02x", (int)a[i * 2 + 1]);
+ ptr+=2;
+ } else {
+ sprintf(ptr, "%x", ((int)a[i * 2 + 1]) & 0xF);
+ ptr++;
+ }
+ if (i != 7) {
+ sprintf(ptr, ":");
+ ptr++;
+ }
+ }
+ return ip6_str;
+}
+
+void set_link_local(struct ipv6_addr *ipv6_addr)
+{
+ ipv6_addr->bytes[0] = 0xfe;
+ ipv6_addr->bytes[1] = 0x80;
+}
+
+// Create Extended Unique Identifier (RFC 2373)
+// Store it in LSB of IPv6 address
+void set_EUI(struct ipv6_addr *ipv6_addr, prox_rte_ether_addr *mac)
+{
+ memcpy(&ipv6_addr->bytes[8], mac, 3); // Copy first 3 bytes of MAC
+ ipv6_addr->bytes[8] = ipv6_addr->bytes[8] ^ 0x02; // Invert Universal/local bit
+ ipv6_addr->bytes[11] = 0xff; // Next 2 bytes are 0xfffe
+ ipv6_addr->bytes[12] = 0xfe;
+ memcpy(&ipv6_addr->bytes[13], &mac->addr_bytes[3], 3); // Copy last 3 bytes
+ // plog_info("mac = "MAC_BYTES_FMT", eui = "IPv6_BYTES_FMT"\n", MAC_BYTES(mac->addr_bytes), IPv6_BYTES(ipv6_addr->bytes));
+}
+
+void create_mac_from_EUI(struct ipv6_addr *ipv6_addr, prox_rte_ether_addr *mac)
+{
+ memcpy(mac, &ipv6_addr->bytes[8], 3);
+ mac->addr_bytes[0] = mac->addr_bytes[0] ^ 0x02;
+ memcpy(&mac->addr_bytes[3], &ipv6_addr->bytes[13], 3);
+}
+void build_router_advertisement(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *ipv6_s_addr, struct ipv6_addr *router_prefix)
+{
+ prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ init_mbuf_seg(mbuf);
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM); // Software calculates the checksum
+
+ memcpy(peth->d_addr.addr_bytes, &prox_cfg.all_nodes_mac_addr, sizeof(prox_rte_ether_addr));
+ memcpy(peth->s_addr.addr_bytes, s_addr, sizeof(prox_rte_ether_addr));
+ peth->ether_type = ETYPE_IPv6;
+
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(peth + 1);
+ ipv6_hdr->vtc_flow = 0x00000060;
+ ipv6_hdr->payload_len = rte_cpu_to_be_16(sizeof(struct icmpv6_RA) + sizeof(struct icmpv6_prefix_option));
+ ipv6_hdr->proto = ICMPv6;
+ ipv6_hdr->hop_limits = 255;
+ memcpy(ipv6_hdr->src_addr, ipv6_s_addr, sizeof(struct ipv6_addr)); // 0 = "Unspecified address" if unknown
+ memcpy(ipv6_hdr->dst_addr, &prox_cfg.all_nodes_ipv6_mcast_addr, sizeof(struct ipv6_addr));
+
+ struct icmpv6_RA *router_advertisement = (struct icmpv6_RA *)(ipv6_hdr + 1);
+ router_advertisement->type = ICMPv6_RA;
+ router_advertisement->code = 0;
+ router_advertisement->hop_limit = 255;
+ router_advertisement->bits = 0; // M and O bits set to 0 => no dhcpv6
+ router_advertisement->router_lifespan = rte_cpu_to_be_16(9000); // 9000 sec
+ router_advertisement->reachable_timeout = rte_cpu_to_be_32(30000); // 1 sec
+ router_advertisement->retrans_timeout = rte_cpu_to_be_32(1000); // 30 sec
+
+ struct icmpv6_option *option = &router_advertisement->options;
+ option->type = ICMPv6_source_link_layer_address;
+ option->length = 1; // 8 bytes
+ memcpy(&option->data, s_addr, sizeof(prox_rte_ether_addr));
+
+ struct icmpv6_prefix_option *prefix_option = (struct icmpv6_prefix_option *)(option + 1);
+ prefix_option->type = ICMPv6_prefix_information;
+ prefix_option->length = 4; // 32 bytes
+ prefix_option->prefix_length = 64; // 64 bits in prefix
+ prefix_option->flag = 0xc0; // on-link flag & autonamous address-configuration flag are set
+ prefix_option->valid_lifetime = rte_cpu_to_be_32(86400); // 1 day
+ prefix_option->preferred_lifetime = rte_cpu_to_be_32(43200); // 12 hours
+ prefix_option->reserved = 0;
+ memcpy(&prefix_option->prefix, router_prefix, sizeof(struct ipv6_addr));
+ // Could Add MTU Option
+ router_advertisement->checksum = 0;
+ router_advertisement->checksum = rte_ipv6_udptcp_cksum(ipv6_hdr, router_advertisement);
+
+ uint16_t pktlen = rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr);
+ rte_pktmbuf_pkt_len(mbuf) = pktlen;
+ rte_pktmbuf_data_len(mbuf) = pktlen;
+}
+
+void build_router_sollicitation(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *ipv6_s_addr)
+{
+ prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+
+ init_mbuf_seg(mbuf);
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM); // Software calculates the checksum
+
+ memcpy(peth->d_addr.addr_bytes, &prox_cfg.all_routers_mac_addr, sizeof(prox_rte_ether_addr));
+ memcpy(peth->s_addr.addr_bytes, s_addr, sizeof(prox_rte_ether_addr));
+ peth->ether_type = ETYPE_IPv6;
+
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(peth + 1);
+ ipv6_hdr->vtc_flow = 0x00000060;
+ ipv6_hdr->payload_len = rte_cpu_to_be_16(sizeof(struct icmpv6_RS));
+ ipv6_hdr->proto = ICMPv6;
+ ipv6_hdr->hop_limits = 255;
+ memcpy(ipv6_hdr->src_addr, ipv6_s_addr, sizeof(struct ipv6_addr)); // 0 = "Unspecified address" if unknown
+ memcpy(ipv6_hdr->dst_addr, &prox_cfg.all_routers_ipv6_mcast_addr, sizeof(struct ipv6_addr));
+
+ struct icmpv6_RS *router_sollicitation = (struct icmpv6_RS *)(ipv6_hdr + 1);
+ router_sollicitation->type = ICMPv6_RS;
+ router_sollicitation->code = 0;
+ router_sollicitation->options.type = ICMPv6_source_link_layer_address;
+ router_sollicitation->options.length = 1; // 8 bytes
+ memcpy(&router_sollicitation->options.data, s_addr, sizeof(prox_rte_ether_addr));
+
+ router_sollicitation->checksum = 0;
+ router_sollicitation->checksum = rte_ipv6_udptcp_cksum(ipv6_hdr, router_sollicitation);
+ uint16_t pktlen = rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr);
+ rte_pktmbuf_pkt_len(mbuf) = pktlen;
+ rte_pktmbuf_data_len(mbuf) = pktlen;
+}
+
+void build_neighbour_sollicitation(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *dst, struct ipv6_addr *src)
+{
+ prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ether_addr mac_dst;
+ set_mcast_mac_from_ipv6(&mac_dst, dst);
+
+ init_mbuf_seg(mbuf);
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM); // Software calculates the checksum
+
+ memcpy(peth->d_addr.addr_bytes, &mac_dst, sizeof(prox_rte_ether_addr));
+ memcpy(peth->s_addr.addr_bytes, s_addr, sizeof(prox_rte_ether_addr));
+ peth->ether_type = ETYPE_IPv6;
+
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(peth + 1);
+ ipv6_hdr->vtc_flow = 0x00000060;
+ ipv6_hdr->payload_len = rte_cpu_to_be_16(sizeof(struct icmpv6_NS));
+ ipv6_hdr->proto = ICMPv6;
+ ipv6_hdr->hop_limits = 255;
+ memcpy(ipv6_hdr->src_addr, src, 16);
+ memcpy(ipv6_hdr->dst_addr, dst, 16);
+
+ struct icmpv6_NS *neighbour_sollicitation = (struct icmpv6_NS *)(ipv6_hdr + 1);
+ neighbour_sollicitation->type = ICMPv6_NS;
+ neighbour_sollicitation->code = 0;
+ neighbour_sollicitation->reserved = 0;
+ memcpy(&neighbour_sollicitation->target_address, dst, sizeof(struct ipv6_addr));
+ neighbour_sollicitation->options.type = ICMPv6_source_link_layer_address;
+ neighbour_sollicitation->options.length = 1; // 8 bytes
+ memcpy(&neighbour_sollicitation->options.data, s_addr, sizeof(prox_rte_ether_addr));
+ neighbour_sollicitation->checksum = 0;
+ neighbour_sollicitation->checksum = rte_ipv6_udptcp_cksum(ipv6_hdr, neighbour_sollicitation);
+
+ uint16_t pktlen = rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr);
+ rte_pktmbuf_pkt_len(mbuf) = pktlen;
+ rte_pktmbuf_data_len(mbuf) = pktlen;
+}
+
+void build_neighbour_advertisement(struct task_base *tbase, struct rte_mbuf *mbuf, prox_rte_ether_addr *target, struct ipv6_addr *src_ipv6_addr, int sollicited)
+{
+ struct task_master *task = (struct task_master *)tbase;
+ prox_rte_ether_hdr *peth = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(peth + 1);
+
+ uint8_t port_id = get_port(mbuf);
+
+ init_mbuf_seg(mbuf);
+ mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM); // Software calculates the checksum
+
+ // If source mac is null, use all_nodes_mac_addr.
+ if ((!sollicited) || (memcmp(peth->s_addr.addr_bytes, &null_addr, sizeof(struct ipv6_addr)) == 0)) {
+ memcpy(peth->d_addr.addr_bytes, &prox_cfg.all_nodes_mac_addr, sizeof(prox_rte_ether_addr));
+ memcpy(ipv6_hdr->dst_addr, &prox_cfg.all_nodes_ipv6_mcast_addr, sizeof(struct ipv6_addr));
+ } else {
+ memcpy(peth->d_addr.addr_bytes, peth->s_addr.addr_bytes, sizeof(prox_rte_ether_addr));
+ memcpy(ipv6_hdr->dst_addr, ipv6_hdr->src_addr, sizeof(struct ipv6_addr));
+ }
+
+ memcpy(peth->s_addr.addr_bytes, &task->internal_port_table[port_id].mac, sizeof(prox_rte_ether_addr));
+ peth->ether_type = ETYPE_IPv6;
+
+ ipv6_hdr->vtc_flow = 0x00000060;
+ ipv6_hdr->payload_len = rte_cpu_to_be_16(sizeof(struct icmpv6_NA));
+ ipv6_hdr->proto = ICMPv6;
+ ipv6_hdr->hop_limits = 255;
+ memcpy(ipv6_hdr->src_addr, src_ipv6_addr, sizeof(struct ipv6_addr));
+
+ struct icmpv6_NA *neighbour_advertisement = (struct icmpv6_NA *)(ipv6_hdr + 1);
+ neighbour_advertisement->type = ICMPv6_NA;
+ neighbour_advertisement->code = 0;
+ neighbour_advertisement->reserved = 0;
+ if (task->internal_port_table[port_id].flags & IPV6_ROUTER)
+ neighbour_advertisement->bits = 0xC0; // R+S bit set
+ else
+ neighbour_advertisement->bits = 0x40; // S bit set
+ if (!sollicited) {
+ memcpy(&neighbour_advertisement->destination_address, src_ipv6_addr, sizeof(struct ipv6_addr));
+ neighbour_advertisement->bits &= 0xBF; // Clear S bit
+ neighbour_advertisement->bits |= 0x20; // Overide bit
+ }
+ // else neighbour_advertisement->destination_address is already set to neighbour_sollicitation->target_address
+
+ struct icmpv6_option *option = &neighbour_advertisement->options;
+ // Do not think this is necessary
+ // option->type = ICMPv6_source_link_layer_address;
+ // option->length = 1; // 8 bytes
+ // memcpy(&option->data, &task->internal_port_table[port_id].mac, sizeof(prox_rte_ether_addr));
+
+ // option = option + 1;
+ option->type = ICMPv6_target_link_layer_address;
+ option->length = 1; // 8 bytes
+ memcpy(&option->data, target, sizeof(prox_rte_ether_addr));
+
+ neighbour_advertisement->checksum = 0;
+ neighbour_advertisement->checksum = rte_ipv6_udptcp_cksum(ipv6_hdr, neighbour_advertisement);
+ uint16_t pktlen = rte_be_to_cpu_16(ipv6_hdr->payload_len) + sizeof(prox_rte_ipv6_hdr) + sizeof(prox_rte_ether_hdr);
+ rte_pktmbuf_pkt_len(mbuf) = pktlen;
+ rte_pktmbuf_data_len(mbuf) = pktlen;
+}
diff --git a/VNFs/DPPD-PROX/prox_ipv6.h b/VNFs/DPPD-PROX/prox_ipv6.h
new file mode 100644
index 0000000..4803005
--- /dev/null
+++ b/VNFs/DPPD-PROX/prox_ipv6.h
@@ -0,0 +1,140 @@
+/*
+// Copyright (c) 2020 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#ifndef _PROX_IP_V6_H_
+#define _PROX_IP_V6_H_
+
+#include "ip6_addr.h"
+
+#define ALL_NODES_IPV6_MCAST_ADDR "ff02:0000:0000:0000:0000:0000:0000:0001" // FF02::1
+#define ALL_ROUTERS_IPV6_MCAST_ADDR "ff02:0000:0000:0000:0000:0000:0000:0002" // FF02::2
+
+#define RANDOM_IPV6 "1234:1234:1234:1234:1234:1234:1234:1234" // Used by PROX as a flag forrandom IP
+
+#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS "ff02:0000:0000:0000:0000:0000:0001:0002" // FF02::1:2
+#define ALL_DHCP_SERVERS "ff05:0000:0000:0000:0000:0000:0001:0003" // FF02::1:2
+
+#define DHCP_CLIENT_UDP_PORT 546
+#define DHCP_SERVER_UDP_PORT 547
+
+#define PROX_UNSOLLICITED 0
+#define PROX_SOLLICITED 1
+
+#define ICMPv6 0x3a
+
+#define ICMPv6_DU 0x01
+#define ICMPv6_PTB 0x02
+#define ICMPv6_TE 0x03
+#define ICMPv6_PaPr 0x04
+#define ICMPv6_RS 0x85
+#define ICMPv6_RA 0x86
+#define ICMPv6_NS 0x87
+#define ICMPv6_NA 0x88
+#define ICMPv6_RE 0x89
+
+#define ICMPv6_source_link_layer_address 1
+#define ICMPv6_target_link_layer_address 2
+#define ICMPv6_prefix_information 3
+#define ICMPv6_redirect_header 4
+#define ICMPv6_mtu 5
+
+extern struct ipv6_addr null_addr;
+
+struct icmpv6_prefix_option {
+ uint8_t type;
+ uint8_t length;
+ uint8_t prefix_length;
+ uint8_t flag;
+ uint32_t valid_lifetime;
+ uint32_t preferred_lifetime;
+ uint32_t reserved;
+ struct ipv6_addr prefix;
+};
+
+struct icmpv6_option {
+ uint8_t type;
+ uint8_t length;
+ uint8_t data[6];
+} __attribute__((__packed__));
+
+struct icmpv6 {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+};
+
+struct icmpv6_RA {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint8_t hop_limit;
+ uint8_t bits;
+ uint16_t router_lifespan;
+ uint32_t reachable_timeout;
+ uint32_t retrans_timeout;
+ struct icmpv6_option options;
+} __attribute__((__packed__));
+
+struct icmpv6_RS {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t reserved;
+ struct icmpv6_option options;
+} __attribute__((__packed__));
+
+struct icmpv6_NS {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t reserved;
+ struct ipv6_addr target_address;
+ struct icmpv6_option options;
+} __attribute__((__packed__));
+
+struct icmpv6_NA {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint16_t bits;
+ uint16_t reserved;
+ struct ipv6_addr destination_address;
+ struct icmpv6_option options;
+} __attribute__((__packed__));
+
+struct icmpv6_RE {
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t reserved;
+ struct ipv6_addr destination_address_hop;
+ struct ipv6_addr destination_address;
+ uint32_t Options;
+} __attribute__((__packed__));
+
+void set_mcast_mac_from_ipv6(prox_rte_ether_addr *mac, struct ipv6_addr *ipv6_addr);
+char *IP6_Canonical(struct ipv6_addr *addr);
+void set_link_local(struct ipv6_addr *ipv6_addr);
+void set_EUI(struct ipv6_addr *ipv6_addr, prox_rte_ether_addr *mac);
+void create_mac_from_EUI(struct ipv6_addr *ipv6_addr, prox_rte_ether_addr *mac);
+
+struct task_base;
+void build_router_sollicitation(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *ipv6_s_addr);
+void build_router_advertisement(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *ipv6_s_addr, struct ipv6_addr *router_prefix);
+void build_neighbour_sollicitation(struct rte_mbuf *mbuf, prox_rte_ether_addr *s_addr, struct ipv6_addr *dst, struct ipv6_addr *src);
+void build_neighbour_advertisement(struct task_base *tbase, struct rte_mbuf *mbuf, prox_rte_ether_addr *target_mac, struct ipv6_addr *ipv6_addr, int sollicited);
+
+#endif /* _PROX_IP_V6_H_ */
diff --git a/VNFs/DPPD-PROX/prox_port_cfg.c b/VNFs/DPPD-PROX/prox_port_cfg.c
index 098d973..a4f3526 100644
--- a/VNFs/DPPD-PROX/prox_port_cfg.c
+++ b/VNFs/DPPD-PROX/prox_port_cfg.c
@@ -208,7 +208,7 @@ void init_rte_dev(int use_dummy_devices)
rc = eth_dev_null_create(tap, name, PROX_RTE_ETHER_MIN_LEN, 0);
#endif
PROX_PANIC(rc != 0, "Unable to create device %s %s\n", "net tap", port_cfg->vdev);
- int vdev_port_id = rte_eth_dev_count() - 1;
+ int vdev_port_id = prox_rte_eth_dev_count_avail() - 1;
PROX_PANIC(vdev_port_id >= PROX_MAX_PORTS, "Too many port defined %d >= %d\n", vdev_port_id, PROX_MAX_PORTS);
plog_info("\tCreating device %s, port %d\n", port_cfg->vdev, vdev_port_id);
prox_port_cfg[vdev_port_id].active = 1;
diff --git a/VNFs/DPPD-PROX/prox_shared.c b/VNFs/DPPD-PROX/prox_shared.c
index db381ff..52f4eb1 100644
--- a/VNFs/DPPD-PROX/prox_shared.c
+++ b/VNFs/DPPD-PROX/prox_shared.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -59,9 +59,9 @@ static void prox_sh_create_hash(struct prox_shared *ps, size_t size)
PROX_PANIC(ps->hash == NULL, "Failed to create hash table for shared data");
ps->size = size;
if (ps->size == INIT_HASH_TABLE_SIZE)
- plog_info("Shared data tracking hash table created with size %zu\n", ps->size);
+ plog_info("\tShared data tracking hash table created with size %zu\n", ps->size);
else
- plog_info("Shared data tracking hash table grew to %zu\n", ps->size);
+ plog_info("\tShared data tracking hash table grew to %zu\n", ps->size);
}
#if RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0)
diff --git a/VNFs/DPPD-PROX/rx_pkt.c b/VNFs/DPPD-PROX/rx_pkt.c
index da59fda..17e3964 100644
--- a/VNFs/DPPD-PROX/rx_pkt.c
+++ b/VNFs/DPPD-PROX/rx_pkt.c
@@ -28,7 +28,8 @@
#include "arp.h"
#include "tx_pkt.h"
#include "handle_master.h"
-#include "input.h" /* Needed for callback on dump */
+#include "input.h"
+#include "prox_ipv6.h" /* Needed for callback on dump */
#define TCP_PORT_BGP rte_cpu_to_be_16(179)
@@ -44,7 +45,9 @@
packets are received if the dequeue step involves finding 32 packets.
*/
-#define MIN_PMD_RX 32
+#define MIN_PMD_RX 32
+#define PROX_L3 1
+#define PROX_NDP 2
static uint16_t rx_pkt_hw_port_queue(struct port_queue *pq, struct rte_mbuf **mbufs, int multi)
{
@@ -112,11 +115,11 @@ static inline void handle_ipv4(struct task_base *tbase, struct rte_mbuf **mbufs,
prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(pip + 1);
if (pip->next_proto_id == IPPROTO_ICMP) {
dump_l3(tbase, mbufs[i]);
- tx_ring(tbase, tbase->l3.ctrl_plane_ring, ICMP_TO_CTRL, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, ICMP_TO_MASTER, mbufs[i]);
(*skip)++;
} else if ((tcp->src_port == TCP_PORT_BGP) || (tcp->dst_port == TCP_PORT_BGP)) {
dump_l3(tbase, mbufs[i]);
- tx_ring(tbase, tbase->l3.ctrl_plane_ring, BGP_TO_CTRL, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, BGP_TO_MASTER, mbufs[i]);
(*skip)++;
} else if (unlikely(*skip)) {
mbufs[i - *skip] = mbufs[i];
@@ -155,13 +158,13 @@ static inline int handle_l3(struct task_base *tbase, uint16_t nb_rx, struct rte_
handle_ipv4(tbase, mbufs, i, pip, &skip);
} else if (vlan->eth_proto == ETYPE_ARP) {
dump_l3(tbase, mbufs[i]);
- tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_TO_CTRL, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_PKT_FROM_NET_TO_MASTER, mbufs[i]);
skip++;
}
break;
case ETYPE_ARP:
dump_l3(tbase, mbufs[i]);
- tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_TO_CTRL, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_PKT_FROM_NET_TO_MASTER, mbufs[i]);
skip++;
break;
default:
@@ -174,8 +177,35 @@ static inline int handle_l3(struct task_base *tbase, uint16_t nb_rx, struct rte_
return skip;
}
+static inline int handle_ndp(struct task_base *tbase, uint16_t nb_rx, struct rte_mbuf ***mbufs_ptr)
+{
+ struct rte_mbuf **mbufs = *mbufs_ptr;
+ int i;
+ prox_rte_ether_hdr *hdr[MAX_PKT_BURST];
+ int skip = 0;
+
+ for (i = 0; i < nb_rx; i++) {
+ PREFETCH0(mbufs[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ hdr[i] = rte_pktmbuf_mtod(mbufs[i], prox_rte_ether_hdr *);
+ PREFETCH0(hdr[i]);
+ }
+ for (i = 0; i < nb_rx; i++) {
+ prox_rte_ipv6_hdr *ipv6_hdr = (prox_rte_ipv6_hdr *)(hdr[i] + 1);
+ if (unlikely((hdr[i]->ether_type == ETYPE_IPv6) && (ipv6_hdr->proto == ICMPv6))) {
+ dump_l3(tbase, mbufs[i]);
+ tx_ring(tbase, tbase->l3.ctrl_plane_ring, NDP_PKT_FROM_NET_TO_MASTER, mbufs[i]);
+ skip++;
+ } else if (unlikely(skip)) {
+ mbufs[i - skip] = mbufs[i];
+ }
+ }
+ return skip;
+}
+
static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi,
- void (*next)(struct rx_params_hw *rx_param_hw), int l3)
+ void (*next)(struct rx_params_hw *rx_param_hw), int l3_ndp)
{
uint8_t last_read_portid;
uint16_t nb_rx, ret;
@@ -191,8 +221,10 @@ static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbuf
nb_rx = rx_pkt_hw_port_queue(pq, *mbufs_ptr, multi);
next(&tbase->rx_params_hw);
- if (l3)
+ if (l3_ndp == PROX_L3)
skip = handle_l3(tbase, nb_rx, mbufs_ptr);
+ else if (l3_ndp == PROX_NDP)
+ skip = handle_ndp(tbase, nb_rx, mbufs_ptr);
if (skip)
TASK_STATS_ADD_RX_NON_DP(&tbase->aux->stats, skip);
@@ -204,7 +236,7 @@ static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbuf
return 0;
}
-static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi, int l3)
+static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi, int l3_ndp)
{
uint16_t nb_rx, n;
int skip = 0;
@@ -230,8 +262,11 @@ static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf
if (nb_rx == 0)
return 0;
- if (l3)
+
+ if (l3_ndp == PROX_L3)
skip = handle_l3(tbase, nb_rx, mbufs_ptr);
+ else if (l3_ndp == PROX_NDP)
+ skip = handle_ndp(tbase, nb_rx, mbufs_ptr);
if (skip)
TASK_STATS_ADD_RX_NON_DP(&tbase->aux->stats, skip);
@@ -275,32 +310,62 @@ uint16_t rx_pkt_hw1_multi(struct task_base *tbase, struct rte_mbuf ***mbufs)
uint16_t rx_pkt_hw_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 0, next_port, 1);
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port, PROX_L3);
+}
+
+uint16_t rx_pkt_hw_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port, PROX_NDP);
}
uint16_t rx_pkt_hw_pow2_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, 1);
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, PROX_L3);
+}
+
+uint16_t rx_pkt_hw_pow2_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, PROX_NDP);
}
uint16_t rx_pkt_hw1_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw1_param(tbase, mbufs, 0, 1);
+ return rx_pkt_hw1_param(tbase, mbufs, 0, PROX_L3);
+}
+
+uint16_t rx_pkt_hw1_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw1_param(tbase, mbufs, 0, PROX_NDP);
}
uint16_t rx_pkt_hw_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 1, next_port, 1);
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port, PROX_L3);
+}
+
+uint16_t rx_pkt_hw_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port, PROX_NDP);
}
uint16_t rx_pkt_hw_pow2_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, 1);
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, PROX_L3);
+}
+
+uint16_t rx_pkt_hw_pow2_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, PROX_NDP);
}
uint16_t rx_pkt_hw1_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs)
{
- return rx_pkt_hw1_param(tbase, mbufs, 1, 1);
+ return rx_pkt_hw1_param(tbase, mbufs, 1, PROX_L3);
+}
+
+uint16_t rx_pkt_hw1_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs)
+{
+ return rx_pkt_hw1_param(tbase, mbufs, 1, PROX_NDP);
}
/* The following functions implement ring access */
diff --git a/VNFs/DPPD-PROX/rx_pkt.h b/VNFs/DPPD-PROX/rx_pkt.h
index 6d8f412..c610ed9 100644
--- a/VNFs/DPPD-PROX/rx_pkt.h
+++ b/VNFs/DPPD-PROX/rx_pkt.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -29,6 +29,9 @@ uint16_t rx_pkt_hw1(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_pow2_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw1_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_pow2_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw1_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
/* The _multi variation of the function is used to work-around the
problem with QoS, multi-seg mbufs and vector PMD. When vector
@@ -40,6 +43,9 @@ uint16_t rx_pkt_hw1_multi(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw_pow2_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_hw1_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw_pow2_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
+uint16_t rx_pkt_hw1_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_sw(struct task_base *tbase, struct rte_mbuf ***mbufs);
uint16_t rx_pkt_sw_pow2(struct task_base *tbase, struct rte_mbuf ***mbufs);
diff --git a/VNFs/DPPD-PROX/task_base.h b/VNFs/DPPD-PROX/task_base.h
index ce70aca..df876e9 100644
--- a/VNFs/DPPD-PROX/task_base.h
+++ b/VNFs/DPPD-PROX/task_base.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -178,6 +178,7 @@ struct task_base_aux {
void (*stop_last)(struct task_base *tbase);
void (*start_first)(struct task_base *tbase);
struct task_rt_dump task_rt_dump;
+ struct rte_mbuf *mbuf;
};
/* The task_base is accessed for _all_ task types. In case
@@ -208,7 +209,6 @@ struct task_base {
struct tx_params_hw_sw tx_params_hw_sw;
};
struct l3_base l3;
- uint32_t local_ipv4;
} __attribute__((packed)) __rte_cache_aligned;
static void task_base_add_rx_pkt_function(struct task_base *tbase, rx_pkt_func to_add)
diff --git a/VNFs/DPPD-PROX/task_init.c b/VNFs/DPPD-PROX/task_init.c
index 8441561..fc12eae 100644
--- a/VNFs/DPPD-PROX/task_init.c
+++ b/VNFs/DPPD-PROX/task_init.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -176,6 +176,8 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
if (targ->nb_rxports == 1) {
if (targ->flags & TASK_ARG_L3)
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi_l3 : rx_pkt_hw1_l3;
+ else if (targ->flags & TASK_ARG_NDP)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi_ndp : rx_pkt_hw1_ndp;
else
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw1_multi : rx_pkt_hw1;
tbase->rx_params_hw1.rx_pq.port = targ->rx_port_queue[0].port;
@@ -185,6 +187,8 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
PROX_ASSERT((targ->nb_rxports != 0) || (targ->task_init->flag_features & TASK_FEATURE_NO_RX));
if (targ->flags & TASK_ARG_L3)
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi_l3 : rx_pkt_hw_l3;
+ else if (targ->flags & TASK_ARG_NDP)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi_ndp : rx_pkt_hw_ndp;
else
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_multi : rx_pkt_hw;
tbase->rx_params_hw.nb_rxports = targ->nb_rxports;
@@ -198,6 +202,8 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
if (rte_is_power_of_2(targ->nb_rxports)) {
if (targ->flags & TASK_ARG_L3)
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi_l3 : rx_pkt_hw_pow2_l3;
+ else if (targ->flags & TASK_ARG_NDP)
+ tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi_ndp : rx_pkt_hw_pow2_ndp;
else
tbase->rx_pkt = (targ->task_init->flag_features & TASK_FEATURE_MULTI_RX)? rx_pkt_hw_pow2_multi : rx_pkt_hw_pow2;
tbase->rx_params_hw.rxport_mask = targ->nb_rxports - 1;
@@ -359,15 +365,20 @@ struct task_base *init_task_struct(struct task_args *targ)
tbase->handle_bulk = t->handle;
- if (targ->flags & TASK_ARG_L3) {
- plog_info("\tTask configured in L3 mode\n");
+ if (targ->flags & (TASK_ARG_L3|TASK_ARG_NDP)) {
+ plog_info("\tTask (%d,%d) configured in L3/NDP mode\n", targ->lconf->id, targ->id);
tbase->l3.ctrl_plane_ring = targ->ctrl_plane_ring;
if (targ->nb_txports != 0) {
tbase->aux->tx_pkt_l2 = tbase->tx_pkt;
- tbase->tx_pkt = tx_pkt_l3;
- // Make sure control plane packets such as arp are not dropped
tbase->aux->tx_ctrlplane_pkt = targ->nb_txrings ? tx_ctrlplane_sw : tx_ctrlplane_hw;
- task_init_l3(tbase, targ);
+ if (targ->flags & TASK_ARG_L3) {
+ tbase->tx_pkt = tx_pkt_l3;
+ task_init_l3(tbase, targ);
+ } else if (targ->flags & TASK_ARG_NDP) {
+ tbase->tx_pkt = tx_pkt_ndp;
+ task_init_l3(tbase, targ);
+ }
+ // Make sure control plane packets such as arp are not dropped
}
}
diff --git a/VNFs/DPPD-PROX/task_init.h b/VNFs/DPPD-PROX/task_init.h
index e6261c2..30a1515 100644
--- a/VNFs/DPPD-PROX/task_init.h
+++ b/VNFs/DPPD-PROX/task_init.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -49,6 +49,8 @@ struct lcore_cfg;
#define TASK_ARG_DO_NOT_SET_DST_MAC 0x400
#define TASK_ARG_HW_SRC_MAC 0x800
#define TASK_ARG_L3 0x1000
+#define TASK_ARG_NDP 0x2000
+#define TASK_ARG_SEND_NA_AT_STARTUP 0x4000
#define PROX_MODE_LEN 32
@@ -126,13 +128,16 @@ struct task_args {
uint8_t tot_rxrings;
uint8_t nb_rxports;
uint32_t byte_offset;
+ uint32_t ipv6_router;
uint32_t gateway_ipv4;
uint32_t local_ipv4;
uint32_t remote_ipv4;
uint32_t local_prefix;
- uint32_t arp_timeout;
- uint32_t arp_update_time;
+ uint32_t reachable_timeout;
+ uint32_t arp_ndp_retransmit_timeout;
struct ipv6_addr local_ipv6; /* For IPv6 Tunnel, it's the local tunnel endpoint address */
+ struct ipv6_addr global_ipv6;
+ struct ipv6_addr router_prefix;
struct rte_ring *rx_rings[MAX_RINGS_PER_TASK];
struct rte_ring *tx_rings[MAX_RINGS_PER_TASK];
struct rte_ring *ctrl_plane_ring;
diff --git a/VNFs/DPPD-PROX/tx_pkt.c b/VNFs/DPPD-PROX/tx_pkt.c
index 51c1afa..60d6b51 100644
--- a/VNFs/DPPD-PROX/tx_pkt.c
+++ b/VNFs/DPPD-PROX/tx_pkt.c
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
#include "log.h"
#include "mbuf_utils.h"
#include "handle_master.h"
+#include "defines.h"
static void buf_pkt_single(struct task_base *tbase, struct rte_mbuf *mbuf, const uint8_t out)
{
@@ -50,6 +51,70 @@ static inline void buf_pkt_all(struct task_base *tbase, struct rte_mbuf **mbufs,
}
#define MAX_PMD_TX 32
+void store_packet(struct task_base *tbase, struct rte_mbuf *mbuf)
+{
+ // If buffer is full, drop the first mbuf
+ if (tbase->aux->mbuf)
+ tx_drop(tbase->aux->mbuf);
+ tbase->aux->mbuf = mbuf;
+}
+
+int tx_pkt_ndp(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
+{
+ // TODO NDP
+ struct ipv6_addr ip_dst;
+ int first = 0, ret, ok = 0, rc;
+ const struct port_queue *port_queue = &tbase->tx_params_hw.tx_port_queue[0];
+ struct rte_mbuf *mbuf = NULL; // used when one need to send both an ARP and a mbuf
+
+ for (int j = 0; j < n_pkts; j++) {
+ if ((out) && (out[j] >= OUT_HANDLED))
+ continue;
+ if (unlikely((rc = write_ip6_dst_mac(tbase, mbufs[j], &ip_dst)) != SEND_MBUF)) {
+ if (j - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, j - first, out);
+ ok += ret;
+ }
+ first = j + 1;
+ switch(rc) {
+ case SEND_ARP_ND:
+ // Original mbuf (packet) is stored to be sent later -> need to allocate new mbuf
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ store_packet(tbase, mbufs[j]);
+ mbuf->port = tbase->l3.reachable_port_id;
+ tx_ring_cti6(tbase, tbase->l3.ctrl_plane_ring, IP6_REQ_MAC_TO_MASTER, mbuf, tbase->l3.core_id, tbase->l3.task_id, &ip_dst);
+ } else {
+ plog_err("Failed to get a mbuf from arp/nd mempool\n");
+ tx_drop(mbufs[j]);
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ }
+ break;
+ case SEND_MBUF_AND_ARP_ND:
+ // We send the mbuf and an ND - we need to allocate another mbuf for ND
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&mbuf);
+ if (likely(ret == 0)) {
+ mbuf->port = tbase->l3.reachable_port_id;
+ tx_ring_cti6(tbase, tbase->l3.ctrl_plane_ring, IP6_REQ_MAC_TO_MASTER, mbuf, tbase->l3.core_id, tbase->l3.task_id, &ip_dst);
+ } else {
+ plog_err("Failed to get a mbuf from arp/nd mempool\n");
+ // We still send the initial mbuf
+ }
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + j, 1, out);
+ break;
+ case DROP_MBUF:
+ tx_drop(mbufs[j]);
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ break;
+ }
+ }
+ }
+ if (n_pkts - first) {
+ ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, n_pkts - first, out);
+ ok += ret;
+ }
+ return ok;
+}
int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out)
{
uint32_t ip_dst;
@@ -69,23 +134,23 @@ int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts,
}
first = j + 1;
switch(rc) {
- case SEND_ARP:
+ case SEND_ARP_ND:
// We re-use the mbuf - no need to create a arp_mbuf and delete the existing mbuf
mbufs[j]->port = tbase->l3.reachable_port_id;
- if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, REQ_MAC_TO_CTRL, mbufs[j], tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
- update_arp_update_time(&tbase->l3, time, 1000);
+ if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, IP4_REQ_MAC_TO_MASTER, mbufs[j], tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 1000);
else
- update_arp_update_time(&tbase->l3, time, 100);
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 100);
break;
- case SEND_MBUF_AND_ARP:
+ case SEND_MBUF_AND_ARP_ND:
// We send the mbuf and an ARP - we need to allocate another mbuf for ARP
- ret = rte_mempool_get(tbase->l3.arp_pool, (void **)&arp_mbuf);
+ ret = rte_mempool_get(tbase->l3.arp_nd_pool, (void **)&arp_mbuf);
if (likely(ret == 0)) {
arp_mbuf->port = tbase->l3.reachable_port_id;
- if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, REQ_MAC_TO_CTRL, arp_mbuf, tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
- update_arp_update_time(&tbase->l3, time, 1000);
+ if (tx_ring_cti(tbase, tbase->l3.ctrl_plane_ring, IP4_REQ_MAC_TO_MASTER, arp_mbuf, tbase->l3.core_id, tbase->l3.task_id, ip_dst) == 0)
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 1000);
else
- update_arp_update_time(&tbase->l3, time, 100);
+ update_arp_ndp_retransmit_timeout(&tbase->l3, time, 100);
} else {
plog_err("Failed to get a mbuf from arp mempool\n");
// We still send the initial mbuf
@@ -644,7 +709,7 @@ static inline void trace_one_tx_pkt(struct task_base *tbase, struct rte_mbuf *mb
static void unset_trace(struct task_base *tbase)
{
if (0 == tbase->aux->task_rt_dump.n_trace) {
- if (tbase->tx_pkt == tx_pkt_l3) {
+ if ((tbase->tx_pkt == tx_pkt_l3) || (tbase->tx_pkt == tx_pkt_ndp)){
tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
tbase->aux->tx_pkt_orig = NULL;
} else {
@@ -713,7 +778,7 @@ int tx_pkt_dump(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkt
ret = tbase->aux->tx_pkt_orig(tbase, mbufs, n_pkts, out);
if (0 == tbase->aux->task_rt_dump.n_print_tx) {
- if (tbase->tx_pkt == tx_pkt_l3) {
+ if ((tbase->tx_pkt == tx_pkt_l3) || (tbase->tx_pkt == tx_pkt_ndp)) {
tbase->aux->tx_pkt_l2 = tbase->aux->tx_pkt_orig;
tbase->aux->tx_pkt_orig = NULL;
} else {
@@ -804,16 +869,16 @@ int tx_ctrlplane_sw(struct task_base *tbase, struct rte_mbuf **mbufs, const uint
return ring_enq_no_drop(tbase->tx_params_sw.tx_rings[0], mbufs, n_pkts, tbase);
}
-static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
{
if (tbase->aux->task_rt_dump.cur_trace) {
trace_one_rx_pkt(tbase, mbuf);
}
- mbuf->udata64 = ((uint64_t)ip << 32) | (core_id << 16) | (task_id << 8) | command;
+ ctrl_ring_set_command_core_task_ip(mbuf, ((uint64_t)ip << 32) | (core_id << 16) | (task_id << 8) | command);
return rte_ring_enqueue(ring, mbuf);
}
-int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
+int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
{
plogx_dbg("\tSending command %s with ip %d.%d.%d.%d to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IP4(ip), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
int ret = tx_ring_all(tbase, ring, command, mbuf, core_id, task_id, ip);
@@ -825,7 +890,7 @@ int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command
return ret;
}
-void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint32_t ip)
+void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint32_t ip)
{
plogx_dbg("\tSending command %s with ip %d.%d.%d.%d to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IP4(ip), ring, mbuf, rte_ring_free_count(ring));
int ret = tx_ring_all(tbase, ring, command, mbuf, 0, 0, ip);
@@ -851,9 +916,9 @@ void tx_ring_route(struct task_base *tbase, struct rte_ring *ring, int add, stru
{
uint8_t command;
if (add)
- command = ROUTE_ADD_FROM_CTRL;
+ command = ROUTE_ADD_FROM_MASTER;
else
- command = ROUTE_DEL_FROM_CTRL;
+ command = ROUTE_DEL_FROM_MASTER;
plogx_dbg("\tSending command %s to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ring, mbuf, rte_ring_free_count(ring));
ctrl_ring_set_command(mbuf, command);
@@ -871,48 +936,58 @@ void tx_ring_route(struct task_base *tbase, struct rte_ring *ring, int add, stru
}
}
-void ctrl_ring_set_command(struct rte_mbuf *mbuf, uint64_t udata64)
+void tx_ring_cti6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, struct ipv6_addr *ip)
{
- mbuf->udata64 = udata64;
-}
-
-uint64_t ctrl_ring_get_command(struct rte_mbuf *mbuf)
-{
- return mbuf->udata64;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command_core_task_ip(mbuf, (core_id << 16) | (task_id << 8) | command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_ip(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->ip = udata32;
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
}
-uint32_t ctrl_ring_get_ip(struct rte_mbuf *mbuf)
+void tx_ring_ip6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip)
{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->ip;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command(mbuf, command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_gateway_ip(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->gateway_ip = udata32;
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
}
-uint32_t ctrl_ring_get_gateway_ip(struct rte_mbuf *mbuf)
+void tx_ring_ip6_data(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip, uint64_t data)
{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->gateway_ip;
-}
+ int ret;
+ plogx_dbg("\tSending command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ if (tbase->aux->task_rt_dump.cur_trace) {
+ trace_one_rx_pkt(tbase, mbuf);
+ }
+ ctrl_ring_set_command(mbuf, command);
+ ctrl_ring_set_ipv6_addr(mbuf, ip);
+ ctrl_ring_set_data(mbuf, data);
+ ret = rte_ring_enqueue(ring, mbuf);
-void ctrl_ring_set_prefix(struct rte_mbuf *mbuf, uint32_t udata32)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- prox_headroom->prefix = udata32;
-}
+ if (unlikely(ret != 0)) {
+ plogx_dbg("\tFail to send command %s with ip "IPv6_BYTES_FMT" to ring %p using mbuf %p - ring size now %d\n", actions_string[command], IPv6_BYTES(ip->bytes), ring, mbuf, rte_ring_free_count(ring));
+ TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
+ rte_pktmbuf_free(mbuf);
+ }
-uint32_t ctrl_ring_get_prefix(struct rte_mbuf *mbuf)
-{
- struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
- return prox_headroom->prefix;
}
diff --git a/VNFs/DPPD-PROX/tx_pkt.h b/VNFs/DPPD-PROX/tx_pkt.h
index f7443cf..b54a2be 100644
--- a/VNFs/DPPD-PROX/tx_pkt.h
+++ b/VNFs/DPPD-PROX/tx_pkt.h
@@ -1,5 +1,5 @@
/*
-// Copyright (c) 2010-2017 Intel Corporation
+// Copyright (c) 2010-2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,15 +18,19 @@
#define _TX_PKT_H_
#include <inttypes.h>
+#include <string.h>
+#include <rte_mbuf.h>
+#include "ip6_addr.h"
struct task_base;
-struct rte_mbuf;
struct prox_headroom {
uint64_t command;
uint32_t ip;
uint32_t prefix;
uint32_t gateway_ip;
+ uint64_t data64;
+ struct ipv6_addr ipv6_addr;
} __attribute__((packed));
void flush_queues_hw(struct task_base *tbase);
@@ -88,19 +92,108 @@ uint16_t tx_try_self(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t
sink. */
int tx_pkt_drop_all(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
-
-int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip);
-void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf, uint32_t ip);
+int tx_pkt_ndp(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
+
+static inline uint8_t get_command(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return prox_headroom->command & 0xFF;
+}
+static inline uint8_t get_task(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return (prox_headroom->command >> 8) & 0xFF;
+}
+static inline uint8_t get_core(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return (prox_headroom->command >> 16) & 0xFF;
+}
+static inline uint32_t get_ip(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return (prox_headroom->command >> 32) & 0xFFFFFFFF;
+}
+
+static inline void ctrl_ring_set_command_core_task_ip(struct rte_mbuf *mbuf, uint64_t udata64)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->command = udata64;
+}
+
+static inline void ctrl_ring_set_command(struct rte_mbuf *mbuf, uint8_t command)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->command = command;
+}
+
+static inline void ctrl_ring_set_ip(struct rte_mbuf *mbuf, uint32_t udata32)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->ip = udata32;
+}
+
+static inline uint32_t ctrl_ring_get_ip(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return prox_headroom->ip;
+}
+
+static inline void ctrl_ring_set_gateway_ip(struct rte_mbuf *mbuf, uint32_t udata32)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->gateway_ip = udata32;
+}
+
+static inline uint32_t ctrl_ring_get_gateway_ip(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return prox_headroom->gateway_ip;
+}
+
+static inline void ctrl_ring_set_prefix(struct rte_mbuf *mbuf, uint32_t udata32)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->prefix = udata32;
+}
+
+static inline uint32_t ctrl_ring_get_prefix(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return prox_headroom->prefix;
+}
+
+static inline void ctrl_ring_set_data(struct rte_mbuf *mbuf, uint64_t data)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ prox_headroom->data64 = data;
+}
+
+static inline uint64_t ctrl_ring_get_data(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return prox_headroom->data64;
+}
+
+static inline void ctrl_ring_set_ipv6_addr(struct rte_mbuf *mbuf, struct ipv6_addr *ip)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ memcpy(&prox_headroom->ipv6_addr, ip, sizeof(struct ipv6_addr));
+}
+
+static inline struct ipv6_addr *ctrl_ring_get_ipv6_addr(struct rte_mbuf *mbuf)
+{
+ struct prox_headroom *prox_headroom = (struct prox_headroom *)(rte_pktmbuf_mtod(mbuf, uint8_t*) - sizeof(struct prox_headroom));
+ return &prox_headroom->ipv6_addr;
+}
+
+int tx_ring_cti(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip);
+void tx_ring_cti6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, struct ipv6_addr *ip);
+void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, uint32_t ip);
+void tx_ring_ip6(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip);
+void tx_ring_ip6_data(struct task_base *tbase, struct rte_ring *ring, uint8_t command, struct rte_mbuf *mbuf, struct ipv6_addr *ip, uint64_t data);
void tx_ring(struct task_base *tbase, struct rte_ring *ring, uint16_t command, struct rte_mbuf *mbuf);
-
-void ctrl_ring_set_command(struct rte_mbuf *mbuf, uint64_t udata64);
-uint64_t ctrl_ring_get_command(struct rte_mbuf *mbuf);
-void ctrl_ring_set_ip(struct rte_mbuf *mbuf, uint32_t udata32);
-uint32_t ctrl_ring_get_ip(struct rte_mbuf *mbuf);
-void ctrl_ring_set_gateway_ip(struct rte_mbuf *mbuf, uint32_t udata32);
-uint32_t ctrl_ring_get_gateway_ip(struct rte_mbuf *mbuf);
-void ctrl_ring_set_prefix(struct rte_mbuf *mbuf, uint32_t udata32);
-uint32_t ctrl_ring_get_prefix(struct rte_mbuf *mbuf);
void tx_ring_route(struct task_base *tbase, struct rte_ring *ring, int add, struct rte_mbuf *mbuf, uint32_t ip, uint32_t gateway_ip, uint32_t prefix);
+static void store_packet(struct task_base *tbase, struct rte_mbuf *mbufs);
#endif /* _TX_PKT_H_ */