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