Added support for gateway ipv6 & cmd for sending unsollicited neighbor advertisement 51/70251/5
authorXavier Simonart <xavier.simonart@intel.com>
Mon, 1 Jun 2020 18:52:57 +0000 (20:52 +0200)
committerXavier Simonart <xavier.simonart@intel.com>
Mon, 21 Sep 2020 08:09:46 +0000 (10:09 +0200)
Change-Id: Iae35d3fa19ad7cf90d8c2e0c104b0e798ac34787
Signed-off-by: Xavier Simonart <xavier.simonart@intel.com>
VNFs/DPPD-PROX/cmd_parser.c
VNFs/DPPD-PROX/packet_utils.c
VNFs/DPPD-PROX/packet_utils.h
VNFs/DPPD-PROX/prox_args.c
VNFs/DPPD-PROX/tx_pkt.c

index 51a71f4..1f2d5fc 100644 (file)
@@ -2162,6 +2162,29 @@ static int parse_cmd_join_igmp(const char *str, struct input *input)
        return 0;
 }
 
+static int parse_cmd_send_unsollicited_na(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_sub_mode(lcore_id, task_id, "ndp")) {
+                               plog_err("Core %u task %u is not running ndp\n", lcore_id, task_id);
+                       }
+                       else {
+                               struct task_base *tbase = lcore_cfg[lcore_id].tasks_all[task_id];
+                               send_unsollicited_neighbour_advertisement(tbase);
+                       }
+               }
+       }
+       return 0;
+}
+
 static int parse_cmd_rx_tx_info(const char *str, struct input *input)
 {
        if (strcmp(str, "") != 0) {
@@ -2301,6 +2324,7 @@ static struct cmd_str cmd_strings[] = {
        {"version", "", "Show version", parse_cmd_version},
        {"join igmp", "<core_id> <task_id> <ip>", "Send igmp membership report for group <ip>", parse_cmd_join_igmp},
        {"leave igmp", "<core_id> <task_id>", "Send igmp leave group", parse_cmd_leave_igmp},
+       {"send unsollicited na", "<core_id> <task_id>", "Send Unsollicited Neighbor Advertisement", parse_cmd_send_unsollicited_na},
        {0,0,0,0},
 };
 
index 70d5c02..a12281d 100644 (file)
@@ -142,20 +142,38 @@ static inline struct ipv6_addr *find_ip6(prox_rte_ether_hdr *pkt, uint16_t len,
        return NULL;
 }
 
-static void send_unsollicited_neighbour_advertisement(struct task_base *tbase, struct task_args *targ)
+void send_unsollicited_neighbour_advertisement(struct task_base *tbase)
 {
        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");
+       struct rte_mbuf *mbuf = NULL;
+
+       if (memcmp(&tbase->l3.local_ipv6, &null_addr, 16) != 0) {
+               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, &tbase->l3.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");
+                       return;
+               }
+       }
+       if (memcmp(&tbase->l3.global_ipv6, &null_addr, 16) != 0) {
+               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, &tbase->l3.global_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");
+                       return;
+               }
+       }
+       if (mbuf == NULL) {
+               plog_err("No neighbor advertisement sent as no local or global ipv6\n");
        }
 }
 
@@ -363,18 +381,27 @@ int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv
                return SEND_MBUF;
        }
        struct l3_base *l3 = &(tbase->l3);
+
+       // Configure source IP
        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) {
+       } else if (memcmp(&l3->global_ipv6 , ip_dst, 8) == 0) {
+               // Same prefix as global -> use global
+               used_ip_src = &l3->global_ipv6;
+       } else if (memcmp(&l3->gw.ip6 , &null_addr, sizeof(struct ipv6_addr)) != 0) {
+               used_ip_src = &l3->global_ipv6;
+               memcpy(ip_dst, &l3->gw.ip6, sizeof(struct ipv6_addr));
+       } else if (memcmp(&l3->global_ipv6 , &null_addr, sizeof(struct ipv6_addr)) != 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));
+
+       // Configure dst mac
        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) {
@@ -504,6 +531,7 @@ void task_init_l3(struct task_base *tbase, struct task_args *targ)
        targ->lconf->ctrl_func_p[targ->task] = handle_ctrl_plane_pkts;
        targ->lconf->ctrl_timeout = freq_to_tsc(targ->ctrl_freq);
        tbase->l3.gw.ip = rte_cpu_to_be_32(targ->gateway_ipv4);
+       memcpy(&tbase->l3.gw.ip6, &targ->gateway_ipv6, sizeof(struct ipv6_addr));
        tbase->flags |= TASK_L3;
        tbase->l3.core_id = targ->lconf->id;
        tbase->l3.task_id = targ->id;
@@ -588,7 +616,7 @@ void task_start_l3(struct task_base *tbase, struct task_args *targ)
 
                // Create IPv6 addr if none were configured
                if (targ->flags & TASK_ARG_NDP) {
-                       if (!memcmp(&targ->local_ipv6, &null_addr, 16)) {
+                       if (!memcmp(&targ->local_ipv6, &null_addr, sizeof(struct ipv6_addr))) {
                                set_link_local(&targ->local_ipv6);
                                set_EUI(&targ->local_ipv6, &port->eth_addr);
                        }
@@ -626,7 +654,7 @@ void task_start_l3(struct task_base *tbase, struct task_args *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);
+                       send_unsollicited_neighbour_advertisement(tbase);
 
                }
        }
index e1b262d..ce54a89 100644 (file)
@@ -83,6 +83,7 @@ int write_ip6_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, struct ipv
 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);
+void send_unsollicited_neighbour_advertisement(struct task_base *tbase);
 
 static inline void update_arp_ndp_retransmit_timeout(struct l3_base *l3, uint64_t *ptr, uint32_t base)
 {
index 3e3e41b..b16ce7b 100644 (file)
@@ -1522,6 +1522,11 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
                }
                return 0;
        }
+       if (STR_EQ(str, "gateway ipv6")) { /* Gateway IP address used when generating */
+               if ((targ->flags & TASK_ARG_NDP) == 0)
+                       plog_warn("gateway ipv6 configured but NDP sub mode not enabled\n");
+               return parse_ip6(&targ->gateway_ipv6, pkey);
+       }
        if (STR_EQ(str, "local ipv4")) { /* source IP address to be used for packets */
                struct ip4_subnet cidr;
                if (parse_ip4_and_prefix(&cidr, pkey) != 0) {
index f45516e..d93c5fb 100644 (file)
@@ -61,7 +61,6 @@ void store_packet(struct task_base *tbase, struct rte_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];