FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
route.cpp
Go to the documentation of this file.
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/route.hpp"
17 #include "vom/route_cmds.hpp"
19 
20 namespace VOM {
21 namespace route {
22 ip_route::event_handler ip_route::m_evh;
23 singular_db<ip_route::key_t, ip_route> ip_route::m_db;
24 
25 const path::special_t path::special_t::STANDARD(0, "standard");
26 const path::special_t path::special_t::LOCAL(0, "local");
27 const path::special_t path::special_t::DROP(0, "standard");
28 const path::special_t path::special_t::UNREACH(0, "unreachable");
29 const path::special_t path::special_t::PROHIBIT(0, "prohibit");
30 
31 path::special_t::special_t(int v, const std::string& s)
32  : enum_base<path::special_t>(v, s)
33 {
34 }
35 
36 const path::flags_t path::flags_t::NONE(0, "none");
37 const path::flags_t path::flags_t::DVR((1 << 0), "dvr");
38 
39 path::flags_t::flags_t(int v, const std::string& s)
40  : enum_base<path::flags_t>(v, s)
41 {
42 }
43 
44 path::path(special_t special)
45  : m_type(special)
46  , m_nh_proto(nh_proto_t::IPV4)
47  , m_flags(flags_t::NONE)
48  , m_nh()
49  , m_rd(nullptr)
50  , m_interface(nullptr)
51  , m_weight(1)
52  , m_preference(0)
53 {
54 }
55 
57  const interface& interface,
58  uint8_t weight,
59  uint8_t preference)
60  : m_type(special_t::STANDARD)
61  , m_nh_proto(nh_proto_t::from_address(nh))
62  , m_flags(flags_t::NONE)
63  , m_nh(nh)
64  , m_rd(nullptr)
65  , m_interface(interface.singular())
66  , m_weight(weight)
67  , m_preference(preference)
68 {
69 }
70 
73  uint8_t weight,
74  uint8_t preference)
75  : m_type(special_t::STANDARD)
76  , m_nh_proto(nh_proto_t::from_address(nh))
77  , m_flags(flags_t::NONE)
78  , m_nh(nh)
79  , m_rd(rd.singular())
80  , m_interface(nullptr)
81  , m_weight(weight)
82  , m_preference(preference)
83 {
84 }
85 
87  const nh_proto_t& proto,
88  const flags_t& flags,
89  uint8_t weight,
90  uint8_t preference)
91  : m_type(special_t::STANDARD)
92  , m_nh_proto(proto)
93  , m_flags(flags)
94  , m_nh()
95  , m_rd(nullptr)
96  , m_interface(interface.singular())
97  , m_weight(weight)
98  , m_preference(preference)
99 {
100 }
101 
102 path::path(const path& p)
103  : m_type(p.m_type)
104  , m_nh_proto(p.m_nh_proto)
105  , m_flags(p.m_flags)
106  , m_nh(p.m_nh)
107  , m_rd(p.m_rd)
108  , m_interface(p.m_interface)
109  , m_weight(p.m_weight)
110  , m_preference(p.m_preference)
111 {
112 }
113 
114 bool
115 path::operator<(const path& p) const
116 {
117  if (m_nh_proto < p.m_nh_proto)
118  return true;
119  if (m_flags < p.m_flags)
120  return true;
121  if (m_type < p.m_type)
122  return true;
123  if (m_rd && !p.m_rd)
124  return false;
125  if (!m_rd && p.m_rd)
126  return true;
127  if (m_rd->table_id() < p.m_rd->table_id())
128  return true;
129  if (m_nh < p.m_nh)
130  return true;
131  if (m_interface && !p.m_interface)
132  return false;
133  if (!m_interface && p.m_interface)
134  return true;
135  if (m_interface->handle() < p.m_interface->handle())
136  return true;
137 
138  return (false);
139 }
140 
142 {
143 }
144 
145 bool
146 path::operator==(const path& p) const
147 {
148  bool result = true;
149  if (m_rd && !p.m_rd)
150  return false;
151  if (!m_rd && p.m_rd)
152  return false;
153  if (m_rd && p.m_rd)
154  result &= (*m_rd == *p.m_rd);
155  if (m_interface && !p.m_interface)
156  return false;
157  if (!m_interface && p.m_interface)
158  return false;
159  if (m_interface && p.m_interface)
160  result &= (*m_interface == *p.m_interface);
161  return (result && (m_type == p.m_type) && (m_nh == p.m_nh) &&
162  (m_nh_proto == p.m_nh_proto) && (m_flags == p.m_flags));
163 }
164 
165 std::string
167 {
168  std::ostringstream s;
169 
170  s << "path:["
171  << "type:" << m_type.to_string() << " proto:" << m_nh_proto.to_string()
172  << " flags:" << m_flags.to_string() << " neighbour:" << m_nh.to_string();
173  if (m_rd) {
174  s << " " << m_rd->to_string();
175  }
176  if (m_interface) {
177  s << " " << m_interface->to_string();
178  }
179  s << " weight:" << static_cast<int>(m_weight)
180  << " preference:" << static_cast<int>(m_preference) << "]";
181 
182  return (s.str());
183 }
184 
186 path::type() const
187 {
188  return m_type;
189 }
190 
193 {
194  return m_nh_proto;
195 }
196 
198 path::flags() const
199 {
200  return m_flags;
201 }
202 
204 path::nh() const
205 {
206  return m_nh;
207 }
208 
209 std::shared_ptr<route_domain>
210 path::rd() const
211 {
212  return m_rd;
213 }
214 
215 std::shared_ptr<interface>
216 path::itf() const
217 {
218  return m_interface;
219 }
220 
221 uint8_t
223 {
224  return m_weight;
225 }
226 
227 uint8_t
229 {
230  return m_preference;
231 }
232 
233 ip_route::ip_route(const prefix_t& prefix, const path& p)
234  : m_hw(false)
235  , m_rd(route_domain::get_default())
236  , m_prefix(prefix)
237  , m_paths({ p })
238 {
239 }
240 
242  : m_hw(false)
243  , m_rd(route_domain::get_default())
244  , m_prefix(prefix)
245  , m_paths()
246 {
247 }
248 
250  : m_hw(r.m_hw)
251  , m_rd(r.m_rd)
252  , m_prefix(r.m_prefix)
253  , m_paths(r.m_paths)
254 {
255 }
256 
257 ip_route::ip_route(const route_domain& rd, const prefix_t& prefix)
258  : m_hw(false)
259  , m_rd(rd.singular())
260  , m_prefix(prefix)
261  , m_paths()
262 {
263 }
264 
266  const prefix_t& prefix,
267  const path& p)
268  : m_hw(false)
269  , m_rd(rd.singular())
270  , m_prefix(prefix)
271  , m_paths({ p })
272 {
273 }
274 
276 {
277  sweep();
278 
279  // not in the DB anymore.
280  m_db.release(key(), this);
281  m_paths.clear();
282 }
283 
284 const ip_route::key_t
286 {
287  return (std::make_pair(m_rd->table_id(), m_prefix));
288 }
289 
290 bool
292 {
293  return ((key() == i.key()) && (m_paths == i.m_paths));
294 }
295 
296 void
298 {
299  m_paths.insert(path);
300 }
301 
302 void
304 {
305  m_paths.erase(path);
306 }
307 
308 void
309 ip_route::sweep()
310 {
311  if (m_hw) {
312  HW::enqueue(
313  new ip_route_cmds::delete_cmd(m_hw, m_rd->table_id(), m_prefix));
314  }
315  HW::write();
316 }
317 
318 void
320 {
321  if (m_hw) {
322  HW::enqueue(
323  new ip_route_cmds::update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
324  }
325 }
326 std::string
328 {
329  std::ostringstream s;
330  s << "route:[" << m_rd->to_string() << ", " << m_prefix.to_string() << " ["
331  << m_paths << "]"
332  << "]";
333 
334  return (s.str());
335 }
336 
337 void
338 ip_route::update(const ip_route& r)
339 {
340  /*
341 * create the table if it is not yet created
342 */
343  if (rc_t::OK != m_hw.rc()) {
344  HW::enqueue(
345  new ip_route_cmds::update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
346  }
347 }
348 
349 std::shared_ptr<ip_route>
350 ip_route::find_or_add(const ip_route& temp)
351 {
352  return (m_db.find_or_add(temp.key(), temp));
353 }
354 
355 std::shared_ptr<ip_route>
357 {
358  return (m_db.find(k));
359 }
360 
361 std::shared_ptr<ip_route>
363 {
364  return find_or_add(*this);
365 }
366 
367 void
368 ip_route::dump(std::ostream& os)
369 {
370  db_dump(m_db, os);
371 }
372 
374 {
375  OM::register_listener(this);
376  inspect::register_handler({ "ip-route" }, "ip route configurations", this);
377 }
378 
379 void
380 ip_route::event_handler::handle_replay()
381 {
382  m_db.replay();
383 }
384 
385 void
386 ip_route::event_handler::handle_populate(const client_db::key_t& key)
387 {
388  std::shared_ptr<ip_route_cmds::dump_v4_cmd> cmd_v4 =
389  std::make_shared<ip_route_cmds::dump_v4_cmd>();
390  std::shared_ptr<ip_route_cmds::dump_v6_cmd> cmd_v6 =
391  std::make_shared<ip_route_cmds::dump_v6_cmd>();
392 
393  HW::enqueue(cmd_v4);
394  HW::enqueue(cmd_v6);
395  HW::write();
396 
397  for (auto& record : *cmd_v4) {
398  auto& payload = record.get_payload();
399 
400  prefix_t pfx(0, payload.address, payload.address_length);
401 
402  /**
403  * populating the route domain here
404  */
405  route_domain rd_temp(payload.table_id);
406  std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
407  if (!rd) {
408  OM::commit(key, rd_temp);
409  }
410  ip_route ip_r(rd_temp, pfx);
411 
412  for (unsigned int i = 0; i < payload.count; i++) {
413  vapi_type_fib_path p = payload.path[i];
414  if (p.is_local) {
415  path path_v4(path::special_t::LOCAL);
416  ip_r.add(path_v4);
417  } else if (p.is_drop) {
418  path path_v4(path::special_t::DROP);
419  ip_r.add(path_v4);
420  } else if (p.is_unreach) {
422  ip_r.add(path_v4);
423  } else if (p.is_prohibit) {
425  ip_r.add(path_v4);
426  } else {
428  std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
429  if (itf) {
430  if (p.is_dvr) {
432  p.weight, p.preference);
433  ip_r.add(path_v4);
434  } else {
435  path path_v4(address, *itf, p.weight, p.preference);
436  ip_r.add(path_v4);
437  }
438  } else {
439  path path_v4(rd_temp, address, p.weight, p.preference);
440  ip_r.add(path_v4);
441  }
442  }
443  }
444  VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();
445 
446  /*
447  * Write each of the discovered interfaces into the OM,
448  * but disable the HW Command q whilst we do, so that no
449  * commands are sent to VPP
450  */
451  OM::commit(key, ip_r);
452  }
453 
454  for (auto& record : *cmd_v6) {
455  auto& payload = record.get_payload();
456 
457  prefix_t pfx(1, payload.address, payload.address_length);
458  route_domain rd_temp(payload.table_id);
459  std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
460  if (!rd) {
461  OM::commit(key, rd_temp);
462  }
463  ip_route ip_r(rd_temp, pfx);
464 
465  for (unsigned int i = 0; i < payload.count; i++) {
466  vapi_type_fib_path p = payload.path[i];
467  if (p.is_local) {
468  path path_v6(path::special_t::LOCAL);
469  ip_r.add(path_v6);
470  } else if (p.is_drop) {
471  path path_v6(path::special_t::DROP);
472  ip_r.add(path_v6);
473  } else if (p.is_unreach) {
475  ip_r.add(path_v6);
476  } else if (p.is_prohibit) {
478  ip_r.add(path_v6);
479  } else {
480  std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
482  if (itf) {
483  if (p.is_dvr) {
485  p.weight, p.preference);
486  ip_r.add(path_v6);
487  } else {
488  path path_v6(address, *itf, p.weight, p.preference);
489  ip_r.add(path_v6);
490  }
491  } else {
492  path path_v6(rd_temp, address, p.weight, p.preference);
493  ip_r.add(path_v6);
494  }
495  }
496  }
497  VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();
498 
499  /*
500  * Write each of the discovered interfaces into the OM,
501  * but disable the HW Command q whilst we do, so that no
502  * commands are sent to VPP
503  */
504  OM::commit(key, ip_r);
505  }
506 }
507 
509 ip_route::event_handler::order() const
510 {
511  return (dependency_t::TABLE);
512 }
513 
514 void
515 ip_route::event_handler::show(std::ostream& os)
516 {
517  db_dump(m_db, os);
518 }
519 
520 std::ostream&
521 operator<<(std::ostream& os, const ip_route::key_t& key)
522 {
523  os << "[" << key.first << ", " << key.second.to_string() << "]";
524 
525  return (os);
526 }
527 
528 std::ostream&
529 operator<<(std::ostream& os, const path_list_t& key)
530 {
531  os << "[";
532  for (auto k : key) {
533  os << k.to_string() << " ";
534  }
535  os << "]";
536 
537  return (os);
538 }
539 }
540 }
541 /*
542  * fd.io coding-style-patch-verification: ON
543  *
544  * Local Variables:
545  * eval: (c-set-style "mozilla")
546  * End:
547  */
void remove(const path &path)
remove a path.
Definition: route.cpp:303
flags_t flags() const
Definition: route.cpp:198
nh_proto_t nh_proto() const
Definition: route.cpp:192
typedef address
Definition: ip_types.api:34
static std::shared_ptr< route_domain > find(const key_t &temp)
Find the instnace of the route domain in the OM.
static const special_t STANDARD
A standard path type.
Definition: route.hpp:45
#define VOM_LOG(lvl)
Definition: logger.hpp:181
A command class that creates or updates the route.
Definition: route_cmds.hpp:32
void db_dump(const DB &db, std::ostream &os)
Print each of the objects in the DB into the stream provided.
const std::string key_t
In the opflex world each entity is known by a URI which can be converted into a string.
Definition: client_db.hpp:51
static std::shared_ptr< interface > find(const handle_t &h)
The the singular instance of the interface in the DB by handle.
Definition: interface.cpp:463
static const nh_proto_t IPV6
Definition: prefix.hpp:36
static const nh_proto_t IPV4
Definition: prefix.hpp:35
A path for IP or MPLS routes.
Definition: route.hpp:32
static void register_handler(const std::vector< std::string > &cmds, const std::string &help, command_handler *ch)
Register a command handler for inspection.
Definition: inspect.cpp:85
ip_route(const prefix_t &prefix)
Construct a route in the default table.
Definition: route.cpp:241
std::string to_string() const
convert to string format for debug purposes
Definition: route.cpp:166
int i
static rc_t write()
Write/Execute all commands hitherto enqueued.
Definition: hw.cpp:236
static const log_level_t DEBUG
Definition: logger.hpp:32
std::shared_ptr< interface > itf() const
Definition: route.cpp:216
void add(const path &path)
Add a path.
Definition: route.cpp:297
A route-domain is a VRF.
static const special_t LOCAL
A local/for-us/recieve.
Definition: route.hpp:50
static const special_t DROP
drop path
Definition: route.hpp:55
~path()
Destructor.
Definition: route.cpp:141
const key_t key() const
Get the route&#39;s key.
Definition: route.cpp:285
std::ostream & operator<<(std::ostream &os, const ip_route::key_t &key)
Definition: route.cpp:521
Types belonging to Routing.
Definition: prefix.hpp:32
rc_t rc() const
Get the HW return code.
Definition: hw.hpp:118
std::string to_string() const
convert to string format for debug purposes
Definition: prefix.cpp:183
std::string to_string() const
Convert to string for debugging.
Definition: route.cpp:327
static const special_t UNREACH
a path will return ICMP unreachables
Definition: route.hpp:60
#define v
Definition: acl.c:491
std::shared_ptr< route_domain > rd() const
Definition: route.cpp:210
~ip_route()
Destructor.
Definition: route.cpp:275
std::shared_ptr< ip_route > singular() const
Return the matching &#39;singular instance&#39;.
Definition: route.cpp:362
path(special_t special)
constructor for special paths
Definition: route.cpp:44
static const special_t PROHIBIT
a path will return ICMP prohibit
Definition: route.hpp:65
std::set< path > path_list_t
A path-list is a set of paths.
Definition: route.hpp:210
A representation of an interface in VPP.
Definition: interface.hpp:41
static const flags_t DVR
A path that resolves via a DVR next-hop.
Definition: route.hpp:88
Tables in which entries are added, e.g bridge/route-domains.
boost::asio::ip::address from_bytes(uint8_t is_ip6, uint8_t *bytes)
Convert a VPP byte stinrg into a boost addresss.
Definition: prefix.cpp:193
static rc_t commit(const client_db::key_t &key, const OBJ &obj)
Make the State in VPP reflect the expressed desired state.
Definition: om.hpp:202
void event_handler(void *tls_async)
Definition: tls_async.c:311
Special path types.
Definition: route.hpp:38
dependency_t
There needs to be a strict order in which object types are read from VPP (at boot time) and replayed ...
Definition: types.hpp:43
uint8_t preference() const
Definition: route.cpp:228
static const rc_t OK
The HW write was successfull.
Definition: types.hpp:112
static void enqueue(cmd *f)
Enqueue A command for execution.
Definition: hw.cpp:194
A cmd class that deletes a route.
Definition: route_cmds.hpp:67
const boost::asio::ip::address & nh() const
Definition: route.cpp:204
bool operator==(const ip_route &i) const
Comparison operator.
Definition: route.cpp:291
static std::shared_ptr< ip_route > find(const ip_route &temp)
Find the instnace of the route domain in the OM.
The VPP Object Model (VOM) library.
Definition: acl_binding.cpp:19
void replay(void)
replay the object to create it in hardware
Definition: route.cpp:319
bool operator<(const path &p) const
Less than operator for set insertion.
Definition: route.cpp:115
A IP route.
Definition: route.hpp:220
static void dump(std::ostream &os)
Dump all route-doamin into the stream provided.
Definition: route.cpp:368
void show(char *chroot_path, int verbose)
Definition: svmtool.c:105
bool operator==(const path &p) const
comparison operator
Definition: route.cpp:146
special_t type() const
Getters.
Definition: route.cpp:186
uint8_t weight() const
Definition: route.cpp:222
const std::string & to_string() const
convert to string format for debug purposes
Definition: enum_base.hpp:36
static bool register_listener(listener *listener)
Register a listener of events.
Definition: om.cpp:127
A prefix defintion.
Definition: prefix.hpp:93
std::pair< route::table_id_t, prefix_t > key_t
The key for a route.
Definition: route.hpp:226