From 48f8c3d212644a33dd0abaaa1a0c71d4decaafdf Mon Sep 17 00:00:00 2001 From: Xavier Simonart Date: Mon, 24 Jun 2019 17:01:54 +0200 Subject: Add support for igmp and multicast Multicast can be enabled through configuration or through command line - Through configuration Add multicast=mcast_address (e.g. multicast=01:00:5e:01:02:03) in the port section - Through command line run enable multicast port_id mcast_address (e.g. enable multicast 1 01:00:5e:01:02:03) IGMP join message is sent unsollicited through command line: join igmp core_id task_id ip (e.g. join igmp 1 0 224.1.1.3) To enable swap answering IGMP Query (w/ IGMP Join) - Through configuration Add igmp ipv4=ip_address within the core/task section - Through command line join igmp core_id task_id ip (e.g. join igmp 1 0 224.1.1.3) (this will 1st initiate an unsollicated join, then answer any subsequent query) UDP/TCP packets received on a multicast address (224.0.0.0 => 239.255.255.255) are discarded To stop sending responses to IGMP query: leave igmp core_id task_id Change-Id: I3808ccabf3b38b5a1e10e1b044db63aa05bcd7b5 Signed-off-by: Xavier Simonart --- VNFs/DPPD-PROX/cmd_parser.c | 84 ++++++++++++++++- VNFs/DPPD-PROX/commands.c | 83 ++++++++++++++++ VNFs/DPPD-PROX/commands.h | 2 + VNFs/DPPD-PROX/config/mcast.cfg | 108 +++++++++++++++++++++ VNFs/DPPD-PROX/defaults.c | 1 + VNFs/DPPD-PROX/handle_swap.c | 204 +++++++++++++++++++++++++++++++--------- VNFs/DPPD-PROX/handle_swap.h | 22 ----- VNFs/DPPD-PROX/igmp.h | 59 ++++++++++++ VNFs/DPPD-PROX/prox_args.c | 17 +++- VNFs/DPPD-PROX/prox_cksum.c | 11 +++ VNFs/DPPD-PROX/prox_cksum.h | 2 + VNFs/DPPD-PROX/prox_port_cfg.c | 15 ++- VNFs/DPPD-PROX/prox_port_cfg.h | 3 + VNFs/DPPD-PROX/task_base.h | 1 - VNFs/DPPD-PROX/task_init.h | 1 + 15 files changed, 543 insertions(+), 70 deletions(-) create mode 100644 VNFs/DPPD-PROX/config/mcast.cfg delete mode 100644 VNFs/DPPD-PROX/handle_swap.h create mode 100644 VNFs/DPPD-PROX/igmp.h diff --git a/VNFs/DPPD-PROX/cmd_parser.c b/VNFs/DPPD-PROX/cmd_parser.c index 79c939b9..d4bfed01 100644 --- a/VNFs/DPPD-PROX/cmd_parser.c +++ b/VNFs/DPPD-PROX/cmd_parser.c @@ -53,6 +53,7 @@ #include "handle_impair.h" #include "rx_pkt.h" #include "prox_compat.h" +#include "igmp.h" static int core_task_is_valid(int lcore_id, int task_id) { @@ -1254,6 +1255,31 @@ static int parse_cmd_tot_imissed_tot(const char *str, struct input *input) return 0; } +static int parse_cmd_enable_multicast(const char *str, struct input *input) +{ + uint8_t port_id; + struct ether_addr mac; + + if (sscanf(str, "%hhu %hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &port_id, mac.addr_bytes, mac.addr_bytes + 1, mac.addr_bytes + 2, mac.addr_bytes + 3, mac.addr_bytes + 4, mac.addr_bytes + 5 ) != 7) { + return -1; + } + cmd_multicast(port_id, 1, &mac); + return 0; +} + +static int parse_cmd_disable_multicast(const char *str, struct input *input) +{ + uint8_t port_id; + struct ether_addr mac; + + if (sscanf(str, "%hhu %hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &port_id, mac.addr_bytes, mac.addr_bytes + 1, mac.addr_bytes + 2, mac.addr_bytes + 3, mac.addr_bytes + 4, mac.addr_bytes + 5 ) != 7) { + return -1; + } + + cmd_multicast(port_id, 0, &mac); + return 0; +} + static int parse_cmd_reset_port(const char *str, struct input *input) { uint32_t port_id; @@ -1987,6 +2013,58 @@ static int parse_cmd_accuracy(const char *str, struct input *input) return 0; } +static int parse_cmd_leave_igmp(const char *str, struct input *input) +{ + unsigned lcores[RTE_MAX_LCORE], lcore_id, task_id, nb_cores; + + if (parse_cores_task(str, lcores, &task_id, &nb_cores)) + return -1; + + 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(lcore_id, task_id, "swap")) { + plog_err("Core %u task %u is not running swap\n", lcore_id, task_id); + } + else { + struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id]; + igmp_leave_group(tbase); + } + } + } + return 0; +} + +static int parse_cmd_join_igmp(const char *str, struct input *input) +{ + unsigned lcores[RTE_MAX_LCORE], lcore_id, task_id, nb_cores; + uint32_t igmp_ip; + uint8_t *igmp_bytes = (uint8_t *)&igmp_ip; + + if (parse_cores_task(str, lcores, &task_id, &nb_cores)) + return -1; + if (!(str = strchr_skip_twice(str, ' '))) + return -1; + if (sscanf(str, "%hhu.%hhu.%hhu.%hhu", igmp_bytes, igmp_bytes + 1, igmp_bytes + 2, igmp_bytes + 3) != 4) { + return -1; + } + 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(lcore_id, task_id, "swap")) { + plog_err("Core %u task %u is not running swap\n", lcore_id, task_id); + } + else { + struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id]; + igmp_join_group(tbase, igmp_ip); + } + } + } + return 0; +} + static int parse_cmd_rx_tx_info(const char *str, struct input *input) { if (strcmp(str, "") != 0) { @@ -2100,7 +2178,9 @@ static struct cmd_str cmd_strings[] = { {"set cache class", " ", "Set cache class", parse_cmd_set_cache_class}, {"get cache class", "", "Get cache class", parse_cmd_get_cache_class}, {"get cache mask", "", "Get cache mask", parse_cmd_get_cache_mask}, - {"reset port", "", "Reset port", parse_cmd_reset_port}, + {"reset port", "", "Reset port", parse_cmd_reset_port}, + {"enable multicast", " ", "Enable multicast", parse_cmd_enable_multicast}, + {"disable multicast", " ", "Disable multicast", parse_cmd_disable_multicast}, {"ring info all", "", "Get information about ring, such as ring size and number of elements in the ring", parse_cmd_ring_info_all}, {"ring info", " ", "Get information about ring on core in task , such as ring size and number of elements in the ring", parse_cmd_ring_info}, {"port info", " [brief?]", "Get port related information, such as MAC address, socket, number of descriptors..., . Adding \"brief\" after command prints short version of output.", parse_cmd_port_info}, @@ -2115,6 +2195,8 @@ static struct cmd_str cmd_strings[] = { {"random delay_us", " ", "Set the delay in usec for the impair mode to ", parse_cmd_random_delay_us}, {"probability", " ", "Set the percent of forwarded packets for the impair mode", parse_cmd_set_probability}, {"version", "", "Show version", parse_cmd_version}, + {"join igmp", " ", "Send igmp membership report for group ", parse_cmd_join_igmp}, + {"leave igmp", " ", "Send igmp leave group", parse_cmd_leave_igmp}, {0,0,0,0}, }; diff --git a/VNFs/DPPD-PROX/commands.c b/VNFs/DPPD-PROX/commands.c index 969dec39..a66f4888 100644 --- a/VNFs/DPPD-PROX/commands.c +++ b/VNFs/DPPD-PROX/commands.c @@ -246,6 +246,61 @@ static struct size_unit to_size_unit(uint64_t bytes) return ret; } +static int add_multicast_addr(uint8_t port_id, struct ether_addr *addr) +{ + unsigned int i; + int rc = 0; + + struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id]; + + if (port_cfg->nb_mc_addr >= NB_MCAST_ADDR) { + plog_err("Already reached maximum number (%d) of mcast addr on port %u\n", NB_MCAST_ADDR, port_id); + return -1; + } + for (i = 0; i < port_cfg->nb_mc_addr; i++) { + if (is_same_ether_addr(addr, &port_cfg->mc_addr[i])) { + plog_info("multicast address already added to port\n"); + return -1; + } + } + + ether_addr_copy(addr, &port_cfg->mc_addr[port_cfg->nb_mc_addr]); + if ((rc = rte_eth_dev_set_mc_addr_list(port_id, port_cfg->mc_addr, port_cfg->nb_mc_addr + 1)) != 0) { + plog_err("rte_eth_dev_set_mc_addr_list returns %d on port %u\n", rc, port_id); + return rc; + } + + port_cfg->nb_mc_addr++; + plog_info("rte_eth_dev_set_mc_addr_list(%d addr) on port %u\n", port_cfg->nb_mc_addr, port_id); + return rc; +} + +static int del_multicast_addr(uint8_t port_id, struct ether_addr *addr) +{ + unsigned int i; + int rc = 0; + + struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id]; + + for (i = 0; i < port_cfg->nb_mc_addr; i++) { + if (is_same_ether_addr(addr, &port_cfg->mc_addr[i])) { + // Copy last address to the slot to be deleted + ether_addr_copy(&port_cfg->mc_addr[port_cfg->nb_mc_addr-1], &port_cfg->mc_addr[i]); + + if ((rc = rte_eth_dev_set_mc_addr_list(port_id, port_cfg->mc_addr, port_cfg->nb_mc_addr - 1)) != 0) { + plog_err("rte_eth_dev_set_mc_addr_list returns %d on port %u\n", rc, port_id); + // When set failed, let restore the situation we were before calling the function... + ether_addr_copy(addr, &port_cfg->mc_addr[i]); + return rc; + } + port_cfg->nb_mc_addr--; + plog_info("rte_eth_dev_set_mc_addr_list(%d addr) on port %u\n", port_cfg->nb_mc_addr, port_id); + return 0; + } + } + plog_err("multicast address not found on port %u\n", port_id); + return -1; +} void cmd_mem_stats(void) { struct rte_malloc_socket_stats sock_stats; @@ -858,6 +913,9 @@ void cmd_portinfo(int port_id, char *dst, size_t max_len) dst += snprintf(dst, end - dst, "\tSocket: %u\n", port_cfg->socket); dst += snprintf(dst, end - dst, "\tPCI address: %s\n", port_cfg->pci_addr); dst += snprintf(dst, end - dst, "\tPromiscuous: %s\n", port_cfg->promiscuous? "yes" : "no"); + for (unsigned int i = 0; i < port_cfg->nb_mc_addr; i++) { + dst += snprintf(dst, end - dst, "\tmcast address: "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->mc_addr[i].addr_bytes)); + } dst += snprintf(dst, end - dst, "\tNumber of RX/TX descriptors: %u/%u\n", port_cfg->n_rxd, port_cfg->n_txd); dst += snprintf(dst, end - dst, "\tNumber of RX/TX queues: %u/%u (max: %u/%u)\n", port_cfg->n_rxq, port_cfg->n_txq, port_cfg->max_rxq, port_cfg->max_txq); dst += snprintf(dst, end - dst, "\tMemory pools:\n"); @@ -899,6 +957,31 @@ void cmd_reset_port(uint8_t portid) } } +void cmd_multicast(uint8_t port_id, unsigned int val, struct ether_addr *mac) +{ + if (!port_is_active(port_id)) { + return; + } + struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id]; + if (val == 1) { + if (port_cfg->nb_mc_addr == 0) { + rte_eth_allmulticast_enable(port_id); + } + if (add_multicast_addr(port_id, mac) != 0) { + if (port_cfg->nb_mc_addr == 0) + rte_eth_allmulticast_disable(port_id); + } + } else if (val == 0) { + if (del_multicast_addr(port_id, mac) == 0) { + if (port_cfg->nb_mc_addr == 0) { + rte_eth_allmulticast_disable(port_id); + } + } + } else { + plog_err("Unexpected value in cmd_multicast on port %d\n", port_id); + } +} + void cmd_write_reg(uint8_t port_id, unsigned int id, unsigned int val) { if (!port_is_active(port_id)) { diff --git a/VNFs/DPPD-PROX/commands.h b/VNFs/DPPD-PROX/commands.h index 6c4a29a3..291930ff 100644 --- a/VNFs/DPPD-PROX/commands.h +++ b/VNFs/DPPD-PROX/commands.h @@ -18,6 +18,7 @@ #define _COMMANDS_H_ #include +#include struct input; @@ -64,6 +65,7 @@ void cmd_set_cache_class(uint32_t lcore_id, uint32_t set); void cmd_cache_reset(void); void cmd_reset_port(uint8_t port_id); +void cmd_multicast(uint8_t port_id, unsigned int val, struct ether_addr *mac); int reconnect_task(uint32_t lcore_id, uint32_t task_id); int bypass_task(uint32_t lcore_id, uint32_t task_id); diff --git a/VNFs/DPPD-PROX/config/mcast.cfg b/VNFs/DPPD-PROX/config/mcast.cfg new file mode 100644 index 00000000..3e673e57 --- /dev/null +++ b/VNFs/DPPD-PROX/config/mcast.cfg @@ -0,0 +1,108 @@ +;; +;; Copyright (c) 2019 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 + +;; This example uses 2 physical ports, connected back to back or through a +;; switch. +;; The 1st physical port (DPDK port 0) generates (through tasks 2 and 3 on +;; core 1) 2x IGMP membership query per second: one towards 224.0.0.3 and +;; one towards 224.0.0.4. +;; mcast packets can be generated using "speed 1 0 1" (to generate packets +;; on core 1, task 0 at 100Mbps) and "speed 1 1 1" (to generate packets +;; on core 1, task 1 at 100Mbps). They will resp. generate mcast packets +;; towards 224.0.0.3 and 224.0.0.4; + +;; 2x VF are configured on the second physical port. +;; They receive packets from the generator, each on their own mcast address. + +[port 0] +name=gen_port + +[port 1] +name=vf0 +multicast=01:00:5e:00:00:03 + +[port 2] +name=vf1 +multicast=01:00:5e:00:00:04 + +[variables] +$mbs=8 + +[defaults] +mempool size=4K + +[global] +start time=5 +name=Basic multicast + +[core 0s0] +mode=master + +[core 1s0] +name=gen +task=0 +mode=gen +tx port=gen_port +bps=0 +pkt inline=01 00 5e 00 00 03 00 00 00 00 00 01 08 00 45 00 05 dc 00 00 00 00 ff 11 00 00 c0 a8 01 01 e0 00 00 03 0b b8 0b b8 05 c8 00 00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 +min bulk size=$mbs + +task=1 +mode=gen +tx port=gen_port +bps=0 +pkt inline=01 00 5e 00 00 04 00 00 00 00 00 01 08 00 45 00 05 dc 00 00 00 00 ff 11 00 00 c0 a8 01 01 e0 00 00 04 0b b8 0b b8 05 c8 00 00 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5 c6 c7 +min bulk size=$mbs + +task=2 +mode=gen +tx port=gen_port +bps=125 +pkt inline=01 00 5e 00 00 03 00 00 01 00 00 01 08 00 45 00 00 1c 00 00 00 00 01 02 b0 dd c0 a8 01 02 e0 00 00 03 11 0a 0c f0 e0 00 00 03 + +task=3 +mode=gen +tx port=gen_port +bps=125 +pkt inline=01 00 5e 00 00 04 00 00 01 00 00 01 08 00 45 00 00 1c 00 00 00 00 01 02 b0 dd c0 a8 01 02 e0 00 00 04 11 0a 0c f0 e0 00 00 04 + +[core 2s0] +name=RX gen +task=0 +mode=nop +rx port=gen_port + +[core 3s1] +name=swap 0 +task=0 +mode=swap +rx port=vf0 +tx port=vf0 +local ipv4=20.21.22.23 +igmp ipv4=224.0.0.3 + +[core 4s1] +name=swap 1 +task=0 +mode=swap +rx port=vf1 +tx port=vf1 +local ipv4=20.21.22.24 +igmp ipv4=224.0.0.4 diff --git a/VNFs/DPPD-PROX/defaults.c b/VNFs/DPPD-PROX/defaults.c index 700b63ef..fce5c5c1 100644 --- a/VNFs/DPPD-PROX/defaults.c +++ b/VNFs/DPPD-PROX/defaults.c @@ -169,6 +169,7 @@ void set_port_defaults(void) { for (uint8_t i = 0; i < PROX_MAX_PORTS; ++i ) { prox_port_cfg[i].promiscuous = 1; + prox_port_cfg[i].nb_mc_addr = 0; prox_port_cfg[i].n_rxd = NB_RX_RING_DESC; prox_port_cfg[i].n_txd = NB_TX_RING_DESC; prox_port_cfg[i].port_conf = default_port_conf; diff --git a/VNFs/DPPD-PROX/handle_swap.c b/VNFs/DPPD-PROX/handle_swap.c index 63c4dbde..39131013 100644 --- a/VNFs/DPPD-PROX/handle_swap.c +++ b/VNFs/DPPD-PROX/handle_swap.c @@ -21,20 +21,28 @@ #include "task_base.h" #include "lconf.h" #include "log.h" -#include "arp.h" -#include "handle_swap.h" #include "prox_port_cfg.h" #include "mpls.h" #include "qinq.h" #include "gre.h" #include "prefetch.h" +#include "igmp.h" +#include "prox_cksum.h" struct task_swap { struct task_base base; - uint8_t src_dst_mac[12]; + struct rte_mempool *igmp_pool; uint32_t runtime_flags; + uint32_t igmp_address; + uint8_t src_dst_mac[12]; + uint32_t local_ipv4; + int offload_crc; }; +#define NB_IGMP_MBUF 1024 +#define IGMP_MBUF_SIZE 2048 +#define NB_CACHE_IGMP_MBUF 256 + static void write_src_and_dst_mac(struct task_swap *task, struct rte_mbuf *mbuf) { struct ether_hdr *hdr; @@ -63,29 +71,46 @@ static void write_src_and_dst_mac(struct task_swap *task, struct rte_mbuf *mbuf) } } } -static inline int handle_arp_request(struct task_swap *task, struct ether_hdr_arp *hdr_arp, struct ether_addr *s_addr, uint32_t ip) + +static inline void build_mcast_mac(uint32_t ip, struct ether_addr *dst_mac) { - if ((hdr_arp->arp.data.tpa == ip) || (ip == 0)) { - build_arp_reply(hdr_arp, s_addr); - return 0; - } else if (task->runtime_flags & TASK_MULTIPLE_MAC) { - struct ether_addr tmp_s_addr; - create_mac(hdr_arp, &tmp_s_addr); - build_arp_reply(hdr_arp, &tmp_s_addr); - return 0; - } else { - plogx_dbg("Received ARP on unexpected IP %x, expecting %x\n", rte_be_to_cpu_32(hdr_arp->arp.data.tpa), rte_be_to_cpu_32(ip)); - return OUT_DISCARD; - } + // MAC address is 01:00:5e followed by 23 LSB of IP address + uint64_t mac = 0x0000005e0001L | ((ip & 0xFFFF7F00L) << 16); + memcpy(dst_mac, &mac, sizeof(struct ether_addr)); } -/* - * swap mode does not send arp requests, so does not expect arp replies - * Need to understand later whether we must send arp requests - */ -static inline int handle_arp_replies(struct task_swap *task, struct ether_hdr_arp *hdr_arp) +static inline void build_igmp_message(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t ip, uint8_t igmp_message) { - return OUT_DISCARD; + struct task_swap *task = (struct task_swap *)tbase; + struct ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *); + struct ether_addr dst_mac; + build_mcast_mac(ip, &dst_mac); + + rte_pktmbuf_pkt_len(mbuf) = 46; + rte_pktmbuf_data_len(mbuf) = 46; + init_mbuf_seg(mbuf); + + ether_addr_copy(&dst_mac, &hdr->d_addr); + ether_addr_copy((struct ether_addr *)&task->src_dst_mac[6], &hdr->s_addr); + hdr->ether_type = ETYPE_IPv4; + + struct ipv4_hdr *ip_hdr = (struct ipv4_hdr *)(hdr + 1); + ip_hdr->version_ihl = 0x45; /**< version and header length */ + ip_hdr->type_of_service = 0; /**< type of service */ + ip_hdr->total_length = rte_cpu_to_be_16(32); /**< length of packet */ + ip_hdr->packet_id = 0; /**< packet ID */ + ip_hdr->fragment_offset = 0; /**< fragmentation offset */ + ip_hdr->time_to_live = 1; /**< time to live */ + ip_hdr->next_proto_id = IPPROTO_IGMP; /**< protocol ID */ + ip_hdr->hdr_checksum = 0; /**< header checksum */ + ip_hdr->src_addr = task->local_ipv4; /**< source address */ + ip_hdr->dst_addr = ip; /**< destination address */ + struct igmpv2_hdr *pigmp = (struct igmpv2_hdr *)(ip_hdr + 1); + pigmp->type = igmp_message; + pigmp->max_resp_time = 0; + pigmp->checksum = 0; + pigmp->group_address = ip; + prox_ip_udp_cksum(mbuf, ip_hdr, sizeof(struct ether_hdr), sizeof(struct ipv4_hdr), task->offload_crc); } static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts) @@ -95,6 +120,8 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui struct ether_addr mac; struct ipv4_hdr *ip_hdr; struct udp_hdr *udp_hdr; + struct gre_hdr *pgre; + struct ipv4_hdr *inner_ip_hdr; uint32_t ip; uint16_t port; uint8_t out[64] = {0}; @@ -102,8 +129,9 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui uint32_t mpls_len = 0; struct qinq_hdr *qinq; struct vlan_hdr *vlan; - struct ether_hdr_arp *hdr_arp; uint16_t j; + struct igmpv2_hdr *pigmp; + uint8_t type; for (j = 0; j < n_pkts; ++j) { PREFETCH0(mbufs[j]); @@ -112,12 +140,14 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui PREFETCH0(rte_pktmbuf_mtod(mbufs[j], void *)); } + // TODO 1: check packet is long enough for Ethernet + IP + UDP = 42 bytes for (uint16_t j = 0; j < n_pkts; ++j) { hdr = rte_pktmbuf_mtod(mbufs[j], struct ether_hdr *); switch (hdr->ether_type) { case ETYPE_MPLSU: mpls = (struct mpls_hdr *)(hdr + 1); while (!(mpls->bytes & 0x00010000)) { + // TODO: verify pcket length mpls++; mpls_len += sizeof(struct mpls_hdr); } @@ -173,30 +203,111 @@ static int handle_swap_bulk(struct task_base *tbase, struct rte_mbuf **mbufs, ui out[j] = OUT_DISCARD; continue; } - udp_hdr = (struct udp_hdr *)(ip_hdr + 1); + // TODO 2 : check packet is long enough for Ethernet + IP + UDP + extra header (VLAN, MPLS, ...) ip = ip_hdr->dst_addr; - ip_hdr->dst_addr = ip_hdr->src_addr; - ip_hdr->src_addr = ip; - if (ip_hdr->next_proto_id == IPPROTO_GRE) { - struct gre_hdr *pgre = (struct gre_hdr *)(ip_hdr + 1); - struct ipv4_hdr *inner_ip_hdr = ((struct ipv4_hdr *)(pgre + 1)); + + switch (ip_hdr->next_proto_id) { + case IPPROTO_GRE: + ip_hdr->dst_addr = ip_hdr->src_addr; + ip_hdr->src_addr = ip; + + pgre = (struct gre_hdr *)(ip_hdr + 1); + inner_ip_hdr = ((struct ipv4_hdr *)(pgre + 1)); ip = inner_ip_hdr->dst_addr; inner_ip_hdr->dst_addr = inner_ip_hdr->src_addr; inner_ip_hdr->src_addr = ip; + udp_hdr = (struct udp_hdr *)(inner_ip_hdr + 1); + // TODO 3.1 : verify proto is UPD or TCP port = udp_hdr->dst_port; udp_hdr->dst_port = udp_hdr->src_port; udp_hdr->src_port = port; - } else { + write_src_and_dst_mac(task, mbufs[j]); + break; + case IPPROTO_UDP: + case IPPROTO_TCP: + if (task->igmp_address && IS_IPV4_MCAST(rte_be_to_cpu_32(ip))) { + out[j] = OUT_DISCARD; + continue; + } + udp_hdr = (struct udp_hdr *)(ip_hdr + 1); + ip_hdr->dst_addr = ip_hdr->src_addr; + ip_hdr->src_addr = ip; + 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[j]); + break; + case IPPROTO_IGMP: + pigmp = (struct igmpv2_hdr *)(ip_hdr + 1); + // TODO: check packet len + type = pigmp->type; + if (type == IGMP_MEMBERSHIP_QUERY) { + if (task->igmp_address) { + // We have an address registered + if ((task->igmp_address == pigmp->group_address) || (pigmp->group_address == 0)) { + // We get a request for the registered address, or to 0.0.0.0 + build_igmp_message(tbase, mbufs[j], task->igmp_address, IGMP_MEMBERSHIP_REPORT); // replace Membership query packet with a response + } else { + // Discard as either we are not registered or this is a query for a different group + out[j] = OUT_DISCARD; + continue; + } + } else { + // Discard as either we are not registered + out[j] = OUT_DISCARD; + continue; + } + } else { + // Do not forward other IGMP packets back + out[j] = OUT_DISCARD; + continue; + } + break; + default: + plog_warn("Unsupported IP protocol 0x%x\n", ip_hdr->next_proto_id); + out[j] = OUT_DISCARD; + continue; } - write_src_and_dst_mac(task, mbufs[j]); } return task->base.tx_pkt(&task->base, mbufs, n_pkts, out); } +void igmp_join_group(struct task_base *tbase, uint32_t igmp_address) +{ + struct task_swap *task = (struct task_swap *)tbase; + struct rte_mbuf *igmp_mbuf; + uint8_t out[64] = {0}; + int ret; + + task->igmp_address = igmp_address; + ret = rte_mempool_get(task->igmp_pool, (void **)&igmp_mbuf); + if (ret != 0) { + plog_err("Unable to allocate igmp mbuf\n"); + return; + } + build_igmp_message(tbase, igmp_mbuf, task->igmp_address, IGMP_MEMBERSHIP_REPORT); + task->base.tx_pkt(&task->base, &igmp_mbuf, 1, out); +} + +void igmp_leave_group(struct task_base *tbase) +{ + struct task_swap *task = (struct task_swap *)tbase; + struct rte_mbuf *igmp_mbuf; + uint8_t out[64] = {0}; + int ret; + + task->igmp_address = 0; + ret = rte_mempool_get(task->igmp_pool, (void **)&igmp_mbuf); + if (ret != 0) { + plog_err("Unable to allocate igmp mbuf\n"); + return; + } + build_igmp_message(tbase, igmp_mbuf, task->igmp_address, IGMP_LEAVE_GROUP); + task->base.tx_pkt(&task->base, &igmp_mbuf, 1, out); +} + static void init_task_swap(struct task_base *tbase, struct task_args *targ) { struct task_swap *task = (struct task_swap *)tbase; @@ -240,27 +351,36 @@ static void init_task_swap(struct task_base *tbase, struct task_args *targ) } } task->runtime_flags = targ->flags; + task->igmp_address = rte_cpu_to_be_32(targ->igmp_address); + if (task->igmp_pool == NULL) { + static char name[] = "igmp0_pool"; + name[4]++; + struct rte_mempool *ret = rte_mempool_create(name, NB_IGMP_MBUF, IGMP_MBUF_SIZE, NB_CACHE_IGMP_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 IGMP memory pool on socket %u with %u elements\n", + rte_socket_id(), NB_IGMP_MBUF); + plog_info("\t\tMempool %p (%s) size = %u * %u cache %u, socket %d\n", ret, name, NB_IGMP_MBUF, + IGMP_MBUF_SIZE, NB_CACHE_IGMP_MBUF, rte_socket_id()); + task->igmp_pool = ret; + } + task->local_ipv4 = rte_cpu_to_be_32(targ->local_ipv4); + + struct prox_port_cfg *port = find_reachable_port(targ); + if (port) { + task->offload_crc = port->requested_tx_offload & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM); + } } static struct task_init task_init_swap = { .mode_str = "swap", .init = init_task_swap, .handle = handle_swap_bulk, - .flag_features = TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS, - .size = sizeof(struct task_swap), -}; - -static struct task_init task_init_swap_arp = { - .mode_str = "swap", - .sub_mode_str = "l3", - .init = init_task_swap, - .handle = handle_swap_bulk, - .flag_features = TASK_FEATURE_TXQ_FLAGS_NOOFFLOADS, + .flag_features = 0, .size = sizeof(struct task_swap), }; __attribute__((constructor)) static void reg_task_swap(void) { reg_task(&task_init_swap); - reg_task(&task_init_swap_arp); } diff --git a/VNFs/DPPD-PROX/handle_swap.h b/VNFs/DPPD-PROX/handle_swap.h deleted file mode 100644 index b589051d..00000000 --- a/VNFs/DPPD-PROX/handle_swap.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -// 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. -*/ - -#ifndef _HANDLE_SWAP_H_ -#define _HANDLE_SWAP_H_ - -struct task_base; - -#endif /* _HANDLE_SWAP_H_ */ diff --git a/VNFs/DPPD-PROX/igmp.h b/VNFs/DPPD-PROX/igmp.h new file mode 100644 index 00000000..7b868aae --- /dev/null +++ b/VNFs/DPPD-PROX/igmp.h @@ -0,0 +1,59 @@ +/* +// Copyright (c) 2019 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 _IGMP_H_ +#define _IGMP_H_ + +#define IGMP_MEMBERSHIP_QUERY 0x11 +#define IGMP_MEMBERSHIP_REPORT_V1 0x12 +#define IGMP_MEMBERSHIP_REPORT 0x16 +#define IGMP_LEAVE_GROUP 0x17 + +struct igmpv1_hdr { + uint8_t type: 4; /* type */ + uint8_t version: 4; /* version */ + uint8_t unused; /* unused */ + uint16_t checksum; /* checksum */ + uint32_t group_address; /* group address */ +} __attribute__((__packed__)); + +struct igmpv2_hdr { + uint8_t type; /* type */ + uint8_t max_resp_time; /* maximum response time */ + uint16_t checksum; /* checksum */ + uint32_t group_address; /* group address */ +} __attribute__((__packed__)); + +struct igmpv3_hdr { + uint8_t type; /* type */ + uint8_t max_resp_time; /* maximum response time */ + uint16_t checksum; /* checksum */ + uint32_t group_address; /* group address */ + uint8_t bits: 4; /* S(suppress router-side processing)QRV(Querier.s Robustness Variable) bits */ + uint8_t reserved: 4; /* reserved */ + uint8_t QQIC; /* Querier.s Query Interval Code */ + uint16_t n_src; /* Number of source addresses */ +} __attribute__((__packed__)); + +struct task_base; + +// igmp_join and leave functions are so far implemented within handle_swap. +// Only swap task can use them right now, as they use igmp_pool +// only defined in swap task. +void igmp_join_group(struct task_base *tbase, uint32_t igmp_address); +void igmp_leave_group(struct task_base *tbase); + +#endif /* _IGMP_H_ */ diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c index b99796b7..df69f979 100644 --- a/VNFs/DPPD-PROX/prox_args.c +++ b/VNFs/DPPD-PROX/prox_args.c @@ -534,6 +534,17 @@ static int get_port_cfg(unsigned sindex, char *str, void *data) } cfg->promiscuous = val; } + else if (STR_EQ(str, "multicast")) { + uint32_t val; + if (cfg->nb_mc_addr >= NB_MCAST_ADDR) { + plog_err("too many multicast addresses\n"); + return -1; + } + if (parse_mac(&cfg->mc_addr[cfg->nb_mc_addr], pkey)) { + return -1; + } + cfg->nb_mc_addr++ ; + } else if (STR_EQ(str, "lsc")) { cfg->lsc_set_explicitely = 1; uint32_t val; @@ -856,9 +867,6 @@ static int get_core_cfg(unsigned sindex, char *str, void *data) if (STR_EQ(str, "fast path handle arp")) { return parse_flag(&targ->runtime_flags, TASK_FP_HANDLE_ARP, pkey); } - if (STR_EQ(str, "multiple arp")) { - return parse_flag(&targ->flags, TASK_MULTIPLE_MAC, pkey); - } /* Using tx port name, only a _single_ port can be assigned to a task. */ if (STR_EQ(str, "tx port")) { @@ -1356,6 +1364,9 @@ static int get_core_cfg(unsigned sindex, char *str, void *data) targ->flags |= TASK_ARG_SRC_MAC_SET; return 0; } + if (STR_EQ(str, "igmp ipv4")) { /* IGMP Group */ + return parse_ip(&targ->igmp_address, pkey); + } if (STR_EQ(str, "gateway ipv4")) { /* Gateway IP address used when generating */ if ((targ->flags & TASK_ARG_L3) == 0) plog_warn("gateway ipv4 configured but L3 sub mode not enabled\n"); diff --git a/VNFs/DPPD-PROX/prox_cksum.c b/VNFs/DPPD-PROX/prox_cksum.c index add52f2b..58e05a6b 100644 --- a/VNFs/DPPD-PROX/prox_cksum.c +++ b/VNFs/DPPD-PROX/prox_cksum.c @@ -112,6 +112,10 @@ inline void prox_ip_udp_cksum(struct rte_mbuf *mbuf, struct ipv4_hdr *pip, uint1 } else #endif prox_tcp_cksum_sw(tcp, l4_len, pip->src_addr, pip->dst_addr); + } else if (pip->next_proto_id == IPPROTO_IGMP) { + struct igmpv2_hdr *igmp = (struct igmpv2_hdr *)(((uint8_t*)pip) + l3_len); + // Not sure NIC can offload IGMP checkum => do it in software + prox_igmp_cksum_sw(igmp, l4_len); } } @@ -153,3 +157,10 @@ inline void prox_tcp_cksum_sw(struct tcp_hdr *tcp, uint16_t len, uint32_t src_ip uint16_t csum = checksum_byte_seq((uint16_t *)tcp, len); tcp->cksum = csum; } + +inline void prox_igmp_cksum_sw(struct igmpv2_hdr *igmp, uint16_t len) +{ + igmp->checksum = 0; + uint16_t csum = checksum_byte_seq((uint16_t *)igmp, len); + igmp->checksum = csum; +} diff --git a/VNFs/DPPD-PROX/prox_cksum.h b/VNFs/DPPD-PROX/prox_cksum.h index c11b17a5..57489900 100644 --- a/VNFs/DPPD-PROX/prox_cksum.h +++ b/VNFs/DPPD-PROX/prox_cksum.h @@ -25,6 +25,7 @@ #include #include #include +#include "igmp.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) @@ -64,5 +65,6 @@ void prox_ip_udp_cksum(struct rte_mbuf *mbuf, struct ipv4_hdr *buf, uint16_t l2_ /* src_ip_addr/dst_ip_addr are in network byte order */ void prox_udp_cksum_sw(struct udp_hdr *udp, uint16_t len, uint32_t src_ip_addr, uint32_t dst_ip_addr); void prox_tcp_cksum_sw(struct 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); #endif /* _PROX_CKSUM_H_ */ diff --git a/VNFs/DPPD-PROX/prox_port_cfg.c b/VNFs/DPPD-PROX/prox_port_cfg.c index c335ee10..ac0ba0f3 100644 --- a/VNFs/DPPD-PROX/prox_port_cfg.c +++ b/VNFs/DPPD-PROX/prox_port_cfg.c @@ -41,6 +41,7 @@ #include "prox_cksum.h" #include "stats_irq.h" #include "prox_compat.h" +#include "rte_ethdev.h" struct prox_port_cfg prox_port_cfg[PROX_MAX_PORTS]; rte_atomic32_t lsc; @@ -518,7 +519,7 @@ static void init_port(struct prox_port_cfg *port_cfg) #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0) port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf &= port_cfg->dev_info.flow_type_rss_offloads; #endif - plog_info("\t\t Enabling RSS rss_hf = 0x%lx (requested 0x%llx)\n", port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf, ETH_RSS_IP|ETH_RSS_UDP); + plog_info("\t\t Enabling RSS rss_hf = 0x%lx (requested 0x%llx, supported 0x%lx)\n", port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf, ETH_RSS_IP|ETH_RSS_UDP, port_cfg->dev_info.flow_type_rss_offloads); // rxmode such as hw src strip #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1) @@ -689,6 +690,18 @@ static void init_port(struct prox_port_cfg *port_cfg) } } } + if (port_cfg->nb_mc_addr) { + rte_eth_allmulticast_enable(port_id); + if ((ret = rte_eth_dev_set_mc_addr_list(port_id, port_cfg->mc_addr, port_cfg->nb_mc_addr)) != 0) { + plog_err("\t\trte_eth_dev_set_mc_addr_list returns %d on port %u\n", ret, port_id); + port_cfg->nb_mc_addr = 0; + rte_eth_allmulticast_disable(port_id); + plog_info("\t\tport %u NOT in multicast mode as failed to add mcast address\n", port_id); + } else { + plog_info("\t\trte_eth_dev_set_mc_addr_list(%d addr) on port %u\n", port_cfg->nb_mc_addr, port_id); + plog_info("\t\tport %u in multicast mode\n", port_id); + } + } } void init_port_all(void) diff --git a/VNFs/DPPD-PROX/prox_port_cfg.h b/VNFs/DPPD-PROX/prox_port_cfg.h index ccf83d6c..c025c03d 100644 --- a/VNFs/DPPD-PROX/prox_port_cfg.h +++ b/VNFs/DPPD-PROX/prox_port_cfg.h @@ -32,6 +32,7 @@ enum addr_type {PROX_PORT_MAC_HW, PROX_PORT_MAC_SET, PROX_PORT_MAC_RAND}; #define IPV4_CKSUM 1 #define UDP_CKSUM 2 +#define NB_MCAST_ADDR 16 struct prox_port_cfg { struct rte_mempool *pool[32]; /* Rx/Tx mempool */ @@ -71,6 +72,8 @@ struct prox_port_cfg { } capabilities; uint32_t max_rx_pkt_len; uint32_t min_rx_bufsize; + uint32_t nb_mc_addr; + struct ether_addr mc_addr[NB_MCAST_ADDR]; }; extern rte_atomic32_t lsc; diff --git a/VNFs/DPPD-PROX/task_base.h b/VNFs/DPPD-PROX/task_base.h index 64d17436..ce70aca2 100644 --- a/VNFs/DPPD-PROX/task_base.h +++ b/VNFs/DPPD-PROX/task_base.h @@ -53,7 +53,6 @@ #define TASK_FEATURE_LUT_QINQ_RSS 0x2000 #define TASK_FEATURE_LUT_QINQ_HASH 0x4000 #define TASK_FEATURE_RX_ALL 0x8000 -#define TASK_MULTIPLE_MAC 0x10000 #define TASK_FEATURE_TXQ_FLAGS_MULTIPLE_MEMPOOL 0x20000 #define FLAG_TX_FLUSH 0x01 diff --git a/VNFs/DPPD-PROX/task_init.h b/VNFs/DPPD-PROX/task_init.h index f513d34f..9fa9f92b 100644 --- a/VNFs/DPPD-PROX/task_init.h +++ b/VNFs/DPPD-PROX/task_init.h @@ -233,6 +233,7 @@ struct task_args { uint irq_debug; struct task_base *tmaster; char sub_mode_str[PROX_MODE_LEN]; + uint32_t igmp_address; }; /* Return the first port that is reachable through the task. If the -- cgit 1.2.3-korg