VOM: mroutes
- fixes in ip.api for dumping mroute path flags Change-Id: I13b0cfb15d374250ed71bd4e13dda9b798c18204 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
Neale Ranns
committed by
Florin Coras
parent
e26c81fc80
commit
7c03ed47d5
@ -158,6 +158,7 @@ list(APPEND VOM_SOURCES
|
||||
neighbour.cpp
|
||||
neighbour_cmds.cpp
|
||||
object_base.cpp
|
||||
mroute_cmds.cpp
|
||||
om.cpp
|
||||
pipe.cpp
|
||||
pipe_cmds.cpp
|
||||
@ -165,6 +166,7 @@ list(APPEND VOM_SOURCES
|
||||
ra_config.cpp
|
||||
ra_prefix.cpp
|
||||
route.cpp
|
||||
route_api_types.cpp
|
||||
route_cmds.cpp
|
||||
route_domain.cpp
|
||||
route_domain_cmds.cpp
|
||||
|
@ -28,6 +28,21 @@ to_api(const ip_address_t& a, vapi_type_address& v)
|
||||
memcpy(v.un.ip6, a.to_v6().to_bytes().data(), 16);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
to_api(const ip_address_t& a,
|
||||
vapi_union_address_union& u,
|
||||
vapi_enum_address_family& af)
|
||||
{
|
||||
if (a.is_v4()) {
|
||||
af = ADDRESS_IP4;
|
||||
memcpy(u.ip4, a.to_v4().to_bytes().data(), 4);
|
||||
} else {
|
||||
af = ADDRESS_IP6;
|
||||
memcpy(u.ip6, a.to_v6().to_bytes().data(), 16);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
to_api(const boost::asio::ip::address& a, vapi_type_ip4_address& v)
|
||||
{
|
||||
@ -54,6 +69,26 @@ from_api(const vapi_type_address& v)
|
||||
return addr;
|
||||
}
|
||||
|
||||
ip_address_t
|
||||
from_api(const vapi_union_address_union& u, vapi_enum_address_family af)
|
||||
{
|
||||
boost::asio::ip::address addr;
|
||||
|
||||
if (ADDRESS_IP6 == af) {
|
||||
std::array<uint8_t, 16> a;
|
||||
std::copy(u.ip6, u.ip6 + 16, std::begin(a));
|
||||
boost::asio::ip::address_v6 v6(a);
|
||||
addr = v6;
|
||||
} else {
|
||||
std::array<uint8_t, 4> a;
|
||||
std::copy(u.ip6, u.ip6 + 4, std::begin(a));
|
||||
boost::asio::ip::address_v4 v4(a);
|
||||
addr = v4;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
to_api(const mac_address_t& a, vapi_type_mac_address& v)
|
||||
{
|
||||
@ -80,6 +115,25 @@ to_api(const route::prefix_t& p)
|
||||
v.address_length = p.mask_width();
|
||||
return v;
|
||||
}
|
||||
|
||||
route::mprefix_t
|
||||
from_api(const vapi_type_mprefix& v)
|
||||
{
|
||||
return route::mprefix_t(from_api(v.src_address, v.af),
|
||||
from_api(v.grp_address, v.af), v.grp_address_length);
|
||||
}
|
||||
|
||||
vapi_type_mprefix
|
||||
to_api(const route::mprefix_t& p)
|
||||
{
|
||||
vapi_enum_address_family af;
|
||||
vapi_type_mprefix v;
|
||||
to_api(p.grp_address(), v.grp_address, af);
|
||||
to_api(p.src_address(), v.src_address, af);
|
||||
v.grp_address_length = p.mask_width();
|
||||
v.af = af;
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -25,17 +25,24 @@ typedef boost::asio::ip::address ip_address_t;
|
||||
|
||||
void to_api(const ip_address_t& a, vapi_type_address& v);
|
||||
void to_api(const boost::asio::ip::address& a, vapi_type_ip4_address& v);
|
||||
void to_api(const boost::asio::ip::address& a,
|
||||
vapi_union_address_union& u,
|
||||
vapi_enum_address_family& af);
|
||||
|
||||
ip_address_t from_api(const vapi_type_address& v);
|
||||
ip_address_t from_api(const vapi_type_ip4_address& v);
|
||||
ip_address_t from_api(const vapi_union_address_union& u,
|
||||
vapi_enum_address_family af);
|
||||
|
||||
void to_api(const mac_address_t& a, vapi_type_mac_address& m);
|
||||
|
||||
mac_address_t from_api(const vapi_type_mac_address& v);
|
||||
|
||||
route::prefix_t from_api(const vapi_type_prefix&);
|
||||
route::mprefix_t from_api(const vapi_type_mprefix&);
|
||||
|
||||
vapi_type_prefix to_api(const route::prefix_t&);
|
||||
vapi_type_mprefix to_api(const route::mprefix_t&);
|
||||
};
|
||||
|
||||
/*
|
||||
|
193
extras/vom/vom/mroute_cmds.cpp
Normal file
193
extras/vom/vom/mroute_cmds.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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/api_types.hpp"
|
||||
#include "vom/mroute_cmds.hpp"
|
||||
#include "vom/route_api_types.hpp"
|
||||
|
||||
namespace VOM {
|
||||
namespace route {
|
||||
namespace ip_mroute_cmds {
|
||||
|
||||
update_cmd::update_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const mprefix_t& mprefix,
|
||||
const path& path,
|
||||
const itf_flags_t& flags)
|
||||
: rpc_cmd(item)
|
||||
, m_id(id)
|
||||
, m_mprefix(mprefix)
|
||||
, m_path(path)
|
||||
, m_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
update_cmd::operator==(const update_cmd& other) const
|
||||
{
|
||||
return ((m_mprefix == other.m_mprefix) && (m_id == other.m_id));
|
||||
}
|
||||
|
||||
rc_t
|
||||
update_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.table_id = m_id;
|
||||
payload.is_add = 1;
|
||||
|
||||
m_mprefix.to_vpp(&payload.is_ipv6, payload.grp_address, payload.src_address,
|
||||
&payload.grp_address_length);
|
||||
|
||||
to_vpp(m_path, payload);
|
||||
payload.itf_flags = m_flags.value();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
return (wait());
|
||||
}
|
||||
|
||||
std::string
|
||||
update_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "ip-mroute-create: " << m_hw_item.to_string() << " table-id:" << m_id
|
||||
<< " mprefix:" << m_mprefix.to_string() << " path:" << m_path.to_string()
|
||||
<< " flags:" << m_flags;
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const mprefix_t& mprefix,
|
||||
const path& path,
|
||||
const itf_flags_t& flags)
|
||||
: rpc_cmd(item)
|
||||
, m_id(id)
|
||||
, m_mprefix(mprefix)
|
||||
, m_path(path)
|
||||
, m_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
delete_cmd::operator==(const delete_cmd& other) const
|
||||
{
|
||||
return ((m_mprefix == other.m_mprefix) && (m_id == other.m_id));
|
||||
}
|
||||
|
||||
rc_t
|
||||
delete_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.table_id = m_id;
|
||||
payload.is_add = 0;
|
||||
|
||||
m_mprefix.to_vpp(&payload.is_ipv6, payload.grp_address, payload.src_address,
|
||||
&payload.grp_address_length);
|
||||
|
||||
to_vpp(m_path, payload);
|
||||
payload.itf_flags = m_flags.value();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
wait();
|
||||
m_hw_item.set(rc_t::NOOP);
|
||||
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
delete_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "ip-mroute-delete: " << m_hw_item.to_string() << " id:" << m_id
|
||||
<< " mprefix:" << m_mprefix.to_string();
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
dump_v4_cmd::dump_v4_cmd()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v4_cmd::operator==(const dump_v4_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v4_cmd::issue(connection& con)
|
||||
{
|
||||
m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
|
||||
|
||||
VAPI_CALL(m_dump->execute());
|
||||
|
||||
wait();
|
||||
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
dump_v4_cmd::to_string() const
|
||||
{
|
||||
return ("ip-mroute-v4-dump");
|
||||
}
|
||||
|
||||
dump_v6_cmd::dump_v6_cmd()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v6_cmd::operator==(const dump_v6_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v6_cmd::issue(connection& con)
|
||||
{
|
||||
m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
|
||||
|
||||
VAPI_CALL(m_dump->execute());
|
||||
|
||||
wait();
|
||||
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
dump_v6_cmd::to_string() const
|
||||
{
|
||||
return ("ip-mroute-v6-dump");
|
||||
}
|
||||
} // namespace ip_mroute_cmds
|
||||
} // namespace mroute
|
||||
} // namespace vom
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
181
extras/vom/vom/mroute_cmds.hpp
Normal file
181
extras/vom/vom/mroute_cmds.hpp
Normal 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_MROUTE_CMDS_H__
|
||||
#define __VOM_MROUTE_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/route.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
#include <vapi/ip.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace route {
|
||||
namespace ip_mroute_cmds {
|
||||
|
||||
/**
|
||||
* A command class that creates or updates the route
|
||||
*/
|
||||
class update_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_mroute_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
update_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const mprefix_t& mprefix,
|
||||
const path& path,
|
||||
const itf_flags_t& flags);
|
||||
|
||||
/**
|
||||
* 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 update_cmd& i) const;
|
||||
|
||||
private:
|
||||
route::table_id_t m_id;
|
||||
mprefix_t m_mprefix;
|
||||
const path m_path;
|
||||
const itf_flags_t& m_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that deletes a route
|
||||
*/
|
||||
class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_mroute_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const mprefix_t& mprefix,
|
||||
const path& path,
|
||||
const itf_flags_t& flags);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
route::table_id_t m_id;
|
||||
mprefix_t m_mprefix;
|
||||
const path m_path;
|
||||
const itf_flags_t& m_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps ipv4 fib
|
||||
*/
|
||||
class dump_v4_cmd : public VOM::dump_cmd<vapi::Ip_mfib_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v4_cmd();
|
||||
dump_v4_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_v4_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps ipv6 fib
|
||||
*/
|
||||
class dump_v6_cmd : public VOM::dump_cmd<vapi::Ip6_mfib_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v6_cmd();
|
||||
dump_v6_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_v6_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
};
|
||||
|
||||
}; // namespace ip_mroute_cmds
|
||||
}; // namespace route
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
@ -190,7 +190,7 @@ route::prefix_t::to_string() const
|
||||
}
|
||||
|
||||
boost::asio::ip::address
|
||||
from_bytes(uint8_t is_ip6, uint8_t* bytes)
|
||||
from_bytes(uint8_t is_ip6, const uint8_t* bytes)
|
||||
{
|
||||
boost::asio::ip::address addr;
|
||||
|
||||
@ -420,6 +420,135 @@ route::prefix_t::high() const
|
||||
return (pfx);
|
||||
}
|
||||
|
||||
/**
|
||||
* The all Zeros prefix
|
||||
*/
|
||||
const route::mprefix_t route::mprefix_t::ZERO;
|
||||
const route::mprefix_t route::mprefix_t::ZEROv6;
|
||||
|
||||
route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len)
|
||||
: m_gaddr(gaddr)
|
||||
, m_saddr()
|
||||
, m_len(len)
|
||||
{
|
||||
}
|
||||
|
||||
route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr)
|
||||
: m_gaddr(gaddr)
|
||||
, m_saddr()
|
||||
, m_len(VOM::mask_width(gaddr))
|
||||
{
|
||||
}
|
||||
|
||||
route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
|
||||
const boost::asio::ip::address& gaddr)
|
||||
: m_gaddr(gaddr)
|
||||
, m_saddr(saddr)
|
||||
, m_len(2 * VOM::mask_width(gaddr))
|
||||
{
|
||||
}
|
||||
|
||||
route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
|
||||
const boost::asio::ip::address& gaddr,
|
||||
uint16_t len)
|
||||
: m_gaddr(gaddr)
|
||||
, m_saddr(saddr)
|
||||
, m_len(len)
|
||||
{
|
||||
}
|
||||
|
||||
route::mprefix_t::mprefix_t(const mprefix_t& o)
|
||||
: m_gaddr(o.m_gaddr)
|
||||
, m_saddr(o.m_saddr)
|
||||
, m_len(o.m_len)
|
||||
{
|
||||
}
|
||||
route::mprefix_t::mprefix_t()
|
||||
: m_gaddr()
|
||||
, m_saddr()
|
||||
, m_len(0)
|
||||
{
|
||||
}
|
||||
|
||||
route::mprefix_t::~mprefix_t()
|
||||
{
|
||||
}
|
||||
|
||||
const boost::asio::ip::address&
|
||||
route::mprefix_t::grp_address() const
|
||||
{
|
||||
return (m_gaddr);
|
||||
}
|
||||
|
||||
const boost::asio::ip::address&
|
||||
route::mprefix_t::src_address() const
|
||||
{
|
||||
return (m_saddr);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
route::mprefix_t::mask_width() const
|
||||
{
|
||||
return (m_len);
|
||||
}
|
||||
|
||||
void
|
||||
route::mprefix_t::to_vpp(uint8_t* is_ip6,
|
||||
uint8_t* saddr,
|
||||
uint8_t* gaddr,
|
||||
uint16_t* len) const
|
||||
{
|
||||
*len = m_len;
|
||||
to_bytes(m_saddr, is_ip6, saddr);
|
||||
to_bytes(m_gaddr, is_ip6, gaddr);
|
||||
}
|
||||
|
||||
route::mprefix_t&
|
||||
route::mprefix_t::operator=(const route::mprefix_t& o)
|
||||
{
|
||||
m_gaddr = o.m_gaddr;
|
||||
m_saddr = o.m_saddr;
|
||||
m_len = o.m_len;
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
bool
|
||||
route::mprefix_t::operator<(const route::mprefix_t& o) const
|
||||
{
|
||||
if (m_len == o.m_len) {
|
||||
if (m_saddr == o.m_saddr)
|
||||
return (m_gaddr < o.m_gaddr);
|
||||
else
|
||||
return (m_saddr < o.m_saddr);
|
||||
} else {
|
||||
return (m_len < o.m_len);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
route::mprefix_t::operator==(const route::mprefix_t& o) const
|
||||
{
|
||||
return (m_len == o.m_len && m_gaddr == o.m_gaddr && m_saddr == o.m_saddr);
|
||||
}
|
||||
|
||||
bool
|
||||
route::mprefix_t::operator!=(const route::mprefix_t& o) const
|
||||
{
|
||||
return (!(*this == o));
|
||||
}
|
||||
|
||||
std::string
|
||||
route::mprefix_t::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
s << "(" << m_saddr.to_string() << "," << m_gaddr.to_string() << "/"
|
||||
<< std::to_string(m_len) << ")";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
|
@ -171,8 +171,8 @@ public:
|
||||
const static prefix_t ZEROv6;
|
||||
|
||||
/**
|
||||
* Convert the prefix into VPP API parameters
|
||||
*/
|
||||
* Convert the prefix into VPP API parameters
|
||||
*/
|
||||
void to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const;
|
||||
|
||||
/**
|
||||
@ -206,8 +206,120 @@ private:
|
||||
*/
|
||||
uint8_t m_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* A prefix defintion. Address + length
|
||||
*/
|
||||
class mprefix_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default Constructor - creates ::/0
|
||||
*/
|
||||
mprefix_t();
|
||||
/**
|
||||
* Constructor for (S,G)
|
||||
*/
|
||||
mprefix_t(const boost::asio::ip::address& saddr,
|
||||
const boost::asio::ip::address& gaddr);
|
||||
/*
|
||||
* Constructor for (*,G)
|
||||
*/
|
||||
mprefix_t(const boost::asio::ip::address& gaddr);
|
||||
|
||||
/*
|
||||
* Constructor for (*,G/n)
|
||||
*/
|
||||
mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len);
|
||||
|
||||
/**
|
||||
*Constructor for (S,G)
|
||||
*/
|
||||
mprefix_t(const boost::asio::ip::address& saddr,
|
||||
const boost::asio::ip::address& gaddr,
|
||||
uint16_t len);
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*/
|
||||
mprefix_t(const mprefix_t&);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~mprefix_t();
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*/
|
||||
const boost::asio::ip::address& grp_address() const;
|
||||
const boost::asio::ip::address& src_address() const;
|
||||
|
||||
/**
|
||||
* Get the network mask width
|
||||
*/
|
||||
uint8_t mask_width() const;
|
||||
|
||||
/**
|
||||
* Assignement
|
||||
*/
|
||||
mprefix_t& operator=(const mprefix_t&);
|
||||
|
||||
/**
|
||||
* Less than operator
|
||||
*/
|
||||
bool operator<(const mprefix_t& o) const;
|
||||
|
||||
/**
|
||||
* equals operator
|
||||
*/
|
||||
bool operator==(const mprefix_t& o) const;
|
||||
|
||||
/**
|
||||
* not equal opartor
|
||||
*/
|
||||
bool operator!=(const mprefix_t& o) const;
|
||||
|
||||
/**
|
||||
* convert to string format for debug purposes
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* The all Zeros prefix
|
||||
*/
|
||||
const static mprefix_t ZERO;
|
||||
|
||||
/**
|
||||
* The all Zeros v6 prefix
|
||||
*/
|
||||
const static mprefix_t ZEROv6;
|
||||
|
||||
/**
|
||||
* Get the L3 protocol
|
||||
*/
|
||||
l3_proto_t l3_proto() const;
|
||||
|
||||
void to_vpp(uint8_t* is_ip6,
|
||||
uint8_t* saddr,
|
||||
uint8_t* gaddr,
|
||||
uint16_t* len) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The address
|
||||
*/
|
||||
boost::asio::ip::address m_gaddr;
|
||||
boost::asio::ip::address m_saddr;
|
||||
|
||||
/**
|
||||
* The prefix length
|
||||
*/
|
||||
uint8_t m_len;
|
||||
};
|
||||
|
||||
}; // namespace route
|
||||
|
||||
boost::asio::ip::address_v4 operator|(const boost::asio::ip::address_v4& addr1,
|
||||
const boost::asio::ip::address_v4& addr2);
|
||||
|
||||
@ -254,7 +366,7 @@ uint32_t mask_width(const boost::asio::ip::address& addr);
|
||||
/**
|
||||
* Convert a VPP byte stinrg into a boost addresss
|
||||
*/
|
||||
boost::asio::ip::address from_bytes(uint8_t is_ip6, uint8_t* array);
|
||||
boost::asio::ip::address from_bytes(uint8_t is_ip6, const uint8_t* array);
|
||||
};
|
||||
|
||||
/*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -204,15 +204,44 @@ private:
|
||||
uint8_t m_preference;
|
||||
};
|
||||
|
||||
class itf_flags_t : public enum_base<itf_flags_t>
|
||||
{
|
||||
public:
|
||||
const static itf_flags_t NONE;
|
||||
/**
|
||||
* Path is accepting multicast traffic
|
||||
*/
|
||||
const static itf_flags_t ACCEPT;
|
||||
|
||||
/**
|
||||
* A local/for-us/recieve
|
||||
*/
|
||||
const static itf_flags_t FORWARD;
|
||||
|
||||
static const itf_flags_t& from_vpp(uint32_t val);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Private constructor taking the value and the string name
|
||||
*/
|
||||
itf_flags_t(int v, const std::string& s);
|
||||
};
|
||||
|
||||
/**
|
||||
* A path-list is a set of paths
|
||||
*/
|
||||
typedef std::set<path> path_list_t;
|
||||
|
||||
/**
|
||||
* A mpath-list is a set of paths and interface flags
|
||||
*/
|
||||
typedef std::set<std::pair<path, itf_flags_t>> mpath_list_t;
|
||||
|
||||
/**
|
||||
* ostream output for iterator
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os, const path_list_t& path_list);
|
||||
std::ostream& operator<<(std::ostream& os, const mpath_list_t& path_list);
|
||||
|
||||
/**
|
||||
* A IP route
|
||||
@ -392,9 +421,170 @@ private:
|
||||
static singular_db<key_t, ip_route> m_db;
|
||||
};
|
||||
|
||||
/**
|
||||
* A IP multicast route
|
||||
*/
|
||||
class ip_mroute : public object_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The key for a route
|
||||
*/
|
||||
typedef std::pair<route::table_id_t, mprefix_t> key_t;
|
||||
|
||||
/**
|
||||
* Construct a route in the default table
|
||||
*/
|
||||
ip_mroute(const mprefix_t& mprefix);
|
||||
|
||||
/**
|
||||
* Copy Construct
|
||||
*/
|
||||
ip_mroute(const ip_mroute& r);
|
||||
|
||||
/**
|
||||
* Construct a route in the given route domain
|
||||
*/
|
||||
ip_mroute(const route_domain& rd, const mprefix_t& mprefix);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ip_mroute();
|
||||
|
||||
/**
|
||||
* Get the route's key
|
||||
*/
|
||||
const key_t key() const;
|
||||
|
||||
/**
|
||||
* Comparison operator
|
||||
*/
|
||||
bool operator==(const ip_mroute& i) const;
|
||||
|
||||
/**
|
||||
* Return the matching 'singular instance'
|
||||
*/
|
||||
std::shared_ptr<ip_mroute> singular() const;
|
||||
|
||||
/**
|
||||
* Find the instnace of the route domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<ip_mroute> find(const ip_mroute& temp);
|
||||
|
||||
/**
|
||||
* Dump all route-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;
|
||||
|
||||
/**
|
||||
* Return the matching 'singular instance'
|
||||
*/
|
||||
static std::shared_ptr<ip_mroute> find(const key_t& k);
|
||||
|
||||
void add(const path& path, const itf_flags_t& flag);
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Find or add the instnace of the route domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<ip_mroute> find_or_add(const ip_mroute& temp);
|
||||
|
||||
/*
|
||||
* It's the OM class that updates the objects in HW
|
||||
*/
|
||||
friend class VOM::OM;
|
||||
|
||||
/**
|
||||
* It's the singular_db class that calls replay()
|
||||
*/
|
||||
friend class singular_db<key_t, ip_mroute>;
|
||||
|
||||
/**
|
||||
* Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
|
||||
*/
|
||||
void update(const ip_mroute& obj);
|
||||
|
||||
/**
|
||||
* Sweep/reap the object if still stale
|
||||
*/
|
||||
void sweep(void);
|
||||
|
||||
/**
|
||||
* HW configuration for the result of creating the route
|
||||
*/
|
||||
HW::item<bool> m_hw;
|
||||
|
||||
/**
|
||||
* The route domain the route is in.
|
||||
*/
|
||||
std::shared_ptr<route_domain> m_rd;
|
||||
|
||||
/**
|
||||
* The mprefix to match
|
||||
*/
|
||||
mprefix_t m_mprefix;
|
||||
|
||||
/**
|
||||
* The set of paths
|
||||
*/
|
||||
mpath_list_t m_paths;
|
||||
|
||||
/**
|
||||
* A map of all routes
|
||||
*/
|
||||
static singular_db<key_t, ip_mroute> m_db;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ip_route::key_t& key);
|
||||
};
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, const ip_mroute::key_t& key);
|
||||
}; // namespace route
|
||||
}; // namesapce VPP
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
119
extras/vom/vom/route_api_types.cpp
Normal file
119
extras/vom/vom/route_api_types.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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/route.hpp>
|
||||
#include <vom/route_api_types.hpp>
|
||||
|
||||
namespace VOM {
|
||||
|
||||
void
|
||||
to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload)
|
||||
{
|
||||
payload.is_drop = 0;
|
||||
payload.is_unreach = 0;
|
||||
payload.is_prohibit = 0;
|
||||
payload.is_local = 0;
|
||||
payload.is_classify = 0;
|
||||
payload.is_multipath = 0;
|
||||
payload.is_resolve_host = 0;
|
||||
payload.is_resolve_attached = 0;
|
||||
|
||||
if (route::path::flags_t::DVR & p.flags()) {
|
||||
payload.is_dvr = 1;
|
||||
}
|
||||
|
||||
if (route::path::special_t::STANDARD == p.type()) {
|
||||
uint8_t path_v6;
|
||||
to_bytes(p.nh(), &path_v6, payload.next_hop_address);
|
||||
|
||||
if (p.rd()) {
|
||||
payload.next_hop_table_id = p.rd()->table_id();
|
||||
}
|
||||
if (p.itf()) {
|
||||
payload.next_hop_sw_if_index = p.itf()->handle().value();
|
||||
}
|
||||
} else if (route::path::special_t::DROP == p.type()) {
|
||||
payload.is_drop = 1;
|
||||
} else if (route::path::special_t::UNREACH == p.type()) {
|
||||
payload.is_unreach = 1;
|
||||
} else if (route::path::special_t::PROHIBIT == p.type()) {
|
||||
payload.is_prohibit = 1;
|
||||
} else if (route::path::special_t::LOCAL == p.type()) {
|
||||
payload.is_local = 1;
|
||||
}
|
||||
payload.next_hop_weight = p.weight();
|
||||
payload.next_hop_preference = p.preference();
|
||||
payload.next_hop_via_label = 0;
|
||||
payload.classify_table_index = 0;
|
||||
}
|
||||
|
||||
void
|
||||
to_vpp(const route::path& p, vapi_payload_ip_mroute_add_del& payload)
|
||||
{
|
||||
if (route::path::special_t::STANDARD == p.type()) {
|
||||
uint8_t path_v6;
|
||||
to_bytes(p.nh(), &path_v6, payload.nh_address);
|
||||
|
||||
if (p.itf()) {
|
||||
payload.next_hop_sw_if_index = p.itf()->handle().value();
|
||||
}
|
||||
|
||||
payload.next_hop_afi = p.nh_proto();
|
||||
}
|
||||
}
|
||||
|
||||
route::path
|
||||
from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nhp)
|
||||
{
|
||||
if (p.is_local) {
|
||||
return route::path(route::path::special_t::LOCAL);
|
||||
} else if (p.is_drop) {
|
||||
return route::path(route::path::special_t::DROP);
|
||||
} else if (p.is_unreach) {
|
||||
return route::path(route::path::special_t::UNREACH);
|
||||
} else if (p.is_prohibit) {
|
||||
return route::path(route::path::special_t::PROHIBIT);
|
||||
} else {
|
||||
boost::asio::ip::address address =
|
||||
from_bytes(nh_proto_t::IPV6 == nhp, p.next_hop);
|
||||
std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
|
||||
if (itf) {
|
||||
if (p.is_dvr) {
|
||||
return route::path(*itf, nhp, route::path::flags_t::DVR, p.weight,
|
||||
p.preference);
|
||||
} else {
|
||||
return route::path(address, *itf, p.weight, p.preference);
|
||||
}
|
||||
} else {
|
||||
std::shared_ptr<route_domain> rd = route_domain::find(p.table_id);
|
||||
if (rd) {
|
||||
return route::path(*rd, address, p.weight, p.preference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOM_LOG(log_level_t::ERROR) << "cannot decode: ";
|
||||
|
||||
return route::path(route::path::special_t::DROP);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
35
extras/vom/vom/route_api_types.hpp
Normal file
35
extras/vom/vom/route_api_types.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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/route.hpp>
|
||||
|
||||
#include <vapi/ip.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
|
||||
void to_vpp(const route::path& p, vapi_payload_ip_mroute_add_del& payload);
|
||||
void to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload);
|
||||
|
||||
route::path from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nh);
|
||||
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
@ -15,53 +15,13 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "vom/route_cmds.hpp"
|
||||
#include <vom/route_api_types.hpp>
|
||||
#include <vom/route_cmds.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace route {
|
||||
namespace ip_route_cmds {
|
||||
|
||||
static void
|
||||
to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload)
|
||||
{
|
||||
payload.is_drop = 0;
|
||||
payload.is_unreach = 0;
|
||||
payload.is_prohibit = 0;
|
||||
payload.is_local = 0;
|
||||
payload.is_classify = 0;
|
||||
payload.is_multipath = 0;
|
||||
payload.is_resolve_host = 0;
|
||||
payload.is_resolve_attached = 0;
|
||||
|
||||
if (route::path::flags_t::DVR & p.flags()) {
|
||||
payload.is_dvr = 1;
|
||||
}
|
||||
|
||||
if (route::path::special_t::STANDARD == p.type()) {
|
||||
uint8_t path_v6;
|
||||
to_bytes(p.nh(), &path_v6, payload.next_hop_address);
|
||||
|
||||
if (p.rd()) {
|
||||
payload.next_hop_table_id = p.rd()->table_id();
|
||||
}
|
||||
if (p.itf()) {
|
||||
payload.next_hop_sw_if_index = p.itf()->handle().value();
|
||||
}
|
||||
} else if (route::path::special_t::DROP == p.type()) {
|
||||
payload.is_drop = 1;
|
||||
} else if (route::path::special_t::UNREACH == p.type()) {
|
||||
payload.is_unreach = 1;
|
||||
} else if (route::path::special_t::PROHIBIT == p.type()) {
|
||||
payload.is_prohibit = 1;
|
||||
} else if (route::path::special_t::LOCAL == p.type()) {
|
||||
payload.is_local = 1;
|
||||
}
|
||||
payload.next_hop_weight = p.weight();
|
||||
payload.next_hop_preference = p.preference();
|
||||
payload.next_hop_via_label = 0;
|
||||
payload.classify_table_index = 0;
|
||||
}
|
||||
|
||||
update_cmd::update_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const prefix_t& prefix,
|
||||
|
@ -528,6 +528,10 @@ typedef struct fib_route_path_t_ {
|
||||
* Exclusive DPO
|
||||
*/
|
||||
dpo_id_t dpo;
|
||||
/**
|
||||
* MFIB interface flags
|
||||
*/
|
||||
u32 frp_mitf_flags;
|
||||
};
|
||||
/**
|
||||
* A path that resolves via a BIER Table.
|
||||
|
@ -502,6 +502,12 @@ define ip_mfib_dump
|
||||
@param count - the number of fib_path in path
|
||||
@param path - array of of fib_path structures
|
||||
*/
|
||||
typedef mfib_path
|
||||
{
|
||||
vl_api_fib_path_t path;
|
||||
u32 itf_flags;
|
||||
};
|
||||
|
||||
manual_endian manual_print define ip_mfib_details
|
||||
{
|
||||
u32 context;
|
||||
@ -513,7 +519,7 @@ manual_endian manual_print define ip_mfib_details
|
||||
u8 src_address[4];
|
||||
u32 count;
|
||||
u32 stats_index;
|
||||
vl_api_fib_path_t path[count];
|
||||
vl_api_mfib_path_t path[count];
|
||||
};
|
||||
|
||||
/** \brief Dump IP6 multicast fib table
|
||||
@ -541,7 +547,7 @@ manual_endian manual_print define ip6_mfib_details
|
||||
u8 grp_address[16];
|
||||
u8 src_address[16];
|
||||
u32 count;
|
||||
vl_api_fib_path_t path[count];
|
||||
vl_api_mfib_path_t path[count];
|
||||
};
|
||||
|
||||
define ip_address_details
|
||||
|
@ -410,7 +410,7 @@ send_ip_mfib_details (vl_api_registration_t * reg,
|
||||
vl_api_ip_mfib_details_t *mp;
|
||||
const mfib_prefix_t *pfx;
|
||||
mfib_entry_t *mfib_entry;
|
||||
vl_api_fib_path_t *fp;
|
||||
vl_api_mfib_path_t *fp;
|
||||
int path_count;
|
||||
|
||||
mfib_entry = mfib_entry_get (mfei);
|
||||
@ -438,7 +438,8 @@ send_ip_mfib_details (vl_api_registration_t * reg,
|
||||
fp = mp->path;
|
||||
vec_foreach (api_rpath, api_rpaths)
|
||||
{
|
||||
fib_api_path_encode (api_rpath, fp);
|
||||
fib_api_path_encode (api_rpath, &fp->path);
|
||||
fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags);
|
||||
fp++;
|
||||
}
|
||||
vec_free (api_rpaths);
|
||||
@ -508,7 +509,7 @@ send_ip6_mfib_details (vpe_api_main_t * am,
|
||||
{
|
||||
vl_api_ip6_mfib_details_t *mp;
|
||||
fib_route_path_encode_t *api_rpath;
|
||||
vl_api_fib_path_t *fp;
|
||||
vl_api_mfib_path_t *fp;
|
||||
int path_count;
|
||||
|
||||
path_count = vec_len (api_rpaths);
|
||||
@ -530,7 +531,8 @@ send_ip6_mfib_details (vpe_api_main_t * am,
|
||||
fp = mp->path;
|
||||
vec_foreach (api_rpath, api_rpaths)
|
||||
{
|
||||
fib_api_path_encode (api_rpath, fp);
|
||||
fib_api_path_encode (api_rpath, &fp->path);
|
||||
fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags);
|
||||
fp++;
|
||||
}
|
||||
|
||||
|
@ -1325,6 +1325,7 @@ void
|
||||
mfib_entry_encode (fib_node_index_t mfib_entry_index,
|
||||
fib_route_path_encode_t **api_rpaths)
|
||||
{
|
||||
fib_route_path_encode_t *api_rpath;
|
||||
mfib_entry_t *mfib_entry;
|
||||
mfib_entry_src_t *bsrc;
|
||||
|
||||
@ -1338,6 +1339,18 @@ mfib_entry_encode (fib_node_index_t mfib_entry_index,
|
||||
fib_path_encode,
|
||||
api_rpaths);
|
||||
}
|
||||
|
||||
vec_foreach(api_rpath, *api_rpaths)
|
||||
{
|
||||
mfib_itf_t *mfib_itf;
|
||||
|
||||
mfib_itf = mfib_entry_itf_find(bsrc->mfes_itfs,
|
||||
api_rpath->rpath.frp_sw_if_index);
|
||||
if (mfib_itf)
|
||||
{
|
||||
api_rpath->rpath.frp_mitf_flags = mfib_itf->mfi_flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mfib_prefix_t *
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "vom/prefix.hpp"
|
||||
#include "vom/route.hpp"
|
||||
#include "vom/route_cmds.hpp"
|
||||
#include "vom/mroute_cmds.hpp"
|
||||
#include "vom/route_domain.hpp"
|
||||
#include "vom/route_domain_cmds.hpp"
|
||||
#include "vom/vxlan_tunnel.hpp"
|
||||
@ -251,6 +252,14 @@ public:
|
||||
{
|
||||
rc = handle_derived<route::ip_route_cmds::delete_cmd>(f_exp, f_act);
|
||||
}
|
||||
else if (typeid(*f_exp) == typeid(route::ip_mroute_cmds::update_cmd))
|
||||
{
|
||||
rc = handle_derived<route::ip_mroute_cmds::update_cmd>(f_exp, f_act);
|
||||
}
|
||||
else if (typeid(*f_exp) == typeid(route::ip_mroute_cmds::delete_cmd))
|
||||
{
|
||||
rc = handle_derived<route::ip_mroute_cmds::delete_cmd>(f_exp, f_act);
|
||||
}
|
||||
else if (typeid(*f_exp) == typeid(neighbour_cmds::create_cmd))
|
||||
{
|
||||
rc = handle_derived<neighbour_cmds::create_cmd>(f_exp, f_act);
|
||||
@ -1762,6 +1771,26 @@ BOOST_AUTO_TEST_CASE(test_routing) {
|
||||
ADD_EXPECT(route::ip_route_cmds::update_cmd(hw_route_dvr, 0, pfx_6, {*path_l2}));
|
||||
TRY_CHECK_RC(OM::write(ian, *route_dvr));
|
||||
|
||||
/*
|
||||
* a multicast route
|
||||
*/
|
||||
route::mprefix_t mpfx_4(boost::asio::ip::address::from_string("232.1.1.1"), 32);
|
||||
route::ip_mroute *mroute_4 = new route::ip_mroute(mpfx_4);
|
||||
|
||||
route::path *mp1 = new route::path(itf1, nh_proto_t::IPV4);
|
||||
route::path *mp2 = new route::path(*itf2, nh_proto_t::IPV4);
|
||||
mroute_4->add(*mp1, route::itf_flags_t::FORWARD);
|
||||
mroute_4->add(*mp1, route::itf_flags_t::ACCEPT);
|
||||
mroute_4->add(*mp2, route::itf_flags_t::FORWARD);
|
||||
HW::item<bool> hw_mroute_4(true, rc_t::OK);
|
||||
ADD_EXPECT(route::ip_mroute_cmds::update_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp1, route::itf_flags_t::FORWARD));
|
||||
ADD_EXPECT(route::ip_mroute_cmds::update_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp2, route::itf_flags_t::FORWARD));
|
||||
ADD_EXPECT(route::ip_mroute_cmds::update_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp1, route::itf_flags_t::ACCEPT));
|
||||
TRY_CHECK_RC(OM::write(ian, *mroute_4));
|
||||
|
||||
STRICT_ORDER_OFF();
|
||||
// delete the stack objects that hold references to others
|
||||
// so the OM::remove is the call that removes the last reference
|
||||
@ -1775,6 +1804,18 @@ BOOST_AUTO_TEST_CASE(test_routing) {
|
||||
delete route_dvr;
|
||||
delete path_l2;
|
||||
delete ne;
|
||||
delete mroute_4;
|
||||
|
||||
ADD_EXPECT(route::ip_mroute_cmds::delete_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp1, route::itf_flags_t::FORWARD));
|
||||
ADD_EXPECT(route::ip_mroute_cmds::delete_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp2, route::itf_flags_t::FORWARD));
|
||||
ADD_EXPECT(route::ip_mroute_cmds::delete_cmd(hw_mroute_4, 0, mpfx_4,
|
||||
*mp1, route::itf_flags_t::ACCEPT));
|
||||
|
||||
delete mp1;
|
||||
delete mp2;
|
||||
|
||||
ADD_EXPECT(neighbour_cmds::delete_cmd(hw_neighbour, hw_ifh.data(), mac_n, nh_10));
|
||||
ADD_EXPECT(route::ip_route_cmds::delete_cmd(hw_route_dvr, 0, pfx_6));
|
||||
ADD_EXPECT(route::ip_route_cmds::delete_cmd(hw_route_5_2, 1, pfx_5));
|
||||
|
Reference in New Issue
Block a user