Improve ctrlplane performance
[samplevnf.git] / VNFs / DPPD-PROX / tx_pkt.c
index 49f4689..8bf501f 100644 (file)
@@ -55,22 +55,46 @@ int tx_pkt_l3(struct task_base *tbase, struct rte_mbuf **mbufs, uint16_t n_pkts,
        uint32_t 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 *arp_mbuf = NULL;       // used when one need to send both an ARP and a mbuf
+       uint64_t *time;
 
        for (int j = 0; j < n_pkts; j++) {
                if ((out) && (out[j] >= OUT_HANDLED))
                        continue;
-               if (unlikely((rc = write_dst_mac(tbase, mbufs[j], &ip_dst)) < 0)) {
+               if (unlikely((rc = write_dst_mac(tbase, mbufs[j], &ip_dst, &time)) != SEND_MBUF)) {
                        if (j - first) {
                                ret = tbase->aux->tx_pkt_l2(tbase, mbufs + first, j - first, out);
                                ok += ret;
                        }
                        first = j + 1;
-                       if (rc == -1) {
+                       switch(rc) {
+                       case SEND_ARP:
+                               // 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;
-                               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);
-                       } else if (rc == -2) {
+                               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);
+                               else
+                                       update_arp_update_time(&tbase->l3, time, 100);
+                               break;
+                       case SEND_MBUF_AND_ARP:
+                               // 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);
+                               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);
+                                       else
+                                               update_arp_update_time(&tbase->l3, time, 100);
+                               } else {
+                                       plog_err("Failed to get a mbuf from arp 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;
                        }
                }
        }
@@ -745,6 +769,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)
 {
@@ -755,23 +812,24 @@ static inline int tx_ring_all(struct task_base *tbase, struct rte_ring *ring, ui
        return rte_ring_enqueue(ring, mbuf);
 }
 
-void 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, uint16_t command,  struct rte_mbuf *mbuf, uint8_t core_id, uint8_t task_id, uint32_t ip)
 {
-       plogx_dbg("\tSending command %s with ip %x to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], ip, ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+       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);
        if (unlikely(ret != 0)) {
-               plogx_dbg("\tFail to send command %s with ip %x to ring %p using mbuf %p, core %d and task %d - ring size now %d\n", actions_string[command], ip, ring, mbuf, core_id, task_id, rte_ring_free_count(ring));
+               plogx_dbg("\tFail to send 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));
                TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
                rte_pktmbuf_free(mbuf);
        }
+       return ret;
 }
 
 void tx_ring_ip(struct task_base *tbase, struct rte_ring *ring, uint16_t command,  struct rte_mbuf *mbuf, uint32_t ip)
 {
-       plogx_dbg("\tSending command %s with ip %x to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ip, ring, mbuf, rte_ring_free_count(ring));
+       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);
        if (unlikely(ret != 0)) {
-               plogx_dbg("\tFail to send command %s with ip %x to ring %p using mbuf %p - ring size now %d\n", actions_string[command], ip, ring, mbuf, rte_ring_free_count(ring));
+               plogx_dbg("\tFail to send 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));
                TASK_STATS_ADD_DROP_DISCARD(&tbase->aux->stats, 1);
                rte_pktmbuf_free(mbuf);
        }