f6f3cf586e181a5b0e53056cea8872976ec68027
[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 vxlan_tunnel& o)
110   : interface(o)
111   , m_tep(o.m_tep)
112 {
113 }
114
115 const handle_t&
116 vxlan_tunnel::handle() const
117 {
118   return (m_hdl.data());
119 }
120
121 void
122 vxlan_tunnel::sweep()
123 {
124   if (m_hdl) {
125     HW::enqueue(new vxlan_tunnel_cmds::delete_cmd(m_hdl, m_tep));
126   }
127   HW::write();
128 }
129
130 void
131 vxlan_tunnel::replay()
132 {
133   if (m_hdl) {
134     HW::enqueue(new vxlan_tunnel_cmds::create_cmd(m_hdl, name(), m_tep));
135   }
136 }
137
138 vxlan_tunnel::~vxlan_tunnel()
139 {
140   sweep();
141
142   /*
143  * release from both DBs
144  */
145   release();
146   m_db.release(m_tep, this);
147 }
148
149 std::string
150 vxlan_tunnel::to_string() const
151 {
152   std::ostringstream s;
153   s << "vxlan-tunnel: " << m_hdl.to_string() << " " << m_tep.to_string();
154
155   return (s.str());
156 }
157
158 void
159 vxlan_tunnel::update(const vxlan_tunnel& desired)
160 {
161   /*
162    * the desired state is always that the interface should be created
163    */
164   if (!m_hdl) {
165     HW::enqueue(new vxlan_tunnel_cmds::create_cmd(m_hdl, name(), m_tep));
166   }
167 }
168
169 std::shared_ptr<vxlan_tunnel>
170 vxlan_tunnel::find_or_add(const vxlan_tunnel& temp)
171 {
172   /*
173    * a VXLAN tunnel needs to be in both the interface-find-by-name
174    * and the vxlan_tunnel-find-by-endpoint singular databases
175    */
176   std::shared_ptr<vxlan_tunnel> sp;
177
178   sp = m_db.find_or_add(temp.m_tep, temp);
179
180   interface::m_db.add(temp.name(), sp);
181
182   return (sp);
183 }
184
185 std::shared_ptr<vxlan_tunnel>
186 vxlan_tunnel::singular() const
187 {
188   return (find_or_add(*this));
189 }
190
191 std::shared_ptr<interface>
192 vxlan_tunnel::singular_i() const
193 {
194   return find_or_add(*this);
195 }
196
197 void
198 vxlan_tunnel::dump(std::ostream& os)
199 {
200   m_db.dump(os);
201 }
202
203 void
204 vxlan_tunnel::event_handler::handle_populate(const client_db::key_t& key)
205 {
206   /*
207    * dump VPP current states
208    */
209   std::shared_ptr<vxlan_tunnel_cmds::dump_cmd> cmd =
210     std::make_shared<vxlan_tunnel_cmds::dump_cmd>();
211
212   HW::enqueue(cmd);
213   HW::write();
214
215   for (auto& record : *cmd) {
216     auto& payload = record.get_payload();
217     handle_t hdl(payload.sw_if_index);
218     boost::asio::ip::address src =
219       from_bytes(payload.is_ipv6, payload.src_address);
220     boost::asio::ip::address dst =
221       from_bytes(payload.is_ipv6, payload.dst_address);
222
223     std::shared_ptr<vxlan_tunnel> vt =
224       vxlan_tunnel(src, dst, payload.vni).singular();
225     vt->set(hdl);
226
227     VOM_LOG(log_level_t::DEBUG) << "dump: " << vt->to_string();
228
229     OM::commit(key, *vt);
230   }
231 }
232
233 vxlan_tunnel::event_handler::event_handler()
234 {
235   OM::register_listener(this);
236   inspect::register_handler({ "vxlan" }, "VXLAN Tunnels", this);
237 }
238
239 void
240 vxlan_tunnel::event_handler::handle_replay()
241 {
242   // replay is handled from the interface DB
243 }
244
245 dependency_t
246 vxlan_tunnel::event_handler::order() const
247 {
248   return (dependency_t::TUNNEL);
249 }
250
251 void
252 vxlan_tunnel::event_handler::show(std::ostream& os)
253 {
254   // dumped by the interface handler
255 }
256
257 }; // namespace VOM
258
259 /*
260  * fd.io coding-style-patch-verification: ON
261  *
262  * Local Variables:
263  * eval: (c-set-style "mozilla")
264  * End:
265  */