<commit_before>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string>
#include <crow.h>
#include <slankdev/string.h>
#include <slankdev/exception.h>
#include <ssn_nfvi.h>

/*
 * JSON Macros
 */
namespace {

static inline
crow::json::wvalue responce_info(bool success, const char* msg)
{
  crow::json::wvalue x;
  x["success"] = success;
  x["msg"] = msg;
  return x;
}

static inline
crow::json::wvalue vnf_port_info(const ssn_vnf_port* port)
{
  using std::string;
  using slankdev::format;

  const string name    = port->name;
  const size_t n_rxq   = port->get_n_rxq();
  const size_t n_txq   = port->get_n_txq();
  const size_t n_rxa   = port->get_n_rxacc();
  const size_t n_txa   = port->get_n_txacc();
  const double perfred = port->get_perf_reduction();

  crow::json::wvalue x;
  x["name"    ] = name;
  x["n_rxq"   ] = n_rxq;
  x["n_txq"   ] = n_txq;
  x["n_rxa"   ] = n_rxa;
  x["n_txa"   ] = n_txa;
  x["perfred" ] = perfred;
  return x;
}

static inline
crow::json::wvalue vnf_block_info(const ssn_vnf_block* block)
{
  using std::string;
  using slankdev::format;

  std::string name = block->name;
  uint32_t coremask = block->get_coremask();
  bool running = block->is_running();

  crow::json::wvalue x;
  x["name"] = name;
  x["cmask"] = coremask;
  x["running"] = running;
  return x;
}

static inline
crow::json::wvalue vnf_info(const ssn_vnf* vnf)
{
  using std::string;
  using slankdev::format;

  string name    = vnf->name;
  size_t n_port  = vnf->n_ports();
  size_t n_block = vnf->n_blocks();
  bool running   = vnf->is_running();

  crow::json::wvalue x;
  x["name"]    = name;
  x["n_port"]  = n_port;
  x["n_block"] = n_block;
  x["running"] = running;

  crow::json::wvalue x_blocks;
  for (size_t i=0; i<n_block; i++) {
    string s = format("block%zd", i);
    x_blocks[s] = vnf_block_info(vnf->get_block(i));
  }
  x["blocks"] = std::move(x_blocks);

  crow::json::wvalue x_ports;
  for (size_t i=0; i<n_port; i++) {
    string s = format("port%zd", i);
    x_ports[s] = vnf_port_info(vnf->get_port(i));
  }
  x["ports"] = std::move(x_ports);
  return x;
}

} /* namespace */




