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 25302 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
58 : const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
59 25302 : if (!attr)
60 6874 : return 0;
61 18428 : const ExtCommunity *extcomm = attr->ext_community();
62 18428 : 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 18282 : return proto_prefix.ReadLabel(offset, false);
76 : }
77 : }
78 :
79 : //
80 : // Write label to the BgpProtoPrefix.
81 : //
82 28988 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
83 : const BgpAttr *attr, size_t offset, uint32_t label) {
84 28988 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
85 28988 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
86 146 : proto_prefix->WriteLabel(offset, label, true);
87 : } else {
88 28842 : proto_prefix->WriteLabel(offset, label, false);
89 : }
90 28988 : }
91 :
92 : //
93 : // Read gateway address from the BgpProtoPrefix.
94 : //
95 1567 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
96 : size_t gw_offset, size_t ip_size) {
97 1567 : assert(ip_size == EvpnPrefix::kIp4AddrSize ||
98 : ip_size == EvpnPrefix::kIp6AddrSize);
99 1567 : if (ip_size == EvpnPrefix::kIp4AddrSize) {
100 : Ip4Address::bytes_type bytes;
101 1966 : copy(proto_prefix.prefix.begin() + gw_offset,
102 983 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
103 983 : return Ip4Address(bytes);
104 : } else {
105 : Ip6Address::bytes_type bytes;
106 1168 : copy(proto_prefix.prefix.begin() + gw_offset,
107 584 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
108 584 : return Ip6Address(bytes);
109 : }
110 : return IpAddress();
111 : }
112 :
113 128463 : EvpnPrefix::EvpnPrefix()
114 128463 : : type_(Unspecified),
115 128461 : tag_(EvpnPrefix::kNullTag),
116 128459 : family_(Address::UNSPEC),
117 128463 : ip_prefixlen_(0) {
118 128455 : }
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 15637 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
147 15637 : const MacAddress &mac_addr, const IpAddress &ip_address)
148 15637 : : type_(MacAdvertisementRoute), rd_(rd), tag_(tag),
149 15636 : mac_addr_(mac_addr), family_(Address::UNSPEC),
150 31273 : ip_address_(ip_address), ip_prefixlen_(0) {
151 15636 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
152 219 : family_ = Address::INET;
153 15418 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
154 28 : family_ = Address::INET6;
155 : }
156 15637 : }
157 :
158 24935 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
159 24935 : const IpAddress &ip_address)
160 24935 : : type_(InclusiveMulticastRoute),
161 24935 : rd_(rd),
162 24935 : tag_(tag),
163 24935 : family_(Address::UNSPEC),
164 24935 : ip_address_(ip_address),
165 49870 : ip_prefixlen_(0) {
166 24935 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
167 24930 : family_ = Address::INET;
168 5 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
169 5 : family_ = Address::INET6;
170 : }
171 24935 : }
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 1030 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
190 1030 : const IpAddress &ip_address, uint8_t ip_prefixlen)
191 1030 : : type_(IpPrefixRoute),
192 1030 : rd_(rd),
193 1030 : tag_(0),
194 1030 : family_(Address::UNSPEC),
195 1030 : ip_address_(ip_address),
196 2060 : ip_prefixlen_(ip_prefixlen) {
197 1030 : assert(ip_address_.is_v4() || ip_address_.is_v6());
198 1030 : if (ip_address_.is_v4()) {
199 650 : family_ = Address::INET;
200 380 : } else if (ip_address_.is_v6()) {
201 380 : family_ = Address::INET6;
202 : }
203 1030 : }
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 28582 : 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 28582 : *new_attr = attr;
236 28582 : *label = 0;
237 28582 : if (l3_label)
238 25891 : *l3_label = 0;
239 28582 : prefix->type_ = proto_prefix.type;
240 28582 : size_t nlri_size = proto_prefix.prefix.size();
241 :
242 28582 : 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 24764 : case MacAdvertisementRoute: {
259 24764 : size_t expected_min_nlri_size =
260 24764 : kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
261 24764 : if (nlri_size < expected_min_nlri_size)
262 63 : return -1;
263 24701 : size_t rd_offset = 0;
264 24701 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
265 24701 : size_t esi_offset = rd_offset + kRdSize;
266 24701 : if (attr) {
267 17800 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
268 17800 : *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
269 : }
270 24701 : size_t tag_offset = esi_offset + kEsiSize;
271 24701 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
272 24701 : size_t mac_len_offset = tag_offset + kTagSize;
273 24701 : size_t mac_len = proto_prefix.prefix[mac_len_offset];
274 24701 : if (mac_len != 48)
275 510 : return -1;
276 24191 : size_t mac_offset = mac_len_offset + 1;
277 24191 : prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
278 24191 : size_t ip_len_offset = mac_offset + kMacSize;
279 24191 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
280 24191 : if (ip_len != 0 && ip_len != 32 && ip_len != 128)
281 506 : return -1;
282 23685 : size_t ip_size = ip_len / 8;
283 23685 : if (nlri_size < expected_min_nlri_size + ip_size)
284 40 : return -1;
285 23645 : size_t ip_offset = ip_len_offset + 1;
286 23645 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
287 23645 : size_t label_offset = ip_offset + ip_size;
288 23645 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
289 23645 : size_t l3_label_offset = label_offset + kLabelSize;
290 23645 : if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
291 76 : *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
292 : }
293 23645 : 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 2117 : case IpPrefixRoute: {
348 : size_t ip_size;
349 2117 : if (attr) {
350 1555 : if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
351 567 : ip_size = kIp6AddrSize;
352 988 : } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
353 896 : ip_size = kIp4AddrSize;
354 : } else {
355 570 : return -1;
356 : }
357 : } else {
358 562 : if (nlri_size == kMinInet6PrefixRouteSize ||
359 562 : nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
360 154 : ip_size = kIp6AddrSize;
361 408 : } else if (nlri_size == kMinInetPrefixRouteSize ||
362 408 : nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
363 320 : ip_size = kIp4AddrSize;
364 : } else {
365 88 : return -1;
366 : }
367 : }
368 :
369 1937 : size_t rd_offset = 0;
370 1937 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
371 1937 : size_t esi_offset = rd_offset + kRdSize;
372 1937 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
373 1937 : if (!esi.IsZero())
374 20 : return -1;
375 1917 : size_t tag_offset = esi_offset + kEsiSize;
376 : // Ignore tag for type5 routes.
377 1917 : prefix->tag_ = 0;
378 1917 : size_t ip_plen_offset = tag_offset + kTagSize;
379 1917 : prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
380 1917 : if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
381 223 : return -1;
382 1694 : if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
383 127 : return -1;
384 1567 : size_t ip_offset = ip_plen_offset + 1;
385 1567 : size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
386 1567 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
387 1567 : size_t gw_offset = ip_offset + ip_size;
388 1567 : IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
389 1567 : if (!gw_address.is_unspecified())
390 20 : return -1;
391 1547 : size_t label_offset = gw_offset + ip_size;
392 1547 : *label = ReadLabel(proto_prefix, attr, label_offset);
393 1547 : 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 26016 : 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 29702 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
452 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
453 29702 : proto_prefix->type = type_;
454 29702 : proto_prefix->prefix.clear();
455 :
456 29702 : 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 27337 : case MacAdvertisementRoute: {
475 27337 : size_t ip_size = GetIpAddressSize();
476 27337 : size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
477 27337 : if (l3_label)
478 76 : nlri_size += kLabelSize;
479 27337 : proto_prefix->prefixlen = nlri_size * 8;
480 27337 : proto_prefix->prefix.resize(nlri_size, 0);
481 :
482 27337 : size_t rd_offset = 0;
483 27337 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
484 27337 : proto_prefix->prefix.begin() + rd_offset);
485 27337 : size_t esi_offset = rd_offset + kRdSize;
486 27337 : if (attr) {
487 17304 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
488 34608 : proto_prefix->prefix.begin() + esi_offset);
489 : }
490 27337 : size_t tag_offset = esi_offset + kEsiSize;
491 27337 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
492 27337 : size_t mac_len_offset = tag_offset + kTagSize;
493 27337 : proto_prefix->prefix[mac_len_offset] = 48;
494 27337 : size_t mac_offset = mac_len_offset + 1;
495 27337 : copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
496 27337 : proto_prefix->prefix.begin() + mac_offset);
497 27337 : size_t ip_len_offset = mac_offset + kMacSize;
498 27337 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
499 27337 : size_t ip_offset = ip_len_offset + 1;
500 27337 : WriteIpAddress(proto_prefix, ip_offset);
501 27337 : size_t label_offset = ip_offset + ip_size;
502 27337 : WriteLabel(proto_prefix, attr, label_offset, label);
503 27337 : 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 27337 : 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 1547 : case IpPrefixRoute: {
545 : size_t ip_size, nlri_size;
546 1547 : if (family_ == Address::INET) {
547 979 : ip_size = kIp4AddrSize;
548 979 : nlri_size = kMinInetPrefixRouteSize + kLabelSize;
549 : } else {
550 568 : ip_size = kIp6AddrSize;
551 568 : nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
552 : }
553 1547 : proto_prefix->prefixlen = nlri_size * 8;
554 1547 : proto_prefix->prefix.resize(nlri_size, 0);
555 :
556 1547 : size_t rd_offset = 0;
557 1547 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
558 1547 : proto_prefix->prefix.begin() + rd_offset);
559 1547 : size_t esi_offset = rd_offset + kRdSize;
560 1547 : if (attr) {
561 1073 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
562 2146 : proto_prefix->prefix.begin() + esi_offset);
563 : }
564 1547 : size_t tag_offset = esi_offset + kEsiSize;
565 : // Tag is not applicable for type5 routes.
566 1547 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
567 1547 : size_t ip_plen_offset = tag_offset + kTagSize;
568 1547 : proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
569 1547 : size_t ip_offset = ip_plen_offset + 1;
570 1547 : WriteIpAddress(proto_prefix, ip_offset);
571 1547 : size_t gw_offset = ip_offset + ip_size;
572 1547 : size_t label_offset = gw_offset + ip_size;
573 1547 : WriteLabel(proto_prefix, attr, label_offset, label);
574 1547 : 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 29702 : }
616 :
617 2730899 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
618 2730899 : KEY_COMPARE(type_, rhs.type_);
619 :
620 2694532 : switch (type_) {
621 41532 : case AutoDiscoveryRoute:
622 41532 : KEY_COMPARE(rd_, rhs.rd_);
623 29285 : KEY_COMPARE(esi_, rhs.esi_);
624 16966 : KEY_COMPARE(tag_, rhs.tag_);
625 4882 : break;
626 1046320 : case MacAdvertisementRoute:
627 1046320 : KEY_COMPARE(rd_, rhs.rd_);
628 545092 : KEY_COMPARE(tag_, rhs.tag_);
629 544526 : KEY_COMPARE(mac_addr_, rhs.mac_addr_);
630 225653 : KEY_COMPARE(ip_address_, rhs.ip_address_);
631 158838 : break;
632 471174 : case InclusiveMulticastRoute:
633 471174 : KEY_COMPARE(rd_, rhs.rd_);
634 190514 : KEY_COMPARE(tag_, rhs.tag_);
635 176196 : KEY_COMPARE(ip_address_, rhs.ip_address_);
636 110080 : break;
637 41429 : case SegmentRoute:
638 41429 : KEY_COMPARE(rd_, rhs.rd_);
639 29181 : KEY_COMPARE(esi_, rhs.esi_);
640 16933 : KEY_COMPARE(ip_address_, rhs.ip_address_);
641 4614 : break;
642 1071185 : case IpPrefixRoute:
643 1071185 : KEY_COMPARE(rd_, rhs.rd_);
644 994131 : KEY_COMPARE(tag_, rhs.tag_);
645 994131 : KEY_COMPARE(ip_address_, rhs.ip_address_);
646 168861 : KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
647 168861 : break;
648 20434 : case SelectiveMulticastRoute:
649 20434 : KEY_COMPARE(rd_, rhs.rd_);
650 20134 : KEY_COMPARE(tag_, rhs.tag_);
651 17344 : KEY_COMPARE(source_, rhs.source_);
652 17344 : KEY_COMPARE(group_, rhs.group_);
653 10524 : KEY_COMPARE(ip_address_, rhs.ip_address_);
654 : default:
655 12982 : break;
656 : }
657 :
658 460257 : return 0;
659 : }
660 :
661 : // Check whether 'this' is more specific than rhs.
662 19889 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
663 19889 : switch (type_) {
664 19889 : case IpPrefixRoute:
665 19889 : if (family_ == Address::INET) {
666 9939 : return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
667 : } else {
668 9950 : 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 75707 : EvpnPrefix EvpnPrefix::FromString(const string &str,
720 : boost::system::error_code *errorp) {
721 75707 : EvpnPrefix prefix;
722 :
723 : // Parse type.
724 75707 : size_t pos1 = str.find('-');
725 75707 : 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 75493 : string type_str = str.substr(0, pos1);
733 75493 : bool ret = stringToInteger(type_str, prefix.type_);
734 75493 : 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 75492 : if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
742 75491 : 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 75491 : size_t pos2 = str.find('-', pos1 + 1);
751 75491 : 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 75485 : string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
758 75485 : boost::system::error_code rd_err;
759 75485 : prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
760 75485 : if (rd_err.failed()) {
761 5 : if (errorp != NULL) {
762 5 : *errorp = rd_err;
763 : }
764 5 : return EvpnPrefix::kNullPrefix;
765 : }
766 :
767 75480 : 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 9269 : case InclusiveMulticastRoute: {
853 : // Parse tag.
854 9269 : size_t pos3 = str.find('-', pos2 + 1);
855 9269 : 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 9268 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
863 9268 : bool ret = stringToInteger(tag_str, prefix.tag_);
864 9268 : 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 9267 : string ip_str = str.substr(pos3 + 1, string::npos);
874 9267 : boost::system::error_code ip_err;
875 9267 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
876 9267 : if (ip_err.failed()) {
877 1 : if (errorp != NULL) {
878 1 : *errorp = ip_err;
879 : }
880 1 : return EvpnPrefix::kNullPrefix;
881 : }
882 9266 : prefix.family_ =
883 9266 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
884 :
885 9266 : break;
886 18535 : }
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 45170 : case IpPrefixRoute: {
925 : // Parse tag.
926 45170 : size_t pos3 = str.find('-', pos2 + 1);
927 45170 : 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 45169 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
935 45169 : bool ret = stringToInteger(tag_str, prefix.tag_);
936 45169 : 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 45167 : string ip_str = str.substr(pos3 + 1, string::npos);
946 45167 : boost::system::error_code ip_err;
947 :
948 45167 : Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
949 45167 : if (!ip_err) {
950 23116 : prefix.family_ = Address::INET;
951 23116 : prefix.ip_address_ = inet_prefix.addr();
952 23116 : prefix.ip_prefixlen_ = inet_prefix.prefixlen();
953 23116 : return prefix;
954 : }
955 :
956 22051 : Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
957 22051 : if (!ip_err) {
958 22037 : prefix.family_ = Address::INET6;
959 22037 : prefix.ip_address_ = inet6_prefix.addr();
960 22037 : prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
961 22037 : 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 45169 : }
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 30296 : return prefix;
1020 75493 : }
1021 :
1022 89405 : string EvpnPrefix::ToString() const {
1023 89405 : string str = integerToString(type_);
1024 89420 : str += "-" + rd_.ToString();
1025 89410 : switch (type_) {
1026 1643 : case AutoDiscoveryRoute:
1027 1643 : str += "-" + esi_.ToString();
1028 1643 : str += "-" + integerToString(tag_);
1029 1643 : break;
1030 42098 : case MacAdvertisementRoute:
1031 42098 : str += "-" + integerToString(tag_);
1032 42098 : str += "-" + mac_addr_.ToString();
1033 42096 : str += "," + ip_address_.to_string();
1034 42098 : 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 25337 : case IpPrefixRoute:
1044 25337 : str += "-" + integerToString(tag_);
1045 25345 : if (family_ == Address::INET) {
1046 13499 : str += "-" + inet_prefix().ToString();
1047 : } else {
1048 11846 : str += "-" + inet6_prefix().ToString();
1049 : }
1050 25342 : break;
1051 9036 : case SelectiveMulticastRoute:
1052 9036 : str += "-" + integerToString(tag_);
1053 9036 : if (!source_.is_unspecified())
1054 9031 : str += "-" + source_.to_string();
1055 9036 : str += "-" + group_.to_string();
1056 9036 : str += "-" + ip_address_.to_string();
1057 9033 : break;
1058 0 : default:
1059 0 : break;
1060 : }
1061 :
1062 89412 : return str;
1063 0 : }
1064 :
1065 8781 : string EvpnPrefix::ToXmppIdString() const {
1066 8781 : string str;
1067 8781 : if (tag_ != 0)
1068 200 : str += integerToString(tag_) + "-";
1069 8781 : str += mac_addr_.ToString();
1070 17562 : str += "," + ip_address_.to_string() + "/" +
1071 26343 : integerToString(ip_address_length());
1072 8781 : if (!group_.is_unspecified()) {
1073 72 : str += "," + group_.to_string() + "," +
1074 108 : source_.to_string();
1075 : }
1076 8781 : return str;
1077 0 : }
1078 :
1079 19942 : uint8_t EvpnPrefix::ip_address_length() const {
1080 19942 : if (type_ == IpPrefixRoute)
1081 2712 : return ip_prefixlen_;
1082 17230 : if (family_ == Address::INET)
1083 552 : return 32;
1084 16678 : if (family_ == Address::INET6)
1085 72 : return 128;
1086 16606 : return 32;
1087 : }
1088 :
1089 28127 : size_t EvpnPrefix::GetIpAddressSize() const {
1090 28127 : if (family_ == Address::INET)
1091 959 : return kIp4AddrSize;
1092 27168 : if (family_ == Address::INET6)
1093 92 : return kIp6AddrSize;
1094 27076 : 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 26002 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
1136 : size_t ip_offset, size_t ip_size, size_t ip_psize) {
1137 26002 : assert(ip_psize <= ip_size);
1138 26002 : if (ip_size == 0) {
1139 23385 : family_ = Address::UNSPEC;
1140 2617 : } else if (ip_size == kIp4AddrSize) {
1141 1941 : family_ = Address::INET;
1142 1941 : Ip4Address::bytes_type bytes = { { 0 } };
1143 3882 : copy(proto_prefix.prefix.begin() + ip_offset,
1144 1941 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1145 1941 : ip_address_ = Ip4Address(bytes);
1146 676 : } else if (ip_size == kIp6AddrSize) {
1147 676 : family_ = Address::INET6;
1148 676 : Ip6Address::bytes_type bytes = { { 0 } };
1149 1352 : copy(proto_prefix.prefix.begin() + ip_offset,
1150 676 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1151 676 : ip_address_ = Ip6Address(bytes);
1152 : }
1153 26002 : }
1154 :
1155 29674 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
1156 : size_t ip_offset) const {
1157 29674 : if (family_ == Address::INET) {
1158 1938 : const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
1159 1938 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1160 3876 : proto_prefix->prefix.begin() + ip_offset);
1161 27736 : } else if (family_ == Address::INET6) {
1162 660 : const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
1163 660 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1164 1320 : proto_prefix->prefix.begin() + ip_offset);
1165 : }
1166 29674 : }
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 351233 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
1195 351233 : : prefix_(prefix) {
1196 351148 : }
1197 :
1198 2704633 : int EvpnRoute::CompareTo(const Route &rhs) const {
1199 2704633 : const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
1200 2704633 : return prefix_.CompareTo(evpn_rhs.prefix_);
1201 : }
1202 :
1203 88001 : string EvpnRoute::ToString() const {
1204 88001 : return prefix_.ToString();
1205 : }
1206 :
1207 12510 : string EvpnRoute::ToXmppIdString() const {
1208 12510 : if (xmpp_id_str_.empty())
1209 4302 : xmpp_id_str_ = prefix_.ToXmppIdString();
1210 12510 : return xmpp_id_str_;
1211 : }
1212 :
1213 55456 : bool EvpnRoute::IsValid() const {
1214 55456 : if (!BgpRoute::IsValid())
1215 8368 : return false;
1216 :
1217 47088 : const BgpAttr *attr = BestPath()->GetAttr();
1218 47088 : switch (prefix_.type()) {
1219 65 : case EvpnPrefix::AutoDiscoveryRoute: {
1220 65 : if (prefix_.tag() == EvpnPrefix::kMaxTag)
1221 65 : return true;
1222 0 : break;
1223 : }
1224 26029 : case EvpnPrefix::MacAdvertisementRoute: {
1225 26029 : return true;
1226 : }
1227 20994 : case EvpnPrefix::InclusiveMulticastRoute: {
1228 20994 : const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
1229 20994 : if (!pmsi_tunnel)
1230 0 : return false;
1231 20994 : uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
1232 20994 : uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
1233 20994 : uint8_t ar_type =
1234 : tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
1235 20994 : if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
1236 20335 : if (ar_type == PmsiTunnelSpec::RegularNVE)
1237 18575 : return true;
1238 1760 : if (ar_type == PmsiTunnelSpec::ARReplicator &&
1239 1760 : (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
1240 1760 : 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 29487 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
1274 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
1275 29487 : prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
1276 29487 : }
1277 :
1278 12453 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
1279 : IpAddress nexthop) const {
1280 12453 : nh.resize(4);
1281 12453 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
1282 12453 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
1283 12453 : }
1284 :
1285 50637 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
1286 50637 : EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
1287 50634 : return KeyPtr(key);
1288 : }
|