Add support for configurable arp timers in L3 mode 95/66695/4
authorXavier Simonart <xavier.simonart@intel.com>
Thu, 13 Dec 2018 11:52:02 +0000 (12:52 +0100)
committerXavier Simonart <xavier.simonart@intel.com>
Mon, 28 Jan 2019 11:14:20 +0000 (12:14 +0100)
L3 mode supports two timers:
- arp_update_time, defaulted to 1 second, which makes PROX to send
  arp request every second for active flows
- arp_timeout, previously defaulted to 30 seconds, which makes PROX
  consider a MAC address as invalid if no arp_reply was received
  within those 30 seconds.

Those timers values were hardcoded. They can now be configured through
the configuration file (within the core section), using resp.
"arp update time" and "arp timeout" keywords. Unit is milli seconds.
The default becomes respectively 1 second and 2 weeks.

Change-Id: I35e46e97df32ca44c2cdfae85a20ee015de5d6e1
Signed-off-by: Xavier Simonart <xavier.simonart@intel.com>
VNFs/DPPD-PROX/packet_utils.c
VNFs/DPPD-PROX/packet_utils.h
VNFs/DPPD-PROX/prox_args.c
VNFs/DPPD-PROX/task_init.h

index e93f430..6c3da0e 100644 (file)
@@ -89,7 +89,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
                        return SEND_MBUF;
                } else if (tsc > l3->gw.arp_update_time) {
                        // long time since we have sent an arp, send arp
-                       l3->gw.arp_update_time = tsc + hz;
+                       l3->gw.arp_update_time = tsc + l3->arp_update_time * hz / 1000;
                        *ip_dst = l3->gw.ip;
                        if ((l3->flags & FLAG_DST_MAC_KNOWN) && (tsc < l3->gw.arp_timeout)){
                                // MAC is valid in the table => send also the mbuf
@@ -120,7 +120,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
                                        return SEND_MBUF;
                                } else if (tsc > l3->optimized_arp_table[idx].arp_update_time) {
                                        // ARP not sent since a long time, send ARP
-                                       l3->optimized_arp_table[idx].arp_update_time = tsc + hz;
+                                       l3->optimized_arp_table[idx].arp_update_time = tsc + l3->arp_update_time * hz / 1000;
                                        if (tsc < l3->optimized_arp_table[idx].arp_timeout) {
                                                // MAC still valid => also send mbuf
                                                memcpy(mac, &l3->optimized_arp_table[idx].mac, sizeof(struct ether_addr));
@@ -137,7 +137,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
                }
                // IP address not found in table
                l3->optimized_arp_table[l3->n_pkts].ip = *ip_dst;
-               l3->optimized_arp_table[l3->n_pkts].arp_update_time = tsc + hz;
+               l3->optimized_arp_table[l3->n_pkts].arp_update_time = tsc + l3->arp_update_time * hz / 1000;
                l3->n_pkts++;
 
                if (l3->n_pkts < 4) {
@@ -171,7 +171,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
                                return DROP_MBUF;
                        } else {
                                l3->arp_table[ret].ip = *ip_dst;
-                               l3->arp_table[ret].arp_update_time = tsc + hz;
+                               l3->arp_table[ret].arp_update_time = tsc + l3->arp_update_time * hz / 1000;
                        }
                        return SEND_ARP;
                } else {
@@ -182,6 +182,7 @@ int write_dst_mac(struct task_base *tbase, struct rte_mbuf *mbuf, uint32_t *ip_d
                                return SEND_MBUF;
                        } else if (tsc > l3->arp_table[ret].arp_update_time) {
                                // ARP not sent since a long time, send ARP
+                               l3->arp_table[ret].arp_update_time = tsc + l3->arp_update_time * hz / 1000;
                                l3->arp_table[ret].arp_update_time = tsc + hz;
                                if (tsc < l3->arp_table[ret].arp_timeout) {
                                        // MAC still valid => send also MBUF
@@ -229,6 +230,14 @@ void task_init_l3(struct task_base *tbase, struct task_args *targ)
        tbase->l3.core_id = targ->lconf->id;
        tbase->l3.task_id = targ->id;
        tbase->l3.tmaster = targ->tmaster;
+       if (tbase->l3.arp_timeout != 0)
+               tbase->l3.arp_timeout = targ->arp_timeout;
+       else
+               tbase->l3.arp_timeout = DEFAULT_ARP_TIMEOUT;
+       if (tbase->l3.arp_update_time != 0)
+               tbase->l3.arp_update_time = targ->arp_update_time;
+       else
+               tbase->l3.arp_update_time = DEFAULT_ARP_UPDATE_TIME;
 }
 
 void task_start_l3(struct task_base *tbase, struct task_args *targ)
@@ -299,7 +308,7 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
                                // MAC address of the gateway
                                memcpy(&l3->gw.mac, &hdr->arp.data.sha, 6);
                                l3->flags |= FLAG_DST_MAC_KNOWN;
-                               l3->gw.arp_timeout = tsc + 30 * hz;
+                               l3->gw.arp_timeout = tsc + l3->arp_timeout * hz / 1000;
                        } 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++) {
@@ -310,7 +319,7 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
                                if (idx < l3->n_pkts) {
                                        // IP not found; this is a reply while we never asked for the request!
                                        memcpy(&l3->optimized_arp_table[idx].mac, &(hdr->arp.data.sha), sizeof(struct ether_addr));
-                                       l3->optimized_arp_table[idx].arp_timeout = tsc + 30 * hz;
+                                       l3->optimized_arp_table[idx].arp_timeout = tsc + l3->arp_timeout * hz / 1000;
                                }
                        } else {
                                int ret = rte_hash_add_key(l3->ip_hash, (const void *)&ip);
@@ -318,7 +327,7 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
                                        plogx_info("Unable add ip %d.%d.%d.%d in mac_hash\n", IP4(ip));
                                } else {
                                        memcpy(&l3->arp_table[ret].mac, &(hdr->arp.data.sha), sizeof(struct ether_addr));
-                                       l3->arp_table[ret].arp_timeout = tsc + 30 * hz;
+                                       l3->arp_table[ret].arp_timeout = tsc + l3->arp_timeout * hz / 1000;
                                }
                        }
                        tx_drop(mbufs[j]);