int rest_api_thread(ssn_nfvi* nfviptr)
{
  using std::string;
  using slankdev::format;
  ssn_nfvi& nfvi = *nfviptr;

  crow::SimpleApp app;
  app.loglevel(crow::LogLevel::Critical);

  CROW_ROUTE(app,"/") ( []() {
      crow::json::wvalue x;
      x["result"] = responce_info(true, "");
      crow::json::wvalue child;
      child["ports"] = "ports operation";
      child["vnfs"]  = "vnfs operation";
      x["cmds"] = std::move(child);
      return x;
  });

  CROW_ROUTE(app,"/system") ( [&nfvi]() {

      crow::json::wvalue x_root;
      x_root["result"] = responce_info(true, "");
      x_root["n_vnf"]  = nfvi.get_vnfs().size();
      x_root["n_port"] = nfvi.get_ports().size();
      x_root["n_vcat"] = nfvi.get_vcat().size();
      x_root["n_pcat"] = nfvi.get_pcat().size();
      return x_root;

  });

  CROW_ROUTE(app,"/vnfcatalog") ( [&nfvi]() {
      /*
       * "n_vcat" : 2
       * "0"  : {
       *    "name" : "l2fwd1b",
       *    "allocator" : "0x033ef1" // pointer
       * },
       * "1" : {
       *    "name" : "l2fwd2b",
       *    "allocator" : "0x033ef2" // pointer
       * }
       */
      crow::json::wvalue x_root;
      const size_t n_vcat = nfvi.get_vcat().size();
      x_root["result"] = responce_info(true, "");
      x_root["n_vcat"] = n_vcat;
      crow::json::wvalue x_vcat;
      for (size_t i=0; i<n_vcat; i++) {
        x_vcat["name"] = nfvi.get_vcat()[i].name;
        x_vcat["allocator"] = format("%p", nfvi.get_vcat()[i].allocator);
        x_root[std::to_string(i)] = std::move(x_vcat);
      }
      return x_root;
  });

  CROW_ROUTE(app,"/portcatalog") ( [&nfvi]() {
      /*
       * "n_vcat" : 2
       * "0"  : {
       *    "name" : "pci",
       *    "allocator" : "0x033ef1" // pointer
       * },
       * "1" : {
       *    "name" : "l2fwd2b",
       *    "allocator" : "0x033ef2" // pointer
       * }
       */
      crow::json::wvalue x_root;
      const size_t n_pcat = nfvi.get_pcat().size();
      x_root["result"] = responce_info(true, "");
      x_root["n_pcat"] = n_pcat;
      crow::json::wvalue x_pcat;
      for (size_t i=0; i<n_pcat; i++) {
        x_pcat["name"] = nfvi.get_pcat()[i].name;
        x_pcat["allocator"] = format("%p", nfvi.get_pcat()[i].allocator);
        x_root[std::to_string(i)] = std::move(x_pcat);
      }
      return x_root;
  });

  CROW_ROUTE(app,"/ports") ( [&nfvi]() {
      /*
       * "n_port" : 1
       * "port0"  : {
       *    "n_rxq"  : 4,
       *    "n_txq"  : 4,
       *    "n_rxa"  : 2,<commit_msg>restapi: add-API port-alloc from catalog<commit_after>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string>
#include <crow.h>
#include <slankdev/string.h>
#include <slankdev/exception.h>
#include <ssn_nfvi.h>

/*
 * JSON Macros
 */
namespace {

static inline
crow::json::wvalue responce_info(bool success, const char* msg)
{
  crow::json::wvalue x;
  x["success"] = success;
  x["msg"] = msg;
  return x;
}

static inline
crow::json::wvalue vnf_port_info(const ssn_vnf_port* port)
{
  using std::string;
  using slankdev::format;

  const string name    = port->name;
  const size_t n_rxq   = port->get_n_rxq();
  const size_t n_txq   = port->get_n_txq();
  const size_t n_rxa   = port->get_n_rxacc();
  const size_t n_txa   = port->get_n_txacc();
  const double perfred = port->get_perf_reduction();

  crow::json::wvalue x;
  x["name"    ] = name;
  x["n_rxq"   ] = n_rxq;
  x["n_txq"   ] = n_txq;
  x["n_rxa"   ] = n_rxa;
  x["n_txa"   ] = n_txa;
  x["perfred" ] = perfred;
  return x;
}

static inline
crow::json::wvalue vnf_block_info(const ssn_vnf_block* block)
{
  using std::string;
  using slankdev::format;

  std::string name = block->name;
  uint32_t coremask = block->get_coremask();
  bool running = block->is_running();

  crow::json::wvalue x;
  x["name"] = name;
  x["cmask"] = coremask;
  x["running"] = running;
  return x;
}

static inline
crow::json::wvalue vnf_info(const ssn_vnf* vnf)
{
  using std::string;
  using slankdev::format;

  string name    = vnf->name;
  size_t n_port  = vnf->n_ports();
  size_t n_block = vnf->n_blocks();
  bool running   = vnf->is_running();

  crow::json::wvalue x;
  x["name"]    = name;
  x["n_port"]  = n_port;
  x["n_block"] = n_block;
  x["running"] = running;

  crow::json::wvalue x_blocks;
  for (size_t i=0; i<n_block; i++) {
    string s = format("block%zd", i);
    x_blocks[s] = vnf_block_info(vnf->get_block(i));
  }
  x["blocks"] = std::move(x_blocks);

  crow::json::wvalue x_ports;
  for (size_t i=0; i<n_port; i++) {
    string s = format("port%zd", i);
    x_ports[s] = vnf_port_info(vnf->get_port(i));
  }
  x["ports"] = std::move(x_ports);
  return x;
}

} /* namespace */




int rest_api_thread(ssn_nfvi* nfviptr)
{
  using std::string;
  using slankdev::format;
  ssn_nfvi& nfvi = *nfviptr;

  crow::SimpleApp app;
  app.loglevel(crow::LogLevel::Critical);
  app.loglevel(crow::LogLevel::Debug);

  CROW_ROUTE(app,"/") ( []() {
      crow::json::wvalue x;
      x["result"] = responce_info(true, "");
      crow::json::wvalue child;
      child["ports"] = "ports operation";
      child["vnfs"]  = "vnfs operation";
      x["cmds"] = std::move(child);
      return x;
  });

  CROW_ROUTE(app,"/system") ( [&nfvi]() {

      crow::json::wvalue x_root;
      x_root["result"] = responce_info(true, "");
      x_root["n_vnf"]  = nfvi.get_vnfs().size();
      x_root["n_port"] = nfvi.get_ports().size();
      x_root["n_vcat"] = nfvi.get_vcat().size();
      x_root["n_pcat"] = nfvi.get_pcat().size();
      return x_root;

  });

  CROW_ROUTE(app,"/vnfcatalog") ( [&nfvi]() {
      /*
       * "n_vcat" : 2
       * "0"  : {
       *    "name" : "l2fwd1b",
       *    "allocator" : "0x033ef1" // pointer
       * },
       * "1" : {
       *    "name" : "l2fwd2b",
       *    "allocator" : "0x033ef2" // pointer
       * }
       */
      crow::json::wvalue x_root;
      const size_t n_vcat = nfvi.get_vcat().size();
      x_root["result"] = responce_info(true, "");
      x_root["n_vcat"] = n_vcat;
      crow::json::wvalue x_vcat;
      for (size_t i=0; i<n_vcat; i++) {
        x_vcat["name"] = nfvi.get_vcat()[i].name;
        x_vcat["allocator"] = format("%p", nfvi.get_vcat()[i].allocator);
        x_root[std::to_string(i)] = std::move(x_vcat);
      }
      return x_root;
  });

  CROW_ROUTE(app, "/portcatalog")
  .methods("GET"_method, "PUT"_method, "DELETE"_method)
  ([&nfvi](const crow::request& req) {

      assert(  (req.method == crow::HTTPMethod::GET)
            || (req.method == crow::HTTPMethod::PUT)
            || (req.method == crow::HTTPMethod::DELETE)  );

      if (req.method == crow::HTTPMethod::GET) {

        /*
         * "n_vcat" : 2
         * "0"  : {
         *    "name" : "pci",
         *    "allocator" : "0x033ef1" // pointer
         * },
         * "1" : {
         *    "name" : "l2fwd2b",
         *    "allocator" : "0x033ef2" // pointer
         * }
         */
        crow::json::wvalue x_root;
        const size_t n_pcat = nfvi.get_pcat().size();
        x_root["result"] = responce_info(true, "");
        x_root["n_pcat"] = n_pcat;
        crow::json::wvalue x_pcat;
        for (size_t i=0; i<n_pcat; i++) {
          x_pcat["name"] = nfvi.get_pcat()[i].name;
          x_pcat["allocator"] = format("%p", nfvi.get_pcat()[i].allocator);
          x_root[std::to_string(i)] = std::move(x_pcat);
        }
        return x_root;

      } else if (req.method == crow::HTTPMethod::PUT) {

        /* Alloc new port */
        /* # User send JSON
         * {
         *    "catname"      : "pci"
         *    "instancename" : "pci0"
         *    "options" : {
         *      ...
         *      "pciaddr" : "0000:01:00.1"
         *      ""
         *    }
         * }
         */
        auto req_json = crow::json::load(req.body);
        std::string cname   = req_json["cname"].s();
        std::string iname   = req_json["iname"].s();

        if (cname == "tap") {

          /*
           * "options" :
           *    {
           *       "ifname" : "eth0"
           *    }
           */
          std::string ifname = req_json["options"]["ifname"].s();
          rte_mempool* mp = nfvi.get_mp();
          ssn_portalloc_tap_arg arg = { mp, ifname };
          nfvi.port_alloc_from_catalog(cname.c_str(), iname.c_str(), &arg);

          crow::json::wvalue x_root;
          x_root["result"] = responce_info(true, "");
          return x_root;

        } else if (cname == "pci") {

          /*
           * "options" :
           *    {
           *       "pciaddr" : "0000:01:00.1"
           *    }
           */
          std::string pciaddr = req_json["options"]["pciaddr"].s();
          rte_mempool* mp = nfvi.get_mp();
          ssn_portalloc_pci_arg arg = { mp, pciaddr };
          nfvi.port_alloc_from_catalog(cname.c_str(), iname.c_str(), &arg);

          crow::json::wvalue x_root;
          x_root["result"] = responce_info(true, "");
          return x_root;

        } else if (cname == "virt") {

          /*
           * "options" :
           *    {
           *    }
           */
          ssn_portalloc_virt_arg arg;
          nfvi.port_alloc_from_catalog(cname.c_str(), iname.c_str(), &arg);

          crow::json::wvalue x_root;
          x_root["result"] = responce_info(true, "");
          return x_root;

        } else {

          crow::json::wvalue x_root;
          x_root["result"] = responce_info(false, "catalog name is invalid");
          return x_root;

        }

      } else if (req.method == crow::HTTPMethod::DELETE) {

        /* Delete port */
        /* # User send JSON
         * {
         *    "instancename" : "pci0"
         * }
         */

      }

  });

  CROW_ROUTE(app,"/ports") ( [&nfvi]() {
      /*
       * "n_port" : 1
       * "port0"  : {
       *    "n_rxq"  : 4,
       *    "n_txq"  : 4,
       *    "n_rxa"  : 2,
{'fraction_non_alphanumeric': 0.1851728446480633, 'fraction_numerical': 0.008912952936276551, 'mean_word_length': 2.3838782412626833, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3176036', 'n_tokens_mistral': 4899, 'n_tokens_neox': 4794, 'n_words': 777}