VPP Object Model (VOM)

The VOM is a C++ library for use by clients/agents of VPP for programming
state. It uses the binary APIs to do so. Various other common client side
functions are also provided. Please see om.hpp for a more detailed description.

Change-Id: Ib756bfe99817093815a9e26ccf464aa5583fc523
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Co-authored-by: Mohsin Kazmi <sykazmi@cisco.com>
This commit is contained in:
Neale Ranns
2017-10-16 04:20:13 -07:00
committed by Damjan Marion
parent 14edd97c20
commit 812ed39f9d
120 changed files with 23171 additions and 55 deletions

1
.gitignore vendored
View File

@@ -18,6 +18,7 @@
/build-root/test-cov/
/build-root/python/
/build-root/vapi_test/
/build-root/vom_test/
/build-config.mk
/dpdk/*.tar.gz
/dpdk/*.tar.xz

View File

@@ -69,6 +69,7 @@ DEB_DEPENDS += debhelper dkms git libtool libapr1-dev dh-systemd
DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config
DEB_DEPENDS += lcov chrpath autoconf nasm indent clang-format libnuma-dev
DEB_DEPENDS += python-all python-dev python-virtualenv python-pip libffi6 check
DEB_DEPENDS += libboost-all-dev
ifeq ($(OS_VERSION_ID),14.04)
DEB_DEPENDS += openjdk-8-jdk-headless
DEB_DEPENDS += libssl-dev
@@ -88,6 +89,7 @@ RPM_DEPENDS = redhat-lsb glibc-static java-1.8.0-openjdk-devel yum-utils
RPM_DEPENDS += apr-devel
RPM_DEPENDS += numactl-devel
RPM_DEPENDS += check check-devel
RPM_DEPENDS += boost boost-devel
ifeq ($(OS_ID)-$(OS_VERSION_ID),fedora-25)
RPM_DEPENDS += subunit subunit-devel

View File

@@ -20,6 +20,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_LIBTOOLFLAGS = --quiet
AM_CFLAGS = -Wall
AM_CXXFLAGS = -Wall -std=gnu++11
SUBDIRS = .
SUFFIXES = .api.h .api .api.json
@@ -82,6 +83,7 @@ SUBDIRS += vpp-api/java
endif
SUBDIRS += vpp-api/vapi
SUBDIRS += vpp-api/vom
###############################################################################
# API

View File

@@ -3,11 +3,12 @@ LT_INIT
AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE([subdir-objects])
AM_SILENT_RULES([yes])
AC_CONFIG_FILES([Makefile plugins/Makefile vpp-api/python/Makefile vpp-api/java/Makefile vpp-api/vapi/Makefile])
AC_CONFIG_FILES([Makefile plugins/Makefile vpp-api/python/Makefile vpp-api/java/Makefile vpp-api/vapi/Makefile vpp-api/vom/Makefile])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC
AC_PROG_CXX
AC_PROG_CPP
AM_PROG_AS
AM_PROG_LIBTOOL
AC_PROG_YACC

View File

@@ -105,7 +105,7 @@ public:
private:
Connection &con;
Common_req (Connection &con) : con{con}, response_state{RESPONSE_NOT_READY}
Common_req (Connection &con) : con (con), response_state{RESPONSE_NOT_READY}
{
}
@@ -759,7 +759,7 @@ private:
}
}
Result_set (Connection &con) : con{con}, complete{false}
Result_set (Connection &con) : con (con), complete{false}
{
}

View File

@@ -0,0 +1,3 @@
BasedOnStyle: mozilla
BinPackParameters: false

151
src/vpp-api/vom/Makefile.am Normal file
View File

@@ -0,0 +1,151 @@
# 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.
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
AM_LIBTOOLFLAGS = --quiet
AM_CXXFLAGS = -Wall -std=gnu++11 -I${top_srcdir} -I${top_builddir}/vpp-api/vapi/ -I$(top_srcdir)/vpp-api/ -I${libdir}/../include
AM_LDFLAGS = -shared -avoid-version -no-undefined
bin_PROGRAMS =
noinst_LTLIBRARIES =
CLEANDIRS =
lib_LTLIBRARIES = libvom.la
libvom_la_DEPENDENCIES =
libvom_la_LIBADD = \
$(top_builddir)/vpp-api/vapi/libvapiclient.la \
-lpthread \
-lboost_thread \
$(BOOST_SYSTEM_LIB) \
$(BOOST_FILESYSTEM_LIB) \
$(BOOST_ASIO_LIB) \
-lm -lrt
libvom_la_SOURCES = \
acl_binding_cmds.cpp \
acl_binding.cpp \
acl_l2_rule.cpp \
acl_l3_rule.cpp \
acl_list_cmds.cpp \
acl_list.cpp \
acl_types.cpp \
arp_proxy_binding_cmds.cpp \
arp_proxy_binding.cpp \
arp_proxy_config_cmds.cpp \
arp_proxy_config.cpp \
bridge_domain_cmds.cpp \
bridge_domain.cpp \
bridge_domain_arp_entry.cpp \
bridge_domain_arp_entry_cmds.cpp \
bridge_domain_entry_cmds.cpp \
bridge_domain_entry.cpp \
client_db.cpp \
cmd.cpp \
connection.cpp \
dhcp_config_cmds.cpp \
dhcp_config.cpp \
hw.cpp \
inspect.cpp \
interface_cmds.cpp \
interface.cpp \
interface_factory.cpp \
interface_ip6_nd_cmds.cpp \
interface_span_cmds.cpp \
interface_span.cpp \
interface_types.cpp \
ip_unnumbered_cmds.cpp \
ip_unnumbered.cpp \
l2_binding_cmds.cpp \
l2_binding.cpp \
l3_binding_cmds.cpp \
l3_binding.cpp \
lldp_binding_cmds.cpp \
lldp_binding.cpp \
lldp_global_cmds.cpp \
lldp_global.cpp \
logger.cpp \
nat_static.cpp \
nat_static_cmds.cpp \
nat_binding.cpp \
nat_binding_cmds.cpp \
neighbour.cpp \
neighbour_cmds.cpp \
object_base.cpp \
om.cpp \
prefix.cpp \
ra_config.cpp \
ra_prefix.cpp \
route.cpp \
route_cmds.cpp \
route_domain.cpp \
route_domain_cmds.cpp \
sub_interface_cmds.cpp \
sub_interface.cpp \
tap_interface.cpp \
tap_interface_cmds.cpp \
types.cpp \
vxlan_tunnel_cmds.cpp \
vxlan_tunnel.cpp
vomincludedir = $(includedir)/vom
vominclude_HEADERS = \
acl_binding.hpp \
acl_l2_rule.hpp \
acl_l3_rule.hpp \
acl_list.hpp \
acl_types.hpp \
arp_proxy_binding.hpp \
arp_proxy_config.hpp \
bridge_domain.hpp \
bridge_domain_arp_entry.hpp \
bridge_domain_entry.hpp \
client_db.hpp \
cmd.hpp \
connection.hpp \
dhcp_config.hpp \
dump_cmd.hpp \
enum_base.hpp \
event_cmd.hpp \
hw.hpp \
inspect.hpp \
interface.hpp \
interface_ip6_nd.hpp \
interface_span.hpp \
ip_unnumbered.hpp \
l2_binding.hpp \
l3_binding.hpp \
lldp_binding.hpp \
lldp_global.hpp \
logger.hpp \
nat_static.hpp \
nat_binding.hpp \
neighbour.hpp \
object_base.hpp \
om.hpp \
prefix.hpp \
ra_config.hpp \
ra_prefix.hpp \
route.hpp \
route_domain.hpp \
rpc_cmd.hpp \
singular_db.hpp \
sub_interface.hpp \
tap_interface.hpp \
types.hpp \
vxlan_tunnel.hpp
# vi:syntax=automake

View File

@@ -0,0 +1,95 @@
/*
* 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/acl_binding.hpp"
#include "vom/om.hpp"
namespace VOM {
namespace ACL {
template <>
void
l2_binding::event_handler::handle_populate(const client_db::key_t& key)
{
/*
* dump VPP Bridge domains
*/
std::shared_ptr<l2_binding::dump_cmd> cmd(new l2_binding::dump_cmd());
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
std::shared_ptr<interface> itf = interface::find(payload.sw_if_index);
for (int ii = 0; ii < payload.count; ii++) {
std::shared_ptr<l2_list> acl = l2_list::find(payload.acls[ii]);
l2_binding binding(direction_t::INPUT, *itf, *acl);
OM::commit(key, binding);
}
}
}
template <>
void
l3_binding::event_handler::handle_populate(const client_db::key_t& key)
{
std::shared_ptr<l3_binding::dump_cmd> cmd(new l3_binding::dump_cmd());
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
std::shared_ptr<interface> itf = interface::find(payload.sw_if_index);
uint8_t n_input = payload.n_input;
for (int ii = 0; ii < payload.count; ii++) {
std::shared_ptr<l3_list> acl = l3_list::find(payload.acls[ii]);
if (n_input) {
l3_binding binding(direction_t::INPUT, *itf, *acl);
n_input--;
OM::commit(key, binding);
} else {
l3_binding binding(direction_t::OUTPUT, *itf, *acl);
OM::commit(key, binding);
}
}
}
}
};
std::ostream&
operator<<(std::ostream& os,
const std::pair<direction_t, interface::key_type>& key)
{
os << "[" << key.first.to_string() << " " << key.second << "]";
return (os);
}
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/*
* 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/acl_binding.hpp"
DEFINE_VAPI_MSG_IDS_ACL_API_JSON;
namespace VOM {
namespace ACL {
template <>
rc_t
l3_binding::bind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.is_add = 1;
payload.is_input = (m_direction == direction_t::INPUT ? 1 : 0);
payload.acl_index = m_acl.value();
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
template <>
rc_t
l3_binding::unbind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.is_add = 0;
payload.is_input = (m_direction == direction_t::INPUT ? 1 : 0);
payload.acl_index = m_acl.value();
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
template <>
rc_t
l3_binding::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.sw_if_index = ~0;
VAPI_CALL(m_dump->execute());
wait();
return rc_t::OK;
}
template <>
rc_t
l2_binding::bind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.is_add = 1;
// payload.is_input = (m_direction == direction_t::INPUT ? 1 : 0);
payload.acl_index = m_acl.value();
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
template <>
rc_t
l2_binding::unbind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.is_add = 0;
// payload.is_input = (m_direction == direction_t::INPUT ? 1 : 0);
payload.acl_index = m_acl.value();
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
template <>
rc_t
l2_binding::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.sw_if_index = ~0;
VAPI_CALL(m_dump->execute());
wait();
return rc_t::OK;
}
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,78 @@
/*
* 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 <sstream>
#include "vom/acl_l2_rule.hpp"
namespace VOM {
namespace ACL {
l2_rule::l2_rule(uint32_t priority,
const action_t& action,
const route::prefix_t& ip,
const mac_address_t& mac,
const mac_address_t& mac_mask)
: m_priority(priority)
, m_action(action)
, m_src_ip(ip)
, m_mac(mac)
, m_mac_mask(mac_mask)
{
}
bool
l2_rule::operator<(const l2_rule& other) const
{
return (other.m_priority < m_priority);
}
void
l2_rule::to_vpp(vapi_type_macip_acl_rule& rule) const
{
rule.is_permit = m_action.value();
m_src_ip.to_vpp(&rule.is_ipv6, rule.src_ip_addr, &rule.src_ip_prefix_len);
m_mac.to_bytes(rule.src_mac, 6);
m_mac_mask.to_bytes(rule.src_mac_mask, 6);
}
bool
l2_rule::operator==(const l2_rule& rule) const
{
return ((m_action == rule.m_action) && (m_src_ip == rule.m_src_ip) &&
(m_mac == rule.m_mac) && (m_mac_mask == rule.m_mac_mask));
}
std::string
l2_rule::to_string() const
{
std::ostringstream s;
s << "L2-rule:["
<< "priority:" << m_priority << " action:" << m_action.to_string()
<< " ip:" << m_src_ip.to_string() << " mac:" << m_mac
<< " mac-mask:" << m_mac_mask << "]";
return (s.str());
}
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,113 @@
/*
* 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.
*/
#ifndef __VOM_L2_ACL_RULE_H__
#define __VOM_L2_ACL_RULE_H__
#include "vom/acl_types.hpp"
#include "vom/prefix.hpp"
#include <vapi/acl.api.vapi.hpp>
namespace VOM {
namespace ACL {
/**
* An ACL rule is the building block of an ACL. An ACL, which is
* the object applied to an interface, is comprised of an ordersed
* sequence of ACL rules.
* This class is a wrapper around the VAPI generated struct and exports
* an API with better types.
*/
class l2_rule
{
public:
/**
* Construct a new object matching the desried state
*/
l2_rule(uint32_t priority,
const action_t& action,
const route::prefix_t& ip,
const mac_address_t& mac,
const mac_address_t& mac_mask);
/**
* Copy Constructor
*/
l2_rule(const l2_rule& o) = default;
/**
* Destructor
*/
~l2_rule() = default;
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* less-than operator
*/
bool operator<(const l2_rule& rule) const;
/**
* comparison operator (for testing)
*/
bool operator==(const l2_rule& rule) const;
/**
* Convert to VPP API fromat
*/
void to_vpp(vapi_type_macip_acl_rule& rule) const;
private:
/**
* Priority. Used to sort the rules in a list in the order
* in which they are applied
*/
uint32_t m_priority;
/**
* Action on match
*/
action_t m_action;
/**
* Source Prefix
*/
route::prefix_t m_src_ip;
/**
* Source Mac
*/
mac_address_t m_mac;
/**
* Source MAC mask
*/
mac_address_t m_mac_mask;
};
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,156 @@
/*
* 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 <sstream>
#include "vom/acl_l3_rule.hpp"
namespace VOM {
namespace ACL {
l3_rule::l3_rule(uint32_t priority,
const action_t& action,
const route::prefix_t& src,
const route::prefix_t& dst)
: m_priority(priority)
, m_action(action)
, m_src(src)
, m_dst(dst)
, m_proto(0)
, m_srcport_or_icmptype_first(0)
, m_srcport_or_icmptype_last(0)
, m_dstport_or_icmpcode_first(0)
, m_dstport_or_icmpcode_last(0)
, m_tcp_flags_mask(0)
, m_tcp_flags_value(0)
{
}
bool
l3_rule::operator<(const l3_rule& other) const
{
return (other.m_priority < m_priority);
}
void
l3_rule::to_vpp(vapi_type_acl_rule& rule) const
{
rule.is_permit = m_action.value();
m_src.to_vpp(&rule.is_ipv6, rule.src_ip_addr, &rule.src_ip_prefix_len);
m_dst.to_vpp(&rule.is_ipv6, rule.dst_ip_addr, &rule.dst_ip_prefix_len);
rule.proto = m_proto;
rule.srcport_or_icmptype_first = m_srcport_or_icmptype_first;
rule.srcport_or_icmptype_last = m_srcport_or_icmptype_last;
rule.dstport_or_icmpcode_first = m_dstport_or_icmpcode_first;
rule.dstport_or_icmpcode_last = m_dstport_or_icmpcode_last;
rule.tcp_flags_mask = m_tcp_flags_mask;
rule.tcp_flags_value = m_tcp_flags_value;
}
bool
l3_rule::operator==(const l3_rule& rule) const
{
return ((m_action == rule.m_action) && (m_src == rule.m_src) &&
(m_dst == rule.m_dst) && (m_proto == rule.m_proto) &&
(m_srcport_or_icmptype_first == rule.m_srcport_or_icmptype_first) &&
(m_srcport_or_icmptype_last == rule.m_srcport_or_icmptype_last) &&
(m_dstport_or_icmpcode_first == rule.m_dstport_or_icmpcode_first) &&
(m_dstport_or_icmpcode_last == rule.m_dstport_or_icmpcode_last) &&
(m_tcp_flags_mask == rule.m_tcp_flags_mask) &&
(m_tcp_flags_value == rule.m_tcp_flags_value));
}
std::string
l3_rule::to_string() const
{
std::ostringstream s;
s << "L3-rule:["
<< "priority:" << m_priority << " action:" << m_action.to_string()
<< " src:" << m_src.to_string() << " dst:" << m_dst.to_string()
<< " proto:" << std::to_string(m_proto)
<< " srcportfrom:" << m_srcport_or_icmptype_first
<< " srcportto: " << m_srcport_or_icmptype_last
<< " dstportfrom:" << m_dstport_or_icmpcode_first
<< " dstportto:" << m_dstport_or_icmpcode_last
<< " tcpflagmask:" << m_tcp_flags_mask
<< " tcpflagvalue:" << m_tcp_flags_value << "]";
return (s.str());
}
void
l3_rule::set_src_ip(route::prefix_t src)
{
m_src = src;
}
void
l3_rule::set_dst_ip(route::prefix_t dst)
{
m_dst = dst;
}
void
l3_rule::set_proto(uint8_t proto)
{
m_proto = proto;
}
void
l3_rule::set_src_from_port(uint16_t srcport_or_icmptype_first)
{
m_srcport_or_icmptype_first = srcport_or_icmptype_first;
}
void
l3_rule::set_src_to_port(uint16_t srcport_or_icmptype_last)
{
m_srcport_or_icmptype_last = srcport_or_icmptype_last;
}
void
l3_rule::set_dst_from_port(uint16_t dstport_or_icmpcode_first)
{
m_dstport_or_icmpcode_first = dstport_or_icmpcode_first;
}
void
l3_rule::set_dst_to_port(uint16_t dstport_or_icmpcode_last)
{
m_dstport_or_icmpcode_last = dstport_or_icmpcode_last;
}
void
l3_rule::set_tcp_flags_mask(uint8_t tcp_flags_mask)
{
m_tcp_flags_mask = tcp_flags_mask;
}
void
l3_rule::set_tcp_flags_value(uint8_t tcp_flags_value)
{
m_tcp_flags_value = tcp_flags_value;
}
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,181 @@
/*
* 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.
*/
#ifndef __VOM_L3_ACL_RULE_H__
#define __VOM_L3_ACL_RULE_H__
#include "vom/acl_types.hpp"
#include "vom/prefix.hpp"
#include <vapi/acl.api.vapi.hpp>
namespace VOM {
namespace ACL {
/**
* An ACL rule is the building block of an ACL. An ACL, which is
* the object applied to an interface, is comprised of an ordersed
* sequence of ACL rules.
* This class is a wrapper around the VAPI generated struct and exports
* an API with better types.
*/
class l3_rule
{
public:
/**
* Construct a new object matching the desried state
*/
l3_rule(uint32_t priority,
const action_t& action,
const route::prefix_t& src,
const route::prefix_t& dst);
/**
* Copy Constructor
*/
l3_rule(const l3_rule& o) = default;
/**
* Destructor
*/
~l3_rule() = default;
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* less-than operator
*/
bool operator<(const l3_rule& rule) const;
/**
* comparison operator (for testing)
*/
bool operator==(const l3_rule& rule) const;
/**
* Convert to VPP API fromat
*/
void to_vpp(vapi_type_acl_rule& rule) const;
/**
* Set Src Ip Address
*/
void set_src_ip(route::prefix_t src);
/**
* Set Dst Ip Address
*/
void set_dst_ip(route::prefix_t dst);
/**
*Set proto
*/
void set_proto(uint8_t proto);
/**
* Set Src port or ICMP Type first
*/
void set_src_from_port(uint16_t srcport_or_icmptype_first);
/**
* Set Src port or ICMP Type last
*/
void set_src_to_port(uint16_t srcport_or_icmptype_last);
/**
* Set Dst port or ICMP code first
*/
void set_dst_from_port(uint16_t dstport_or_icmpcode_first);
/**
* Set Dst port or ICMP code last
*/
void set_dst_to_port(uint16_t dstport_or_icmpcode_last);
/**
* Set TCP flags mask
*/
void set_tcp_flags_mask(uint8_t tcp_flags_mask);
/**
* Set TCP flags value
*/
void set_tcp_flags_value(uint8_t tcp_flags_value);
private:
/**
* Priority. Used to sort the rules in a list in the order
* in which they are applied
*/
uint32_t m_priority;
/**
* Action on match
*/
action_t m_action;
/**
* Source Prefix
*/
route::prefix_t m_src;
/**
* Destination Prefix
*/
route::prefix_t m_dst;
/**
* L4 protocol. IANA number. 1 = ICMP, 58 = ICMPv6, 6 = TCP, 17 =
* UDP.
* 0 => ignore L4 and ignore the ports/tcpflags when matching.
*/
uint8_t m_proto;
/**
* If the L4 protocol is TCP or UDP, the below
* hold ranges of ports, else if the L4 is ICMP/ICMPv6
* they hold ranges of ICMP(v6) types/codes.
*
* Ranges are inclusive, i.e. to match "any" TCP/UDP port,
* use first=0,last=65535. For ICMP(v6),
* use first=0,last=255.
*/
uint16_t m_srcport_or_icmptype_first;
uint16_t m_srcport_or_icmptype_last;
uint16_t m_dstport_or_icmpcode_first;
uint16_t m_dstport_or_icmpcode_last;
/*
* for proto = 6, this matches if the
* TCP flags in the packet, ANDed with tcp_flags_mask,
* is equal to tcp_flags_value.
*/
uint8_t m_tcp_flags_mask;
uint8_t m_tcp_flags_value;
};
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,113 @@
/*
* 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/acl_list.hpp"
#include "vom/logger.hpp"
namespace VOM {
namespace ACL {
template <>
void
l2_list::event_handler::handle_populate(const client_db::key_t& key)
{
/* hack to get this function instantiated */
m_evh.order();
/*
* dump VPP Bridge domains
*/
std::shared_ptr<l2_list::dump_cmd> cmd(new l2_list::dump_cmd());
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
const handle_t hdl(payload.acl_index);
l2_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
for (unsigned int ii = 0; ii < payload.count; ii++) {
const route::prefix_t pfx(payload.r[ii].is_ipv6,
payload.r[ii].src_ip_addr,
payload.r[ii].src_ip_prefix_len);
l2_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), pfx,
{ payload.r[ii].src_mac }, { payload.r[ii].src_mac_mask });
acl.insert(rule);
}
VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
/*
* Write each of the discovered ACLs into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, acl);
}
}
template <>
void
l3_list::event_handler::handle_populate(const client_db::key_t& key)
{
/* hack to get this function instantiated */
m_evh.order();
/*
* dump VPP Bridge domains
*/
std::shared_ptr<l3_list::dump_cmd> cmd(new l3_list::dump_cmd());
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
const handle_t hdl(payload.acl_index);
l3_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
for (unsigned int ii = 0; ii < payload.count; ii++) {
const route::prefix_t src(payload.r[ii].is_ipv6,
payload.r[ii].src_ip_addr,
payload.r[ii].src_ip_prefix_len);
const route::prefix_t dst(payload.r[ii].is_ipv6,
payload.r[ii].dst_ip_addr,
payload.r[ii].dst_ip_prefix_len);
l3_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), src, dst);
acl.insert(rule);
}
VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
/*
* Write each of the discovered ACLs into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, acl);
}
}
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*
* 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/acl_list.hpp"
namespace VOM {
namespace ACL {
template <>
rc_t
l3_list::update_cmd::issue(connection& con)
{
msg_t req(con.ctx(), m_rules.size(), std::ref(*this));
uint32_t ii = 0;
auto& payload = req.get_request().get_payload();
payload.acl_index = m_hw_item.data().value();
payload.count = m_rules.size();
memset(payload.tag, 0, sizeof(payload.tag));
memcpy(payload.tag, m_key.c_str(),
std::min(m_key.length(), sizeof(payload.tag)));
auto it = m_rules.cbegin();
while (it != m_rules.cend()) {
it->to_vpp(payload.r[ii]);
++it;
++ii;
}
VAPI_CALL(req.execute());
m_hw_item = wait();
complete();
return rc_t::OK;
}
template <>
rc_t
l3_list::delete_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.acl_index = m_hw_item.data().value();
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
return rc_t::OK;
}
template <>
rc_t
l3_list::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.acl_index = ~0;
VAPI_CALL(m_dump->execute());
wait();
return rc_t::OK;
}
template <>
rc_t
l2_list::update_cmd::issue(connection& con)
{
msg_t req(con.ctx(), m_rules.size(), std::ref(*this));
uint32_t ii = 0;
auto& payload = req.get_request().get_payload();
// payload.acl_index = m_hw_item.data().value();
payload.count = m_rules.size();
memset(payload.tag, 0, sizeof(payload.tag));
memcpy(payload.tag, m_key.c_str(),
std::min(m_key.length(), sizeof(payload.tag)));
auto it = m_rules.cbegin();
while (it != m_rules.cend()) {
it->to_vpp(payload.r[ii]);
++it;
++ii;
}
VAPI_CALL(req.execute());
m_hw_item = wait();
return rc_t::OK;
}
template <>
rc_t
l2_list::delete_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.acl_index = m_hw_item.data().value();
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
return rc_t::OK;
}
template <>
rc_t
l2_list::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.acl_index = ~0;
VAPI_CALL(m_dump->execute());
wait();
return rc_t::OK;
}
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,59 @@
/*
* 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/acl_types.hpp"
namespace VOM {
namespace ACL {
const action_t action_t::PERMITANDREFLEX(2, "permitandreflex");
const action_t action_t::PERMIT(1, "permit");
const action_t action_t::DENY(0, "deny");
action_t::action_t(int v, const std::string s)
: enum_base(v, s)
{
}
const action_t&
action_t::from_int(uint8_t i)
{
if (i == 2)
return action_t::PERMITANDREFLEX;
else if (i)
return action_t::PERMIT;
return action_t::DENY;
}
const action_t&
action_t::from_bool(bool b, uint8_t c)
{
if (b) {
if (c)
return action_t::PERMITANDREFLEX;
return action_t::PERMIT;
}
return action_t::DENY;
}
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,75 @@
/*
* 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.
*/
#ifndef __VOM_ACL_TYPES_H__
#define __VOM_ACL_TYPES_H__
#include "vom/types.hpp"
namespace VOM {
namespace ACL {
/**
* ACL Actions
*/
struct action_t : public enum_base<action_t>
{
/**
* Constructor
*/
action_t(int v, const std::string s);
/**
* Destructor
*/
~action_t() = default;
/**
* Permit and Reflexive
*/
const static action_t PERMITANDREFLEX;
/**
* Permit Action
*/
const static action_t PERMIT;
/**
* Deny Action
*/
const static action_t DENY;
/**
* Get the enum type from a VPP integer value
*/
static const action_t& from_int(uint8_t i);
/**
*Get the enum type from a bool value and optional uint8_t value
*which implements the connection tracking ....
*/
static const action_t& from_bool(bool b, uint8_t c);
};
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,142 @@
/*
* 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/arp_proxy_binding.hpp"
#include "vom/cmd.hpp"
namespace VOM {
/**
* A DB of all LLDP configs
*/
singular_db<interface::key_type, arp_proxy_binding> arp_proxy_binding::m_db;
arp_proxy_binding::event_handler arp_proxy_binding::m_evh;
arp_proxy_binding::arp_proxy_binding(const interface& itf,
const arp_proxy_config& proxy_cfg)
: m_itf(itf.singular())
, m_arp_proxy_cfg(proxy_cfg.singular())
, m_binding(true)
{
}
arp_proxy_binding::arp_proxy_binding(const arp_proxy_binding& o)
: m_itf(o.m_itf)
, m_arp_proxy_cfg(o.m_arp_proxy_cfg)
, m_binding(o.m_binding)
{
}
arp_proxy_binding::~arp_proxy_binding()
{
sweep();
// not in the DB anymore.
m_db.release(m_itf->key(), this);
}
void
arp_proxy_binding::sweep()
{
if (m_binding) {
HW::enqueue(new unbind_cmd(m_binding, m_itf->handle()));
}
HW::write();
}
void
arp_proxy_binding::dump(std::ostream& os)
{
m_db.dump(os);
}
void
arp_proxy_binding::replay()
{
if (m_binding) {
HW::enqueue(new bind_cmd(m_binding, m_itf->handle()));
}
}
std::string
arp_proxy_binding::to_string() const
{
std::ostringstream s;
s << "ArpProxy-binding: " << m_itf->to_string();
return (s.str());
}
void
arp_proxy_binding::update(const arp_proxy_binding& desired)
{
/*
* the desired state is always that the interface should be created
*/
if (!m_binding) {
HW::enqueue(new bind_cmd(m_binding, m_itf->handle()));
}
}
std::shared_ptr<arp_proxy_binding>
arp_proxy_binding::find_or_add(const arp_proxy_binding& temp)
{
return (m_db.find_or_add(temp.m_itf->key(), temp));
}
std::shared_ptr<arp_proxy_binding>
arp_proxy_binding::singular() const
{
return find_or_add(*this);
}
arp_proxy_binding::event_handler::event_handler()
{
OM::register_listener(this);
inspect::register_handler({ "arp-proxy" }, "ARP proxy bindings", this);
}
void
arp_proxy_binding::event_handler::handle_replay()
{
m_db.replay();
}
void
arp_proxy_binding::event_handler::handle_populate(const client_db::key_t& key)
{
// FIXME
}
dependency_t
arp_proxy_binding::event_handler::order() const
{
return (dependency_t::BINDING);
}
void
arp_proxy_binding::event_handler::show(std::ostream& os)
{
m_db.dump(os);
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,234 @@
/*
* 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.
*/
#ifndef __VOM_ARP_PROXY_BINDING_H__
#define __VOM_ARP_PROXY_BINDING_H__
#include "vom/arp_proxy_config.hpp"
#include "vom/dump_cmd.hpp"
#include "vom/hw.hpp"
#include "vom/inspect.hpp"
#include "vom/interface.hpp"
#include "vom/object_base.hpp"
#include "vom/om.hpp"
#include "vom/rpc_cmd.hpp"
#include "vom/singular_db.hpp"
#include <vapi/vpe.api.vapi.hpp>
namespace VOM {
/**
* A representation of LLDP client configuration on an interface
*/
class arp_proxy_binding : public object_base
{
public:
/**
* Construct a new object matching the desried state
*/
arp_proxy_binding(const interface& itf, const arp_proxy_config& proxy_cfg);
/**
* Copy Constructor
*/
arp_proxy_binding(const arp_proxy_binding& o);
/**
* Destructor
*/
~arp_proxy_binding();
/**
* Return the 'singular' of the LLDP binding that matches this object
*/
std::shared_ptr<arp_proxy_binding> singular() const;
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Dump all LLDP bindings into the stream provided
*/
static void dump(std::ostream& os);
/**
* A command class that binds the LLDP config to the interface
*/
class bind_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_intfc_enable_disable>
{
public:
/**
* Constructor
*/
bind_cmd(HW::item<bool>& item, const handle_t& itf);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const bind_cmd& i) const;
private:
/**
* Reference to the HW::item of the interface to bind
*/
const handle_t& m_itf;
};
/**
* A cmd class that Unbinds ArpProxy Config from an interface
*/
class unbind_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_intfc_enable_disable>
{
public:
/**
* Constructor
*/
unbind_cmd(HW::item<bool>& item, const handle_t& itf);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const unbind_cmd& i) const;
private:
/**
* Reference to the HW::item of the interface to unbind
*/
const handle_t& m_itf;
};
private:
/**
* Class definition for listeners to OM events
*/
class event_handler : public OM::listener, public inspect::command_handler
{
public:
event_handler();
virtual ~event_handler() = default;
/**
* Handle a populate event
*/
void handle_populate(const client_db::key_t& key);
/**
* Handle a replay event
*/
void handle_replay();
/**
* Show the object in the Singular DB
*/
void show(std::ostream& os);
/**
* Get the sortable Id of the listener
*/
dependency_t order() const;
};
/**
* event_handler to register with OM
*/
static event_handler m_evh;
/**
* Enquue commonds to the VPP command Q for the update
*/
void update(const arp_proxy_binding& obj);
/**
* Find or add LLDP binding to the OM
*/
static std::shared_ptr<arp_proxy_binding> find_or_add(
const arp_proxy_binding& temp);
/*
* It's the OM class that calls singular()
*/
friend class OM;
/**
* It's the singular_db class that calls replay()
*/
friend class singular_db<interface::key_type, arp_proxy_binding>;
/**
* Sweep/reap the object if still stale
*/
void sweep(void);
/**
* replay the object to create it in hardware
*/
void replay(void);
/**
* A reference counting pointer to the interface on which LLDP config
* resides. By holding the reference here, we can guarantee that
* this object will outlive the interface
*/
const std::shared_ptr<interface> m_itf;
/**
* A reference counting pointer to the prxy config.
*/
const std::shared_ptr<arp_proxy_config> m_arp_proxy_cfg;
/**
* HW configuration for the binding. The bool representing the
* do/don't bind.
*/
HW::item<bool> m_binding;
/**
* A map of all ArpProxy bindings keyed against the interface.
*/
static singular_db<interface::key_type, arp_proxy_binding> m_db;
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,104 @@
/*
* 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/arp_proxy_binding.hpp"
namespace VOM {
arp_proxy_binding::bind_cmd::bind_cmd(HW::item<bool>& item, const handle_t& itf)
: rpc_cmd(item)
, m_itf(itf)
{
}
bool
arp_proxy_binding::bind_cmd::operator==(const bind_cmd& other) const
{
return (m_itf == other.m_itf);
}
rc_t
arp_proxy_binding::bind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.enable_disable = 1;
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
std::string
arp_proxy_binding::bind_cmd::to_string() const
{
std::ostringstream s;
s << "ARP-proxy-bind: " << m_hw_item.to_string()
<< " itf:" << m_itf.to_string();
return (s.str());
}
arp_proxy_binding::unbind_cmd::unbind_cmd(HW::item<bool>& item,
const handle_t& itf)
: rpc_cmd(item)
, m_itf(itf)
{
}
bool
arp_proxy_binding::unbind_cmd::operator==(const unbind_cmd& other) const
{
return (m_itf == other.m_itf);
}
rc_t
arp_proxy_binding::unbind_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_itf.value();
payload.enable_disable = 0;
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
return rc_t::OK;
}
std::string
arp_proxy_binding::unbind_cmd::to_string() const
{
std::ostringstream s;
s << "ARP-proxy-unbind: " << m_hw_item.to_string()
<< " itf:" << m_itf.to_string();
return (s.str());
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,147 @@
/*
* 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/arp_proxy_config.hpp"
#include "vom/cmd.hpp"
namespace VOM {
/**
* A DB of all LLDP configs
*/
singular_db<arp_proxy_config::key_t, arp_proxy_config> arp_proxy_config::m_db;
arp_proxy_config::event_handler arp_proxy_config::m_evh;
arp_proxy_config::arp_proxy_config(const boost::asio::ip::address_v4& low,
const boost::asio::ip::address_v4& high)
: m_low(low)
, m_high(high)
, m_config(true)
{
}
arp_proxy_config::arp_proxy_config(const arp_proxy_config& o)
: m_low(o.m_low)
, m_high(o.m_high)
, m_config(o.m_config)
{
}
arp_proxy_config::~arp_proxy_config()
{
sweep();
// not in the DB anymore.
m_db.release(std::make_pair(m_low, m_high), this);
}
void
arp_proxy_config::sweep()
{
if (m_config) {
HW::enqueue(new unconfig_cmd(m_config, m_low, m_high));
}
HW::write();
}
void
arp_proxy_config::dump(std::ostream& os)
{
m_db.dump(os);
}
void
arp_proxy_config::replay()
{
if (m_config) {
HW::enqueue(new config_cmd(m_config, m_low, m_high));
}
}
std::string
arp_proxy_config::to_string() const
{
std::ostringstream s;
s << "ARP-proxy:"
<< " low:" << m_low.to_string() << " high:" << m_high.to_string();
return (s.str());
}
void
arp_proxy_config::update(const arp_proxy_config& desired)
{
if (!m_config) {
HW::enqueue(new config_cmd(m_config, m_low, m_high));
}
}
std::shared_ptr<arp_proxy_config>
arp_proxy_config::find_or_add(const arp_proxy_config& temp)
{
return (m_db.find_or_add(std::make_pair(temp.m_low, temp.m_high), temp));
}
std::shared_ptr<arp_proxy_config>
arp_proxy_config::singular() const
{
return find_or_add(*this);
}
arp_proxy_config::event_handler::event_handler()
{
OM::register_listener(this);
inspect::register_handler({ "arp-proxy" }, "ARP Proxy configurations", this);
}
void
arp_proxy_config::event_handler::handle_replay()
{
m_db.replay();
}
void
arp_proxy_config::event_handler::handle_populate(const client_db::key_t& key)
{
// VPP provides no dump for ARP proxy.
}
dependency_t
arp_proxy_config::event_handler::order() const
{
return (dependency_t::GLOBAL);
}
void
arp_proxy_config::event_handler::show(std::ostream& os)
{
m_db.dump(os);
}
std::ostream&
operator<<(std::ostream& os, const arp_proxy_config::key_t& key)
{
os << "[" << key.first << ", " << key.second << "]";
return (os);
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,241 @@
/*
* 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.
*/
#ifndef __VOM_ARP_PROXY_CONFIG_H__
#define __VOM_ARP_PROXY_CONFIG_H__
#include "vom/dump_cmd.hpp"
#include "vom/hw.hpp"
#include "vom/inspect.hpp"
#include "vom/object_base.hpp"
#include "vom/om.hpp"
#include "vom/rpc_cmd.hpp"
#include "vom/singular_db.hpp"
#include <vapi/vpe.api.vapi.hpp>
namespace VOM {
/**
* A representation of LLDP client configuration on an interface
*/
class arp_proxy_config : public object_base
{
public:
/**
* Key type
*/
typedef std::pair<boost::asio::ip::address_v4, boost::asio::ip::address_v4>
key_t;
/**
* Construct a new object matching the desried state
*/
arp_proxy_config(const boost::asio::ip::address_v4& low,
const boost::asio::ip::address_v4& high);
/**
* Copy Constructor
*/
arp_proxy_config(const arp_proxy_config& o);
/**
* Destructor
*/
~arp_proxy_config();
/**
* Return the 'singular' of the LLDP config that matches this object
*/
std::shared_ptr<arp_proxy_config> singular() const;
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Dump all LLDP configs into the stream provided
*/
static void dump(std::ostream& os);
/**
* A command class that adds the ARP Proxy config
*/
class config_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_add_del>
{
public:
/**
* Constructor
*/
config_cmd(HW::item<bool>& item,
const boost::asio::ip::address_v4& lo,
const boost::asio::ip::address_v4& high);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const config_cmd& i) const;
private:
/**
* Address range
*/
const boost::asio::ip::address_v4 m_low;
const boost::asio::ip::address_v4 m_high;
};
/**
* A cmd class that Unconfigs ArpProxy Config from an interface
*/
class unconfig_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_add_del>
{
public:
/**
* Constructor
*/
unconfig_cmd(HW::item<bool>& item,
const boost::asio::ip::address_v4& lo,
const boost::asio::ip::address_v4& hig);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const unconfig_cmd& i) const;
private:
/**
* Address range
*/
const boost::asio::ip::address_v4 m_low;
const boost::asio::ip::address_v4 m_high;
};
private:
/**
* Class definition for listeners to OM events
*/
class event_handler : public OM::listener, public inspect::command_handler
{
public:
event_handler();
virtual ~event_handler() = default;
/**
* Handle a populate event
*/
void handle_populate(const client_db::key_t& key);
/**
* Handle a replay event
*/
void handle_replay();
/**
* Show the object in the Singular DB
*/
void show(std::ostream& os);
/**
* Get the sortable Id of the listener
*/
dependency_t order() const;
};
/**
* event_handler to register with OM
*/
static event_handler m_evh;
/**
* Enquue commonds to the VPP command Q for the update
*/
void update(const arp_proxy_config& obj);
/**
* Find or add LLDP config to the OM
*/
static std::shared_ptr<arp_proxy_config> find_or_add(
const arp_proxy_config& temp);
/*
* It's the OM class that calls singular()
*/
friend class OM;
/**
* It's the singular_db class that calls replay()
*/
friend class singular_db<arp_proxy_config::key_t, arp_proxy_config>;
/**
* Sweep/reap the object if still stale
*/
void sweep(void);
/**
* replay the object to create it in hardware
*/
void replay(void);
/**
* Address range
*/
const boost::asio::ip::address_v4 m_low;
const boost::asio::ip::address_v4 m_high;
/**
* A map of all ArpProxy configs keyed against the interface.
*/
static singular_db<arp_proxy_config::key_t, arp_proxy_config> m_db;
/**
* HW configuration for the config. The bool representing the
* do/don't configured/unconfigured.
*/
HW::item<bool> m_config;
};
std::ostream& operator<<(std::ostream& os, const arp_proxy_config::key_t& key);
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,120 @@
/*
* 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/arp_proxy_config.hpp"
#include <vapi/vpe.api.vapi.hpp>
namespace VOM {
arp_proxy_config::config_cmd::config_cmd(
HW::item<bool>& item,
const boost::asio::ip::address_v4& low,
const boost::asio::ip::address_v4& high)
: rpc_cmd(item)
, m_low(low)
, m_high(high)
{
}
bool
arp_proxy_config::config_cmd::operator==(const config_cmd& o) const
{
return ((m_low == o.m_low) && (m_high == o.m_high));
}
rc_t
arp_proxy_config::config_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.is_add = 1;
std::copy_n(std::begin(m_low.to_bytes()), m_low.to_bytes().size(),
payload.low_address);
std::copy_n(std::begin(m_high.to_bytes()), m_high.to_bytes().size(),
payload.hi_address);
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return (rc_t::OK);
}
std::string
arp_proxy_config::config_cmd::to_string() const
{
std::ostringstream s;
s << "ARP-proxy-config: " << m_hw_item.to_string()
<< " low:" << m_low.to_string() << " high:" << m_high.to_string();
return (s.str());
}
arp_proxy_config::unconfig_cmd::unconfig_cmd(
HW::item<bool>& item,
const boost::asio::ip::address_v4& low,
const boost::asio::ip::address_v4& high)
: rpc_cmd(item)
, m_low(low)
, m_high(high)
{
}
bool
arp_proxy_config::unconfig_cmd::operator==(const unconfig_cmd& o) const
{
return ((m_low == o.m_low) && (m_high == o.m_high));
}
rc_t
arp_proxy_config::unconfig_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.is_add = 0;
std::copy_n(std::begin(m_low.to_bytes()), m_low.to_bytes().size(),
payload.low_address);
std::copy_n(std::begin(m_high.to_bytes()), m_high.to_bytes().size(),
payload.hi_address);
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
return (rc_t::OK);
}
std::string
arp_proxy_config::unconfig_cmd::to_string() const
{
std::ostringstream s;
s << "ARP-proxy-unconfig: " << m_hw_item.to_string()
<< " low:" << m_low.to_string() << " high:" << m_high.to_string();
return (s.str());
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,210 @@
/*
* 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/bridge_domain.hpp"
#include "vom/cmd.hpp"
#include "vom/interface.hpp"
#include "vom/l2_binding.hpp"
#include "vom/logger.hpp"
namespace VOM {
/**
* A DB of al the interfaces, key on the name
*/
singular_db<uint32_t, bridge_domain> bridge_domain::m_db;
bridge_domain::event_handler bridge_domain::m_evh;
/**
* Construct a new object matching the desried state
*/
bridge_domain::bridge_domain(uint32_t id)
: m_id(id)
{
}
bridge_domain::bridge_domain(const bridge_domain& o)
: m_id(o.m_id)
{
}
uint32_t
bridge_domain::id() const
{
return (m_id.data());
}
void
bridge_domain::sweep()
{
if (rc_t::OK == m_id.rc()) {
HW::enqueue(new delete_cmd(m_id));
}
HW::write();
}
void
bridge_domain::replay()
{
if (rc_t::OK == m_id.rc()) {
HW::enqueue(new create_cmd(m_id));
}
}
bridge_domain::~bridge_domain()
{
sweep();
// not in the DB anymore.
m_db.release(m_id.data(), this);
}
std::string
bridge_domain::to_string() const
{
std::ostringstream s;
s << "bridge-domain:[" << m_id.to_string() << "]";
return (s.str());
}
std::shared_ptr<bridge_domain>
bridge_domain::find(uint32_t id)
{
/*
* Loop throught the entire map looking for matching interface.
* not the most efficient algorithm, but it will do for now. The
* number of L3 configs is low and this is only called during bootup
*/
std::shared_ptr<bridge_domain> bd;
auto it = m_db.cbegin();
while (it != m_db.cend()) {
/*
* The key in the DB is a pair of the interface's name and prefix.
* If the keys match, save the L3-config
*/
auto key = it->first;
if (id == key) {
bd = it->second.lock();
break;
}
++it;
}
return (bd);
}
void
bridge_domain::update(const bridge_domain& desired)
{
/*
* the desired state is always that the interface should be created
*/
if (rc_t::OK != m_id.rc()) {
HW::enqueue(new create_cmd(m_id));
}
}
std::shared_ptr<bridge_domain>
bridge_domain::find_or_add(const bridge_domain& temp)
{
return (m_db.find_or_add(temp.m_id.data(), temp));
}
std::shared_ptr<bridge_domain>
bridge_domain::singular() const
{
return find_or_add(*this);
}
void
bridge_domain::dump(std::ostream& os)
{
m_db.dump(os);
}
void
bridge_domain::event_handler::handle_populate(const client_db::key_t& key)
{
/*
* dump VPP Bridge domains
*/
std::shared_ptr<bridge_domain::dump_cmd> cmd(new bridge_domain::dump_cmd());
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
bridge_domain bd(payload.bd_id);
VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
/*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, bd);
/**
* For each interface in the BD construct an l2_binding
*/
for (unsigned int ii = 0; ii < payload.n_sw_ifs; ii++) {
std::shared_ptr<interface> itf =
interface::find(payload.sw_if_details[ii].sw_if_index);
l2_binding l2(*itf, bd);
OM::commit(key, l2);
}
}
}
bridge_domain::event_handler::event_handler()
{
OM::register_listener(this);
inspect::register_handler({ "bd", "bridge" }, "Bridge Domains", this);
}
void
bridge_domain::event_handler::handle_replay()
{
m_db.replay();
}
dependency_t
bridge_domain::event_handler::order() const
{
return (dependency_t::TABLE);
}
void
bridge_domain::event_handler::show(std::ostream& os)
{
m_db.dump(os);
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,254 @@
/*
* 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.
*/
#ifndef __VOM_BRIDGE_DOMAIN_H__
#define __VOM_BRIDGE_DOMAIN_H__
#include "vom/dump_cmd.hpp"
#include "vom/enum_base.hpp"
#include "vom/hw.hpp"
#include "vom/inspect.hpp"
#include "vom/object_base.hpp"
#include "vom/om.hpp"
#include "vom/rpc_cmd.hpp"
#include "vom/singular_db.hpp"
#include <vapi/l2.api.vapi.hpp>
namespace VOM {
/**
* A base class for all object_base in the VPP object_base-Model.
* provides the abstract interface.
*/
class bridge_domain : public object_base
{
public:
/**
* The value of the defaultbridge domain
*/
const static uint32_t DEFAULT_TABLE = 0;
/**
* Construct a new object matching the desried state
*/
bridge_domain(uint32_t id);
/**
* Copy Constructor
*/
bridge_domain(const bridge_domain& o);
/**
* Destructor
*/
~bridge_domain();
/**
* Return the matchin 'singular' instance of the bridge-domain
*/
std::shared_ptr<bridge_domain> singular() const;
/**
* convert to string format for debug purposes
*/
std::string to_string(void) const;
/**
* Return VPP's handle for this obejct
*/
uint32_t id() const;
/**
* Static function to find the bridge_domain in the model
*/
static std::shared_ptr<bridge_domain> find(uint32_t id);
/**
* Dump all bridge-doamin into the stream provided
*/
static void dump(std::ostream& os);
/**
* A command class that creates an Bridge-Domain
*/
class create_cmd
: public rpc_cmd<HW::item<uint32_t>, rc_t, vapi::Bridge_domain_add_del>
{
public:
/**
* Constructor
*/
create_cmd(HW::item<uint32_t>& item);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const create_cmd& i) const;
};
/**
* A cmd class that Delete an Bridge-Domain
*/
class delete_cmd
: public rpc_cmd<HW::item<uint32_t>, rc_t, vapi::Bridge_domain_add_del>
{
public:
/**
* Constructor
*/
delete_cmd(HW::item<uint32_t>& item);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const delete_cmd& i) const;
};
/**
* A cmd class that Dumps all the IPv4 L3 configs
*/
class dump_cmd : public VOM::dump_cmd<vapi::Bridge_domain_dump>
{
public:
/**
* Constructor
*/
dump_cmd();
dump_cmd(const dump_cmd& d);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const dump_cmd& i) const;
private:
/**
* HW reutrn code
*/
HW::item<bool> item;
};
private:
/**
* Class definition for listeners to OM events
*/
class event_handler : public OM::listener, public inspect::command_handler
{
public:
event_handler();
virtual ~event_handler() = default;
/**
* Handle a populate event
*/
void handle_populate(const client_db::key_t& key);
/**
* Handle a replay event
*/
void handle_replay();
/**
* Show the object in the Singular DB
*/
void show(std::ostream& os);
/**
* Get the sortable Id of the listener
*/
dependency_t order() const;
};
/**
* Instance of the event handler to register with OM
*/
static event_handler m_evh;
/**
* Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
*/
void update(const bridge_domain& obj);
/**
* Find or add an singular of a Bridge-Domain in the object_base Model
*/
static std::shared_ptr<bridge_domain> find_or_add(const bridge_domain& temp);
/*
* It's the OM class that calls singular()
*/
friend class OM;
/**
* It's the singular_db class that calls replay()
*/
friend class singular_db<uint32_t, bridge_domain>;
/**
* Sweep/reap the object if still stale
*/
void sweep(void);
/**
* replay the object to create it in hardware
*/
void replay(void);
/**
* The ID we assign to this BD and the HW result in VPP
*/
HW::item<uint32_t> m_id;
/**
* A map of all interfaces key against the interface's name
*/
static singular_db<uint32_t, bridge_domain> m_db;
};
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,172 @@
/*
* 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/bridge_domain_arp_entry.hpp"
namespace VOM {
singular_db<bridge_domain_arp_entry::key_t, bridge_domain_arp_entry>
bridge_domain_arp_entry::m_db;
bridge_domain_arp_entry::event_handler bridge_domain_arp_entry::m_evh;
bridge_domain_arp_entry::bridge_domain_arp_entry(
const bridge_domain& bd,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr)
: m_hw(false)
, m_bd(bd.singular())
, m_mac(mac)
, m_ip_addr(ip_addr)
{
}
bridge_domain_arp_entry::bridge_domain_arp_entry(
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr)
: m_hw(false)
, m_bd(nullptr)
, m_mac(mac)
, m_ip_addr(ip_addr)
{
/*
* the route goes in the default table
*/
bridge_domain bd(bridge_domain::DEFAULT_TABLE);
m_bd = bd.singular();
}
bridge_domain_arp_entry::bridge_domain_arp_entry(
const bridge_domain_arp_entry& bde)
: m_hw(bde.m_hw)
, m_bd(bde.m_bd)
, m_mac(bde.m_mac)
, m_ip_addr(bde.m_ip_addr)
{
}
bridge_domain_arp_entry::~bridge_domain_arp_entry()
{
sweep();
// not in the DB anymore.
m_db.release(std::make_tuple(m_bd->id(), m_mac, m_ip_addr), this);
}
void
bridge_domain_arp_entry::sweep()
{
if (m_hw) {
HW::enqueue(new delete_cmd(m_hw, m_bd->id(), m_mac, m_ip_addr));
}
HW::write();
}
void
bridge_domain_arp_entry::replay()
{
if (m_hw) {
HW::enqueue(new create_cmd(m_hw, m_bd->id(), m_mac, m_ip_addr));
}
}
std::string
bridge_domain_arp_entry::to_string() const
{
std::ostringstream s;
s << "bridge-domain-arp-entry:[" << m_bd->to_string() << ", "
<< m_mac.to_string() << ", " << m_ip_addr.to_string() << "]";
return (s.str());
}
void
bridge_domain_arp_entry::update(const bridge_domain_arp_entry& r)
{
/*
* create the table if it is not yet created
*/
if (rc_t::OK != m_hw.rc()) {
HW::enqueue(new create_cmd(m_hw, m_bd->id(), m_mac, m_ip_addr));
}
}
std::shared_ptr<bridge_domain_arp_entry>
bridge_domain_arp_entry::find_or_add(const bridge_domain_arp_entry& temp)
{
return (m_db.find_or_add(
std::make_tuple(temp.m_bd->id(), temp.m_mac, temp.m_ip_addr), temp));
}
std::shared_ptr<bridge_domain_arp_entry>
bridge_domain_arp_entry::singular() const
{
return find_or_add(*this);
}
void
bridge_domain_arp_entry::dump(std::ostream& os)
{
m_db.dump(os);
}
std::ostream&
operator<<(std::ostream& os, const bridge_domain_arp_entry::key_t& key)
{
os << "[" << std::get<0>(key) << ", " << std::get<1>(key) << ", "
<< std::get<2>(key) << "]";
return (os);
}
bridge_domain_arp_entry::event_handler::event_handler()
{
OM::register_listener(this);
inspect::register_handler({ "bd-arp" },
"bridge domain ARP termination entries", this);
}
void
bridge_domain_arp_entry::event_handler::handle_replay()
{
m_db.replay();
}
void
bridge_domain_arp_entry::event_handler::handle_populate(
const client_db::key_t& key)
{
}
dependency_t
bridge_domain_arp_entry::event_handler::order() const
{
return (dependency_t::ENTRY);
}
void
bridge_domain_arp_entry::event_handler::show(std::ostream& os)
{
m_db.dump(os);
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

View File

@@ -0,0 +1,260 @@
/*
* 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.
*/
#ifndef __VOM_BRIDGE_DOMAIN_ARP_ENTRY_H__
#define __VOM_BRIDGE_DOMAIN_ARP_ENTRY_H__
#include "vom/bridge_domain.hpp"
#include "vom/interface.hpp"
#include "vom/singular_db.hpp"
#include "vom/types.hpp"
#include <vapi/l2.api.vapi.hpp>
namespace VOM {
/**
* A entry in the ARP termination table of a Bridge Domain
*/
class bridge_domain_arp_entry : public object_base
{
public:
/**
* The key for a bridge_domain ARP entry;
* the BD, IP address and MAC address
*/
typedef std::tuple<uint32_t, mac_address_t, boost::asio::ip::address> key_t;
/**
* Construct a bridge_domain in the given bridge domain
*/
bridge_domain_arp_entry(const bridge_domain& bd,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr);
/**
* Construct a bridge_domain in the default table
*/
bridge_domain_arp_entry(const mac_address_t& mac,
const boost::asio::ip::address& ip_addr);
/**
* Copy Construct
*/
bridge_domain_arp_entry(const bridge_domain_arp_entry& r);
/**
* Destructor
*/
~bridge_domain_arp_entry();
/**
* Return the matching 'singular instance'
*/
std::shared_ptr<bridge_domain_arp_entry> singular() const;
/**
* Find the instnace of the bridge_domain domain in the OM
*/
static std::shared_ptr<bridge_domain_arp_entry> find(
const bridge_domain_arp_entry& temp);
/**
* Dump all bridge_domain-doamin into the stream provided
*/
static void dump(std::ostream& os);
/**
* replay the object to create it in hardware
*/
void replay(void);
/**
* Convert to string for debugging
*/
std::string to_string() const;
/**
* A command class that creates or updates the bridge domain ARP Entry
*/
class create_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Bd_ip_mac_add_del>
{
public:
/**
* Constructor
*/
create_cmd(HW::item<bool>& item,
uint32_t id,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const create_cmd& i) const;
private:
uint32_t m_bd;
mac_address_t m_mac;
boost::asio::ip::address m_ip_addr;
};
/**
* A cmd class that deletes a bridge domain ARP entry
*/
class delete_cmd
: public rpc_cmd<HW::item<bool>, rc_t, vapi::Bd_ip_mac_add_del>
{
public:
/**
* Constructor
*/
delete_cmd(HW::item<bool>& item,
uint32_t id,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
/**
* Comparison operator - only used for UT
*/
bool operator==(const delete_cmd& i) const;
private:
uint32_t m_bd;
mac_address_t m_mac;
boost::asio::ip::address m_ip_addr;
};
private:
/**
* Class definition for listeners to OM events
*/
class event_handler : public OM::listener, public inspect::command_handler
{
public:
event_handler();
virtual ~event_handler() = default;
/**
* Handle a populate event
*/
void handle_populate(const client_db::key_t& key);
/**
* Handle a replay event
*/
void handle_replay();
/**
* Show the object in the Singular DB
*/
void show(std::ostream& os);
/**
* Get the sortable Id of the listener
*/
dependency_t order() const;
};
/**
* event_handler to register with OM
*/
static event_handler m_evh;
/**
* Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
*/
void update(const bridge_domain_arp_entry& obj);
/**
* Find or add the instnace of the bridge_domain domain in the OM
*/
static std::shared_ptr<bridge_domain_arp_entry> find_or_add(
const bridge_domain_arp_entry& temp);
/*
* It's the VPPHW class that updates the objects in HW
*/
friend class OM;
/**
* It's the singular_db class that calls replay()
*/
friend class singular_db<key_t, bridge_domain_arp_entry>;
/**
* Sweep/reap the object if still stale
*/
void sweep(void);
/**
* HW configuration for the result of creating the bridge_domain
*/
HW::item<bool> m_hw;
/**
* The bridge_domain domain the bridge_domain is in.
*/
std::shared_ptr<bridge_domain> m_bd;
/**
* The mac to match
*/
mac_address_t m_mac;
/**
* The IP address
*/
boost::asio::ip::address m_ip_addr;
/**
* A map of all bridge_domains
*/
static singular_db<key_t, bridge_domain_arp_entry> m_db;
};
std::ostream& operator<<(std::ostream& os,
const bridge_domain_arp_entry::key_t& key);
};
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/
#endif

View File

@@ -0,0 +1,124 @@
/*
* 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/bridge_domain_arp_entry.hpp"
namespace VOM {
bridge_domain_arp_entry::create_cmd::create_cmd(
HW::item<bool>& item,
uint32_t bd,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr)
: rpc_cmd(item)
, m_bd(bd)
, m_mac(mac)
, m_ip_addr(ip_addr)
{
}
bool
bridge_domain_arp_entry::create_cmd::operator==(const create_cmd& other) const
{
return ((m_mac == other.m_mac) && (m_ip_addr == other.m_ip_addr) &&
(m_bd == other.m_bd));
}
rc_t
bridge_domain_arp_entry::create_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.bd_id = m_bd;
payload.is_add = 1;
m_mac.to_bytes(payload.mac_address, 6);
to_bytes(m_ip_addr, &payload.is_ipv6, payload.ip_address);
VAPI_CALL(req.execute());
m_hw_item.set(wait());
return rc_t::OK;
}
std::string
bridge_domain_arp_entry::create_cmd::to_string() const
{
std::ostringstream s;
s << "bridge-domain-arp-entry-create: " << m_hw_item.to_string()
<< " bd:" << m_bd << " mac:" << m_mac.to_string()
<< " ip:" << m_ip_addr.to_string();
return (s.str());
}
bridge_domain_arp_entry::delete_cmd::delete_cmd(
HW::item<bool>& item,
uint32_t bd,
const mac_address_t& mac,
const boost::asio::ip::address& ip_addr)
: rpc_cmd(item)
, m_bd(bd)
, m_mac(mac)
, m_ip_addr(ip_addr)
{
}
bool
bridge_domain_arp_entry::delete_cmd::operator==(const delete_cmd& other) const
{
return ((m_mac == other.m_mac) && (m_ip_addr == other.m_ip_addr) &&
(m_bd == other.m_bd));
}
rc_t
bridge_domain_arp_entry::delete_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.bd_id = m_bd;
payload.is_add = 0;
m_mac.to_bytes(payload.mac_address, 6);
to_bytes(m_ip_addr, &payload.is_ipv6, payload.ip_address);
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
return rc_t::OK;
}
std::string
bridge_domain_arp_entry::delete_cmd::to_string() const
{
std::ostringstream s;
s << "bridge-domain-arp-entry-delete: " << m_hw_item.to_string()
<< " bd:" << m_bd << " mac:" << m_mac.to_string()
<< " ip:" << m_ip_addr.to_string();
return (s.str());
}
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "mozilla")
* End:
*/

Some files were not shown because too many files have changed in this diff Show More