blob: abd589eef9f95db3d44052b39a091e383de61e80 [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 <boost/algorithm/string.hpp>
17#include <sstream>
18
19#include "vom/prefix.hpp"
20
21namespace VOM {
22/*
23 * Keep this in sync with VPP's fib_protocol_t
24 */
25const l3_proto_t l3_proto_t::IPV4(0, "ipv4");
26const l3_proto_t l3_proto_t::IPV6(1, "ipv6");
27const l3_proto_t l3_proto_t::MPLS(2, "mpls");
28
29l3_proto_t::l3_proto_t(int v, const std::string& s)
30 : enum_base<l3_proto_t>(v, s)
31{
32}
33
34bool
35l3_proto_t::is_ipv6()
36{
37 return (*this == IPV6);
38}
39
40bool
41l3_proto_t::is_ipv4()
42{
43 return (*this == IPV4);
44}
45
46const l3_proto_t&
47l3_proto_t::from_address(const boost::asio::ip::address& addr)
48{
49 if (addr.is_v6()) {
50 return IPV6;
51 }
52
53 return IPV4;
54}
55
Neale Rannsf068c3e2018-01-03 04:18:48 -080056const nh_proto_t&
57l3_proto_t::to_nh_proto() const
58{
59 if (*this == IPV4)
60 return nh_proto_t::IPV4;
61 else if (*this == IPV6)
62 return nh_proto_t::IPV6;
63 else if (*this == MPLS)
64 return nh_proto_t::MPLS;
65
66 return nh_proto_t::IPV4;
67}
68
Neale Ranns041fa502017-12-20 08:49:51 -080069std::ostream&
70operator<<(std::ostream& os, const l3_proto_t& l3p)
71{
72 os << l3p.to_string();
73 return os;
74}
75
Neale Ranns812ed392017-10-16 04:20:13 -070076/*
77 * Keep this in sync with VPP's dpo_proto_t
78 */
79const nh_proto_t nh_proto_t::IPV4(0, "ipv4");
80const nh_proto_t nh_proto_t::IPV6(1, "ipv6");
81const nh_proto_t nh_proto_t::MPLS(2, "mpls");
82const nh_proto_t nh_proto_t::ETHERNET(3, "ethernet");
83
84nh_proto_t::nh_proto_t(int v, const std::string& s)
85 : enum_base<nh_proto_t>(v, s)
86{
87}
88
89const nh_proto_t&
90nh_proto_t::from_address(const boost::asio::ip::address& addr)
91{
92 if (addr.is_v6()) {
93 return IPV6;
94 }
95
96 return IPV4;
97}
98
99/**
100 * The all Zeros prefix
101 */
102const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
103const route::prefix_t route::prefix_t::ZEROv6("::", 0);
104
105route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len)
106 : m_addr(addr)
107 , m_len(len)
108{
109}
110
111route::prefix_t::prefix_t(const boost::asio::ip::address& addr)
112 : m_addr(addr)
113 , m_len(VOM::mask_width(addr))
114{
115}
116
117route::prefix_t::prefix_t(const std::string& s, uint8_t len)
118 : m_addr(boost::asio::ip::address::from_string(s))
119 , m_len(len)
120{
121}
122
123route::prefix_t::prefix_t(const prefix_t& o)
124 : m_addr(o.m_addr)
125 , m_len(o.m_len)
126{
127}
128
129route::prefix_t::prefix_t()
130 : m_addr()
131 , m_len(0)
132{
133}
134
135route::prefix_t::~prefix_t()
136{
137}
138
139route::prefix_t&
140route::prefix_t::operator=(const route::prefix_t& o)
141{
142 m_addr = o.m_addr;
143 m_len = o.m_len;
144
145 return (*this);
146}
147
148const boost::asio::ip::address&
149route::prefix_t::address() const
150{
151 return (m_addr);
152}
153
154uint8_t
155route::prefix_t::mask_width() const
156{
157 return (m_len);
158}
159
160bool
161route::prefix_t::operator<(const route::prefix_t& o) const
162{
163 if (m_len == o.m_len) {
164 return (m_addr < o.m_addr);
165 } else {
166 return (m_len < o.m_len);
167 }
168}
169
170bool
171route::prefix_t::operator==(const route::prefix_t& o) const
172{
173 return (m_len == o.m_len && m_addr == o.m_addr);
174}
175
176bool
177route::prefix_t::operator!=(const route::prefix_t& o) const
178{
179 return (!(*this == o));
180}
181
182std::string
183route::prefix_t::to_string() const
184{
185 std::ostringstream s;
186
187 s << m_addr.to_string() << "/" << std::to_string(m_len);
188
189 return (s.str());
190}
191
192boost::asio::ip::address
193from_bytes(uint8_t is_ip6, uint8_t* bytes)
194{
195 boost::asio::ip::address addr;
196
197 if (is_ip6) {
198 std::array<uint8_t, 16> a;
199 std::copy(bytes, bytes + 16, std::begin(a));
200 boost::asio::ip::address_v6 v6(a);
201 addr = v6;
202 } else {
203 std::array<uint8_t, 4> a;
204 std::copy(bytes, bytes + 4, std::begin(a));
205 boost::asio::ip::address_v4 v4(a);
206 addr = v4;
207 }
208
209 return (addr);
210}
211
212route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
213 : m_addr(from_bytes(is_ip6, addr))
214 , m_len(len)
215{
216}
217void
218to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
219{
220 memcpy(array, addr.to_bytes().data(), 16);
221}
222
223void
224to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
225{
226 memcpy(array, addr.to_bytes().data(), 4);
227}
228
229void
230to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
231{
232 if (addr.is_v6()) {
233 *is_ip6 = 1;
234 to_bytes(addr.to_v6(), array);
235 } else {
236 *is_ip6 = 0;
237 to_bytes(addr.to_v4(), array);
238 }
239}
240
241uint32_t
242mask_width(const boost::asio::ip::address& addr)
243{
244 if (addr.is_v6()) {
245 return 128;
246 }
247 return 32;
248}
249
250void
251route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
252{
253 *len = m_len;
254 to_bytes(m_addr, is_ip6, addr);
255}
256
257l3_proto_t
258route::prefix_t::l3_proto() const
259{
260 if (m_addr.is_v6()) {
261 return (l3_proto_t::IPV6);
262 } else {
263 return (l3_proto_t::IPV4);
264 }
265
266 return (l3_proto_t::IPV4);
267}
268
269std::ostream&
270operator<<(std::ostream& os, const route::prefix_t& pfx)
271{
272 os << pfx.to_string();
273
274 return (os);
275}
276
277boost::asio::ip::address_v4
278operator|(const boost::asio::ip::address_v4& addr1,
279 const boost::asio::ip::address_v4& addr2)
280{
281 uint32_t a;
282 a = addr1.to_ulong() | addr2.to_ulong();
283 boost::asio::ip::address_v4 addr(a);
284 return (addr);
285}
286
287boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
288 const boost::asio::ip::address_v4& addr2)
289{
290 uint32_t a;
291 a = addr1.to_ulong() & addr2.to_ulong();
292 boost::asio::ip::address_v4 addr(a);
293 return (addr);
294}
295
296boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
297{
298 uint32_t a;
299 a = ~addr1.to_ulong();
300 boost::asio::ip::address_v4 addr(a);
301 return (addr);
302}
303
Neale Rannsd3464b52017-12-07 08:48:02 -0800304boost::asio::ip::address_v6
305operator|(const boost::asio::ip::address_v6& addr1,
306 const boost::asio::ip::address_v6& addr2)
Neale Ranns812ed392017-10-16 04:20:13 -0700307{
Neale Rannsd3464b52017-12-07 08:48:02 -0800308 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
309 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
Neale Ranns812ed392017-10-16 04:20:13 -0700310
Neale Rannsd3464b52017-12-07 08:48:02 -0800311 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
312 ii < b1.max_size(); ii++) {
313 b1[ii] |= b2[ii];
314 }
315
316 boost::asio::ip::address_v6 addr(b1);
Neale Ranns812ed392017-10-16 04:20:13 -0700317 return (addr);
318}
319
Neale Rannsd3464b52017-12-07 08:48:02 -0800320boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
321 const boost::asio::ip::address_v6& addr2)
Neale Ranns812ed392017-10-16 04:20:13 -0700322{
Neale Rannsd3464b52017-12-07 08:48:02 -0800323 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
324 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
325
326 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
327 ii < b1.max_size(); ii++) {
328 b1[ii] &= b2[ii];
329 }
330
331 boost::asio::ip::address_v6 addr(b1);
332 return (addr);
Neale Ranns812ed392017-10-16 04:20:13 -0700333}
334
Neale Rannsd3464b52017-12-07 08:48:02 -0800335boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
336{
337 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
338
339 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
340 ii < b1.max_size(); ii++) {
341 b1[ii] = ~b1[ii];
342 }
343
344 boost::asio::ip::address_v6 addr(b1);
345 return (addr);
346}
347boost::asio::ip::address
348operator|(const boost::asio::ip::address& addr1,
349 const boost::asio::ip::address& addr2)
350{
351 if (addr1.is_v6())
352 return (addr1.to_v6() | addr2.to_v6());
353 else
354 return (addr1.to_v4() | addr2.to_v4());
355}
356
357boost::asio::ip::address operator&(const boost::asio::ip::address& addr1,
358 const boost::asio::ip::address& addr2)
359{
360 if (addr1.is_v6())
361 return (addr1.to_v6() & addr2.to_v6());
362 else
363 return (addr1.to_v4() & addr2.to_v4());
364}
365
366boost::asio::ip::address operator~(const boost::asio::ip::address& addr1)
367{
368 if (addr1.is_v6())
369 return ~(addr1.to_v6());
370 else
371 return ~(addr1.to_v4());
372}
373
374boost::asio::ip::address
375route::prefix_t::mask() const
376{
377 if (m_addr.is_v6()) {
378 boost::asio::ip::address_v6::bytes_type b =
379 boost::asio::ip::address_v6::any().to_bytes();
380
381 uint8_t n_bits = mask_width();
382
383 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
384 ii < b.max_size(); ii++) {
385 for (int8_t bit = 7; bit >= 0 && n_bits; bit--) {
386 b[ii] |= (1 << bit);
387 n_bits--;
388 }
389 if (!n_bits)
390 break;
391 }
392
393 return (boost::asio::ip::address_v6(b));
394 } else {
395 uint32_t a;
396
397 a = ~((1 << (32 - mask_width())) - 1);
398
399 return (boost::asio::ip::address_v4(a));
400 }
401}
402
403route::prefix_t
404route::prefix_t::low() const
405{
406 prefix_t pfx(*this);
407
408 pfx.m_addr = pfx.m_addr & pfx.mask();
409
410 return (pfx);
411}
412
413route::prefix_t
Neale Ranns812ed392017-10-16 04:20:13 -0700414route::prefix_t::high() const
415{
Neale Rannsd3464b52017-12-07 08:48:02 -0800416 prefix_t pfx(*this);
417
418 pfx.m_addr = pfx.m_addr | ~pfx.mask();
419
420 return (pfx);
Neale Ranns812ed392017-10-16 04:20:13 -0700421}
Neale Rannsd3464b52017-12-07 08:48:02 -0800422
423}; // namespace VOM
424
Neale Ranns812ed392017-10-16 04:20:13 -0700425/*
426 * fd.io coding-style-patch-verification: ON
427 *
428 * Local Variables:
429 * eval: (c-set-style "mozilla")
430 * End:
431 */