summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>2020-10-13 17:26:47 +0200
committerBeno�t Ganne <bganne@cisco.com>2020-10-21 12:44:40 +0000
commit2082835fea3ccd85e7368327d5baa749be01b537 (patch)
tree6809264cf75a64dee50259c1c0d2145c426b85ea /src/plugins
parenta5203b53d4fa227560333b890d3e79fc220d1bfd (diff)
cnat: allow max_u16 translation backends
Type: fix Allow for 65536 backends for a translation. - use u32 instead of u8 - filter out back_walk with more than FIB_PATH_LIST_POPULAR backends - we're still limited by u16 lb_n_buckets in src/vnet/dpo/load_balance.h Change-Id: Ib37b958e59b25ef5ef9f92b82008d626860faddd Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/cnat/cnat.api2
-rw-r--r--src/plugins/cnat/cnat_api.c13
-rw-r--r--src/plugins/cnat/cnat_translation.c13
-rw-r--r--src/plugins/cnat/cnat_translation.h5
4 files changed, 25 insertions, 8 deletions
diff --git a/src/plugins/cnat/cnat.api b/src/plugins/cnat/cnat.api
index a9507c90b4d..7bf6be8b349 100644
--- a/src/plugins/cnat/cnat.api
+++ b/src/plugins/cnat/cnat.api
@@ -53,7 +53,7 @@ typedef cnat_translation
vl_api_ip_proto_t ip_proto;
u8 is_real_ip;
u8 flags;
- u8 n_paths;
+ u32 n_paths;
vl_api_cnat_endpoint_tuple_t paths[n_paths];
};
diff --git a/src/plugins/cnat/cnat_api.c b/src/plugins/cnat/cnat_api.c
index f692451c14b..338cb5926a8 100644
--- a/src/plugins/cnat/cnat_api.c
+++ b/src/plugins/cnat/cnat_api.c
@@ -88,16 +88,17 @@ vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
u32 id = ~0;
u8 flags;
int rv = 0;
- u8 pi;
+ u32 pi, n_paths;
rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
if (rv)
goto done;
- vec_validate (paths, mp->translation.n_paths - 1);
+ n_paths = clib_net_to_host_u32 (mp->translation.n_paths);
+ vec_validate (paths, n_paths - 1);
- for (pi = 0; pi < mp->translation.n_paths; pi++)
+ for (pi = 0; pi < n_paths; pi++)
{
path = &paths[pi];
cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
@@ -146,7 +147,7 @@ cnat_translation_send_details (u32 cti, void *args)
vl_api_cnat_endpoint_tuple_t *path;
size_t msg_size;
cnat_translation_t *ct;
- u8 n_paths;
+ u32 n_paths;
ctx = args;
ct = cnat_translation_get (cti);
@@ -158,8 +159,8 @@ cnat_translation_send_details (u32 cti, void *args)
/* fill in the message */
mp->context = ctx->context;
- mp->translation.n_paths = n_paths;
- mp->translation.id = htonl (cti);
+ mp->translation.n_paths = clib_host_to_net_u32 (n_paths);
+ mp->translation.id = clib_host_to_net_u32 (cti);
cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
diff --git a/src/plugins/cnat/cnat_translation.c b/src/plugins/cnat/cnat_translation.c
index 4833df9fc37..263ec05e973 100644
--- a/src/plugins/cnat/cnat_translation.c
+++ b/src/plugins/cnat/cnat_translation.c
@@ -180,7 +180,7 @@ cnat_translation_stack (cnat_translation_t * ct)
fib_protocol_t fproto;
cnat_ep_trk_t *trk;
dpo_proto_t dproto;
- u8 ep_idx = 0;
+ u32 ep_idx = 0;
index_t lbi;
fproto = ip_address_family_to_fib_proto (ct->ct_vip.ce_ip.version);
@@ -198,6 +198,7 @@ cnat_translation_stack (cnat_translation_t * ct)
dpo_set (&ct->ct_lb, DPO_LOAD_BALANCE, dproto, lbi);
dpo_stack (cnat_client_dpo, dproto, &ct->ct_lb, &ct->ct_lb);
+ ct->flags |= CNAT_TRANSLATION_STACKED;
}
int
@@ -277,6 +278,7 @@ cnat_translation_update (cnat_endpoint_t * vip,
}
vec_reset_length (ct->ct_paths);
+ ct->flags &= ~CNAT_TRANSLATION_STACKED;
u64 path_idx = 0;
vec_foreach (path, paths)
@@ -457,6 +459,12 @@ cnat_translation_back_walk_notify (fib_node_t * node,
*/
cnat_translation_t *ct = cnat_translation_get_from_node (node);
+ /* If we have more than FIB_PATH_LIST_POPULAR paths
+ * we might get called during path tracking
+ * (cnat_tracker_track) */
+ if (!(ct->flags & CNAT_TRANSLATION_STACKED))
+ return (FIB_NODE_BACK_WALK_CONTINUE);
+
cnat_translation_stack (ct);
return (FIB_NODE_BACK_WALK_CONTINUE);
@@ -601,9 +609,12 @@ cnat_if_addr_add_del_backend_cb (addr_resolution_t * ar,
ip_address_copy (&ep->ce_ip, address);
ep->ce_flags |= CNAT_EP_FLAG_RESOLVED;
}
+
+ ct->flags &= ~CNAT_TRANSLATION_STACKED;
cnat_tracker_track (ar->cti, trk);
cnat_translation_stack (ct);
+ ct->flags |= CNAT_TRANSLATION_STACKED;
}
static void
diff --git a/src/plugins/cnat/cnat_translation.h b/src/plugins/cnat/cnat_translation.h
index cfcbf5bc13b..a4ae1ece718 100644
--- a/src/plugins/cnat/cnat_translation.h
+++ b/src/plugins/cnat/cnat_translation.h
@@ -58,7 +58,12 @@ typedef struct cnat_ep_trk_t_
typedef enum cnat_translation_flag_t_
{
+ /* Do allocate a source port */
CNAT_TRANSLATION_FLAG_ALLOCATE_PORT = (1 << 0),
+ /* Has this translation been satcked ?
+ * this allow not being called twice when
+ * with more then FIB_PATH_LIST_POPULAR backends */
+ CNAT_TRANSLATION_STACKED = (1 << 1),
} cnat_translation_flag_t;
typedef enum
74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * 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/hw.hpp"
#include "vom/logger.hpp"

