Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include "bgp/evpn/evpn_route.h"
7 :
8 : #include <algorithm>
9 : #include <sstream>
10 :
11 : #include "base/string_util.h"
12 : #include "bgp/bgp_server.h"
13 : #include "bgp/evpn/evpn_table.h"
14 :
15 : using std::copy;
16 : using std::string;
17 : using std::vector;
18 :
19 : const EvpnPrefix EvpnPrefix::kNullPrefix;
20 : const uint32_t EvpnPrefix::kInvalidLabel = 0x01000000;
21 : const uint32_t EvpnPrefix::kNullTag = 0;
22 : const uint32_t EvpnPrefix::kMaxTag = 0xFFFFFFFF;
23 : const uint32_t EvpnPrefix::kMaxVni = 0x00FFFFFF;
24 : const int32_t EvpnPrefix::kMaxVniSigned =
25 : static_cast<uint32_t>(EvpnPrefix::kMaxVni);
26 :
27 : const size_t EvpnPrefix::kRdSize = RouteDistinguisher::kSize;
28 : const size_t EvpnPrefix::kEsiSize = EthernetSegmentId::kSize;
29 : const size_t EvpnPrefix::kTagSize = 4;
30 : const size_t EvpnPrefix::kIp4AddrSize = 4;
31 : const size_t EvpnPrefix::kIp6AddrSize = 16;
32 : const size_t EvpnPrefix::kMacSize = MacAddress::size();
33 : const size_t EvpnPrefix::kLabelSize = BgpProtoPrefix::kLabelSize;
34 :
35 : const size_t EvpnPrefix::kMinAutoDiscoveryRouteSize =
36 : kRdSize + kEsiSize + kTagSize;
37 : const size_t EvpnPrefix::kMinMacAdvertisementRouteSize =
38 : kRdSize + kEsiSize + kTagSize + 1 + kMacSize + 1;
39 : const size_t EvpnPrefix::kMinInclusiveMulticastRouteSize =
40 : kRdSize + kTagSize + 1;
41 : const size_t EvpnPrefix::kMinSelectiveMulticastRouteSize =
42 : kRdSize + kTagSize + 3;
43 : const size_t EvpnPrefix::kMinSegmentRouteSize =
44 : kRdSize + kEsiSize + 1;
45 : const size_t EvpnPrefix::kMinInetPrefixRouteSize =
46 : kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp4AddrSize;
47 : const size_t EvpnPrefix::kMinInet6PrefixRouteSize =
48 : kRdSize + kEsiSize + kTagSize + 1 + 2 * kIp6AddrSize;
49 :
50 : //
51 : // Read label from the BgpProtoPrefix.
52 : // If the encapsulation is VXLAN and ethernet tag is non-zero use that as
53 : // the label for backward compatibility with older JUNOS code.
54 : //
55 : // Note that Ethernet AD Routes per ESI always set ethernet tag to kMaxTag
56 : // and their label is supposed to be set to 0 on write and ignored on read.
57 : //
58 25546 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
59 : const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
60 25546 : if (!attr)
61 6883 : return 0;
62 18663 : const ExtCommunity *extcomm = attr->ext_community();
63 18663 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
64 146 : if (tag) {
65 60 : if (tag == EvpnPrefix::kMaxTag) {
66 4 : return 0;
67 56 : } else if (tag <= EvpnPrefix::kMaxVni) {
68 28 : return tag;
69 : } else {
70 28 : return proto_prefix.ReadLabel(offset, true);
71 : }
72 : } else {
73 86 : return proto_prefix.ReadLabel(offset, true);
74 : }
75 : } else {
76 18517 : return proto_prefix.ReadLabel(offset, false);
77 : }
78 : }
79 :
80 : //
81 : // Write label to the BgpProtoPrefix.
82 : //
83 29329 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
84 : const BgpAttr *attr, size_t offset, uint32_t label) {
85 29329 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
86 29329 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
87 146 : proto_prefix->WriteLabel(offset, label, true);
88 : } else {
89 29182 : proto_prefix->WriteLabel(offset, label, false);
90 : }
91 29328 : }
92 :
93 : //
94 : // Read gateway address from the BgpProtoPrefix.
95 : //
96 1779 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
97 : size_t gw_offset, size_t ip_size) {
98 1779 : assert(ip_size == EvpnPrefix::kIp4AddrSize ||
99 : ip_size == EvpnPrefix::kIp6AddrSize);
100 1779 : if (ip_size == EvpnPrefix::kIp4AddrSize) {
101 : Ip4Address::bytes_type bytes;
102 2252 : copy(proto_prefix.prefix.begin() + gw_offset,
103 1126 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
104 1126 : return Ip4Address(bytes);
105 : } else {
106 : Ip6Address::bytes_type bytes;
107 1306 : copy(proto_prefix.prefix.begin() + gw_offset,
108 653 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
109 653 : return Ip6Address(bytes);
110 : }
111 : return IpAddress();
112 : }
113 :
114 128684 : EvpnPrefix::EvpnPrefix()
115 128684 : : type_(Unspecified),
116 128680 : tag_(EvpnPrefix::kNullTag),
117 128680 : family_(Address::UNSPEC),
118 128684 : ip_prefixlen_(0) {
119 128667 : }
120 :
121 92 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
122 92 : const EthernetSegmentId &esi, uint32_t tag)
123 92 : : type_(AutoDiscoveryRoute),
124 92 : rd_(rd),
125 92 : esi_(esi),
126 92 : tag_(tag),
127 92 : family_(Address::UNSPEC),
128 92 : ip_prefixlen_(0) {
129 92 : }
130 :
131 3 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
132 3 : const MacAddress &mac_addr, const IpAddress &ip_address)
133 3 : : type_(MacAdvertisementRoute),
134 3 : rd_(rd),
135 3 : tag_(EvpnPrefix::kNullTag),
136 3 : mac_addr_(mac_addr),
137 3 : family_(Address::UNSPEC),
138 3 : ip_address_(ip_address),
139 6 : ip_prefixlen_(0) {
140 3 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
141 1 : family_ = Address::INET;
142 2 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
143 1 : family_ = Address::INET6;
144 : }
145 3 : }
146 :
147 15637 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
148 15637 : const MacAddress &mac_addr, const IpAddress &ip_address)
149 15637 : : type_(MacAdvertisementRoute), rd_(rd), tag_(tag),
150 15636 : mac_addr_(mac_addr), family_(Address::UNSPEC),
151 31272 : ip_address_(ip_address), ip_prefixlen_(0) {
152 15636 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
153 220 : family_ = Address::INET;
154 15415 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
155 28 : family_ = Address::INET6;
156 : }
157 15635 : }
158 :
159 24876 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
160 24876 : const IpAddress &ip_address)
161 24876 : : type_(InclusiveMulticastRoute),
162 24876 : rd_(rd),
163 24876 : tag_(tag),
164 24876 : family_(Address::UNSPEC),
165 24876 : ip_address_(ip_address),
166 49752 : ip_prefixlen_(0) {
167 24876 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
168 24871 : family_ = Address::INET;
169 5 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
170 5 : family_ = Address::INET6;
171 : }
172 24876 : }
173 :
174 2 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
175 2 : const EthernetSegmentId &esi, const IpAddress &ip_address)
176 2 : : type_(SegmentRoute),
177 2 : rd_(rd),
178 2 : esi_(esi),
179 2 : tag_(EvpnPrefix::kNullTag),
180 2 : family_(Address::UNSPEC),
181 2 : ip_address_(ip_address),
182 4 : ip_prefixlen_(0) {
183 2 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
184 1 : family_ = Address::INET;
185 1 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
186 1 : family_ = Address::INET6;
187 : }
188 2 : }
189 :
190 1039 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
191 1039 : const IpAddress &ip_address, uint8_t ip_prefixlen)
192 1039 : : type_(IpPrefixRoute),
193 1039 : rd_(rd),
194 1039 : tag_(0),
195 1039 : family_(Address::UNSPEC),
196 1039 : ip_address_(ip_address),
197 2078 : ip_prefixlen_(ip_prefixlen) {
198 1039 : assert(ip_address_.is_v4() || ip_address_.is_v6());
199 1039 : if (ip_address_.is_v4()) {
200 653 : family_ = Address::INET;
201 386 : } else if (ip_address_.is_v6()) {
202 386 : family_ = Address::INET6;
203 : }
204 1039 : }
205 :
206 46 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
207 : const IpAddress &source, const IpAddress &group,
208 46 : const IpAddress &ip_address)
209 46 : : type_(SelectiveMulticastRoute),
210 46 : rd_(rd),
211 46 : tag_(tag),
212 46 : family_(Address::UNSPEC),
213 46 : ip_address_(ip_address),
214 46 : source_(source),
215 46 : group_(group),
216 46 : ip_prefixlen_(0), flags_(0x2) {
217 46 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
218 46 : family_ = Address::INET;
219 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
220 0 : family_ = Address::INET6;
221 : }
222 46 : string ip = group.to_v4().to_string();
223 46 : char *str = const_cast<char *>(ip.c_str());
224 46 : char * mac_ip = strstr(str, ".");
225 46 : std::ostringstream oss;
226 46 : oss << "01:00:5e:" << strtok(mac_ip, ".");
227 46 : oss << ":" << strtok(NULL, ".");
228 46 : oss << ":" << strtok(NULL, "");
229 46 : mac_addr_ = MacAddress::FromString(oss.str(), NULL);
230 46 : }
231 :
232 28826 : int EvpnPrefix::FromProtoPrefix(BgpServer *server,
233 : const BgpProtoPrefix &proto_prefix, const BgpAttr *attr,
234 : const Address::Family family, EvpnPrefix *prefix, BgpAttrPtr *new_attr,
235 : uint32_t *label, uint32_t *l3_label) {
236 28826 : *new_attr = attr;
237 28826 : *label = 0;
238 28826 : if (l3_label)
239 26135 : *l3_label = 0;
240 28826 : prefix->type_ = proto_prefix.type;
241 28826 : size_t nlri_size = proto_prefix.prefix.size();
242 :
243 28826 : switch (prefix->type_) {
244 81 : case AutoDiscoveryRoute: {
245 81 : size_t expected_min_nlri_size =
246 81 : kMinAutoDiscoveryRouteSize + (attr ? kLabelSize : 0);
247 81 : if (nlri_size < expected_min_nlri_size)
248 47 : return -1;
249 34 : size_t rd_offset = 0;
250 34 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
251 34 : size_t esi_offset = rd_offset + kRdSize;
252 34 : prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
253 34 : size_t tag_offset = esi_offset + kEsiSize;
254 34 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
255 34 : size_t label_offset = tag_offset + kTagSize;
256 34 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
257 34 : break;
258 : }
259 24796 : case MacAdvertisementRoute: {
260 24796 : size_t expected_min_nlri_size =
261 24796 : kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
262 24796 : if (nlri_size < expected_min_nlri_size)
263 63 : return -1;
264 24733 : size_t rd_offset = 0;
265 24733 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
266 24733 : size_t esi_offset = rd_offset + kRdSize;
267 24733 : if (attr) {
268 17816 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
269 17816 : *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
270 : }
271 24733 : size_t tag_offset = esi_offset + kEsiSize;
272 24733 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
273 24733 : size_t mac_len_offset = tag_offset + kTagSize;
274 24733 : size_t mac_len = proto_prefix.prefix[mac_len_offset];
275 24733 : if (mac_len != 48)
276 510 : return -1;
277 24223 : size_t mac_offset = mac_len_offset + 1;
278 24223 : prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
279 24223 : size_t ip_len_offset = mac_offset + kMacSize;
280 24223 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
281 24223 : if (ip_len != 0 && ip_len != 32 && ip_len != 128)
282 506 : return -1;
283 23717 : size_t ip_size = ip_len / 8;
284 23717 : if (nlri_size < expected_min_nlri_size + ip_size)
285 40 : return -1;
286 23677 : size_t ip_offset = ip_len_offset + 1;
287 23677 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
288 23677 : size_t label_offset = ip_offset + ip_size;
289 23677 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
290 23677 : size_t l3_label_offset = label_offset + kLabelSize;
291 23677 : if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
292 76 : *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
293 : }
294 23677 : break;
295 : }
296 1027 : case InclusiveMulticastRoute: {
297 1027 : if (nlri_size < kMinInclusiveMulticastRouteSize)
298 13 : return -1;
299 1014 : size_t rd_offset = 0;
300 1014 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
301 1014 : size_t tag_offset = rd_offset + kRdSize;
302 1014 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
303 1014 : size_t ip_len_offset = tag_offset + kTagSize;
304 1014 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
305 1014 : if (ip_len != 32 && ip_len != 128)
306 254 : return -1;
307 760 : size_t ip_size = ip_len / 8;
308 760 : if (nlri_size < kMinInclusiveMulticastRouteSize + ip_size)
309 20 : return -1;
310 740 : size_t ip_offset = ip_len_offset + 1;
311 740 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
312 740 : const PmsiTunnel *pmsi_tunnel = attr ? attr->pmsi_tunnel() : NULL;
313 1128 : if (pmsi_tunnel &&
314 388 : (pmsi_tunnel->tunnel_type() == PmsiTunnelSpec::IngressReplication ||
315 0 : pmsi_tunnel->tunnel_type() ==
316 : PmsiTunnelSpec::AssistedReplicationContrail)) {
317 388 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
318 388 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
319 24 : if (prefix->tag_ && prefix->tag_ <= kMaxVni) {
320 8 : *label = prefix->tag_;
321 : } else {
322 16 : *label = pmsi_tunnel->GetLabel(extcomm);
323 : }
324 : } else {
325 364 : *label = pmsi_tunnel->GetLabel(extcomm);
326 : }
327 : }
328 740 : break;
329 : }
330 295 : case SegmentRoute: {
331 295 : if (nlri_size < kMinSegmentRouteSize)
332 19 : return -1;
333 276 : size_t rd_offset = 0;
334 276 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
335 276 : size_t esi_offset = rd_offset + kRdSize;
336 276 : prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
337 276 : size_t ip_len_offset = esi_offset + kEsiSize;
338 276 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
339 276 : if (ip_len != 32 && ip_len != 128)
340 254 : return -1;
341 22 : size_t ip_size = ip_len / 8;
342 22 : if (nlri_size < kMinSegmentRouteSize + ip_size)
343 20 : return -1;
344 2 : size_t ip_offset = ip_len_offset + 1;
345 2 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
346 2 : break;
347 : }
348 2329 : case IpPrefixRoute: {
349 : size_t ip_size;
350 2329 : if (attr) {
351 1774 : if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
352 643 : ip_size = kIp6AddrSize;
353 1131 : } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
354 1039 : ip_size = kIp4AddrSize;
355 : } else {
356 570 : return -1;
357 : }
358 : } else {
359 555 : if (nlri_size == kMinInet6PrefixRouteSize ||
360 555 : nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
361 147 : ip_size = kIp6AddrSize;
362 408 : } else if (nlri_size == kMinInetPrefixRouteSize ||
363 408 : nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
364 320 : ip_size = kIp4AddrSize;
365 : } else {
366 88 : return -1;
367 : }
368 : }
369 :
370 2149 : size_t rd_offset = 0;
371 2149 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
372 2149 : size_t esi_offset = rd_offset + kRdSize;
373 2149 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
374 2149 : if (!esi.IsZero())
375 20 : return -1;
376 2129 : size_t tag_offset = esi_offset + kEsiSize;
377 : // Ignore tag for type5 routes.
378 2129 : prefix->tag_ = 0;
379 2129 : size_t ip_plen_offset = tag_offset + kTagSize;
380 2129 : prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
381 2129 : if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
382 223 : return -1;
383 1906 : if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
384 127 : return -1;
385 1779 : size_t ip_offset = ip_plen_offset + 1;
386 1779 : size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
387 1779 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
388 1779 : size_t gw_offset = ip_offset + ip_size;
389 1779 : IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
390 1779 : if (!gw_address.is_unspecified())
391 20 : return -1;
392 1759 : size_t label_offset = gw_offset + ip_size;
393 1759 : *label = ReadLabel(proto_prefix, attr, label_offset);
394 1759 : break;
395 : }
396 49 : case SelectiveMulticastRoute: {
397 49 : if (nlri_size < kMinSelectiveMulticastRouteSize)
398 1 : return -1;
399 48 : size_t rd_offset = 0;
400 48 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
401 48 : size_t tag_offset = rd_offset + kRdSize;
402 48 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
403 48 : size_t src_len_offset = tag_offset + kTagSize;
404 48 : size_t src_len = proto_prefix.prefix[src_len_offset];
405 48 : if (src_len != 32 && src_len != 128 && src_len != 0)
406 0 : return -1;
407 48 : size_t src_size = src_len / 8;
408 48 : size_t src_offset = src_len_offset + 1;
409 48 : if (src_size > 0) {
410 48 : if (nlri_size < src_offset + src_size)
411 0 : return -1;
412 48 : prefix->ReadSource(proto_prefix, src_offset, src_size);
413 : }
414 48 : size_t grp_len_offset = src_offset + src_size;
415 48 : size_t grp_len = proto_prefix.prefix[grp_len_offset];
416 48 : if (grp_len != 32 && grp_len != 128)
417 0 : return -1;
418 48 : size_t grp_size = grp_len / 8;
419 48 : size_t grp_offset = grp_len_offset + 1;
420 48 : if (nlri_size < grp_offset + grp_size)
421 0 : return -1;
422 48 : prefix->ReadGroup(proto_prefix, grp_offset, grp_size);
423 48 : size_t ip_len_offset = grp_offset + grp_size;
424 48 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
425 48 : if (ip_len != 32 && ip_len != 128)
426 0 : return -1;
427 48 : size_t ip_size = ip_len / 8;
428 48 : size_t ip_offset = ip_len_offset + 1;
429 48 : if (nlri_size < ip_offset + ip_size)
430 0 : return -1;
431 48 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
432 48 : size_t flag_offset = ip_offset + ip_size;
433 48 : if (nlri_size <= flag_offset + 4)
434 48 : prefix->flags_ = get_value(&proto_prefix.prefix[flag_offset], 4);
435 48 : break;
436 : }
437 249 : default: {
438 249 : return -1;
439 : break;
440 : }
441 : }
442 26260 : return 0;
443 : }
444 :
445 : //
446 : // Build the BgpProtoPrefix for this EvpnPrefix.
447 : //
448 : // The ESI for MacAdvertisementRoute is not part of the key and hence
449 : // must be obtained from the BgpAttr. The BgpAttr is NULL and label is
450 : // 0 when withdrawing the route.
451 : //
452 30044 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
453 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
454 30044 : proto_prefix->type = type_;
455 30044 : proto_prefix->prefix.clear();
456 :
457 30044 : switch (type_) {
458 28 : case AutoDiscoveryRoute: {
459 28 : size_t nlri_size = kMinAutoDiscoveryRouteSize + kLabelSize;
460 28 : proto_prefix->prefixlen = nlri_size * 8;
461 28 : proto_prefix->prefix.resize(nlri_size, 0);
462 :
463 28 : size_t rd_offset = 0;
464 28 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
465 28 : proto_prefix->prefix.begin() + rd_offset);
466 28 : size_t esi_offset = rd_offset + kRdSize;
467 28 : copy(esi_.GetData(), esi_.GetData() + kEsiSize,
468 28 : proto_prefix->prefix.begin() + esi_offset);
469 28 : size_t tag_offset = esi_offset + kEsiSize;
470 28 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
471 28 : size_t label_offset = tag_offset + kTagSize;
472 28 : WriteLabel(proto_prefix, attr, label_offset, label);
473 28 : break;
474 : }
475 27467 : case MacAdvertisementRoute: {
476 27467 : size_t ip_size = GetIpAddressSize();
477 27467 : size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
478 27467 : if (l3_label)
479 76 : nlri_size += kLabelSize;
480 27467 : proto_prefix->prefixlen = nlri_size * 8;
481 27467 : proto_prefix->prefix.resize(nlri_size, 0);
482 :
483 27467 : size_t rd_offset = 0;
484 27467 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
485 27467 : proto_prefix->prefix.begin() + rd_offset);
486 27467 : size_t esi_offset = rd_offset + kRdSize;
487 27467 : if (attr) {
488 17352 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
489 34704 : proto_prefix->prefix.begin() + esi_offset);
490 : }
491 27467 : size_t tag_offset = esi_offset + kEsiSize;
492 27467 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
493 27467 : size_t mac_len_offset = tag_offset + kTagSize;
494 27467 : proto_prefix->prefix[mac_len_offset] = 48;
495 27467 : size_t mac_offset = mac_len_offset + 1;
496 27467 : copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
497 27467 : proto_prefix->prefix.begin() + mac_offset);
498 27467 : size_t ip_len_offset = mac_offset + kMacSize;
499 27467 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
500 27467 : size_t ip_offset = ip_len_offset + 1;
501 27467 : WriteIpAddress(proto_prefix, ip_offset);
502 27467 : size_t label_offset = ip_offset + ip_size;
503 27467 : WriteLabel(proto_prefix, attr, label_offset, label);
504 27467 : if (l3_label) {
505 76 : size_t l3_label_offset = label_offset + kLabelSize;
506 76 : WriteLabel(proto_prefix, attr, l3_label_offset, l3_label);
507 : }
508 27467 : break;
509 : }
510 740 : case InclusiveMulticastRoute: {
511 740 : size_t ip_size = GetIpAddressSize();
512 740 : size_t nlri_size = kMinInclusiveMulticastRouteSize + ip_size;
513 740 : proto_prefix->prefixlen = nlri_size * 8;
514 740 : proto_prefix->prefix.resize(nlri_size, 0);
515 :
516 740 : size_t rd_offset = 0;
517 740 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
518 740 : proto_prefix->prefix.begin() + rd_offset);
519 740 : size_t tag_offset = rd_offset + kRdSize;
520 740 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
521 740 : size_t ip_len_offset = tag_offset + kTagSize;
522 740 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
523 740 : size_t ip_offset = ip_len_offset + 1;
524 740 : WriteIpAddress(proto_prefix, ip_offset);
525 740 : break;
526 : }
527 2 : case SegmentRoute: {
528 2 : size_t ip_size = GetIpAddressSize();
529 2 : size_t nlri_size = kMinSegmentRouteSize + ip_size;
530 2 : proto_prefix->prefixlen = nlri_size * 8;
531 2 : proto_prefix->prefix.resize(nlri_size, 0);
532 :
533 2 : size_t rd_offset = 0;
534 2 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
535 2 : proto_prefix->prefix.begin() + rd_offset);
536 2 : size_t esi_offset = rd_offset + kRdSize;
537 2 : copy(esi_.GetData(), esi_.GetData() + kEsiSize,
538 2 : proto_prefix->prefix.begin() + esi_offset);
539 2 : size_t ip_len_offset = esi_offset + kEsiSize;
540 2 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
541 2 : size_t ip_offset = ip_len_offset + 1;
542 2 : WriteIpAddress(proto_prefix, ip_offset);
543 2 : break;
544 : }
545 1759 : case IpPrefixRoute: {
546 : size_t ip_size, nlri_size;
547 1759 : if (family_ == Address::INET) {
548 1122 : ip_size = kIp4AddrSize;
549 1122 : nlri_size = kMinInetPrefixRouteSize + kLabelSize;
550 : } else {
551 637 : ip_size = kIp6AddrSize;
552 637 : nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
553 : }
554 1759 : proto_prefix->prefixlen = nlri_size * 8;
555 1759 : proto_prefix->prefix.resize(nlri_size, 0);
556 :
557 1759 : size_t rd_offset = 0;
558 1759 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
559 1759 : proto_prefix->prefix.begin() + rd_offset);
560 1759 : size_t esi_offset = rd_offset + kRdSize;
561 1759 : if (attr) {
562 1292 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
563 2584 : proto_prefix->prefix.begin() + esi_offset);
564 : }
565 1759 : size_t tag_offset = esi_offset + kEsiSize;
566 : // Tag is not applicable for type5 routes.
567 1759 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
568 1759 : size_t ip_plen_offset = tag_offset + kTagSize;
569 1759 : proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
570 1759 : size_t ip_offset = ip_plen_offset + 1;
571 1759 : WriteIpAddress(proto_prefix, ip_offset);
572 1758 : size_t gw_offset = ip_offset + ip_size;
573 1758 : size_t label_offset = gw_offset + ip_size;
574 1758 : WriteLabel(proto_prefix, attr, label_offset, label);
575 1757 : break;
576 : }
577 48 : case SelectiveMulticastRoute: {
578 48 : size_t ip_size = GetIpAddressSize();
579 48 : size_t nlri_size = kMinSelectiveMulticastRouteSize + 2 * ip_size + 1;
580 48 : if (!source_.is_unspecified())
581 48 : nlri_size += ip_size;
582 48 : proto_prefix->prefixlen = nlri_size * 8;
583 48 : proto_prefix->prefix.resize(nlri_size, 0);
584 :
585 48 : size_t rd_offset = 0;
586 48 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
587 48 : proto_prefix->prefix.begin() + rd_offset);
588 48 : size_t tag_offset = rd_offset + kRdSize;
589 48 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
590 48 : size_t src_len_offset = tag_offset + kTagSize;
591 48 : size_t grp_len_offset = src_len_offset + 1;
592 48 : if (source_.is_unspecified()) {
593 0 : proto_prefix->prefix[src_len_offset] = 0;
594 : } else {
595 48 : proto_prefix->prefix[src_len_offset] = ip_size * 8;
596 48 : size_t src_offset = src_len_offset + 1;
597 48 : WriteSource(proto_prefix, src_offset);
598 48 : grp_len_offset += ip_size;
599 : }
600 48 : proto_prefix->prefix[grp_len_offset] = ip_size * 8;
601 48 : size_t grp_offset = grp_len_offset + 1;
602 48 : WriteGroup(proto_prefix, grp_offset);
603 48 : size_t ip_len_offset = grp_offset + ip_size;
604 48 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
605 48 : size_t ip_offset = ip_len_offset + 1;
606 48 : WriteIpAddress(proto_prefix, ip_offset);
607 48 : size_t flag_offset = ip_offset + ip_size;
608 48 : put_value(&proto_prefix->prefix[flag_offset], 1, flags_);
609 48 : break;
610 : }
611 0 : default: {
612 0 : assert(false);
613 : break;
614 : }
615 : }
616 30042 : }
617 :
618 2739867 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
619 2739867 : KEY_COMPARE(type_, rhs.type_);
620 :
621 2703547 : switch (type_) {
622 41839 : case AutoDiscoveryRoute:
623 41839 : KEY_COMPARE(rd_, rhs.rd_);
624 29520 : KEY_COMPARE(esi_, rhs.esi_);
625 17201 : KEY_COMPARE(tag_, rhs.tag_);
626 4882 : break;
627 1046697 : case MacAdvertisementRoute:
628 1046697 : KEY_COMPARE(rd_, rhs.rd_);
629 545306 : KEY_COMPARE(tag_, rhs.tag_);
630 544740 : KEY_COMPARE(mac_addr_, rhs.mac_addr_);
631 225552 : KEY_COMPARE(ip_address_, rhs.ip_address_);
632 158782 : break;
633 471093 : case InclusiveMulticastRoute:
634 471093 : KEY_COMPARE(rd_, rhs.rd_);
635 190561 : KEY_COMPARE(tag_, rhs.tag_);
636 176140 : KEY_COMPARE(ip_address_, rhs.ip_address_);
637 109846 : break;
638 41571 : case SegmentRoute:
639 41571 : KEY_COMPARE(rd_, rhs.rd_);
640 29252 : KEY_COMPARE(esi_, rhs.esi_);
641 16933 : KEY_COMPARE(ip_address_, rhs.ip_address_);
642 4614 : break;
643 1081879 : case IpPrefixRoute:
644 1081879 : KEY_COMPARE(rd_, rhs.rd_);
645 1001735 : KEY_COMPARE(tag_, rhs.tag_);
646 1001735 : KEY_COMPARE(ip_address_, rhs.ip_address_);
647 170525 : KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
648 170525 : break;
649 20489 : case SelectiveMulticastRoute:
650 20489 : KEY_COMPARE(rd_, rhs.rd_);
651 20148 : KEY_COMPARE(tag_, rhs.tag_);
652 17358 : KEY_COMPARE(source_, rhs.source_);
653 17358 : KEY_COMPARE(group_, rhs.group_);
654 10538 : KEY_COMPARE(ip_address_, rhs.ip_address_);
655 : default:
656 10517 : break;
657 : }
658 :
659 459166 : return 0;
660 : }
661 :
662 : // Check whether 'this' is more specific than rhs.
663 19866 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
664 19866 : switch (type_) {
665 19868 : case IpPrefixRoute:
666 19868 : if (family_ == Address::INET) {
667 9942 : return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
668 : } else {
669 9926 : return inet6_prefix().IsMoreSpecific(rhs.inet6_prefix());
670 : }
671 : break;
672 0 : default:
673 0 : break;
674 : }
675 0 : return false;
676 : }
677 :
678 3336 : bool EvpnPrefix::GetSourceFromString(EvpnPrefix *prefix, const string &str,
679 : size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
680 3336 : *pos2 = str.find('-', pos1 + 1);
681 3336 : if (*pos2 == string::npos) {
682 0 : if (errorp != NULL) {
683 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
684 : }
685 0 : return false;
686 : }
687 3336 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
688 3336 : boost::system::error_code source_err;
689 3336 : prefix->source_ = Ip4Address::from_string(temp_str, source_err);
690 3336 : if (source_err.failed()) {
691 0 : if (errorp != NULL) {
692 0 : *errorp = source_err;
693 : }
694 0 : return false;
695 : }
696 3336 : return true;
697 3336 : }
698 :
699 3336 : bool EvpnPrefix::GetGroupFromString(EvpnPrefix *prefix, const string &str,
700 : size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
701 3336 : *pos2 = str.find('-', pos1 + 1);
702 3336 : if (*pos2 == string::npos) {
703 0 : if (errorp != NULL) {
704 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
705 : }
706 0 : return false;
707 : }
708 3336 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
709 3336 : boost::system::error_code group_err;
710 3336 : prefix->group_ = Ip4Address::from_string(temp_str, group_err);
711 3336 : if (group_err.failed()) {
712 0 : if (errorp != NULL) {
713 0 : *errorp = group_err;
714 : }
715 0 : return false;
716 : }
717 3336 : return true;
718 3336 : }
719 :
720 75686 : EvpnPrefix EvpnPrefix::FromString(const string &str,
721 : boost::system::error_code *errorp) {
722 75686 : EvpnPrefix prefix;
723 :
724 : // Parse type.
725 75686 : size_t pos1 = str.find('-');
726 75686 : if (pos1 == string::npos) {
727 214 : if (errorp != NULL) {
728 214 : *errorp = make_error_code(boost::system::errc::invalid_argument);
729 : }
730 214 : return EvpnPrefix::kNullPrefix;
731 : }
732 :
733 75472 : string type_str = str.substr(0, pos1);
734 75472 : bool ret = stringToInteger(type_str, prefix.type_);
735 75472 : if (!ret) {
736 1 : if (errorp != NULL) {
737 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
738 : }
739 1 : return EvpnPrefix::kNullPrefix;
740 : }
741 :
742 75471 : if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
743 75470 : prefix.type_ > EvpnPrefix::SelectiveMulticastRoute) {
744 1 : if (errorp != NULL) {
745 1 : *errorp = make_error_code(boost::system::errc::invalid_argument);
746 : }
747 1 : return EvpnPrefix::kNullPrefix;
748 : }
749 :
750 : // Parse RD.
751 75470 : size_t pos2 = str.find('-', pos1 + 1);
752 75470 : if (pos2 == string::npos) {
753 6 : if (errorp != NULL) {
754 6 : *errorp = make_error_code(boost::system::errc::invalid_argument);
755 : }
756 6 : return EvpnPrefix::kNullPrefix;
757 : }
758 75464 : string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
759 75464 : boost::system::error_code rd_err;
760 75464 : prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
761 75464 : if (rd_err.failed()) {
762 5 : if (errorp != NULL) {
763 5 : *errorp = rd_err;
764 : }
765 5 : return EvpnPrefix::kNullPrefix;
766 : }
767 :
768 75459 : switch (prefix.type_) {
769 3162 : case AutoDiscoveryRoute: {
770 : // Parse ESI.
771 3162 : size_t pos3 = str.find('-', pos2 + 1);
772 3162 : if (pos3 == string::npos) {
773 1 : if (errorp != NULL) {
774 : *errorp =
775 1 : make_error_code(boost::system::errc::invalid_argument);
776 : }
777 3 : return EvpnPrefix::kNullPrefix;
778 : }
779 3161 : string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
780 3161 : boost::system::error_code esi_err;
781 3161 : prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
782 3161 : if (esi_err.failed()) {
783 1 : if (errorp != NULL) {
784 1 : *errorp = esi_err;
785 : }
786 1 : return EvpnPrefix::kNullPrefix;
787 : }
788 :
789 : // Parse tag.
790 3160 : string tag_str = str.substr(pos3 + 1, string::npos);
791 3160 : bool ret = stringToInteger(tag_str, prefix.tag_);
792 3160 : if (!ret) {
793 1 : if (errorp != NULL) {
794 : *errorp =
795 1 : make_error_code(boost::system::errc::invalid_argument);
796 : }
797 1 : return EvpnPrefix::kNullPrefix;
798 : }
799 :
800 3159 : break;
801 6321 : }
802 :
803 11455 : case MacAdvertisementRoute: {
804 : // Parse tag.
805 11455 : size_t pos3 = str.find('-', pos2 + 1);
806 11455 : if (pos3 == string::npos) {
807 1 : if (errorp != NULL) {
808 : *errorp =
809 1 : make_error_code(boost::system::errc::invalid_argument);
810 : }
811 5 : return EvpnPrefix::kNullPrefix;
812 : }
813 11454 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
814 11454 : bool ret = stringToInteger(tag_str, prefix.tag_);
815 11454 : if (!ret) {
816 1 : if (errorp != NULL) {
817 : *errorp =
818 1 : make_error_code(boost::system::errc::invalid_argument);
819 : }
820 1 : return EvpnPrefix::kNullPrefix;
821 : }
822 :
823 : // Parse MAC.
824 11453 : size_t pos4 = str.rfind(',');
825 11453 : string mac_str = str.substr(pos3 + 1, pos4 - pos3 -1);
826 11453 : boost::system::error_code mac_err;
827 11453 : prefix.mac_addr_ = MacAddress::FromString(mac_str, &mac_err);
828 11453 : if (mac_err.failed()) {
829 2 : if (errorp != NULL) {
830 2 : *errorp = mac_err;
831 : }
832 2 : return EvpnPrefix::kNullPrefix;
833 : }
834 :
835 : // Parse IP - treat all 0s as unspecified.
836 11451 : string ip_str = str.substr(pos4 + 1, string::npos);
837 11451 : boost::system::error_code ip_err;
838 11451 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
839 11451 : if (ip_err.failed()) {
840 1 : if (errorp != NULL) {
841 1 : *errorp = ip_err;
842 : }
843 1 : return EvpnPrefix::kNullPrefix;
844 : }
845 11450 : if (prefix.ip_address_.is_v4() && !prefix.ip_address_.is_unspecified())
846 11326 : prefix.family_ = Address::INET;
847 11450 : if (prefix.ip_address_.is_v6() && !prefix.ip_address_.is_unspecified())
848 55 : prefix.family_ = Address::INET6;
849 :
850 11450 : break;
851 34358 : }
852 :
853 9269 : case InclusiveMulticastRoute: {
854 : // Parse tag.
855 9269 : size_t pos3 = str.find('-', pos2 + 1);
856 9269 : if (pos3 == string::npos) {
857 1 : if (errorp != NULL) {
858 : *errorp =
859 1 : make_error_code(boost::system::errc::invalid_argument);
860 : }
861 3 : return EvpnPrefix::kNullPrefix;
862 : }
863 9268 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
864 9268 : bool ret = stringToInteger(tag_str, prefix.tag_);
865 9268 : if (!ret) {
866 1 : if (errorp != NULL) {
867 : *errorp =
868 1 : make_error_code(boost::system::errc::invalid_argument);
869 : }
870 1 : return EvpnPrefix::kNullPrefix;
871 : }
872 :
873 : // Parse IP.
874 9267 : string ip_str = str.substr(pos3 + 1, string::npos);
875 9267 : boost::system::error_code ip_err;
876 9267 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
877 9267 : if (ip_err.failed()) {
878 1 : if (errorp != NULL) {
879 1 : *errorp = ip_err;
880 : }
881 1 : return EvpnPrefix::kNullPrefix;
882 : }
883 9266 : prefix.family_ =
884 9266 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
885 :
886 9266 : break;
887 18535 : }
888 :
889 3088 : case SegmentRoute: {
890 : // Parse ESI.
891 3088 : size_t pos3 = str.find('-', pos2 + 1);
892 3088 : if (pos3 == string::npos) {
893 1 : if (errorp != NULL) {
894 : *errorp =
895 1 : make_error_code(boost::system::errc::invalid_argument);
896 : }
897 3 : return EvpnPrefix::kNullPrefix;
898 : }
899 3087 : string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
900 3087 : boost::system::error_code esi_err;
901 3087 : prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
902 3087 : if (esi_err.failed()) {
903 1 : if (errorp != NULL) {
904 1 : *errorp = esi_err;
905 : }
906 1 : return EvpnPrefix::kNullPrefix;
907 : }
908 :
909 : // Parse IP.
910 3086 : string ip_str = str.substr(pos3 + 1, string::npos);
911 3086 : boost::system::error_code ip_err;
912 3086 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
913 3086 : if (ip_err.failed()) {
914 1 : if (errorp != NULL) {
915 1 : *errorp = ip_err;
916 : }
917 1 : return EvpnPrefix::kNullPrefix;
918 : }
919 3085 : prefix.family_ =
920 3085 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
921 :
922 3085 : break;
923 6173 : }
924 :
925 45149 : case IpPrefixRoute: {
926 : // Parse tag.
927 45149 : size_t pos3 = str.find('-', pos2 + 1);
928 45149 : if (pos3 == string::npos) {
929 1 : if (errorp != NULL) {
930 : *errorp =
931 1 : make_error_code(boost::system::errc::invalid_argument);
932 : }
933 1 : return EvpnPrefix::kNullPrefix;
934 : }
935 45148 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
936 45148 : bool ret = stringToInteger(tag_str, prefix.tag_);
937 45148 : if (!ret) {
938 2 : if (errorp != NULL) {
939 : *errorp =
940 2 : make_error_code(boost::system::errc::invalid_argument);
941 : }
942 2 : return EvpnPrefix::kNullPrefix;
943 : }
944 :
945 : // Parse IP prefix - first try v4, then v6.
946 45146 : string ip_str = str.substr(pos3 + 1, string::npos);
947 45146 : boost::system::error_code ip_err;
948 :
949 45146 : Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
950 45146 : if (!ip_err) {
951 23102 : prefix.family_ = Address::INET;
952 23102 : prefix.ip_address_ = inet_prefix.addr();
953 23102 : prefix.ip_prefixlen_ = inet_prefix.prefixlen();
954 23102 : return prefix;
955 : }
956 :
957 22044 : Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
958 22044 : if (!ip_err) {
959 22030 : prefix.family_ = Address::INET6;
960 22030 : prefix.ip_address_ = inet6_prefix.addr();
961 22030 : prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
962 22030 : return prefix;
963 : }
964 :
965 14 : if (errorp != NULL) {
966 14 : *errorp = make_error_code(boost::system::errc::invalid_argument);
967 : }
968 14 : return EvpnPrefix::kNullPrefix;
969 : break;
970 45148 : }
971 :
972 3336 : case SelectiveMulticastRoute: {
973 : // Parse tag.
974 3336 : size_t pos3 = str.find('-', pos2 + 1);
975 3336 : if (pos3 == string::npos) {
976 0 : if (errorp != NULL) {
977 : *errorp =
978 0 : make_error_code(boost::system::errc::invalid_argument);
979 : }
980 0 : return EvpnPrefix::kNullPrefix;
981 : }
982 3336 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
983 3336 : bool ret = stringToInteger(tag_str, prefix.tag_);
984 3336 : if (!ret) {
985 0 : if (errorp != NULL) {
986 : *errorp =
987 0 : make_error_code(boost::system::errc::invalid_argument);
988 : }
989 0 : return EvpnPrefix::kNullPrefix;
990 : }
991 :
992 : // Look for source.
993 : size_t pos4;
994 3336 : if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
995 0 : return EvpnPrefix::kNullPrefix;
996 :
997 : // Look for group.
998 : size_t pos5;
999 3336 : if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
1000 0 : return EvpnPrefix::kNullPrefix;
1001 :
1002 : // Parse IP.
1003 3336 : string ip_str = str.substr(pos5 + 1, string::npos);
1004 3336 : boost::system::error_code ip_err;
1005 3336 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
1006 3336 : if (ip_err.failed()) {
1007 0 : if (errorp != NULL) {
1008 0 : *errorp = ip_err;
1009 : }
1010 0 : return EvpnPrefix::kNullPrefix;
1011 : }
1012 3336 : prefix.family_ =
1013 3336 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
1014 :
1015 3336 : break;
1016 6672 : }
1017 :
1018 : }
1019 :
1020 30296 : return prefix;
1021 75472 : }
1022 :
1023 89436 : string EvpnPrefix::ToString() const {
1024 89436 : string str = integerToString(type_);
1025 89439 : str += "-" + rd_.ToString();
1026 89436 : switch (type_) {
1027 1643 : case AutoDiscoveryRoute:
1028 1643 : str += "-" + esi_.ToString();
1029 1643 : str += "-" + integerToString(tag_);
1030 1643 : break;
1031 42079 : case MacAdvertisementRoute:
1032 42079 : str += "-" + integerToString(tag_);
1033 42078 : str += "-" + mac_addr_.ToString();
1034 42078 : str += "," + ip_address_.to_string();
1035 42078 : break;
1036 9751 : case InclusiveMulticastRoute:
1037 9751 : str += "-" + integerToString(tag_);
1038 9751 : str += "-" + ip_address_.to_string();
1039 9751 : break;
1040 1543 : case SegmentRoute:
1041 1543 : str += "-" + esi_.ToString();
1042 1543 : str += "-" + ip_address_.to_string();
1043 1543 : break;
1044 25360 : case IpPrefixRoute:
1045 25360 : str += "-" + integerToString(tag_);
1046 25362 : if (family_ == Address::INET) {
1047 13515 : str += "-" + inet_prefix().ToString();
1048 : } else {
1049 11847 : str += "-" + inet6_prefix().ToString();
1050 : }
1051 25362 : break;
1052 9060 : case SelectiveMulticastRoute:
1053 9060 : str += "-" + integerToString(tag_);
1054 9060 : if (!source_.is_unspecified())
1055 9055 : str += "-" + source_.to_string();
1056 9060 : str += "-" + group_.to_string();
1057 9060 : str += "-" + ip_address_.to_string();
1058 9058 : break;
1059 0 : default:
1060 0 : break;
1061 : }
1062 :
1063 89435 : return str;
1064 0 : }
1065 :
1066 8762 : string EvpnPrefix::ToXmppIdString() const {
1067 8762 : string str;
1068 8762 : if (tag_ != 0)
1069 200 : str += integerToString(tag_) + "-";
1070 8762 : str += mac_addr_.ToString();
1071 17526 : str += "," + ip_address_.to_string() + "/" +
1072 26287 : integerToString(ip_address_length());
1073 8762 : if (!group_.is_unspecified()) {
1074 72 : str += "," + group_.to_string() + "," +
1075 108 : source_.to_string();
1076 : }
1077 8762 : return str;
1078 0 : }
1079 :
1080 19921 : uint8_t EvpnPrefix::ip_address_length() const {
1081 19921 : if (type_ == IpPrefixRoute)
1082 2716 : return ip_prefixlen_;
1083 17205 : if (family_ == Address::INET)
1084 541 : return 32;
1085 16664 : if (family_ == Address::INET6)
1086 71 : return 128;
1087 16593 : return 32;
1088 : }
1089 :
1090 28257 : size_t EvpnPrefix::GetIpAddressSize() const {
1091 28257 : if (family_ == Address::INET)
1092 958 : return kIp4AddrSize;
1093 27299 : if (family_ == Address::INET6)
1094 92 : return kIp6AddrSize;
1095 27207 : return 0;
1096 : }
1097 :
1098 48 : void EvpnPrefix::ReadSource(const BgpProtoPrefix &proto_prefix,
1099 : size_t ip_offset, size_t ip_size) {
1100 48 : if (ip_size == 0) {
1101 0 : family_ = Address::UNSPEC;
1102 48 : } else if (ip_size == kIp4AddrSize) {
1103 48 : family_ = Address::INET;
1104 48 : Ip4Address::bytes_type bytes = { { 0 } };
1105 96 : copy(proto_prefix.prefix.begin() + ip_offset,
1106 48 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1107 48 : source_ = Ip4Address(bytes);
1108 0 : } else if (ip_size == kIp6AddrSize) {
1109 0 : family_ = Address::INET6;
1110 0 : Ip6Address::bytes_type bytes = { { 0 } };
1111 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1112 0 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1113 0 : source_ = Ip6Address(bytes);
1114 : }
1115 48 : }
1116 :
1117 48 : void EvpnPrefix::ReadGroup(const BgpProtoPrefix &proto_prefix,
1118 : size_t ip_offset, size_t ip_size) {
1119 48 : if (ip_size == 0) {
1120 0 : family_ = Address::UNSPEC;
1121 48 : } else if (ip_size == kIp4AddrSize) {
1122 48 : family_ = Address::INET;
1123 48 : Ip4Address::bytes_type bytes = { { 0 } };
1124 96 : copy(proto_prefix.prefix.begin() + ip_offset,
1125 48 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1126 48 : group_ = Ip4Address(bytes);
1127 0 : } else if (ip_size == kIp6AddrSize) {
1128 0 : family_ = Address::INET6;
1129 0 : Ip6Address::bytes_type bytes = { { 0 } };
1130 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1131 0 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1132 0 : group_ = Ip6Address(bytes);
1133 : }
1134 48 : }
1135 :
1136 26246 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
1137 : size_t ip_offset, size_t ip_size, size_t ip_psize) {
1138 26246 : assert(ip_psize <= ip_size);
1139 26246 : if (ip_size == 0) {
1140 23417 : family_ = Address::UNSPEC;
1141 2829 : } else if (ip_size == kIp4AddrSize) {
1142 2084 : family_ = Address::INET;
1143 2084 : Ip4Address::bytes_type bytes = { { 0 } };
1144 4168 : copy(proto_prefix.prefix.begin() + ip_offset,
1145 2084 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1146 2084 : ip_address_ = Ip4Address(bytes);
1147 745 : } else if (ip_size == kIp6AddrSize) {
1148 745 : family_ = Address::INET6;
1149 745 : Ip6Address::bytes_type bytes = { { 0 } };
1150 1490 : copy(proto_prefix.prefix.begin() + ip_offset,
1151 745 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1152 745 : ip_address_ = Ip6Address(bytes);
1153 : }
1154 26246 : }
1155 :
1156 30016 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
1157 : size_t ip_offset) const {
1158 30016 : if (family_ == Address::INET) {
1159 2080 : const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
1160 2080 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1161 4160 : proto_prefix->prefix.begin() + ip_offset);
1162 27936 : } else if (family_ == Address::INET6) {
1163 729 : const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
1164 729 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1165 1458 : proto_prefix->prefix.begin() + ip_offset);
1166 : }
1167 30016 : }
1168 :
1169 48 : void EvpnPrefix::WriteSource(BgpProtoPrefix *proto_prefix,
1170 : size_t ip_offset) const {
1171 48 : if (family_ == Address::INET) {
1172 48 : const Ip4Address::bytes_type &bytes = source_.to_v4().to_bytes();
1173 48 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1174 96 : proto_prefix->prefix.begin() + ip_offset);
1175 0 : } else if (family_ == Address::INET6) {
1176 0 : const Ip6Address::bytes_type &bytes = source_.to_v6().to_bytes();
1177 0 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1178 0 : proto_prefix->prefix.begin() + ip_offset);
1179 : }
1180 48 : }
1181 :
1182 48 : void EvpnPrefix::WriteGroup(BgpProtoPrefix *proto_prefix,
1183 : size_t ip_offset) const {
1184 48 : if (family_ == Address::INET) {
1185 48 : const Ip4Address::bytes_type &bytes = group_.to_v4().to_bytes();
1186 48 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1187 96 : proto_prefix->prefix.begin() + ip_offset);
1188 0 : } else if (family_ == Address::INET6) {
1189 0 : const Ip6Address::bytes_type &bytes = group_.to_v6().to_bytes();
1190 0 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1191 0 : proto_prefix->prefix.begin() + ip_offset);
1192 : }
1193 48 : }
1194 :
1195 352046 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
1196 352046 : : prefix_(prefix) {
1197 351968 : }
1198 :
1199 2713556 : int EvpnRoute::CompareTo(const Route &rhs) const {
1200 2713556 : const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
1201 2713556 : return prefix_.CompareTo(evpn_rhs.prefix_);
1202 : }
1203 :
1204 88032 : string EvpnRoute::ToString() const {
1205 88032 : return prefix_.ToString();
1206 : }
1207 :
1208 12511 : string EvpnRoute::ToXmppIdString() const {
1209 12511 : if (xmpp_id_str_.empty())
1210 4302 : xmpp_id_str_ = prefix_.ToXmppIdString();
1211 12511 : return xmpp_id_str_;
1212 : }
1213 :
1214 55319 : bool EvpnRoute::IsValid() const {
1215 55319 : if (!BgpRoute::IsValid())
1216 8368 : return false;
1217 :
1218 46951 : const BgpAttr *attr = BestPath()->GetAttr();
1219 46951 : switch (prefix_.type()) {
1220 56 : case EvpnPrefix::AutoDiscoveryRoute: {
1221 56 : if (prefix_.tag() == EvpnPrefix::kMaxTag)
1222 56 : return true;
1223 0 : break;
1224 : }
1225 25961 : case EvpnPrefix::MacAdvertisementRoute: {
1226 25961 : return true;
1227 : }
1228 20934 : case EvpnPrefix::InclusiveMulticastRoute: {
1229 20934 : const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
1230 20934 : if (!pmsi_tunnel)
1231 0 : return false;
1232 20934 : uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
1233 20934 : uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
1234 20934 : uint8_t ar_type =
1235 : tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
1236 20934 : if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
1237 20276 : if (ar_type == PmsiTunnelSpec::RegularNVE)
1238 18544 : return true;
1239 1732 : if (ar_type == PmsiTunnelSpec::ARReplicator &&
1240 1732 : (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
1241 1732 : return true;
1242 : }
1243 0 : return false;
1244 : }
1245 658 : if (tunnel_type == PmsiTunnelSpec::AssistedReplicationContrail &&
1246 : ar_type == PmsiTunnelSpec::ARLeaf) {
1247 658 : return true;
1248 : }
1249 0 : return false;
1250 : }
1251 0 : case EvpnPrefix::SegmentRoute: {
1252 0 : return false;
1253 : }
1254 0 : case EvpnPrefix::IpPrefixRoute: {
1255 0 : return false;
1256 : }
1257 0 : case EvpnPrefix::SelectiveMulticastRoute: {
1258 0 : return false;
1259 : }
1260 0 : default: {
1261 0 : break;
1262 : }
1263 : }
1264 :
1265 0 : return false;
1266 : }
1267 :
1268 25 : void EvpnRoute::SetKey(const DBRequestKey *reqkey) {
1269 25 : const EvpnTable::RequestKey *key =
1270 : static_cast<const EvpnTable::RequestKey *>(reqkey);
1271 25 : prefix_ = key->prefix;
1272 25 : }
1273 :
1274 29829 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
1275 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
1276 29829 : prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
1277 29827 : }
1278 :
1279 13016 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
1280 : IpAddress nexthop) const {
1281 13016 : nh.resize(4);
1282 13015 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
1283 13015 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
1284 13015 : }
1285 :
1286 51289 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
1287 51289 : EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
1288 51285 : return KeyPtr(key);
1289 : }
|