VPP Object Model (VOM)
[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
19 namespace VOM {
20 const std::string VXLAN_TUNNEL_NAME = "vxlan-tunnel-itf";
21
22 vxlan_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  */
29 singular_db<vxlan_tunnel::endpoint_t, vxlan_tunnel> vxlan_tunnel::m_db;
30
31 vxlan_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
40 vxlan_tunnel::endpoint_t::endpoint_t()
41   : src()
42   , dst()
43   , vni(0)
44 {
45 }
46
47 bool
48 vxlan_tunnel::endpoint_t::operator==(const endpoint_t& other) const
49 {
50   return ((src == other.src) && (dst == other.dst) && (vni == other.vni));
51 }
52
53 bool
54 vxlan_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
66 std::string
67 vxlan_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
78 std::ostream&
79 operator<<(std::ostream& os, const vxlan_tunnel::endpoint_t& ep)
80 {
81   os << ep.to_string();
82
83   return (os);
84 }
85
86 std::string
87 vxlan_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
98 vxlan_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
108 vxlan_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
121 vxlan_tunnel::vxlan_tunnel(const vxlan_tunnel& o)
122   : interface(o)
123   , m_tep(o.m_tep)
124 {
125 }
126
127 const handle_t&
128 vxlan_tunnel::handle() const
129 {
130   return (m_hdl.data());
131 }
132
133 void
134 vxlan_tunnel::sweep()
135 {
136   if (m_hdl) {
137     HW::enqueue(new delete_cmd(m_hdl, m_tep));
138   }
139   HW::write();
140 }
141
142 void
143 vxlan_tunnel::replay()
144 {
145   if (m_hdl) {
146     HW::enqueue(new create_cmd(m_hdl, name(), m_tep));
147   }
148 }
149
150 vxlan_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
161 std::string
162 vxlan_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
170 void
171 vxlan_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
181 std::shared_ptr<vxlan_tunnel>
182 vxlan_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
197 std::shared_ptr<vxlan_tunnel>
198 vxlan_tunnel::singular() const
199 {
200   return (find_or_add(*this));
201 }
202
203 std::shared_ptr<interface>
204 vxlan_tunnel::singular_i() const
205 {
206   return find_or_add(*this);
207 }
208
209 void
210 vxlan_tunnel::dump(std::ostream& os)
211 {
212   m_db.dump(os);
213 }
214
215 void
216 vxlan_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
242 vxlan_tunnel::event_handler::event_handler()
243 {
244   OM::register_listener(this);
245   inspect::register_handler({ "vxlan" }, "VXLAN Tunnels", this);
246 }
247
248 void
249 vxlan_tunnel::event_handler::handle_replay()
250 {
251   // replay is handled from the interface DB
252 }
253
254 dependency_t
255 vxlan_tunnel::event_handler::order() const
256 {
257   return (dependency_t::TUNNEL);
258 }
259
260 void
261 vxlan_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  */