aboutsummaryrefslogtreecommitdiffstats
path: root/src/vppinfra/FEATURE.yaml
blob: b21963bdacf79b67287c62413c07b6032f960c16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
---
name: VPP infrastructure library
maintainer:
  - Dave Barach <dave@barachs.net>
features:
  - Abstract device driver ring support
  - Address sanitizer support
  - Altivec, Neon, MMX, AVX2, AVX512 SIMD vector unit support
  - Atomic op support
  - Backtrace support
  - Bitmaps
  - Bounded-index extensible hashing templates
  - C11 safe-string support
  - Cache control primitives, including prefetching
  - C-dynamic arrays (vectors)
  - Circular doubly-linked list support with a head sentinel
  - Contiguous N x fixed block allocator
  - CPU clock based timebase support
  - Doubly-linked list support
  - ELF file parser
  - Endian-order support
  - Error return / reporting support
  - FIFO support
  - Fundamental types, u8, u16, u32, and so on
  - High-performance event logger
  - High-performance memcpy support
  - High-performance mmap-based circular log support
  - High-performance timer-wheel templates
  - Linux socket support
  - Linux sysfs file parsing support
  - Low-level CPU support
  - Mapped pcap file support
  - Memory allocator, "Doug Lea" malloc with a few tweaks
  - Minimal overhead Linux system-call support
  - Multi-architecture setjmp / longjmp support
  - Numerous Unit tests
  - Physical memory allocator support
  - Pools, a high performance fixed block allocation scheme
  - Red/black trees.
  - Rigorously vetted linear congruential random numbers (32 and 64 bit)
  - Serialization / unserialization support
  - SHA256, SHA512 support
  - Simple first-fit virtual space allocator
  - Simple hashing support
  - Simple macro expander
  - Sparse vector support
  - Spinlock support
  - Time Range support
  - Unix / Linux errno support
  - Vector-based printf / scanf equivalents (format, unformat)
  - Warshall's algorithm (positive transitive closure of a relation)
  - XXhash support
description: "VPP's foundation / infrastructure support library.
             The library dates from 2000 and hardly changes anymore.
             Heavily used across vpp, issues are not expected."
state: production
properties: [MULTITHREAD]
t-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 <boost/algorithm/string.hpp>
#include <sstream>

#include "vom/prefix.hpp"

namespace VOM {
/*
 * Keep this in sync with VPP's fib_protocol_t
 */
const l3_proto_t l3_proto_t::IPV4(0, "ipv4");
const l3_proto_t l3_proto_t::IPV6(1, "ipv6");
const l3_proto_t l3_proto_t::MPLS(2, "mpls");

l3_proto_t::l3_proto_t(int v, const std::string& s)
  : enum_base<l3_proto_t>(v, s)
{
}

bool
l3_proto_t::is_ipv6()
{
  return (*this == IPV6);
}

bool
l3_proto_t::is_ipv4()
{
  return (*this == IPV4);
}

const l3_proto_t&
l3_proto_t::from_address(const boost::asio::ip::address& addr)
{
  if (addr.is_v6()) {
    return IPV6;
  }

  return IPV4;
}

const nh_proto_t&
l3_proto_t::to_nh_proto() const
{
  if (*this == IPV4)
    return nh_proto_t::IPV4;
  else if (*this == IPV6)
    return nh_proto_t::IPV6;
  else if (*this == MPLS)
    return nh_proto_t::MPLS;

  return nh_proto_t::IPV4;
}

std::ostream&
operator<<(std::ostream& os, const l3_proto_t& l3p)
{
  os << l3p.to_string();
  return os;
}

/*
 * Keep this in sync with VPP's dpo_proto_t
 */
const nh_proto_t nh_proto_t::IPV4(0, "ipv4");
const nh_proto_t nh_proto_t::IPV6(1, "ipv6");
const nh_proto_t nh_proto_t::MPLS(2, "mpls");
const nh_proto_t nh_proto_t::ETHERNET(3, "ethernet");

nh_proto_t::nh_proto_t(int v, const std::string& s)
  : enum_base<nh_proto_t>(v, s)
{
}

const nh_proto_t&
nh_proto_t::from_address(const boost::asio::ip::address& addr)
{
  if (addr.is_v6()) {
    return IPV6;
  }

  return IPV4;
}

/**
 * The all Zeros prefix
 */
const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
const route::prefix_t route::prefix_t::ZEROv6("::", 0);

route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len)
  : m_addr(addr)
  , m_len(len)
{
}

route::prefix_t::prefix_t(const boost::asio::ip::address& addr)
  : m_addr(addr)
  , m_len(VOM::mask_width(addr))
{
}

route::prefix_t::prefix_t(const std::string& s, uint8_t len)
  : m_addr(boost::asio::ip::address::from_string(s))
  , m_len(len)
{
}

route::prefix_t::prefix_t(const prefix_t& o)
  : m_addr(o.m_addr)
  , m_len(o.m_len)
{
}

route::prefix_t::prefix_t()
  : m_addr()
  , m_len(0)
{
}

route::prefix_t::~prefix_t()
{
}

route::prefix_t&
route::prefix_t::operator=(const route::prefix_t& o)
{
  m_addr = o.m_addr;
  m_len = o.m_len;

  return (*this);
}

const boost::asio::ip::address&
route::prefix_t::address() const
{
  return (m_addr);
}

uint8_t
route::prefix_t::mask_width() const
{
  return (m_len);
}

bool
route::prefix_t::operator<(const route::prefix_t& o) const
{
  if (m_len == o.m_len) {
    return (m_addr < o.m_addr);
  } else {
    return (m_len < o.m_len);
  }
}

