/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * 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 "vom/interface_cmds.hpp"
#include "vom/cmd.hpp"

DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
DEFINE_VAPI_MSG_IDS_AF_PACKET_API_JSON;
DEFINE_VAPI_MSG_IDS_TAP_API_JSON;
DEFINE_VAPI_MSG_IDS_VHOST_USER_API_JSON;
DEFINE_VAPI_MSG_IDS_STATS_API_JSON;

namespace VOM {
namespace interface_cmds {
loopback_create_cmd::loopback_create_cmd(HW::item<handle_t>& item,
                                         const std::string& name)
  : create_cmd(item, name)
{
}

rc_t
loopback_create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  VAPI_CALL(req.execute());

  m_hw_item = wait();

  if (m_hw_item.rc() == rc_t::OK) {
    insert_interface();
  }

  return rc_t::OK;
}
std::string
loopback_create_cmd::to_string() const
{
  std::ostringstream s;
  s << "loopback-itf-create: " << m_hw_item.to_string() << " name:" << m_name;

  return (s.str());
}

af_packet_create_cmd::af_packet_create_cmd(HW::item<handle_t>& item,
                                           const std::string& name)
  : create_cmd(item, name)
{
}

rc_t
af_packet_create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();

  payload.use_random_hw_addr = 1;
  memset(payload.host_if_name, 0, sizeof(payload.host_if_name));
  memcpy(payload.host_if_name, m_name.c_str(),
         std::min(m_name.length(), sizeof(payload.host_if_name)));

  VAPI_CALL(req.execute());

  m_hw_item = wait();

  if (m_hw_item.rc() == rc_t::OK) {
    insert_interface();
  }

  return rc_t::OK;
}
std::string
af_packet_create_cmd::to_string() const
{
  std::ostringstream s;
  s << "af-packet-itf-create: " << m_hw_item.to_string() << " name:" << m_name;

  return (s.str());
}

tap_create_cmd::tap_create_cmd(HW::item<handle_t>& item,
                               const std::string& name)
  : create_cmd(item, name)
{
}

rc_t
tap_create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();

  memset(payload.tap_name, 0, sizeof(payload.tap_name));
  memcpy(payload.tap_name, m_name.c_str(),
         std::min(m_name.length(), sizeof(payload.tap_name)));
  payload.use_random_mac = 1;

  VAPI_CALL(req.execute());

  m_hw_item = wait();

  if (m_hw_item.rc() == rc_t::OK) {
    insert_interface();
  }

  return rc_t::OK;
}

std::string
tap_create_cmd::to_string() const
{
  std::ostringstream s;
  s << "tap-intf-create: " << m_hw_item.to_string() << " name:" << m_name;

  return (s.str());
}

vhost_create_cmd::vhost_create_cmd(HW::item<handle_t>& item,
                                   const std::string& name,
                                   const std::string& tag)
  : create_cmd(item, name)
  , m_tag(tag)
{
}

rc_t
vhost_create_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  memset(payload.sock_filename, 0, sizeof(payload.sock_filename));
  memcpy(payload.sock_filename, m_name.c_str(),
         std::min(m_name.length(), sizeof(payload.sock_filename)));
  memset(payload.tag, 0, sizeof(payload.tag));

  if (!m_tag.empty())
    memcpy(payload.tag, m_tag.c_str(),
           std::min(m_tag.length(), sizeof(payload.tag)));

  payload.is_server = 0;
  payload.use_custom_mac = 0;
  payload.renumber = 0;

  VAPI_CALL(req.execute());

  m_hw_item = wait();

  if (m_hw_item.rc() == rc_t::OK) {
    insert_interface();
  }

  return rc_t::OK;
}

std::string
vhost_create_cmd::to_string() const
{
  std::ostringstream s;
  s << "vhost-intf-create: " << m_hw_item.to_string() << " name:" << m_name
    << " tag:" << m_tag;

  return (s.str());
}

loopback_delete_cmd::loopback_delete_cmd(HW::item<handle_t>& item)
  : delete_cmd(item)
{
}

rc_t
loopback_delete_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.sw_if_index = m_hw_item.data().value();

  VAPI_CALL(req.execute());

  wait();
  m_hw_item.set(rc_t::NOOP);

  remove_interface();
  return rc_t::OK;
}

std::string
loopback_delete_cmd::to_string() const
{
  std::ostringstream s;
  s << "loopback-itf-delete: " << m_hw_item.to_string();

  return (s.str());
}

af_packet_delete_cmd::af_packet_delete_cmd(HW::item<handle_t>& item,
                                           const std::string& name)
  : delete_cmd(item, name)
{
}

