Prevent dropping ARP packets 57/66157/1
authorXavier Simonart <xavier.simonart@intel.com>
Wed, 26 Dec 2018 14:26:27 +0000 (15:26 +0100)
committerXavier Simonart <xavier.simonart@intel.com>
Thu, 3 Jan 2019 12:18:19 +0000 (13:18 +0100)
JIRA: SAMPLEVNF-152

When system is overloaded, ARP packets were sometimes dropped, as any
other packets.
This was causing two issues:
- The count of TX non dataplane packets was wrong
- If many consecutive ARP packets were dropped, the underlying switch might
  see its ARP timer expiring, causing performance degradation (packets being
  broadcasted).
ARP packets are now always sent as no-drop.

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

index e93f430..274d2f8 100644 (file)
@@ -325,9 +325,10 @@ void handle_ctrl_plane_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, ui
                        break;
                case ARP_REPLY_FROM_CTRL:
                case ARP_REQ_FROM_CTRL:
-                       TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
                        out[0] = 0;
-                       tbase->aux->tx_pkt_l2(tbase, &mbufs[j], 1, out);
+                       // tx_ctrlplane_pkt does not drop packets
+                       tbase->aux->tx_ctrlplane_pkt(tbase, &mbufs[j], 1, out);
+                       TASK_STATS_ADD_TX_NON_DP(&tbase->aux->stats, 1);
                        break;
                }
        }
index b4a3337..64d1743 100644 (file)
@@ -174,6 +174,7 @@ struct task_base_aux {
        int (*tx_pkt_hw)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, uint8_t *out);
        uint16_t (*tx_pkt_try)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts);
        void (*stop)(struct task_base *tbase);
+       int (*tx_ctrlplane_pkt)(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, uint8_t *out);
        void (*start)(struct task_base *tbase);
        void (*stop_last)(struct task_base *tbase);
        void (*start_first)(struct task_base *tbase);
index 2361d32..08ccaf9 100644 (file)
@@ -208,7 +208,7 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
        if ((targ->nb_txrings != 0) && (!targ->tx_opt_ring) && (!(targ->flags & TASK_ARG_DROP))) {
                // Transmitting to a ring in NO DROP. We need to make sure the receiving task in not running on the same core.
                // Otherwise we might end up in a dead lock: trying in a loop to transmit to a task which cannot receive anymore
-               // (as npt being scheduled).
+               // (as not being scheduled).
                struct core_task ct;
                struct task_args *dtarg;
                for (unsigned int j = 0; j < targ->nb_txrings; j++) {
@@ -277,6 +277,7 @@ static size_t init_rx_tx_rings_ports(struct task_args *targ, struct task_base *t
                        prev = prev->tx_opt_ring_task;
                }
        }
+
        if (targ->nb_txrings == 1 || targ->nb_txports == 1 || targ->tx_opt_ring) {
                if (targ->task_init->flag_features & TASK_FEATURE_NEVER_DISCARDS) {
                        if (targ->tx_opt_ring) {
@@ -350,13 +351,6 @@ struct task_base *init_task_struct(struct task_args *targ)
        offset = init_rx_tx_rings_ports(targ, tbase, offset);
        tbase->aux = (struct task_base_aux *)(((uint8_t *)tbase) + offset);
 
-       if (targ->nb_txports != 0) {
-               if (targ->flags & TASK_ARG_L3) {
-                       tbase->aux->tx_pkt_l2 = tbase->tx_pkt;
-                       tbase->tx_pkt = tx_pkt_l3;
-               }
-       }
-
        if (targ->task_init->flag_features & TASK_FEATURE_RX_ALL) {
                task_base_add_rx_pkt_function(tbase, rx_pkt_all);
                tbase->aux->all_mbufs = prox_zmalloc(MAX_RX_PKT_ALL * sizeof(* tbase->aux->all_mbufs), task_socket);
@@ -372,10 +366,13 @@ struct task_base *init_task_struct(struct task_args *targ)
        if (targ->flags & TASK_ARG_L3) {
                plog_info("\tTask configured in L3 mode\n");
                tbase->l3.ctrl_plane_ring = targ->ctrl_plane_ring;
-       }
-       if (targ->nb_txports != 0) {
-               if (targ->flags & TASK_ARG_L3)
+               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);
+               }
        }
 
        targ->tbase = tbase;
index c5047e5..d494236 100644 (file)
@@ -762,6 +762,39 @@ int tx_pkt_drop_all(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n
        }
        return n_pkts;
 }
+static inline void dump_pkts(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts)
+{
+       uint32_t n_dump = tbase->aux->task_rt_dump.n_print_tx;
+       uint32_t n_trace = tbase->aux->task_rt_dump.n_trace;
+
+       if (unlikely(n_dump)) {
+               n_dump = n_pkts < n_dump? n_pkts : n_dump;
+               for (uint32_t i = 0; i < n_dump; ++i) {
+                       plogdx_info(mbufs[i], "TX: ");
+               }
+               tbase->aux->task_rt_dump.n_print_tx -= n_dump;
+       } else if (unlikely(n_trace)) {
+               n_trace = n_pkts < n_trace? n_pkts : n_trace;
+               for (uint32_t i = 0; i < n_trace; ++i) {
+                       plogdx_info(mbufs[i], "TX: ");
+               }
+               tbase->aux->task_rt_dump.n_trace - n_trace;
+       }
+}
+
+// ctrlplane packets are slow path, hence cost of checking if dump ortrace is needed in not too important
+// easier to have this implementation than an implementation similar to dataplane tx
+int tx_ctrlplane_hw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, __attribute__((unused)) uint8_t *out)
+{
+       dump_pkts(tbase, mbufs, n_pkts);
+       return txhw_no_drop(&tbase->tx_params_hw.tx_port_queue[0], mbufs, n_pkts, tbase);
+}
+
+int tx_ctrlplane_sw(struct task_base *tbase, struct rte_mbuf **mbufs, const uint16_t n_pkts, __attribute__((unused)) uint8_t *out)
+{
+       dump_pkts(tbase, mbufs, n_pkts);
+        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)
 {
index e8caed5..a688153 100644 (file)
@@ -64,6 +64,8 @@ int tx_pkt_no_drop_hw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t
 int tx_pkt_no_drop_sw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
 int tx_pkt_hw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
 int tx_pkt_sw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
+int tx_ctrlplane_hw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
+int tx_ctrlplane_sw(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
 
 int tx_pkt_trace(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);
 int tx_pkt_dump(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts, uint8_t *out);