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