rc_t
af_packet_delete_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  memset(payload.host_if_name, 0, sizeof(payload.host_if_name));
  memcpy(payload.host_if_name, m_name.c_str(),
         std::min(m_name.length(), sizeof(payload.host_if_name)));

  VAPI_CALL(req.execute());

  wait();
  m_hw_item.set(rc_t::NOOP);

  remove_interface();
  return rc_t::OK;
}
std::string
af_packet_delete_cmd::to_string() const
{
  std::ostringstream s;
  s << "af_packet-itf-delete: " << m_hw_item.to_string();

  return (s.str());
}

tap_delete_cmd::tap_delete_cmd(HW::item<handle_t>& item)
  : delete_cmd(item)
{
}

rc_t
tap_delete_cmd::issue(connection& con)
{
  // finally... call VPP

  remove_interface();
  return rc_t::OK;
}
std::string
tap_delete_cmd::to_string() const
{
  std::ostringstream s;
  s << "tap-itf-delete: " << m_hw_item.to_string();

  return (s.str());
}

vhost_delete_cmd::vhost_delete_cmd(HW::item<handle_t>& item,
                                   const std::string& name)
  : delete_cmd(item, name)
{
}

rc_t
vhost_delete_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.sw_if_index = m_hw_item.data().value();

  VAPI_CALL(req.execute());

  wait();
  remove_interface();

  return rc_t::OK;
}
std::string
vhost_delete_cmd::to_string() const
{
  std::ostringstream s;
  s << "vhost-itf-delete: " << m_hw_item.to_string() << " name:" << m_name;

  return (s.str());
}

state_change_cmd::state_change_cmd(HW::item<interface::admin_state_t>& state,
                                   const HW::item<handle_t>& hdl)
  : rpc_cmd(state)
  , m_hdl(hdl)
{
}

bool
state_change_cmd::operator==(const state_change_cmd& other) const
{
  return ((m_hdl == other.m_hdl) && (m_hw_item == other.m_hw_item));
}

rc_t
state_change_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.sw_if_index = m_hdl.data().value();
  payload.admin_up_down = m_hw_item.data().value();

  VAPI_CALL(req.execute());

  m_hw_item.set(wait());

  return rc_t::OK;
}

std::string
state_change_cmd::to_string() const
{
  std::ostringstream s;
  s << "itf-state-change: " << m_hw_item.to_string()
    << " hdl:" << m_hdl.to_string();
  return (s.str());
}

set_table_cmd::set_table_cmd(HW::item<route::table_id_t>& table,
                             const l3_proto_t& proto,
                             const HW::item<handle_t>& hdl)
  : rpc_cmd(table)
  , m_hdl(hdl)
  , m_proto(proto)
{
}

bool
set_table_cmd::operator==(const set_table_cmd& other) const
{
  return ((m_hdl == other.m_hdl) && (m_proto == other.m_proto) &&
          (m_hw_item == other.m_hw_item));
}

rc_t
set_table_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.sw_if_index = m_hdl.data().value();
  payload.is_ipv6 = m_proto.is_ipv6();
  payload.vrf_id = m_hw_item.data();

  VAPI_CALL(req.execute());

  m_hw_item.set(wait());

  return (rc_t::OK);
}

std::string
set_table_cmd::to_string() const
{
  std::ostringstream s;
  s << "itf-set-table: " << m_hw_item.to_string()
    << " proto:" << m_proto.to_string() << " hdl:" << m_hdl.to_string();
  return (s.str());
}

set_mac_cmd::set_mac_cmd(HW::item<l2_address_t>& mac,
                         const HW::item<handle_t>& hdl)
  : rpc_cmd(mac)
  , m_hdl(hdl)
{
}

bool
set_mac_cmd::operator==(const set_mac_cmd& other) const
{
  return ((m_hdl == other.m_hdl) && (m_hw_item == other.m_hw_item));
}

rc_t
set_mac_cmd::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.sw_if_index = m_hdl.data().value();
  m_hw_item.data().to_mac().to_bytes(payload.mac_address,
                                     sizeof(payload.mac_address));

  VAPI_CALL(req.execute());

  m_hw_item.set(wait());

  return (rc_t::OK);
}

std::string
set_mac_cmd::to_string() const
{
  std::ostringstream s;
  s << "itf-set-mac: " << m_hw_item.to_string() << " hdl:" << m_hdl.to_string();
  return (s.str());
}

events_cmd::events_cmd(interface::event_listener& el)
  : event_cmd(el.status())
  , m_listener(el)
{
}

bool
events_cmd::operator==(const events_cmd& other) const
{
  return (true);
}

rc_t
events_cmd::issue(connection& con)
{
  /*
 * First set the call back to handle the interface events
 */
  m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));

  /*
 * then send the request to enable them
 */
  msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));

  auto& payload = req.get_request().get_payload();
  payload.enable_disable = 1;
  payload.pid = getpid();

  VAPI_CALL(req.execute());

  wait();

  return (rc_t::OK);
}