#include <vapi/vpe.api.vapi.hpp>

namespace VOM {
HW::cmd_q::cmd_q()
  : m_enabled(true)
  , m_connected(false)
  , m_conn()
{
}

HW::cmd_q::~cmd_q()
{
  m_connected = false;

  if (m_rx_thread && m_rx_thread->joinable()) {
    m_rx_thread->join();
  }
}

HW::cmd_q&
HW::cmd_q::operator=(const HW::cmd_q& f)
{
  return (*this);
}

/**
 * Run the connect/dispatch thread.
 */
void
HW::cmd_q::rx_run()
{
  while (m_connected) {
    m_conn.ctx().dispatch();
  }
}

void
HW::cmd_q::enqueue(cmd* c)
{
  std::shared_ptr<cmd> sp(c);

  m_queue.push_back(sp);
}

void
HW::cmd_q::enqueue(std::shared_ptr<cmd> c)
{
  m_queue.push_back(c);
}

void
HW::cmd_q::enqueue(std::queue<cmd*>& cmds)
{
  while (cmds.size()) {
    std::shared_ptr<cmd> sp(cmds.front());

    m_queue.push_back(sp);
    cmds.pop();
  }
}

void
HW::cmd_q::dequeue(cmd* c)
{
  c->retire(m_conn);
  m_pending.erase(c);
}

void
HW::cmd_q::dequeue(std::shared_ptr<cmd> c)
{
  c->retire(m_conn);
  m_pending.erase(c.get());
}

void
HW::cmd_q::connect()
{
  if (m_connected) {
    m_conn.disconnect();
  }

  m_connected = false;

  if (m_rx_thread && m_rx_thread->joinable()) {
    m_rx_thread->join();
  }

  m_conn.connect();

  m_connected = true;
  m_rx_thread.reset(new std::thread(&HW::cmd_q::rx_run, this));
}

void
HW::cmd_q::enable()
{
  m_enabled = true;
}

void
HW::cmd_q::disable()
{
  m_enabled = false;
}

rc_t
HW::cmd_q::write()
{
  rc_t rc = rc_t::OK;

  /*
 * The queue is enabled, Execute each command in the queue.
 * If one execution fails, abort the rest
 */
  auto it = m_queue.begin();

  while (it != m_queue.end()) {
    std::shared_ptr<cmd> c = *it;

    VOM_LOG(log_level_t::DEBUG) << *c;

    if (m_enabled) {
      /*
 * before we issue the command we must move it to the pending
 * store
 * ince a async event can be recieved before the command
 * completes
 */
      m_pending[c.get()] = c;

      rc = c->issue(m_conn);

      if (rc_t::INPROGRESS == rc) {
        /*
 * this command completes asynchronously
 * leave the command in the pending store
 */
      } else {
        /*
 * the command completed, remove from the pending store
 */
        m_pending.erase(c.get());

        if (rc_t::OK == rc) {
          /*
 * move to the next
 */
        } else {
          /*
 * barf out without issuing the rest
 */
          break;
        }
      }
    } else {
      /*
 * The HW is disabled, so set each command as succeeded
 */
      c->succeeded();
    }

    ++it;
  }

  /*
 * erase all objects in the queue
 */
  m_queue.erase(m_queue.begin(), m_queue.end());

  return (rc);
}

/*
 * The single Command Queue
 */
HW::cmd_q* HW::m_cmdQ;
HW::item<bool> HW::m_poll_state;

/**
 * Initialse the connection to VPP
 */
void
HW::init(HW::cmd_q* f)
{
  m_cmdQ = f;
}

/**
 * Initialse the connection to VPP
 */
void
HW::init()
{
  m_cmdQ = new cmd_q();
}

void
HW::enqueue(cmd* cmd)
{
  m_cmdQ->enqueue(cmd);
}

void
HW::enqueue(std::shared_ptr<cmd> cmd)
{
  m_cmdQ->enqueue(cmd);
}

void
HW::enqueue(std::queue<cmd*>& cmds)
{
  m_cmdQ->enqueue(cmds);
}

void
HW::dequeue(cmd* cmd)
{
  m_cmdQ->dequeue(cmd);
}

void
HW::dequeue(std::shared_ptr<cmd> cmd)
{
  m_cmdQ->dequeue(cmd);
}

void
HW::connect()
{
  m_cmdQ->connect();
}

void
HW::enable()
{
  m_cmdQ->enable();
}

void
HW::disable()
{
  m_cmdQ->disable();
}

rc_t
HW::write()
{
  return (m_cmdQ->write());
}

bool
HW::poll()
{
  std::shared_ptr<cmd> poll(new Poll(m_poll_state));

  HW::enqueue(poll);
  HW::write();

  return (m_poll_state);
}

template <>
std::string
HW::item<bool>::to_string() const
{
  std::ostringstream os;

  os << "hw-item:["
     << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
  return (os.str());
}

template <>
std::string
HW::item<unsigned int>::to_string() const
{
  std::ostringstream os;

  os << "hw-item:["
     << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
  return (os.str());
}

HW::Poll::Poll(HW::item<bool>& item)
  : rpc_cmd(item)
{
}

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

  VAPI_CALL(req.execute());

  m_hw_item.set(wait());

  return (rc_t::OK);
}

std::string
HW::Poll::to_string() const
{
  std::ostringstream s;

  s << "poll: " << m_hw_item.to_string();

  return (s.str());
}
}

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