blob: 7079021ee6e16f8dc4cbcaad9e62b1297f224263 [file] [log] [blame]
Neale Ranns812ed392017-10-16 04:20:13 -07001/*
2 * Copyright (c) 2017 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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
15
16#include "vom/vxlan_tunnel.hpp"
17#include "vom/logger.hpp"
18
19namespace VOM {
20const std::string VXLAN_TUNNEL_NAME = "vxlan-tunnel-itf";
21
22vxlan_tunnel::event_handler vxlan_tunnel::m_evh;
23
24/**
25 * A DB of all vxlan_tunnels
26 * this does not register as a listener for replay events, since the tunnels
27 * are also in the base-class interface DB and so will be poked from there.
28 */
29singular_db<vxlan_tunnel::endpoint_t, vxlan_tunnel> vxlan_tunnel::m_db;
30
31vxlan_tunnel::endpoint_t::endpoint_t(const boost::asio::ip::address& src,
32 const boost::asio::ip::address& dst,
33 uint32_t vni)
34 : src(src)
35 , dst(dst)
36 , vni(vni)
37{
38}
39
40vxlan_tunnel::endpoint_t::endpoint_t()
41 : src()
42 , dst()
43 , vni(0)
44{
45}
46
47bool
48vxlan_tunnel::endpoint_t::operator==(const endpoint_t& other) const
49{
50 return ((src == other.src) && (dst == other.dst) && (vni == other.vni));
51}
52
53bool
54vxlan_tunnel::endpoint_t::operator<(const vxlan_tunnel::endpoint_t& o) const
55{
56 if (src < o.src)
57 return true;
58 if (dst < o.dst)
59 return true;
60 if (vni < o.vni)
61 return true;
62
63 return false;
64}
65
66std::string
67vxlan_tunnel::endpoint_t::to_string() const
68{
69 std::ostringstream s;
70
71 s << "ep:["
72 << "src:" << src.to_string() << " dst:" << dst.to_string() << " vni:" << vni
73 << "]";
74
75 return (s.str());
76}
77
78std::ostream&
79operator<<(std::ostream& os, const vxlan_tunnel::endpoint_t& ep)
80{
81 os << ep.to_string();
82
83 return (os);
84}
85
86std::string
87vxlan_tunnel::mk_name(const boost::asio::ip::address& src,
88 const boost::asio::ip::address& dst,
89 uint32_t vni)
90{
91 std::ostringstream s;
92
93 s << VXLAN_TUNNEL_NAME << "-" << src << "-" << dst << ":" << vni;
94
95 return (s.str());
96}
97
98vxlan_tunnel::vxlan_tunnel(const boost::asio::ip::address& src,
99 const boost::asio::ip::address& dst,
100 uint32_t vni)
101 : interface(mk_name(src, dst, vni),
102 interface::type_t::VXLAN,
103 interface::admin_state_t::UP)
104 , m_tep(src, dst, vni)
105{
106}
107
108vxlan_tunnel::vxlan_tunnel(const handle_t& hdl,
109 const boost::asio::ip::address& src,
110 const boost::asio::ip::address& dst,
111 uint32_t vni)
112 : interface(hdl,
113 l2_address_t::ZERO,
114 mk_name(src, dst, vni),
115 interface::type_t::VXLAN,
116 interface::admin_state_t::UP)
117 , m_tep(src, dst, vni)
118{
119}
120
121vxlan_tunnel::vxlan_tunnel(const vxlan_tunnel& o)
122 : interface(o)
123 , m_tep(o.m_tep)
124{
125}
126
127const handle_t&
128vxlan_tunnel::handle() const
129{
130 return (m_hdl.data());
131}
132
133void
134vxlan_tunnel::sweep()
135{
136 if (m_hdl) {
137 HW::enqueue(new delete_cmd(m_hdl, m_tep));
138 }
139 HW::write();
140}
141
142void
143vxlan_tunnel::replay()
144{
145 if (m_hdl) {
146 HW::enqueue(new create_cmd(m_hdl, name(), m_tep));
147 }
148}
149
150vxlan_tunnel::~vxlan_tunnel()
151{
152 sweep();
153
154 /*
155 * release from both DBs
156 */
157 release();
158 m_db.release(m_tep, this);
159}
160
161std::string
162vxlan_tunnel::to_string() const
163{
164 std::ostringstream s;
165 s << "vxlan-tunnel: " << m_hdl.to_string() << " " << m_tep.to_string();
166
167 return (s.str());
168}
169
170void
171vxlan_tunnel::update(const vxlan_tunnel& desired)
172{
173 /*
174 * the desired state is always that the interface should be created
175 */
176 if (!m_hdl) {
177 HW::enqueue(new create_cmd(m_hdl, name(), m_tep));
178 }
179}
180
181std::shared_ptr<vxlan_tunnel>
182vxlan_tunnel::find_or_add(const vxlan_tunnel& temp)
183{
184 /*
185 * a VXLAN tunnel needs to be in both the interface-find-by-name
186 * and the vxlan_tunnel-find-by-endpoint singular databases
187 */
188 std::shared_ptr<vxlan_tunnel> sp;
189
190 sp = m_db.find_or_add(temp.m_tep, temp);
191
192 interface::m_db.add(temp.name(), sp);
193
194 return (sp);
195}
196
197std::shared_ptr<vxlan_tunnel>
198vxlan_tunnel::singular() const
199{
200 return (find_or_add(*this));
201}
202
203std::shared_ptr<interface>
204vxlan_tunnel::singular_i() const
205{
206 return find_or_add(*this);
207}
208
209void
210vxlan_tunnel::dump(std::ostream& os)
211{
212 m_db.dump(os);
213}
214
215void
216vxlan_tunnel::event_handler::handle_populate(const client_db::key_t& key)
217{
218 /*
219 * dump VPP current states
220 */
221 std::shared_ptr<vxlan_tunnel::dump_cmd> cmd(new vxlan_tunnel::dump_cmd());
222
223 HW::enqueue(cmd);
224 HW::write();
225
226 for (auto& record : *cmd) {
227 auto& payload = record.get_payload();
228 handle_t hdl(payload.sw_if_index);
229 boost::asio::ip::address src =
230 from_bytes(payload.is_ipv6, payload.src_address);
231 boost::asio::ip::address dst =
232 from_bytes(payload.is_ipv6, payload.dst_address);
233
234 vxlan_tunnel vt(hdl, src, dst, payload.vni);
235
236 VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string();
237
238 OM::commit(key, vt);
239 }
240}
241
242vxlan_tunnel::event_handler::event_handler()
243{
244 OM::register_listener(this);
245 inspect::register_handler({ "vxlan" }, "VXLAN Tunnels", this);
246}
247
248void
249vxlan_tunnel::event_handler::handle_replay()
250{
251 // replay is handled from the interface DB
252}
253
254dependency_t
255vxlan_tunnel::event_handler::order() const
256{
257 return (dependency_t::TUNNEL);
258}
259
260void
261vxlan_tunnel::event_handler::show(std::ostream& os)
262{
263 m_db.dump(os);
264}
265}
266/*
267 * fd.io coding-style-patch-verification: ON
268 *
269 * Local Variables:
270 * eval: (c-set-style "mozilla")
271 * End:
272 */