index 74a3f60..cb4dc91 100644 (file)
@@ -33,6 +33,8 @@ enum {
        SEND_ARP,
        DROP_MBUF
 };
+#define DEFAULT_ARP_TIMEOUT    (1000 * 3600 * 24 * 15) // ~15 days = disabled by default
+#define DEFAULT_ARP_UPDATE_TIME (1000)                 // 1 second
 
 struct task_base;
 struct task_args;
@@ -50,6 +52,8 @@ struct l3_base {
        uint8_t reachable_port_id;
        uint8_t core_id;
        uint8_t task_id;
+       uint32_t arp_timeout;
+       uint32_t arp_update_time;
        struct arp_table gw;
        struct arp_table optimized_arp_table[4];
        struct rte_hash *ip_hash;
index 59c514f..d77eab1 100644 (file)
@@ -1362,6 +1362,10 @@ static int get_core_cfg(unsigned sindex, char *str, void *data)
         if (STR_EQ(str, "local ipv6")) { /* source IPv6 address to be used for packets */
                 return parse_ip6(&targ->local_ipv6, pkey);
         }
+       if (STR_EQ(str, "arp timeout"))
+               return parse_int(&targ->arp_timeout, pkey);
+       if (STR_EQ(str, "arp update time"))
+               return parse_int(&targ->arp_update_time, pkey);
        if (STR_EQ(str, "number of packets"))
                return parse_int(&targ->n_pkts, pkey);
        if (STR_EQ(str, "pipes")) {
index 5186826..91a0d7e 100644 (file)
@@ -127,6 +127,8 @@ struct task_args {
        uint32_t               gateway_ipv4;
        uint32_t               local_ipv4;
        uint32_t               remote_ipv4;
+       uint32_t               arp_timeout;
+       uint32_t               arp_update_time;
        struct ipv6_addr       local_ipv6;    /* For IPv6 Tunnel, it's the local tunnel endpoint address */
        struct rte_ring        *rx_rings[MAX_RINGS_PER_TASK];
        struct rte_ring        *tx_rings[MAX_RINGS_PER_TASK];