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