2 * Copyright (c) 2018 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include "vom/l2_xconnect.hpp"
17 #include "vom/l2_vtr_cmds.hpp"
18 #include "vom/l2_xconnect_cmds.hpp"
19 #include "vom/singular_db_funcs.hpp"
23 * A DB of all the L2 x-connect Configs
25 singular_db<l2_xconnect::key_t, l2_xconnect> l2_xconnect::m_db;
27 l2_xconnect::event_handler l2_xconnect::m_evh;
30 * Construct a new object matching the desried state
32 l2_xconnect::l2_xconnect(const interface& east_itf, const interface& west_itf)
33 : m_east_itf(east_itf.singular())
34 , m_west_itf(west_itf.singular())
37 , m_vtr_op(l2_vtr::option_t::DISABLED, rc_t::UNSET)
42 l2_xconnect::l2_xconnect(const l2_xconnect& o)
43 : m_east_itf(o.m_east_itf)
44 , m_west_itf(o.m_west_itf)
45 , m_xconnect_east(o.m_xconnect_east)
46 , m_xconnect_west(o.m_xconnect_west)
47 , m_vtr_op(o.m_vtr_op)
48 , m_vtr_op_tag(o.m_vtr_op_tag)
52 const l2_xconnect::key_t
53 l2_xconnect::key() const
55 if (m_east_itf->name() < m_west_itf->name())
56 return (std::make_pair(m_east_itf->key(), m_west_itf->key()));
57 return (std::make_pair(m_west_itf->key(), m_east_itf->key()));
61 l2_xconnect::operator==(const l2_xconnect& l) const
63 return ((*m_east_itf == *l.m_east_itf) && (*m_west_itf == *l.m_west_itf));
66 std::shared_ptr<l2_xconnect>
67 l2_xconnect::find(const key_t& key)
69 return (m_db.find(key));
75 if (m_xconnect_east && m_xconnect_west &&
76 handle_t::INVALID != m_east_itf->handle() &&
77 handle_t::INVALID != m_west_itf->handle()) {
78 HW::enqueue(new l2_xconnect_cmds::unbind_cmd(
79 m_xconnect_east, m_east_itf->handle(), m_west_itf->handle()));
80 HW::enqueue(new l2_xconnect_cmds::unbind_cmd(
81 m_xconnect_west, m_west_itf->handle(), m_east_itf->handle()));
90 if (m_xconnect_east && m_xconnect_west &&
91 handle_t::INVALID != m_east_itf->handle() &&
92 handle_t::INVALID != m_west_itf->handle()) {
93 HW::enqueue(new l2_xconnect_cmds::bind_cmd(
94 m_xconnect_east, m_east_itf->handle(), m_west_itf->handle()));
95 HW::enqueue(new l2_xconnect_cmds::bind_cmd(
96 m_xconnect_west, m_west_itf->handle(), m_east_itf->handle()));
99 if (m_vtr_op && handle_t::INVALID != m_east_itf->handle()) {
101 new l2_vtr_cmds::set_cmd(m_vtr_op, m_east_itf->handle(), m_vtr_op_tag));
105 l2_xconnect::~l2_xconnect()
109 // not in the DB anymore.
110 m_db.release(key(), this);
114 l2_xconnect::to_string() const
116 std::ostringstream s;
117 s << "L2-xconnect:[" << m_east_itf->to_string() << " "
118 << m_west_itf->to_string() << " " << m_xconnect_east.to_string() << " "
119 << m_xconnect_west.to_string() << "]";
125 l2_xconnect::set(const l2_vtr::option_t& op, uint16_t tag)
127 assert(rc_t::UNSET == m_vtr_op.rc());
128 m_vtr_op.set(rc_t::NOOP);
134 l2_xconnect::update(const l2_xconnect& desired)
137 * the desired state is always that the interface should be created
139 if (rc_t::OK != m_xconnect_east.rc() && rc_t::OK != m_xconnect_west.rc()) {
140 HW::enqueue(new l2_xconnect_cmds::bind_cmd(
141 m_xconnect_east, m_east_itf->handle(), m_west_itf->handle()));
142 HW::enqueue(new l2_xconnect_cmds::bind_cmd(
143 m_xconnect_west, m_west_itf->handle(), m_east_itf->handle()));
147 * set the VTR operation if request
149 if (m_vtr_op.update(desired.m_vtr_op)) {
151 new l2_vtr_cmds::set_cmd(m_vtr_op, m_east_itf->handle(), m_vtr_op_tag));
155 std::shared_ptr<l2_xconnect>
156 l2_xconnect::find_or_add(const l2_xconnect& temp)
158 return (m_db.find_or_add(temp.key(), temp));
161 std::shared_ptr<l2_xconnect>
162 l2_xconnect::singular() const
164 return find_or_add(*this);
168 l2_xconnect::dump(std::ostream& os)
173 l2_xconnect::event_handler::event_handler()
175 OM::register_listener(this);
176 inspect::register_handler({ "l2-xconnect" }, "L2 xconnects", this);
180 l2_xconnect::event_handler::handle_replay()
186 l2_xconnect::event_handler::handle_populate(const client_db::key_t& key)
189 * This needs to be done here
191 std::shared_ptr<l2_xconnect_cmds::dump_cmd> cmd =
192 std::make_shared<l2_xconnect_cmds::dump_cmd>();
197 for (auto& x_record : *cmd) {
198 auto& payload = x_record.get_payload();
200 VOM_LOG(log_level_t::DEBUG) << "l2-xconnect dump: "
201 << " east-itf: " << payload.rx_sw_if_index
202 << " west-itf: " << payload.tx_sw_if_index;
204 std::shared_ptr<interface> east_itf =
205 interface::find(payload.rx_sw_if_index);
206 std::shared_ptr<interface> west_itf =
207 interface::find(payload.tx_sw_if_index);
209 if (east_itf && west_itf) {
210 if (east_itf->name() > west_itf->name())
212 l2_xconnect l2_xc(*east_itf, *west_itf);
213 OM::commit(key, l2_xc);
219 l2_xconnect::event_handler::order() const
221 return (dependency_t::BINDING);
225 l2_xconnect::event_handler::show(std::ostream& os)
232 * fd.io coding-style-patch-verification: ON
235 * eval: (c-set-style "mozilla")