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 25358 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
58 : const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
59 25358 : if (!attr)
60 6888 : return 0;
61 18470 : const ExtCommunity *extcomm = attr->ext_community();
62 18470 : 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 18324 : return proto_prefix.ReadLabel(offset, false);
76 : }
77 : }
78 :
79 : //
80 : // Write label to the BgpProtoPrefix.
81 : //
82 29377 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
83 : const BgpAttr *attr, size_t offset, uint32_t label) {
84 29377 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
85 29377 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
86 146 : proto_prefix->WriteLabel(offset, label, true);
87 : } else {
88 29231 : proto_prefix->WriteLabel(offset, label, false);
89 : }
90 29377 : }
91 :
92 : //
93 : // Read gateway address from the BgpProtoPrefix.
94 : //
95 1591 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
96 : size_t gw_offset, size_t ip_size) {
97 1591 : assert(ip_size == EvpnPrefix::kIp4AddrSize ||
98 : ip_size == EvpnPrefix::kIp6AddrSize);
99 1591 : if (ip_size == EvpnPrefix::kIp4AddrSize) {
100 : Ip4Address::bytes_type bytes;
101 2010 : copy(proto_prefix.prefix.begin() + gw_offset,
102 1005 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
103 1005 : return Ip4Address(bytes);
104 : } else {
105 : Ip6Address::bytes_type bytes;
106 1172 : copy(proto_prefix.prefix.begin() + gw_offset,
107 586 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
108 586 : return Ip6Address(bytes);
109 : }
110 : return IpAddress();
111 : }
112 :
113 128512 : EvpnPrefix::EvpnPrefix()
114 128512 : : type_(Unspecified),
115 128509 : tag_(EvpnPrefix::kNullTag),
116 128506 : family_(Address::UNSPEC),
117 128512 : ip_prefixlen_(0) {
118 128495 : }
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 15633 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
152 219 : family_ = Address::INET;
153 15414 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
154 28 : family_ = Address::INET6;
155 : }
156 15633 : }
157 :
158 24875 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
159 24875 : const IpAddress &ip_address)
160 24875 : : type_(InclusiveMulticastRoute),
161 24875 : rd_(rd),
162 24875 : tag_(tag),
163 24875 : family_(Address::UNSPEC),
164 24875 : ip_address_(ip_address),
165 49750 : ip_prefixlen_(0) {
166 24875 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
167 24870 : family_ = Address::INET;
168 5 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
169 5 : family_ = Address::INET6;
170 : }
171 24875 : }
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 1021 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
190 1021 : const IpAddress &ip_address, uint8_t ip_prefixlen)
191 1021 : : type_(IpPrefixRoute),
192 1021 : rd_(rd),
193 1021 : tag_(0),
194 1021 : family_(Address::UNSPEC),
195 1021 : ip_address_(ip_address),
196 2042 : ip_prefixlen_(ip_prefixlen) {
197 1021 : assert(ip_address_.is_v4() || ip_address_.is_v6());
198 1021 : if (ip_address_.is_v4()) {
199 647 : family_ = Address::INET;
200 374 : } else if (ip_address_.is_v6()) {
201 374 : family_ = Address::INET6;
202 : }
203 1021 : }
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 28640 : 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 28640 : *new_attr = attr;
236 28640 : *label = 0;
237 28640 : if (l3_label)
238 25949 : *l3_label = 0;
239 28640 : prefix->type_ = proto_prefix.type;
240 28640 : size_t nlri_size = proto_prefix.prefix.size();
241 :
242 28640 : 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 24796 : case MacAdvertisementRoute: {
259 24796 : size_t expected_min_nlri_size =
260 24796 : kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
261 24796 : if (nlri_size < expected_min_nlri_size)
262 63 : return -1;
263 24733 : size_t rd_offset = 0;
264 24733 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
265 24733 : size_t esi_offset = rd_offset + kRdSize;
266 24733 : if (attr) {
267 17816 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
268 17816 : *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
269 : }
270 24733 : size_t tag_offset = esi_offset + kEsiSize;
271 24733 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
272 24733 : size_t mac_len_offset = tag_offset + kTagSize;
273 24733 : size_t mac_len = proto_prefix.prefix[mac_len_offset];
274 24733 : if (mac_len != 48)
275 510 : return -1;
276 24223 : size_t mac_offset = mac_len_offset + 1;
277 24223 : prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
278 24223 : size_t ip_len_offset = mac_offset + kMacSize;
279 24223 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
280 24223 : if (ip_len != 0 && ip_len != 32 && ip_len != 128)
281 506 : return -1;
282 23717 : size_t ip_size = ip_len / 8;
283 23717 : if (nlri_size < expected_min_nlri_size + ip_size)
284 40 : return -1;
285 23677 : size_t ip_offset = ip_len_offset + 1;
286 23677 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
287 23677 : size_t label_offset = ip_offset + ip_size;
288 23677 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
289 23677 : size_t l3_label_offset = label_offset + kLabelSize;
290 23677 : if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
291 76 : *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
292 : }
293 23677 : 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 2141 : case IpPrefixRoute: {
348 : size_t ip_size;
349 2141 : if (attr) {
350 1581 : if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
351 572 : ip_size = kIp6AddrSize;
352 1009 : } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
353 917 : ip_size = kIp4AddrSize;
354 : } else {
355 570 : return -1;
356 : }
357 : } else {
358 560 : if (nlri_size == kMinInet6PrefixRouteSize ||
359 560 : nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
360 151 : ip_size = kIp6AddrSize;
361 409 : } else if (nlri_size == kMinInetPrefixRouteSize ||
362 409 : nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
363 321 : ip_size = kIp4AddrSize;
364 : } else {
365 88 : return -1;
366 : }
367 : }
368 :
369 1961 : size_t rd_offset = 0;
370 1961 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
371 1961 : size_t esi_offset = rd_offset + kRdSize;
372 1961 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
373 1961 : if (!esi.IsZero())
374 20 : return -1;
375 1941 : size_t tag_offset = esi_offset + kEsiSize;
376 : // Ignore tag for type5 routes.
377 1941 : prefix->tag_ = 0;
378 1941 : size_t ip_plen_offset = tag_offset + kTagSize;
379 1941 : prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
380 1941 : if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
381 223 : return -1;
382 1718 : if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
383 127 : return -1;
384 1591 : size_t ip_offset = ip_plen_offset + 1;
385 1591 : size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
386 1591 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
387 1591 : size_t gw_offset = ip_offset + ip_size;
388 1591 : IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
389 1591 : if (!gw_address.is_unspecified())
390 20 : return -1;
391 1571 : size_t label_offset = gw_offset + ip_size;
392 1571 : *label = ReadLabel(proto_prefix, attr, label_offset);
393 1571 : break;
394 : }
395 51 : case SelectiveMulticastRoute: {
396 51 : if (nlri_size < kMinSelectiveMulticastRouteSize)
397 1 : return -1;
398 50 : size_t rd_offset = 0;
399 50 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
400 50 : size_t tag_offset = rd_offset + kRdSize;
401 50 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
402 50 : size_t src_len_offset = tag_offset + kTagSize;
403 50 : size_t src_len = proto_prefix.prefix[src_len_offset];
404 50 : if (src_len != 32 && src_len != 128 && src_len != 0)
405 0 : return -1;
406 50 : size_t src_size = src_len / 8;
407 50 : size_t src_offset = src_len_offset + 1;
408 50 : if (src_size > 0) {
409 50 : if (nlri_size < src_offset + src_size)
410 0 : return -1;
411 50 : prefix->ReadSource(proto_prefix, src_offset, src_size);
412 : }
413 50 : size_t grp_len_offset = src_offset + src_size;
414 50 : size_t grp_len = proto_prefix.prefix[grp_len_offset];
415 50 : if (grp_len != 32 && grp_len != 128)
416 0 : return -1;
417 50 : size_t grp_size = grp_len / 8;
418 50 : size_t grp_offset = grp_len_offset + 1;
419 50 : if (nlri_size < grp_offset + grp_size)
420 0 : return -1;
421 50 : prefix->ReadGroup(proto_prefix, grp_offset, grp_size);
422 50 : size_t ip_len_offset = grp_offset + grp_size;
423 50 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
424 50 : if (ip_len != 32 && ip_len != 128)
425 0 : return -1;
426 50 : size_t ip_size = ip_len / 8;
427 50 : size_t ip_offset = ip_len_offset + 1;
428 50 : if (nlri_size < ip_offset + ip_size)
429 0 : return -1;
430 50 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
431 50 : size_t flag_offset = ip_offset + ip_size;
432 50 : if (nlri_size <= flag_offset + 4)
433 50 : prefix->flags_ = get_value(&proto_prefix.prefix[flag_offset], 4);
434 50 : break;
435 : }
436 249 : default: {
437 249 : return -1;
438 : break;
439 : }
440 : }
441 26074 : 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 30093 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
452 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
453 30093 : proto_prefix->type = type_;
454 30093 : proto_prefix->prefix.clear();
455 :
456 30093 : 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 27702 : case MacAdvertisementRoute: {
475 27702 : size_t ip_size = GetIpAddressSize();
476 27702 : size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
477 27702 : if (l3_label)
478 76 : nlri_size += kLabelSize;
479 27702 : proto_prefix->prefixlen = nlri_size * 8;
480 27702 : proto_prefix->prefix.resize(nlri_size, 0);
481 :
482 27702 : size_t rd_offset = 0;
483 27702 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
484 27702 : proto_prefix->prefix.begin() + rd_offset);
485 27702 : size_t esi_offset = rd_offset + kRdSize;
486 27702 : if (attr) {
487 17352 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
488 34704 : proto_prefix->prefix.begin() + esi_offset);
489 : }
490 27702 : size_t tag_offset = esi_offset + kEsiSize;
491 27702 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
492 27702 : size_t mac_len_offset = tag_offset + kTagSize;
493 27702 : proto_prefix->prefix[mac_len_offset] = 48;
494 27702 : size_t mac_offset = mac_len_offset + 1;
495 27702 : copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
496 27702 : proto_prefix->prefix.begin() + mac_offset);
497 27702 : size_t ip_len_offset = mac_offset + kMacSize;
498 27702 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
499 27702 : size_t ip_offset = ip_len_offset + 1;
500 27702 : WriteIpAddress(proto_prefix, ip_offset);
501 27702 : size_t label_offset = ip_offset + ip_size;
502 27702 : WriteLabel(proto_prefix, attr, label_offset, label);
503 27702 : 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 27702 : 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 1571 : case IpPrefixRoute: {
545 : size_t ip_size, nlri_size;
546 1571 : if (family_ == Address::INET) {
547 1001 : ip_size = kIp4AddrSize;
548 1001 : nlri_size = kMinInetPrefixRouteSize + kLabelSize;
549 : } else {
550 570 : ip_size = kIp6AddrSize;
551 570 : nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
552 : }
553 1571 : proto_prefix->prefixlen = nlri_size * 8;
554 1571 : proto_prefix->prefix.resize(nlri_size, 0);
555 :
556 1571 : size_t rd_offset = 0;
557 1571 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
558 1571 : proto_prefix->prefix.begin() + rd_offset);
559 1571 : size_t esi_offset = rd_offset + kRdSize;
560 1571 : if (attr) {
561 1099 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
562 2198 : proto_prefix->prefix.begin() + esi_offset);
563 : }
564 1571 : size_t tag_offset = esi_offset + kEsiSize;
565 : // Tag is not applicable for type5 routes.
566 1571 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
567 1571 : size_t ip_plen_offset = tag_offset + kTagSize;
568 1571 : proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
569 1571 : size_t ip_offset = ip_plen_offset + 1;
570 1571 : WriteIpAddress(proto_prefix, ip_offset);
571 1571 : size_t gw_offset = ip_offset + ip_size;
572 1571 : size_t label_offset = gw_offset + ip_size;
573 1571 : WriteLabel(proto_prefix, attr, label_offset, label);
574 1571 : break;
575 : }
576 50 : case SelectiveMulticastRoute: {
577 50 : size_t ip_size = GetIpAddressSize();
578 50 : size_t nlri_size = kMinSelectiveMulticastRouteSize + 2 * ip_size + 1;
579 50 : if (!source_.is_unspecified())
580 50 : nlri_size += ip_size;
581 50 : proto_prefix->prefixlen = nlri_size * 8;
582 50 : proto_prefix->prefix.resize(nlri_size, 0);
583 :
584 50 : size_t rd_offset = 0;
585 50 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
586 50 : proto_prefix->prefix.begin() + rd_offset);
587 50 : size_t tag_offset = rd_offset + kRdSize;
588 50 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
589 50 : size_t src_len_offset = tag_offset + kTagSize;
590 50 : size_t grp_len_offset = src_len_offset + 1;
591 50 : if (source_.is_unspecified()) {
592 0 : proto_prefix->prefix[src_len_offset] = 0;
593 : } else {
594 50 : proto_prefix->prefix[src_len_offset] = ip_size * 8;
595 50 : size_t src_offset = src_len_offset + 1;
596 50 : WriteSource(proto_prefix, src_offset);
597 50 : grp_len_offset += ip_size;
598 : }
599 50 : proto_prefix->prefix[grp_len_offset] = ip_size * 8;
600 50 : size_t grp_offset = grp_len_offset + 1;
601 50 : WriteGroup(proto_prefix, grp_offset);
602 50 : size_t ip_len_offset = grp_offset + ip_size;
603 50 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
604 50 : size_t ip_offset = ip_len_offset + 1;
605 50 : WriteIpAddress(proto_prefix, ip_offset);
606 50 : size_t flag_offset = ip_offset + ip_size;
607 50 : put_value(&proto_prefix->prefix[flag_offset], 1, flags_);
608 50 : break;
609 : }
610 0 : default: {
611 0 : assert(false);
612 : break;
613 : }
614 : }
615 30093 : }
616 :
617 2721583 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
618 2721583 : KEY_COMPARE(type_, rhs.type_);
619 :
620 2685495 : switch (type_) {
621 41269 : case AutoDiscoveryRoute:
622 41269 : KEY_COMPARE(rd_, rhs.rd_);
623 29204 : KEY_COMPARE(esi_, rhs.esi_);
624 17201 : KEY_COMPARE(tag_, rhs.tag_);
625 4882 : break;
626 1044845 : case MacAdvertisementRoute:
627 1044845 : KEY_COMPARE(rd_, rhs.rd_);
628 544021 : KEY_COMPARE(tag_, rhs.tag_);
629 543455 : KEY_COMPARE(mac_addr_, rhs.mac_addr_);
630 225339 : KEY_COMPARE(ip_address_, rhs.ip_address_);
631 158753 : break;
632 471120 : case InclusiveMulticastRoute:
633 471120 : KEY_COMPARE(rd_, rhs.rd_);
634 190383 : KEY_COMPARE(tag_, rhs.tag_);
635 176083 : KEY_COMPARE(ip_address_, rhs.ip_address_);
636 109789 : break;
637 40868 : case SegmentRoute:
638 40868 : KEY_COMPARE(rd_, rhs.rd_);
639 28737 : KEY_COMPARE(esi_, rhs.esi_);
640 16814 : KEY_COMPARE(ip_address_, rhs.ip_address_);
641 4614 : break;
642 1066983 : case IpPrefixRoute:
643 1066983 : KEY_COMPARE(rd_, rhs.rd_);
644 987204 : KEY_COMPARE(tag_, rhs.tag_);
645 987204 : KEY_COMPARE(ip_address_, rhs.ip_address_);
646 167520 : KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
647 167520 : break;
648 20477 : case SelectiveMulticastRoute:
649 20477 : KEY_COMPARE(rd_, rhs.rd_);
650 20149 : KEY_COMPARE(tag_, rhs.tag_);
651 17359 : KEY_COMPARE(source_, rhs.source_);
652 17359 : KEY_COMPARE(group_, rhs.group_);
653 10539 : KEY_COMPARE(ip_address_, rhs.ip_address_);
654 : default:
655 10472 : break;
656 : }
657 :
658 456030 : return 0;
659 : }
660 :
661 : // Check whether 'this' is more specific than rhs.
662 19824 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
663 19824 : switch (type_) {
664 19825 : case IpPrefixRoute:
665 19825 : if (family_ == Address::INET) {
666 9899 : return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
667 : } else {
668 9926 : 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 75716 : EvpnPrefix EvpnPrefix::FromString(const string &str,
720 : boost::system::error_code *errorp) {
721 75716 : EvpnPrefix prefix;
722 :
723 : // Parse type.
724 75716 : size_t pos1 = str.find('-');
725 75716 : 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 75502 : string type_str = str.substr(0, pos1);
733 75502 : bool ret = stringToInteger(type_str, prefix.type_);
734 75502 : 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 75501 : if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
742 75500 : 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 75500 : size_t pos2 = str.find('-', pos1 + 1);
751 75500 : 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 75494 : string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
758 75494 : boost::system::error_code rd_err;
759 75494 : prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
760 75494 : if (rd_err.failed()) {
761 5 : if (errorp != NULL) {
762 5 : *errorp = rd_err;
763 : }
764 5 : return EvpnPrefix::kNullPrefix;
765 : }
766 :
767 75489 : 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 45177 : case IpPrefixRoute: {
925 : // Parse tag.
926 45177 : size_t pos3 = str.find('-', pos2 + 1);
927 45177 : 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 45176 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
935 45176 : bool ret = stringToInteger(tag_str, prefix.tag_);
936 45176 : 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 45174 : string ip_str = str.substr(pos3 + 1, string::npos);
946 45174 : boost::system::error_code ip_err;
947 :
948 45174 : Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
949 45174 : if (!ip_err) {
950 23114 : prefix.family_ = Address::INET;
951 23114 : prefix.ip_address_ = inet_prefix.addr();
952 23114 : prefix.ip_prefixlen_ = inet_prefix.prefixlen();
953 23114 : return prefix;
954 : }
955 :
956 22060 : Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
957 22060 : if (!ip_err) {
958 22046 : prefix.family_ = Address::INET6;
959 22046 : prefix.ip_address_ = inet6_prefix.addr();
960 22046 : prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
961 22046 : 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 45176 : }
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 75502 : }
1021 :
1022 89461 : string EvpnPrefix::ToString() const {
1023 89461 : string str = integerToString(type_);
1024 89469 : str += "-" + rd_.ToString();
1025 89463 : switch (type_) {
1026 1643 : case AutoDiscoveryRoute:
1027 1643 : str += "-" + esi_.ToString();
1028 1643 : str += "-" + integerToString(tag_);
1029 1643 : break;
1030 42081 : case MacAdvertisementRoute:
1031 42081 : str += "-" + integerToString(tag_);
1032 42082 : str += "-" + mac_addr_.ToString();
1033 42079 : str += "," + ip_address_.to_string();
1034 42080 : 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 25381 : case IpPrefixRoute:
1044 25381 : str += "-" + integerToString(tag_);
1045 25387 : if (family_ == Address::INET) {
1046 13506 : str += "-" + inet_prefix().ToString();
1047 : } else {
1048 11881 : str += "-" + inet6_prefix().ToString();
1049 : }
1050 25369 : 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 9058 : break;
1058 0 : default:
1059 0 : break;
1060 : }
1061 :
1062 89446 : return str;
1063 0 : }
1064 :
1065 8824 : string EvpnPrefix::ToXmppIdString() const {
1066 8824 : string str;
1067 8824 : if (tag_ != 0)
1068 200 : str += integerToString(tag_) + "-";
1069 8824 : str += mac_addr_.ToString();
1070 17648 : str += "," + ip_address_.to_string() + "/" +
1071 26472 : integerToString(ip_address_length());
1072 8824 : if (!group_.is_unspecified()) {
1073 72 : str += "," + group_.to_string() + "," +
1074 108 : source_.to_string();
1075 : }
1076 8824 : return str;
1077 0 : }
1078 :
1079 19899 : uint8_t EvpnPrefix::ip_address_length() const {
1080 19899 : if (type_ == IpPrefixRoute)
1081 2729 : return ip_prefixlen_;
1082 17170 : if (family_ == Address::INET)
1083 561 : return 32;
1084 16609 : if (family_ == Address::INET6)
1085 72 : return 128;
1086 16537 : return 32;
1087 : }
1088 :
1089 28494 : size_t EvpnPrefix::GetIpAddressSize() const {
1090 28494 : if (family_ == Address::INET)
1091 962 : return kIp4AddrSize;
1092 27532 : if (family_ == Address::INET6)
1093 92 : return kIp6AddrSize;
1094 27440 : return 0;
1095 : }
1096 :
1097 50 : void EvpnPrefix::ReadSource(const BgpProtoPrefix &proto_prefix,
1098 : size_t ip_offset, size_t ip_size) {
1099 50 : if (ip_size == 0) {
1100 0 : family_ = Address::UNSPEC;
1101 50 : } else if (ip_size == kIp4AddrSize) {
1102 50 : family_ = Address::INET;
1103 50 : Ip4Address::bytes_type bytes = { { 0 } };
1104 100 : copy(proto_prefix.prefix.begin() + ip_offset,
1105 50 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1106 50 : 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 50 : }
1115 :
1116 50 : void EvpnPrefix::ReadGroup(const BgpProtoPrefix &proto_prefix,
1117 : size_t ip_offset, size_t ip_size) {
1118 50 : if (ip_size == 0) {
1119 0 : family_ = Address::UNSPEC;
1120 50 : } else if (ip_size == kIp4AddrSize) {
1121 50 : family_ = Address::INET;
1122 50 : Ip4Address::bytes_type bytes = { { 0 } };
1123 100 : copy(proto_prefix.prefix.begin() + ip_offset,
1124 50 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1125 50 : 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 50 : }
1134 :
1135 26060 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
1136 : size_t ip_offset, size_t ip_size, size_t ip_psize) {
1137 26060 : assert(ip_psize <= ip_size);
1138 26060 : if (ip_size == 0) {
1139 23417 : family_ = Address::UNSPEC;
1140 2643 : } else if (ip_size == kIp4AddrSize) {
1141 1965 : family_ = Address::INET;
1142 1965 : Ip4Address::bytes_type bytes = { { 0 } };
1143 3930 : copy(proto_prefix.prefix.begin() + ip_offset,
1144 1965 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1145 1965 : ip_address_ = Ip4Address(bytes);
1146 678 : } else if (ip_size == kIp6AddrSize) {
1147 678 : family_ = Address::INET6;
1148 678 : Ip6Address::bytes_type bytes = { { 0 } };
1149 1356 : copy(proto_prefix.prefix.begin() + ip_offset,
1150 678 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1151 678 : ip_address_ = Ip6Address(bytes);
1152 : }
1153 26060 : }
1154 :
1155 30065 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
1156 : size_t ip_offset) const {
1157 30065 : if (family_ == Address::INET) {
1158 1963 : const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
1159 1963 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1160 3926 : proto_prefix->prefix.begin() + ip_offset);
1161 28102 : } else if (family_ == Address::INET6) {
1162 662 : const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
1163 662 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1164 1324 : proto_prefix->prefix.begin() + ip_offset);
1165 : }
1166 30065 : }
1167 :
1168 50 : void EvpnPrefix::WriteSource(BgpProtoPrefix *proto_prefix,
1169 : size_t ip_offset) const {
1170 50 : if (family_ == Address::INET) {
1171 50 : const Ip4Address::bytes_type &bytes = source_.to_v4().to_bytes();
1172 50 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1173 100 : 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 50 : }
1180 :
1181 50 : void EvpnPrefix::WriteGroup(BgpProtoPrefix *proto_prefix,
1182 : size_t ip_offset) const {
1183 50 : if (family_ == Address::INET) {
1184 50 : const Ip4Address::bytes_type &bytes = group_.to_v4().to_bytes();
1185 50 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1186 100 : 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 50 : }
1193 :
1194 351020 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
1195 351020 : : prefix_(prefix) {
1196 350926 : }
1197 :
1198 2694488 : int EvpnRoute::CompareTo(const Route &rhs) const {
1199 2694488 : const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
1200 2694488 : return prefix_.CompareTo(evpn_rhs.prefix_);
1201 : }
1202 :
1203 88057 : string EvpnRoute::ToString() const {
1204 88057 : return prefix_.ToString();
1205 : }
1206 :
1207 12427 : string EvpnRoute::ToXmppIdString() const {
1208 12427 : if (xmpp_id_str_.empty())
1209 4302 : xmpp_id_str_ = prefix_.ToXmppIdString();
1210 12427 : return xmpp_id_str_;
1211 : }
1212 :
1213 55325 : bool EvpnRoute::IsValid() const {
1214 55325 : if (!BgpRoute::IsValid())
1215 8367 : return false;
1216 :
1217 46958 : const BgpAttr *attr = BestPath()->GetAttr();
1218 46958 : switch (prefix_.type()) {
1219 62 : case EvpnPrefix::AutoDiscoveryRoute: {
1220 62 : if (prefix_.tag() == EvpnPrefix::kMaxTag)
1221 62 : return true;
1222 0 : break;
1223 : }
1224 25962 : case EvpnPrefix::MacAdvertisementRoute: {
1225 25962 : return true;
1226 : }
1227 20934 : case EvpnPrefix::InclusiveMulticastRoute: {
1228 20934 : const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
1229 20934 : if (!pmsi_tunnel)
1230 0 : return false;
1231 20934 : uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
1232 20934 : uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
1233 20934 : uint8_t ar_type =
1234 : tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
1235 20934 : if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
1236 20275 : if (ar_type == PmsiTunnelSpec::RegularNVE)
1237 18509 : return true;
1238 1766 : if (ar_type == PmsiTunnelSpec::ARReplicator &&
1239 1766 : (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
1240 1766 : 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 29878 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
1274 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
1275 29878 : prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
1276 29878 : }
1277 :
1278 12584 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
1279 : IpAddress nexthop) const {
1280 12584 : nh.resize(4);
1281 12584 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
1282 12584 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
1283 12584 : }
1284 :
1285 50653 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
1286 50653 : EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
1287 50652 : return KeyPtr(key);
1288 : }
|