Adding PROX(Packet pROcessing eXecution engine) VNF to sampleVNF
[samplevnf.git] / VNFs / DPPD-PROX / lconf.c
diff --git a/VNFs/DPPD-PROX/lconf.c b/VNFs/DPPD-PROX/lconf.c
new file mode 100644 (file)
index 0000000..88d8f4f
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+// 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.
+*/
+
+#include "prox_malloc.h"
+#include "lconf.h"
+#include "rx_pkt.h"
+#include "tx_pkt.h"
+#include "log.h"
+#include "quit.h"
+#include "prox_cfg.h"
+
+struct lcore_cfg *lcore_cfg;
+/* only used at initialization time */
+struct lcore_cfg  lcore_cfg_init[RTE_MAX_LCORE];
+
+static int core_targ_next_from(struct lcore_cfg **lconf, struct task_args **targ, struct lcore_cfg *lcore_cfg, const int with_master)
+{
+       uint32_t lcore_id, task_id;
+
+       if (*lconf && *targ) {
+               lcore_id = *lconf - lcore_cfg;
+               task_id = *targ - lcore_cfg[lcore_id].targs;
+
+               if (task_id + 1 < lcore_cfg[lcore_id].n_tasks_all) {
+                       *targ = &lcore_cfg[lcore_id].targs[task_id + 1];
+                       return 0;
+               } else {
+                       if (prox_core_next(&lcore_id, with_master))
+                               return -1;
+                       *lconf = &lcore_cfg[lcore_id];
+                       *targ = &lcore_cfg[lcore_id].targs[0];
+                       return 0;
+               }
+       } else {
+               lcore_id = -1;
+
+               if (prox_core_next(&lcore_id, with_master))
+                       return -1;
+               *lconf = &lcore_cfg[lcore_id];
+               *targ = &lcore_cfg[lcore_id].targs[0];
+               return 0;
+       }
+}
+
+int core_targ_next(struct lcore_cfg **lconf, struct task_args **targ, const int with_master)
+{
+       return core_targ_next_from(lconf, targ, lcore_cfg, with_master);
+}
+
+int core_targ_next_early(struct lcore_cfg **lconf, struct task_args **targ, const int with_master)
+{
+       return core_targ_next_from(lconf, targ, lcore_cfg_init, with_master);
+}
+
+struct task_args *core_targ_get(uint32_t lcore_id, uint32_t task_id)
+{
+       return &lcore_cfg[lcore_id].targs[task_id];
+}
+
+void lcore_cfg_alloc_hp(void)
+{
+       size_t mem_size = RTE_MAX_LCORE * sizeof(struct lcore_cfg);
+
+       lcore_cfg = prox_zmalloc(mem_size, rte_socket_id());
+       PROX_PANIC(lcore_cfg == NULL, "Could not allocate memory for core control structures\n");
+       rte_memcpy(lcore_cfg, lcore_cfg_init, mem_size);
+
+       /* get thread ID for master core */
+       lcore_cfg[rte_lcore_id()].thread_id = pthread_self();
+}
+
+int lconf_run(__attribute__((unused)) void *dummy)
+{
+       uint32_t lcore_id = rte_lcore_id();
+       struct lcore_cfg *lconf = &lcore_cfg[lcore_id];
+
+       /* get thread ID, and set cancellation type to asynchronous */
+       lconf->thread_id = pthread_self();
+       int ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+       if (ret != 0)
+               plog_warn("pthread_setcanceltype() failed on core %u: %i\n", lcore_id, ret);
+
+       plog_info("Entering main loop on core %u\n", lcore_id);
+       return lconf->thread_x(lconf);
+}
+
+static void msg_stop(struct lcore_cfg *lconf)
+{
+       int idx = -1;
+       struct task_base *t = NULL;
+
+       if (lconf->msg.task_id == -1) {
+               for (int i = 0; i < lconf->n_tasks_all; ++i) {
+                       if (lconf->task_is_running[i]) {
+                               lconf->task_is_running[i] = 0;
+                               t = lconf->tasks_all[i];
+                               if (t->aux->stop)
+                                   t->aux->stop(t);
+                       }
+               }
+               lconf->n_tasks_run = 0;
+
+               if (t && t->aux->stop_last)
+                       t->aux->stop_last(t);
+       }
+       else {
+               for (int i = 0; i < lconf->n_tasks_run; ++i) {
+                       if (lconf_get_task_id(lconf, lconf->tasks_run[i]) == lconf->msg.task_id) {
+                               idx = i;
+                       }
+                       else if (idx != -1) {
+                               lconf->tasks_run[idx] = lconf->tasks_run[i];
+
+                               idx++;
+                       }
+               }
+               lconf->task_is_running[lconf->msg.task_id] = 0;
+
+               t = lconf->tasks_all[lconf->msg.task_id];
+               if (t->aux->stop)
+                       t->aux->stop(t);
+               lconf->n_tasks_run--;
+               if (lconf->n_tasks_run == 0 && t->aux->stop_last)
+                       t->aux->stop_last(t);
+       }
+}
+
+static void msg_start(struct lcore_cfg *lconf)
+{
+       int idx = 1;
+       struct task_base *t = NULL;
+
+       if (lconf->msg.task_id == -1) {
+               for (int i = 0; i < lconf->n_tasks_all; ++i) {
+                       t = lconf->tasks_run[i] = lconf->tasks_all[i];
+                       lconf->task_is_running[i] = 1;
+                       if (lconf->n_tasks_run == 0 && t->aux->start_first) {
+                               t->aux->start_first(t);
+                               lconf->n_tasks_run = 1;
+                       }
+                       if (t->aux->start)
+                               t->aux->start(t);
+               }
+               lconf->n_tasks_run = lconf->n_tasks_all;
+       }
+       else if (lconf->n_tasks_run == 0) {
+               t = lconf->tasks_run[0] = lconf->tasks_all[lconf->msg.task_id];
+               lconf->n_tasks_run = 1;
+               lconf->task_is_running[lconf->msg.task_id] = 1;
+
+               if (t->aux->start_first)
+                       t->aux->start_first(t);
+               if (t->aux->start)
+                       t->aux->start(t);
+       }
+       else {
+               for (int i = lconf->n_tasks_run - 1; i >= 0; --i) {
+                       idx = lconf_get_task_id(lconf, lconf->tasks_run[i]);
+                       if (idx == lconf->msg.task_id) {
+                               break;
+                       }
+                       else if (idx > lconf->msg.task_id) {
+                               lconf->tasks_run[i + 1] = lconf->tasks_run[i];
+                               if (i == 0) {
+                                       lconf->tasks_run[i] = lconf->tasks_all[lconf->msg.task_id];
+                                       lconf->n_tasks_run++;
+                                       break;
+                               }
+                       }
+                       else {
+                               lconf->tasks_run[i + 1] = lconf->tasks_all[lconf->msg.task_id];
+                               lconf->n_tasks_run++;
+                               break;
+                       }
+               }
+               lconf->task_is_running[lconf->msg.task_id] = 1;
+
+               if (lconf->tasks_all[lconf->msg.task_id]->aux->start)
+                       lconf->tasks_all[lconf->msg.task_id]->aux->start(lconf->tasks_all[lconf->msg.task_id]);
+       }
+}
+
+int lconf_do_flags(struct lcore_cfg *lconf)
+{
+       struct task_base *t;
+       int ret = 0;
+
+       switch (lconf->msg.type) {
+       case LCONF_MSG_STOP:
+               msg_stop(lconf);
+               ret = -1;
+               break;
+       case LCONF_MSG_START:
+               msg_start(lconf);
+               ret = -1;
+               break;
+       case LCONF_MSG_DUMP_RX:
+       case LCONF_MSG_DUMP_TX:
+       case LCONF_MSG_DUMP:
+               t = lconf->tasks_all[lconf->msg.task_id];
+
+               if (lconf->msg.val) {
+                       if (lconf->msg.type == LCONF_MSG_DUMP ||
+                           lconf->msg.type == LCONF_MSG_DUMP_RX) {
+                               t->aux->task_rt_dump.n_print_rx = lconf->msg.val;
+
+                               task_base_add_rx_pkt_function(t, rx_pkt_dump);
+                       }
+
+                       if (lconf->msg.type == LCONF_MSG_DUMP ||
+                           lconf->msg.type == LCONF_MSG_DUMP_TX) {
+                               t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
+                               if (t->aux->tx_pkt_orig)
+                                       t->tx_pkt = t->aux->tx_pkt_orig;
+                               t->aux->tx_pkt_orig = t->tx_pkt;
+                               t->tx_pkt = tx_pkt_dump;
+                       }
+               }
+               break;
+       case LCONF_MSG_TRACE:
+               t = lconf->tasks_all[lconf->msg.task_id];
+
+               if (lconf->msg.val) {
+                       t->aux->task_rt_dump.n_trace = lconf->msg.val;
+
+                       if (task_base_get_original_rx_pkt_function(t) != rx_pkt_dummy) {
+                               task_base_add_rx_pkt_function(t, rx_pkt_trace);
+                               if (t->aux->tx_pkt_orig)
+                                       t->tx_pkt = t->aux->tx_pkt_orig;
+                               t->aux->tx_pkt_orig = t->tx_pkt;
+                               t->tx_pkt = tx_pkt_trace;
+                       } else {
+                               t->aux->task_rt_dump.n_print_tx = lconf->msg.val;
+                               if (t->aux->tx_pkt_orig)
+                                       t->tx_pkt = t->aux->tx_pkt_orig;
+                               t->aux->tx_pkt_orig = t->tx_pkt;
+                               t->tx_pkt = tx_pkt_dump;
+                       }
+               }
+               break;
+       case LCONF_MSG_RX_DISTR_START:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       task_base_add_rx_pkt_function(t, rx_pkt_distr);
+                       memset(t->aux->rx_bucket, 0, sizeof(t->aux->rx_bucket));
+                       lconf->flags |= LCONF_FLAG_RX_DISTR_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_TX_DISTR_START:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+
+                       t->aux->tx_pkt_orig = t->tx_pkt;
+                       t->tx_pkt = tx_pkt_distr;
+                       memset(t->aux->tx_bucket, 0, sizeof(t->aux->tx_bucket));
+                       lconf->flags |= LCONF_FLAG_TX_DISTR_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_RX_DISTR_STOP:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       task_base_del_rx_pkt_function(t, rx_pkt_distr);
+                       lconf->flags &= ~LCONF_FLAG_RX_DISTR_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_TX_DISTR_STOP:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       if (t->aux->tx_pkt_orig) {
+                               t->tx_pkt = t->aux->tx_pkt_orig;
+                               t->aux->tx_pkt_orig = NULL;
+                               lconf->flags &= ~LCONF_FLAG_TX_DISTR_ACTIVE;
+                       }
+               }
+               break;
+       case LCONF_MSG_RX_DISTR_RESET:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+
+                       memset(t->aux->rx_bucket, 0, sizeof(t->aux->rx_bucket));
+               }
+               break;
+       case LCONF_MSG_TX_DISTR_RESET:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+
+                       memset(t->aux->tx_bucket, 0, sizeof(t->aux->tx_bucket));
+               }
+               break;
+       case LCONF_MSG_RX_BW_START:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       task_base_add_rx_pkt_function(t, rx_pkt_bw);
+                       lconf->flags |= LCONF_FLAG_RX_BW_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_RX_BW_STOP:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       task_base_del_rx_pkt_function(t, rx_pkt_bw);
+                       lconf->flags &= ~LCONF_FLAG_RX_BW_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_TX_BW_START:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+
+                       t->aux->tx_pkt_orig = t->tx_pkt;
+                       t->tx_pkt = tx_pkt_bw;
+                       lconf->flags |= LCONF_FLAG_TX_BW_ACTIVE;
+               }
+               break;
+       case LCONF_MSG_TX_BW_STOP:
+               for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
+                       t = lconf->tasks_all[task_id];
+                       if (t->aux->tx_pkt_orig) {
+                               t->tx_pkt = t->aux->tx_pkt_orig;
+                               t->aux->tx_pkt_orig = NULL;
+                               lconf->flags &= ~LCONF_FLAG_TX_BW_ACTIVE;
+                       }
+               }
+               break;
+       }
+
+       lconf_unset_req(lconf);
+       return ret;
+}
+
+int lconf_get_task_id(const struct lcore_cfg *lconf, const struct task_base *task)
+{
+       for (int i = 0; i < lconf->n_tasks_all; ++i) {
+               if (lconf->tasks_all[i] == task)
+                       return i;
+       }
+
+       return -1;
+}
+
+int lconf_task_is_running(const struct lcore_cfg *lconf, uint8_t task_id)
+{
+       return lconf->task_is_running[task_id];
+}