bool
route::prefix_t::operator==(const route::prefix_t& o) const
{
  return (m_len == o.m_len && m_addr == o.m_addr);
}

bool
route::prefix_t::operator!=(const route::prefix_t& o) const
{
  return (!(*this == o));
}

std::string
route::prefix_t::to_string() const
{
  std::ostringstream s;

  s << m_addr.to_string() << "/" << std::to_string(m_len);

  return (s.str());
}

boost::asio::ip::address
from_bytes(uint8_t is_ip6, uint8_t* bytes)
{
  boost::asio::ip::address addr;

  if (is_ip6) {
    std::array<uint8_t, 16> a;
    std::copy(bytes, bytes + 16, std::begin(a));
    boost::asio::ip::address_v6 v6(a);
    addr = v6;
  } else {
    std::array<uint8_t, 4> a;
    std::copy(bytes, bytes + 4, std::begin(a));
    boost::asio::ip::address_v4 v4(a);
    addr = v4;
  }

  return (addr);
}

route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
  : m_addr(from_bytes(is_ip6, addr))
  , m_len(len)
{
}
void
to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
{
  memcpy(array, addr.to_bytes().data(), 16);
}

void
to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
{
  memcpy(array, addr.to_bytes().data(), 4);
}

void
to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
{
  if (addr.is_v6()) {
    *is_ip6 = 1;
    to_bytes(addr.to_v6(), array);
  } else {
    *is_ip6 = 0;
    to_bytes(addr.to_v4(), array);
  }
}

uint32_t
mask_width(const boost::asio::ip::address& addr)
{
  if (addr.is_v6()) {
    return 128;
  }
  return 32;
}

void
route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
{
  *len = m_len;
  to_bytes(m_addr, is_ip6, addr);
}

l3_proto_t
route::prefix_t::l3_proto() const
{
  if (m_addr.is_v6()) {
    return (l3_proto_t::IPV6);
  } else {
    return (l3_proto_t::IPV4);
  }

  return (l3_proto_t::IPV4);
}

std::ostream&
operator<<(std::ostream& os, const route::prefix_t& pfx)
{
  os << pfx.to_string();

  return (os);
}

boost::asio::ip::address_v4
operator|(const boost::asio::ip::address_v4& addr1,
          const boost::asio::ip::address_v4& addr2)
{
  uint32_t a;
  a = addr1.to_ulong() | addr2.to_ulong();
  boost::asio::ip::address_v4 addr(a);
  return (addr);
}

boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
                                      const boost::asio::ip::address_v4& addr2)
{
  uint32_t a;
  a = addr1.to_ulong() & addr2.to_ulong();
  boost::asio::ip::address_v4 addr(a);
  return (addr);
}

boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
{
  uint32_t a;
  a = ~addr1.to_ulong();
  boost::asio::ip::address_v4 addr(a);
  return (addr);
}

boost::asio::ip::address_v6
operator|(const boost::asio::ip::address_v6& addr1,
          const boost::asio::ip::address_v6& addr2)
{
  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();

  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
       ii < b1.max_size(); ii++) {
    b1[ii] |= b2[ii];
  }

  boost::asio::ip::address_v6 addr(b1);
  return (addr);
}

boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
                                      const boost::asio::ip::address_v6& addr2)
{
  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();

  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
       ii < b1.max_size(); ii++) {
    b1[ii] &= b2[ii];
  }

  boost::asio::ip::address_v6 addr(b1);
  return (addr);
}

boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
{
  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();

  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
       ii < b1.max_size(); ii++) {
    b1[ii] = ~b1[ii];
  }

  boost::asio::ip::address_v6 addr(b1);
  return (addr);
}
boost::asio::ip::address
operator|(const boost::asio::ip::address& addr1,
          const boost::asio::ip::address& addr2)
{
  if (addr1.is_v6())
    return (addr1.to_v6() | addr2.to_v6());
  else
    return (addr1.to_v4() | addr2.to_v4());
}

boost::asio::ip::address operator&(const boost::asio::ip::address& addr1,
                                   const boost::asio::ip::address& addr2)
{
  if (addr1.is_v6())
    return (addr1.to_v6() & addr2.to_v6());
  else
    return (addr1.to_v4() & addr2.to_v4());
}

boost::asio::ip::address operator~(const boost::asio::ip::address& addr1)
{
  if (addr1.is_v6())
    return ~(addr1.to_v6());
  else
    return ~(addr1.to_v4());
}

boost::asio::ip::address
route::prefix_t::mask() const
{
  if (m_addr.is_v6()) {
    boost::asio::ip::address_v6::bytes_type b =
      boost::asio::ip::address_v6::any().to_bytes();

    uint8_t n_bits = mask_width();

    for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
         ii < b.max_size(); ii++) {
      for (int8_t bit = 7; bit >= 0 && n_bits; bit--) {
        b[ii] |= (1 << bit);
        n_bits--;
      }
      if (!n_bits)
        break;
    }

    return (boost::asio::ip::address_v6(b));
  } else {
    uint32_t a;

    a = ~((1 << (32 - mask_width())) - 1);

    return (boost::asio::ip::address_v4(a));
  }
}

route::prefix_t
route::prefix_t::low() const
{
  prefix_t pfx(*this);

  pfx.m_addr = pfx.m_addr & pfx.mask();

  return (pfx);
}

route::prefix_t
route::prefix_t::high() const
{
  prefix_t pfx(*this);

  pfx.m_addr = pfx.m_addr | ~pfx.mask();

  return (pfx);
}

}; // namespace VOM

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