void
events_cmd::retire(connection& con)
{
  /*
 * disable interface events.
 */
  msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));

  auto& payload = req.get_request().get_payload();
  payload.enable_disable = 0;
  payload.pid = getpid();

  VAPI_CALL(req.execute());

  wait();
}

void
events_cmd::notify()
{
  m_listener.handle_interface_event(this);
}

std::string
events_cmd::to_string() const
{
  return ("itf-events");
}

/**
 * Interface statistics
 */
stats_enable_cmd::stats_enable_cmd(interface::stat_listener& el,
                                   const handle_t& handle)
  : event_cmd(el.status())
  , m_listener(el)
  , m_swifindex(handle)
{
}

bool
stats_enable_cmd::operator==(const stats_enable_cmd& other) const
{
  return (true);
}

rc_t
stats_enable_cmd::issue(connection& con)
{
  /*
   * First set the call back to handle the interface stats
   */
  m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));

  /*
   * then send the request to enable them
   */
  msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));

  auto& payload = req.get_request().get_payload();
  payload.enable_disable = 1;
  payload.pid = getpid();
  payload.num = 1;

  payload.sw_ifs[0] = m_swifindex.value();

  VAPI_CALL(req.execute());

  wait();

  return (rc_t::OK);
}

void
stats_enable_cmd::retire(connection& con)
{
  /*
   * disable interface stats.
   */
  msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));

  auto& payload = req.get_request().get_payload();
  payload.enable_disable = 0;
  payload.pid = getpid();
  payload.num = 1;
  payload.sw_ifs[0] = m_swifindex.value();

  VAPI_CALL(req.execute());

  wait();
}

void
stats_enable_cmd::notify()
{
  m_listener.handle_interface_stat(this);
}

std::string
stats_enable_cmd::to_string() const
{
  std::ostringstream s;
  s << "itf-stats-enable itf:" << m_swifindex.to_string();
  return (s.str());
}

stats_disable_cmd::stats_disable_cmd(const handle_t& handle)
  : rpc_cmd(m_res)
  , m_swifindex(handle)
{
}

bool
stats_disable_cmd::operator==(const stats_disable_cmd& other) const
{
  return (true);
}

rc_t
stats_disable_cmd::issue(connection& con)
{
  /*
   * then send the request to enable them
   */
  msg_t req(con.ctx(), 1, std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.enable_disable = 0;
  payload.pid = getpid();
  payload.num = 1;

  payload.sw_ifs[0] = m_swifindex.value();

  VAPI_CALL(req.execute());

  wait();

  return (rc_t::OK);
}

std::string
stats_disable_cmd::to_string() const
{
  std::ostringstream s;
  s << "itf-stats-disable itf:" << m_swifindex.to_string();
  return (s.str());
}

dump_cmd::dump_cmd()
{
}

bool
dump_cmd::operator==(const dump_cmd& other) const
{
  return (true);
}

rc_t
dump_cmd::issue(connection& con)
{
  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));

  auto& payload = m_dump->get_request().get_payload();
  payload.name_filter_valid = 0;

  VAPI_CALL(m_dump->execute());

  wait();

  return rc_t::OK;
}

std::string
dump_cmd::to_string() const
{
  return ("itf-dump");
}

vhost_dump_cmd::vhost_dump_cmd()
{
}

bool
vhost_dump_cmd::operator==(const vhost_dump_cmd& other) const
{
  return (true);
}

rc_t
vhost_dump_cmd::issue(connection& con)
{
  m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));

  VAPI_CALL(m_dump->execute());

  wait();

  return rc_t::OK;
}

std::string
vhost_dump_cmd::to_string() const
{
  return ("vhost-itf-dump");
}

set_tag::set_tag(HW::item<handle_t>& item, const std::string& name)
  : rpc_cmd(item)
  , m_name(name)
{
}

rc_t
set_tag::issue(connection& con)
{
  msg_t req(con.ctx(), std::ref(*this));

  auto& payload = req.get_request().get_payload();
  payload.is_add = 1;
  payload.sw_if_index = m_hw_item.data().value();
  memcpy(payload.tag, m_name.c_str(), m_name.length());

  VAPI_CALL(req.execute());

  wait();

  return rc_t::OK;
}
std::string
set_tag::to_string() const
{
  std::ostringstream s;
  s << "itf-set-tag: " << m_hw_item.to_string() << " name:" << m_name;

  return (s.str());
}

bool
set_tag::operator==(const set_tag& o) const
{
  return ((m_name == o.m_name) && (m_hw_item.data() == o.m_hw_item.data()));
}
}; // namespace interface_cmds
}; // namespace VOM

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */
