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 0 : static uint32_t ReadLabel(const BgpProtoPrefix &proto_prefix,
58 : const BgpAttr *attr, size_t offset, uint32_t tag = EvpnPrefix::kNullTag) {
59 0 : if (!attr)
60 0 : return 0;
61 0 : const ExtCommunity *extcomm = attr->ext_community();
62 0 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
63 0 : if (tag) {
64 0 : if (tag == EvpnPrefix::kMaxTag) {
65 0 : return 0;
66 0 : } else if (tag <= EvpnPrefix::kMaxVni) {
67 0 : return tag;
68 : } else {
69 0 : return proto_prefix.ReadLabel(offset, true);
70 : }
71 : } else {
72 0 : return proto_prefix.ReadLabel(offset, true);
73 : }
74 : } else {
75 0 : return proto_prefix.ReadLabel(offset, false);
76 : }
77 : }
78 :
79 : //
80 : // Write label to the BgpProtoPrefix.
81 : //
82 0 : static void WriteLabel(BgpProtoPrefix *proto_prefix,
83 : const BgpAttr *attr, size_t offset, uint32_t label) {
84 0 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
85 0 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
86 0 : proto_prefix->WriteLabel(offset, label, true);
87 : } else {
88 0 : proto_prefix->WriteLabel(offset, label, false);
89 : }
90 0 : }
91 :
92 : //
93 : // Read gateway address from the BgpProtoPrefix.
94 : //
95 0 : static IpAddress ReadGwAddress(const BgpProtoPrefix &proto_prefix,
96 : size_t gw_offset, size_t ip_size) {
97 0 : assert(ip_size == EvpnPrefix::kIp4AddrSize ||
98 : ip_size == EvpnPrefix::kIp6AddrSize);
99 0 : if (ip_size == EvpnPrefix::kIp4AddrSize) {
100 : Ip4Address::bytes_type bytes;
101 0 : copy(proto_prefix.prefix.begin() + gw_offset,
102 0 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
103 0 : return Ip4Address(bytes);
104 : } else {
105 : Ip6Address::bytes_type bytes;
106 0 : copy(proto_prefix.prefix.begin() + gw_offset,
107 0 : proto_prefix.prefix.begin() + gw_offset + ip_size, bytes.begin());
108 0 : return Ip6Address(bytes);
109 : }
110 : return IpAddress();
111 : }
112 :
113 1 : EvpnPrefix::EvpnPrefix()
114 1 : : type_(Unspecified),
115 1 : tag_(EvpnPrefix::kNullTag),
116 1 : family_(Address::UNSPEC),
117 1 : ip_prefixlen_(0) {
118 1 : }
119 :
120 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
121 0 : const EthernetSegmentId &esi, uint32_t tag)
122 0 : : type_(AutoDiscoveryRoute),
123 0 : rd_(rd),
124 0 : esi_(esi),
125 0 : tag_(tag),
126 0 : family_(Address::UNSPEC),
127 0 : ip_prefixlen_(0) {
128 0 : }
129 :
130 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
131 0 : const MacAddress &mac_addr, const IpAddress &ip_address)
132 0 : : type_(MacAdvertisementRoute),
133 0 : rd_(rd),
134 0 : tag_(EvpnPrefix::kNullTag),
135 0 : mac_addr_(mac_addr),
136 0 : family_(Address::UNSPEC),
137 0 : ip_address_(ip_address),
138 0 : ip_prefixlen_(0) {
139 0 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
140 0 : family_ = Address::INET;
141 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
142 0 : family_ = Address::INET6;
143 : }
144 0 : }
145 :
146 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
147 0 : const MacAddress &mac_addr, const IpAddress &ip_address)
148 0 : : type_(MacAdvertisementRoute), rd_(rd), tag_(tag),
149 0 : mac_addr_(mac_addr), family_(Address::UNSPEC),
150 0 : ip_address_(ip_address), ip_prefixlen_(0) {
151 0 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
152 0 : family_ = Address::INET;
153 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
154 0 : family_ = Address::INET6;
155 : }
156 0 : }
157 :
158 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
159 0 : const IpAddress &ip_address)
160 0 : : type_(InclusiveMulticastRoute),
161 0 : rd_(rd),
162 0 : tag_(tag),
163 0 : family_(Address::UNSPEC),
164 0 : ip_address_(ip_address),
165 0 : ip_prefixlen_(0) {
166 0 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
167 0 : family_ = Address::INET;
168 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
169 0 : family_ = Address::INET6;
170 : }
171 0 : }
172 :
173 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
174 0 : const EthernetSegmentId &esi, const IpAddress &ip_address)
175 0 : : type_(SegmentRoute),
176 0 : rd_(rd),
177 0 : esi_(esi),
178 0 : tag_(EvpnPrefix::kNullTag),
179 0 : family_(Address::UNSPEC),
180 0 : ip_address_(ip_address),
181 0 : ip_prefixlen_(0) {
182 0 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
183 0 : family_ = Address::INET;
184 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
185 0 : family_ = Address::INET6;
186 : }
187 0 : }
188 :
189 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd,
190 0 : const IpAddress &ip_address, uint8_t ip_prefixlen)
191 0 : : type_(IpPrefixRoute),
192 0 : rd_(rd),
193 0 : tag_(0),
194 0 : family_(Address::UNSPEC),
195 0 : ip_address_(ip_address),
196 0 : ip_prefixlen_(ip_prefixlen) {
197 0 : assert(ip_address_.is_v4() || ip_address_.is_v6());
198 0 : if (ip_address_.is_v4()) {
199 0 : family_ = Address::INET;
200 0 : } else if (ip_address_.is_v6()) {
201 0 : family_ = Address::INET6;
202 : }
203 0 : }
204 :
205 0 : EvpnPrefix::EvpnPrefix(const RouteDistinguisher &rd, uint32_t tag,
206 : const IpAddress &source, const IpAddress &group,
207 0 : const IpAddress &ip_address)
208 0 : : type_(SelectiveMulticastRoute),
209 0 : rd_(rd),
210 0 : tag_(tag),
211 0 : family_(Address::UNSPEC),
212 0 : ip_address_(ip_address),
213 0 : source_(source),
214 0 : group_(group),
215 0 : ip_prefixlen_(0), flags_(0x2) {
216 0 : if (ip_address_.is_v4() && !ip_address_.is_unspecified()) {
217 0 : family_ = Address::INET;
218 0 : } else if (ip_address_.is_v6() && !ip_address_.is_unspecified()) {
219 0 : family_ = Address::INET6;
220 : }
221 0 : string ip = group.to_v4().to_string();
222 0 : char *str = const_cast<char *>(ip.c_str());
223 0 : char * mac_ip = strstr(str, ".");
224 0 : std::ostringstream oss;
225 0 : oss << "01:00:5e:" << strtok(mac_ip, ".");
226 0 : oss << ":" << strtok(NULL, ".");
227 0 : oss << ":" << strtok(NULL, "");
228 0 : mac_addr_ = MacAddress::FromString(oss.str(), NULL);
229 0 : }
230 :
231 0 : 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 0 : *new_attr = attr;
236 0 : *label = 0;
237 0 : if (l3_label)
238 0 : *l3_label = 0;
239 0 : prefix->type_ = proto_prefix.type;
240 0 : size_t nlri_size = proto_prefix.prefix.size();
241 :
242 0 : switch (prefix->type_) {
243 0 : case AutoDiscoveryRoute: {
244 0 : size_t expected_min_nlri_size =
245 0 : kMinAutoDiscoveryRouteSize + (attr ? kLabelSize : 0);
246 0 : if (nlri_size < expected_min_nlri_size)
247 0 : return -1;
248 0 : size_t rd_offset = 0;
249 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
250 0 : size_t esi_offset = rd_offset + kRdSize;
251 0 : prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
252 0 : size_t tag_offset = esi_offset + kEsiSize;
253 0 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
254 0 : size_t label_offset = tag_offset + kTagSize;
255 0 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
256 0 : break;
257 : }
258 0 : case MacAdvertisementRoute: {
259 0 : size_t expected_min_nlri_size =
260 0 : kMinMacAdvertisementRouteSize + (attr ? kLabelSize : 0);
261 0 : if (nlri_size < expected_min_nlri_size)
262 0 : return -1;
263 0 : size_t rd_offset = 0;
264 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
265 0 : size_t esi_offset = rd_offset + kRdSize;
266 0 : if (attr) {
267 0 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
268 0 : *new_attr = server->attr_db()->ReplaceEsiAndLocate(attr, esi);
269 : }
270 0 : size_t tag_offset = esi_offset + kEsiSize;
271 0 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
272 0 : size_t mac_len_offset = tag_offset + kTagSize;
273 0 : size_t mac_len = proto_prefix.prefix[mac_len_offset];
274 0 : if (mac_len != 48)
275 0 : return -1;
276 0 : size_t mac_offset = mac_len_offset + 1;
277 0 : prefix->mac_addr_ = MacAddress(&proto_prefix.prefix[mac_offset]);
278 0 : size_t ip_len_offset = mac_offset + kMacSize;
279 0 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
280 0 : if (ip_len != 0 && ip_len != 32 && ip_len != 128)
281 0 : return -1;
282 0 : size_t ip_size = ip_len / 8;
283 0 : if (nlri_size < expected_min_nlri_size + ip_size)
284 0 : return -1;
285 0 : size_t ip_offset = ip_len_offset + 1;
286 0 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
287 0 : size_t label_offset = ip_offset + ip_size;
288 0 : *label = ReadLabel(proto_prefix, attr, label_offset, prefix->tag_);
289 0 : size_t l3_label_offset = label_offset + kLabelSize;
290 0 : if (l3_label && nlri_size >= l3_label_offset + kLabelSize) {
291 0 : *l3_label = ReadLabel(proto_prefix, attr, l3_label_offset);
292 : }
293 0 : break;
294 : }
295 0 : case InclusiveMulticastRoute: {
296 0 : if (nlri_size < kMinInclusiveMulticastRouteSize)
297 0 : return -1;
298 0 : size_t rd_offset = 0;
299 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
300 0 : size_t tag_offset = rd_offset + kRdSize;
301 0 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
302 0 : size_t ip_len_offset = tag_offset + kTagSize;
303 0 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
304 0 : if (ip_len != 32 && ip_len != 128)
305 0 : return -1;
306 0 : size_t ip_size = ip_len / 8;
307 0 : if (nlri_size < kMinInclusiveMulticastRouteSize + ip_size)
308 0 : return -1;
309 0 : size_t ip_offset = ip_len_offset + 1;
310 0 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
311 0 : const PmsiTunnel *pmsi_tunnel = attr ? attr->pmsi_tunnel() : NULL;
312 0 : if (pmsi_tunnel &&
313 0 : (pmsi_tunnel->tunnel_type() == PmsiTunnelSpec::IngressReplication ||
314 0 : pmsi_tunnel->tunnel_type() ==
315 : PmsiTunnelSpec::AssistedReplicationContrail)) {
316 0 : const ExtCommunity *extcomm = attr ? attr->ext_community() : NULL;
317 0 : if (extcomm && extcomm->ContainsTunnelEncapVxlan()) {
318 0 : if (prefix->tag_ && prefix->tag_ <= kMaxVni) {
319 0 : *label = prefix->tag_;
320 : } else {
321 0 : *label = pmsi_tunnel->GetLabel(extcomm);
322 : }
323 : } else {
324 0 : *label = pmsi_tunnel->GetLabel(extcomm);
325 : }
326 : }
327 0 : break;
328 : }
329 0 : case SegmentRoute: {
330 0 : if (nlri_size < kMinSegmentRouteSize)
331 0 : return -1;
332 0 : size_t rd_offset = 0;
333 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
334 0 : size_t esi_offset = rd_offset + kRdSize;
335 0 : prefix->esi_ = EthernetSegmentId(&proto_prefix.prefix[esi_offset]);
336 0 : size_t ip_len_offset = esi_offset + kEsiSize;
337 0 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
338 0 : if (ip_len != 32 && ip_len != 128)
339 0 : return -1;
340 0 : size_t ip_size = ip_len / 8;
341 0 : if (nlri_size < kMinSegmentRouteSize + ip_size)
342 0 : return -1;
343 0 : size_t ip_offset = ip_len_offset + 1;
344 0 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
345 0 : break;
346 : }
347 0 : case IpPrefixRoute: {
348 : size_t ip_size;
349 0 : if (attr) {
350 0 : if (nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
351 0 : ip_size = kIp6AddrSize;
352 0 : } else if (nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
353 0 : ip_size = kIp4AddrSize;
354 : } else {
355 0 : return -1;
356 : }
357 : } else {
358 0 : if (nlri_size == kMinInet6PrefixRouteSize ||
359 0 : nlri_size == kMinInet6PrefixRouteSize + kLabelSize) {
360 0 : ip_size = kIp6AddrSize;
361 0 : } else if (nlri_size == kMinInetPrefixRouteSize ||
362 0 : nlri_size == kMinInetPrefixRouteSize + kLabelSize) {
363 0 : ip_size = kIp4AddrSize;
364 : } else {
365 0 : return -1;
366 : }
367 : }
368 :
369 0 : size_t rd_offset = 0;
370 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
371 0 : size_t esi_offset = rd_offset + kRdSize;
372 0 : EthernetSegmentId esi(&proto_prefix.prefix[esi_offset]);
373 0 : if (!esi.IsZero())
374 0 : return -1;
375 0 : size_t tag_offset = esi_offset + kEsiSize;
376 : // Ignore tag for type5 routes.
377 0 : prefix->tag_ = 0;
378 0 : size_t ip_plen_offset = tag_offset + kTagSize;
379 0 : prefix->ip_prefixlen_ = proto_prefix.prefix[ip_plen_offset];
380 0 : if (ip_size == kIp4AddrSize && prefix->ip_prefixlen_ > 32)
381 0 : return -1;
382 0 : if (ip_size == kIp6AddrSize && prefix->ip_prefixlen_ > 128)
383 0 : return -1;
384 0 : size_t ip_offset = ip_plen_offset + 1;
385 0 : size_t ip_psize = (prefix->ip_prefixlen_ + 7) / 8;
386 0 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_psize);
387 0 : size_t gw_offset = ip_offset + ip_size;
388 0 : IpAddress gw_address = ReadGwAddress(proto_prefix, gw_offset, ip_size);
389 0 : if (!gw_address.is_unspecified())
390 0 : return -1;
391 0 : size_t label_offset = gw_offset + ip_size;
392 0 : *label = ReadLabel(proto_prefix, attr, label_offset);
393 0 : break;
394 : }
395 0 : case SelectiveMulticastRoute: {
396 0 : if (nlri_size < kMinSelectiveMulticastRouteSize)
397 0 : return -1;
398 0 : size_t rd_offset = 0;
399 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
400 0 : size_t tag_offset = rd_offset + kRdSize;
401 0 : prefix->tag_ = get_value(&proto_prefix.prefix[tag_offset], kTagSize);
402 0 : size_t src_len_offset = tag_offset + kTagSize;
403 0 : size_t src_len = proto_prefix.prefix[src_len_offset];
404 0 : if (src_len != 32 && src_len != 128 && src_len != 0)
405 0 : return -1;
406 0 : size_t src_size = src_len / 8;
407 0 : size_t src_offset = src_len_offset + 1;
408 0 : if (src_size > 0) {
409 0 : if (nlri_size < src_offset + src_size)
410 0 : return -1;
411 0 : prefix->ReadSource(proto_prefix, src_offset, src_size);
412 : }
413 0 : size_t grp_len_offset = src_offset + src_size;
414 0 : size_t grp_len = proto_prefix.prefix[grp_len_offset];
415 0 : if (grp_len != 32 && grp_len != 128)
416 0 : return -1;
417 0 : size_t grp_size = grp_len / 8;
418 0 : size_t grp_offset = grp_len_offset + 1;
419 0 : if (nlri_size < grp_offset + grp_size)
420 0 : return -1;
421 0 : prefix->ReadGroup(proto_prefix, grp_offset, grp_size);
422 0 : size_t ip_len_offset = grp_offset + grp_size;
423 0 : size_t ip_len = proto_prefix.prefix[ip_len_offset];
424 0 : if (ip_len != 32 && ip_len != 128)
425 0 : return -1;
426 0 : size_t ip_size = ip_len / 8;
427 0 : size_t ip_offset = ip_len_offset + 1;
428 0 : if (nlri_size < ip_offset + ip_size)
429 0 : return -1;
430 0 : prefix->ReadIpAddress(proto_prefix, ip_offset, ip_size, ip_size);
431 0 : size_t flag_offset = ip_offset + ip_size;
432 0 : if (nlri_size <= flag_offset + 4)
433 0 : prefix->flags_ = get_value(&proto_prefix.prefix[flag_offset], 4);
434 0 : break;
435 : }
436 0 : default: {
437 0 : return -1;
438 : break;
439 : }
440 : }
441 0 : 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 0 : void EvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
452 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
453 0 : proto_prefix->type = type_;
454 0 : proto_prefix->prefix.clear();
455 :
456 0 : switch (type_) {
457 0 : case AutoDiscoveryRoute: {
458 0 : size_t nlri_size = kMinAutoDiscoveryRouteSize + kLabelSize;
459 0 : proto_prefix->prefixlen = nlri_size * 8;
460 0 : proto_prefix->prefix.resize(nlri_size, 0);
461 :
462 0 : size_t rd_offset = 0;
463 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
464 0 : proto_prefix->prefix.begin() + rd_offset);
465 0 : size_t esi_offset = rd_offset + kRdSize;
466 0 : copy(esi_.GetData(), esi_.GetData() + kEsiSize,
467 0 : proto_prefix->prefix.begin() + esi_offset);
468 0 : size_t tag_offset = esi_offset + kEsiSize;
469 0 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
470 0 : size_t label_offset = tag_offset + kTagSize;
471 0 : WriteLabel(proto_prefix, attr, label_offset, label);
472 0 : break;
473 : }
474 0 : case MacAdvertisementRoute: {
475 0 : size_t ip_size = GetIpAddressSize();
476 0 : size_t nlri_size = kMinMacAdvertisementRouteSize + ip_size + kLabelSize;
477 0 : if (l3_label)
478 0 : nlri_size += kLabelSize;
479 0 : proto_prefix->prefixlen = nlri_size * 8;
480 0 : proto_prefix->prefix.resize(nlri_size, 0);
481 :
482 0 : size_t rd_offset = 0;
483 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
484 0 : proto_prefix->prefix.begin() + rd_offset);
485 0 : size_t esi_offset = rd_offset + kRdSize;
486 0 : if (attr) {
487 0 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
488 0 : proto_prefix->prefix.begin() + esi_offset);
489 : }
490 0 : size_t tag_offset = esi_offset + kEsiSize;
491 0 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
492 0 : size_t mac_len_offset = tag_offset + kTagSize;
493 0 : proto_prefix->prefix[mac_len_offset] = 48;
494 0 : size_t mac_offset = mac_len_offset + 1;
495 0 : copy(mac_addr_.GetData(), mac_addr_.GetData() + kMacSize,
496 0 : proto_prefix->prefix.begin() + mac_offset);
497 0 : size_t ip_len_offset = mac_offset + kMacSize;
498 0 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
499 0 : size_t ip_offset = ip_len_offset + 1;
500 0 : WriteIpAddress(proto_prefix, ip_offset);
501 0 : size_t label_offset = ip_offset + ip_size;
502 0 : WriteLabel(proto_prefix, attr, label_offset, label);
503 0 : if (l3_label) {
504 0 : size_t l3_label_offset = label_offset + kLabelSize;
505 0 : WriteLabel(proto_prefix, attr, l3_label_offset, l3_label);
506 : }
507 0 : break;
508 : }
509 0 : case InclusiveMulticastRoute: {
510 0 : size_t ip_size = GetIpAddressSize();
511 0 : size_t nlri_size = kMinInclusiveMulticastRouteSize + ip_size;
512 0 : proto_prefix->prefixlen = nlri_size * 8;
513 0 : proto_prefix->prefix.resize(nlri_size, 0);
514 :
515 0 : size_t rd_offset = 0;
516 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
517 0 : proto_prefix->prefix.begin() + rd_offset);
518 0 : size_t tag_offset = rd_offset + kRdSize;
519 0 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
520 0 : size_t ip_len_offset = tag_offset + kTagSize;
521 0 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
522 0 : size_t ip_offset = ip_len_offset + 1;
523 0 : WriteIpAddress(proto_prefix, ip_offset);
524 0 : break;
525 : }
526 0 : case SegmentRoute: {
527 0 : size_t ip_size = GetIpAddressSize();
528 0 : size_t nlri_size = kMinSegmentRouteSize + ip_size;
529 0 : proto_prefix->prefixlen = nlri_size * 8;
530 0 : proto_prefix->prefix.resize(nlri_size, 0);
531 :
532 0 : size_t rd_offset = 0;
533 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
534 0 : proto_prefix->prefix.begin() + rd_offset);
535 0 : size_t esi_offset = rd_offset + kRdSize;
536 0 : copy(esi_.GetData(), esi_.GetData() + kEsiSize,
537 0 : proto_prefix->prefix.begin() + esi_offset);
538 0 : size_t ip_len_offset = esi_offset + kEsiSize;
539 0 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
540 0 : size_t ip_offset = ip_len_offset + 1;
541 0 : WriteIpAddress(proto_prefix, ip_offset);
542 0 : break;
543 : }
544 0 : case IpPrefixRoute: {
545 : size_t ip_size, nlri_size;
546 0 : if (family_ == Address::INET) {
547 0 : ip_size = kIp4AddrSize;
548 0 : nlri_size = kMinInetPrefixRouteSize + kLabelSize;
549 : } else {
550 0 : ip_size = kIp6AddrSize;
551 0 : nlri_size = kMinInet6PrefixRouteSize + kLabelSize;
552 : }
553 0 : proto_prefix->prefixlen = nlri_size * 8;
554 0 : proto_prefix->prefix.resize(nlri_size, 0);
555 :
556 0 : size_t rd_offset = 0;
557 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
558 0 : proto_prefix->prefix.begin() + rd_offset);
559 0 : size_t esi_offset = rd_offset + kRdSize;
560 0 : if (attr) {
561 0 : copy(attr->esi().GetData(), attr->esi().GetData() + kEsiSize,
562 0 : proto_prefix->prefix.begin() + esi_offset);
563 : }
564 0 : size_t tag_offset = esi_offset + kEsiSize;
565 : // Tag is not applicable for type5 routes.
566 0 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, 0);
567 0 : size_t ip_plen_offset = tag_offset + kTagSize;
568 0 : proto_prefix->prefix[ip_plen_offset] = ip_prefixlen_;
569 0 : size_t ip_offset = ip_plen_offset + 1;
570 0 : WriteIpAddress(proto_prefix, ip_offset);
571 0 : size_t gw_offset = ip_offset + ip_size;
572 0 : size_t label_offset = gw_offset + ip_size;
573 0 : WriteLabel(proto_prefix, attr, label_offset, label);
574 0 : break;
575 : }
576 0 : case SelectiveMulticastRoute: {
577 0 : size_t ip_size = GetIpAddressSize();
578 0 : size_t nlri_size = kMinSelectiveMulticastRouteSize + 2 * ip_size + 1;
579 0 : if (!source_.is_unspecified())
580 0 : nlri_size += ip_size;
581 0 : proto_prefix->prefixlen = nlri_size * 8;
582 0 : proto_prefix->prefix.resize(nlri_size, 0);
583 :
584 0 : size_t rd_offset = 0;
585 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
586 0 : proto_prefix->prefix.begin() + rd_offset);
587 0 : size_t tag_offset = rd_offset + kRdSize;
588 0 : put_value(&proto_prefix->prefix[tag_offset], kTagSize, tag_);
589 0 : size_t src_len_offset = tag_offset + kTagSize;
590 0 : size_t grp_len_offset = src_len_offset + 1;
591 0 : if (source_.is_unspecified()) {
592 0 : proto_prefix->prefix[src_len_offset] = 0;
593 : } else {
594 0 : proto_prefix->prefix[src_len_offset] = ip_size * 8;
595 0 : size_t src_offset = src_len_offset + 1;
596 0 : WriteSource(proto_prefix, src_offset);
597 0 : grp_len_offset += ip_size;
598 : }
599 0 : proto_prefix->prefix[grp_len_offset] = ip_size * 8;
600 0 : size_t grp_offset = grp_len_offset + 1;
601 0 : WriteGroup(proto_prefix, grp_offset);
602 0 : size_t ip_len_offset = grp_offset + ip_size;
603 0 : proto_prefix->prefix[ip_len_offset] = ip_size * 8;
604 0 : size_t ip_offset = ip_len_offset + 1;
605 0 : WriteIpAddress(proto_prefix, ip_offset);
606 0 : size_t flag_offset = ip_offset + ip_size;
607 0 : put_value(&proto_prefix->prefix[flag_offset], 1, flags_);
608 0 : break;
609 : }
610 0 : default: {
611 0 : assert(false);
612 : break;
613 : }
614 : }
615 0 : }
616 :
617 0 : int EvpnPrefix::CompareTo(const EvpnPrefix &rhs) const {
618 0 : KEY_COMPARE(type_, rhs.type_);
619 :
620 0 : switch (type_) {
621 0 : case AutoDiscoveryRoute:
622 0 : KEY_COMPARE(rd_, rhs.rd_);
623 0 : KEY_COMPARE(esi_, rhs.esi_);
624 0 : KEY_COMPARE(tag_, rhs.tag_);
625 0 : break;
626 0 : case MacAdvertisementRoute:
627 0 : KEY_COMPARE(rd_, rhs.rd_);
628 0 : KEY_COMPARE(tag_, rhs.tag_);
629 0 : KEY_COMPARE(mac_addr_, rhs.mac_addr_);
630 0 : KEY_COMPARE(ip_address_, rhs.ip_address_);
631 0 : break;
632 0 : case InclusiveMulticastRoute:
633 0 : KEY_COMPARE(rd_, rhs.rd_);
634 0 : KEY_COMPARE(tag_, rhs.tag_);
635 0 : KEY_COMPARE(ip_address_, rhs.ip_address_);
636 0 : break;
637 0 : case SegmentRoute:
638 0 : KEY_COMPARE(rd_, rhs.rd_);
639 0 : KEY_COMPARE(esi_, rhs.esi_);
640 0 : KEY_COMPARE(ip_address_, rhs.ip_address_);
641 0 : break;
642 0 : case IpPrefixRoute:
643 0 : KEY_COMPARE(rd_, rhs.rd_);
644 0 : KEY_COMPARE(tag_, rhs.tag_);
645 0 : KEY_COMPARE(ip_address_, rhs.ip_address_);
646 0 : KEY_COMPARE(ip_prefixlen_, rhs.ip_prefixlen_);
647 0 : break;
648 0 : case SelectiveMulticastRoute:
649 0 : KEY_COMPARE(rd_, rhs.rd_);
650 0 : KEY_COMPARE(tag_, rhs.tag_);
651 0 : KEY_COMPARE(source_, rhs.source_);
652 0 : KEY_COMPARE(group_, rhs.group_);
653 0 : KEY_COMPARE(ip_address_, rhs.ip_address_);
654 : default:
655 0 : break;
656 : }
657 :
658 0 : return 0;
659 : }
660 :
661 : // Check whether 'this' is more specific than rhs.
662 0 : bool EvpnPrefix::IsMoreSpecific(const EvpnPrefix &rhs) const {
663 0 : switch (type_) {
664 0 : case IpPrefixRoute:
665 0 : if (family_ == Address::INET) {
666 0 : return inet_prefix().IsMoreSpecific(rhs.inet_prefix());
667 : } else {
668 0 : return inet6_prefix().IsMoreSpecific(rhs.inet6_prefix());
669 : }
670 : break;
671 0 : default:
672 0 : break;
673 : }
674 0 : return false;
675 : }
676 :
677 0 : bool EvpnPrefix::GetSourceFromString(EvpnPrefix *prefix, const string &str,
678 : size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
679 0 : *pos2 = str.find('-', pos1 + 1);
680 0 : 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 0 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
687 0 : boost::system::error_code source_err;
688 0 : prefix->source_ = Ip4Address::from_string(temp_str, source_err);
689 0 : if (source_err.failed()) {
690 0 : if (errorp != NULL) {
691 0 : *errorp = source_err;
692 : }
693 0 : return false;
694 : }
695 0 : return true;
696 0 : }
697 :
698 0 : bool EvpnPrefix::GetGroupFromString(EvpnPrefix *prefix, const string &str,
699 : size_t pos1, size_t *pos2, boost::system::error_code *errorp) {
700 0 : *pos2 = str.find('-', pos1 + 1);
701 0 : 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 0 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
708 0 : boost::system::error_code group_err;
709 0 : prefix->group_ = Ip4Address::from_string(temp_str, group_err);
710 0 : if (group_err.failed()) {
711 0 : if (errorp != NULL) {
712 0 : *errorp = group_err;
713 : }
714 0 : return false;
715 : }
716 0 : return true;
717 0 : }
718 :
719 0 : EvpnPrefix EvpnPrefix::FromString(const string &str,
720 : boost::system::error_code *errorp) {
721 0 : EvpnPrefix prefix;
722 :
723 : // Parse type.
724 0 : size_t pos1 = str.find('-');
725 0 : if (pos1 == string::npos) {
726 0 : if (errorp != NULL) {
727 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
728 : }
729 0 : return EvpnPrefix::kNullPrefix;
730 : }
731 :
732 0 : string type_str = str.substr(0, pos1);
733 0 : bool ret = stringToInteger(type_str, prefix.type_);
734 0 : if (!ret) {
735 0 : if (errorp != NULL) {
736 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
737 : }
738 0 : return EvpnPrefix::kNullPrefix;
739 : }
740 :
741 0 : if (prefix.type_ < EvpnPrefix::AutoDiscoveryRoute ||
742 0 : prefix.type_ > EvpnPrefix::SelectiveMulticastRoute) {
743 0 : if (errorp != NULL) {
744 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
745 : }
746 0 : return EvpnPrefix::kNullPrefix;
747 : }
748 :
749 : // Parse RD.
750 0 : size_t pos2 = str.find('-', pos1 + 1);
751 0 : if (pos2 == string::npos) {
752 0 : if (errorp != NULL) {
753 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
754 : }
755 0 : return EvpnPrefix::kNullPrefix;
756 : }
757 0 : string rd_str = str.substr(pos1 + 1, pos2 - pos1 - 1);
758 0 : boost::system::error_code rd_err;
759 0 : prefix.rd_ = RouteDistinguisher::FromString(rd_str, &rd_err);
760 0 : if (rd_err.failed()) {
761 0 : if (errorp != NULL) {
762 0 : *errorp = rd_err;
763 : }
764 0 : return EvpnPrefix::kNullPrefix;
765 : }
766 :
767 0 : switch (prefix.type_) {
768 0 : case AutoDiscoveryRoute: {
769 : // Parse ESI.
770 0 : size_t pos3 = str.find('-', pos2 + 1);
771 0 : if (pos3 == string::npos) {
772 0 : if (errorp != NULL) {
773 : *errorp =
774 0 : make_error_code(boost::system::errc::invalid_argument);
775 : }
776 0 : return EvpnPrefix::kNullPrefix;
777 : }
778 0 : string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
779 0 : boost::system::error_code esi_err;
780 0 : prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
781 0 : if (esi_err.failed()) {
782 0 : if (errorp != NULL) {
783 0 : *errorp = esi_err;
784 : }
785 0 : return EvpnPrefix::kNullPrefix;
786 : }
787 :
788 : // Parse tag.
789 0 : string tag_str = str.substr(pos3 + 1, string::npos);
790 0 : bool ret = stringToInteger(tag_str, prefix.tag_);
791 0 : if (!ret) {
792 0 : if (errorp != NULL) {
793 : *errorp =
794 0 : make_error_code(boost::system::errc::invalid_argument);
795 : }
796 0 : return EvpnPrefix::kNullPrefix;
797 : }
798 :
799 0 : break;
800 0 : }
801 :
802 0 : case MacAdvertisementRoute: {
803 : // Parse tag.
804 0 : size_t pos3 = str.find('-', pos2 + 1);
805 0 : if (pos3 == string::npos) {
806 0 : if (errorp != NULL) {
807 : *errorp =
808 0 : make_error_code(boost::system::errc::invalid_argument);
809 : }
810 0 : return EvpnPrefix::kNullPrefix;
811 : }
812 0 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
813 0 : bool ret = stringToInteger(tag_str, prefix.tag_);
814 0 : if (!ret) {
815 0 : if (errorp != NULL) {
816 : *errorp =
817 0 : make_error_code(boost::system::errc::invalid_argument);
818 : }
819 0 : return EvpnPrefix::kNullPrefix;
820 : }
821 :
822 : // Parse MAC.
823 0 : size_t pos4 = str.rfind(',');
824 0 : string mac_str = str.substr(pos3 + 1, pos4 - pos3 -1);
825 0 : boost::system::error_code mac_err;
826 0 : prefix.mac_addr_ = MacAddress::FromString(mac_str, &mac_err);
827 0 : if (mac_err.failed()) {
828 0 : if (errorp != NULL) {
829 0 : *errorp = mac_err;
830 : }
831 0 : return EvpnPrefix::kNullPrefix;
832 : }
833 :
834 : // Parse IP - treat all 0s as unspecified.
835 0 : string ip_str = str.substr(pos4 + 1, string::npos);
836 0 : boost::system::error_code ip_err;
837 0 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
838 0 : if (ip_err.failed()) {
839 0 : if (errorp != NULL) {
840 0 : *errorp = ip_err;
841 : }
842 0 : return EvpnPrefix::kNullPrefix;
843 : }
844 0 : if (prefix.ip_address_.is_v4() && !prefix.ip_address_.is_unspecified())
845 0 : prefix.family_ = Address::INET;
846 0 : if (prefix.ip_address_.is_v6() && !prefix.ip_address_.is_unspecified())
847 0 : prefix.family_ = Address::INET6;
848 :
849 0 : break;
850 0 : }
851 :
852 0 : case InclusiveMulticastRoute: {
853 : // Parse tag.
854 0 : size_t pos3 = str.find('-', pos2 + 1);
855 0 : if (pos3 == string::npos) {
856 0 : if (errorp != NULL) {
857 : *errorp =
858 0 : make_error_code(boost::system::errc::invalid_argument);
859 : }
860 0 : return EvpnPrefix::kNullPrefix;
861 : }
862 0 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
863 0 : bool ret = stringToInteger(tag_str, prefix.tag_);
864 0 : if (!ret) {
865 0 : if (errorp != NULL) {
866 : *errorp =
867 0 : make_error_code(boost::system::errc::invalid_argument);
868 : }
869 0 : return EvpnPrefix::kNullPrefix;
870 : }
871 :
872 : // Parse IP.
873 0 : string ip_str = str.substr(pos3 + 1, string::npos);
874 0 : boost::system::error_code ip_err;
875 0 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
876 0 : if (ip_err.failed()) {
877 0 : if (errorp != NULL) {
878 0 : *errorp = ip_err;
879 : }
880 0 : return EvpnPrefix::kNullPrefix;
881 : }
882 0 : prefix.family_ =
883 0 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
884 :
885 0 : break;
886 0 : }
887 :
888 0 : case SegmentRoute: {
889 : // Parse ESI.
890 0 : size_t pos3 = str.find('-', pos2 + 1);
891 0 : if (pos3 == string::npos) {
892 0 : if (errorp != NULL) {
893 : *errorp =
894 0 : make_error_code(boost::system::errc::invalid_argument);
895 : }
896 0 : return EvpnPrefix::kNullPrefix;
897 : }
898 0 : string esi_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
899 0 : boost::system::error_code esi_err;
900 0 : prefix.esi_ = EthernetSegmentId::FromString(esi_str, &esi_err);
901 0 : if (esi_err.failed()) {
902 0 : if (errorp != NULL) {
903 0 : *errorp = esi_err;
904 : }
905 0 : return EvpnPrefix::kNullPrefix;
906 : }
907 :
908 : // Parse IP.
909 0 : string ip_str = str.substr(pos3 + 1, string::npos);
910 0 : boost::system::error_code ip_err;
911 0 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
912 0 : if (ip_err.failed()) {
913 0 : if (errorp != NULL) {
914 0 : *errorp = ip_err;
915 : }
916 0 : return EvpnPrefix::kNullPrefix;
917 : }
918 0 : prefix.family_ =
919 0 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
920 :
921 0 : break;
922 0 : }
923 :
924 0 : case IpPrefixRoute: {
925 : // Parse tag.
926 0 : size_t pos3 = str.find('-', pos2 + 1);
927 0 : if (pos3 == string::npos) {
928 0 : if (errorp != NULL) {
929 : *errorp =
930 0 : make_error_code(boost::system::errc::invalid_argument);
931 : }
932 0 : return EvpnPrefix::kNullPrefix;
933 : }
934 0 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
935 0 : bool ret = stringToInteger(tag_str, prefix.tag_);
936 0 : if (!ret) {
937 0 : if (errorp != NULL) {
938 : *errorp =
939 0 : make_error_code(boost::system::errc::invalid_argument);
940 : }
941 0 : return EvpnPrefix::kNullPrefix;
942 : }
943 :
944 : // Parse IP prefix - first try v4, then v6.
945 0 : string ip_str = str.substr(pos3 + 1, string::npos);
946 0 : boost::system::error_code ip_err;
947 :
948 0 : Ip4Prefix inet_prefix = Ip4Prefix::FromString(ip_str, &ip_err);
949 0 : if (!ip_err) {
950 0 : prefix.family_ = Address::INET;
951 0 : prefix.ip_address_ = inet_prefix.addr();
952 0 : prefix.ip_prefixlen_ = inet_prefix.prefixlen();
953 0 : return prefix;
954 : }
955 :
956 0 : Inet6Prefix inet6_prefix = Inet6Prefix::FromString(ip_str, &ip_err);
957 0 : if (!ip_err) {
958 0 : prefix.family_ = Address::INET6;
959 0 : prefix.ip_address_ = inet6_prefix.addr();
960 0 : prefix.ip_prefixlen_ = inet6_prefix.prefixlen();
961 0 : return prefix;
962 : }
963 :
964 0 : if (errorp != NULL) {
965 0 : *errorp = make_error_code(boost::system::errc::invalid_argument);
966 : }
967 0 : return EvpnPrefix::kNullPrefix;
968 : break;
969 0 : }
970 :
971 0 : case SelectiveMulticastRoute: {
972 : // Parse tag.
973 0 : size_t pos3 = str.find('-', pos2 + 1);
974 0 : 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 0 : string tag_str = str.substr(pos2 + 1, pos3 - pos2 - 1);
982 0 : bool ret = stringToInteger(tag_str, prefix.tag_);
983 0 : 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 0 : if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
994 0 : return EvpnPrefix::kNullPrefix;
995 :
996 : // Look for group.
997 : size_t pos5;
998 0 : if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
999 0 : return EvpnPrefix::kNullPrefix;
1000 :
1001 : // Parse IP.
1002 0 : string ip_str = str.substr(pos5 + 1, string::npos);
1003 0 : boost::system::error_code ip_err;
1004 0 : prefix.ip_address_ = IpAddress::from_string(ip_str, ip_err);
1005 0 : if (ip_err.failed()) {
1006 0 : if (errorp != NULL) {
1007 0 : *errorp = ip_err;
1008 : }
1009 0 : return EvpnPrefix::kNullPrefix;
1010 : }
1011 0 : prefix.family_ =
1012 0 : prefix.ip_address_.is_v4() ? Address::INET : Address::INET6;
1013 :
1014 0 : break;
1015 0 : }
1016 :
1017 : }
1018 :
1019 0 : return prefix;
1020 0 : }
1021 :
1022 0 : string EvpnPrefix::ToString() const {
1023 0 : string str = integerToString(type_);
1024 0 : str += "-" + rd_.ToString();
1025 0 : switch (type_) {
1026 0 : case AutoDiscoveryRoute:
1027 0 : str += "-" + esi_.ToString();
1028 0 : str += "-" + integerToString(tag_);
1029 0 : break;
1030 0 : case MacAdvertisementRoute:
1031 0 : str += "-" + integerToString(tag_);
1032 0 : str += "-" + mac_addr_.ToString();
1033 0 : str += "," + ip_address_.to_string();
1034 0 : break;
1035 0 : case InclusiveMulticastRoute:
1036 0 : str += "-" + integerToString(tag_);
1037 0 : str += "-" + ip_address_.to_string();
1038 0 : break;
1039 0 : case SegmentRoute:
1040 0 : str += "-" + esi_.ToString();
1041 0 : str += "-" + ip_address_.to_string();
1042 0 : break;
1043 0 : case IpPrefixRoute:
1044 0 : str += "-" + integerToString(tag_);
1045 0 : if (family_ == Address::INET) {
1046 0 : str += "-" + inet_prefix().ToString();
1047 : } else {
1048 0 : str += "-" + inet6_prefix().ToString();
1049 : }
1050 0 : break;
1051 0 : case SelectiveMulticastRoute:
1052 0 : str += "-" + integerToString(tag_);
1053 0 : if (!source_.is_unspecified())
1054 0 : str += "-" + source_.to_string();
1055 0 : str += "-" + group_.to_string();
1056 0 : str += "-" + ip_address_.to_string();
1057 0 : break;
1058 0 : default:
1059 0 : break;
1060 : }
1061 :
1062 0 : return str;
1063 0 : }
1064 :
1065 0 : string EvpnPrefix::ToXmppIdString() const {
1066 0 : string str;
1067 0 : if (tag_ != 0)
1068 0 : str += integerToString(tag_) + "-";
1069 0 : str += mac_addr_.ToString();
1070 0 : str += "," + ip_address_.to_string() + "/" +
1071 0 : integerToString(ip_address_length());
1072 0 : if (!group_.is_unspecified()) {
1073 0 : str += "," + group_.to_string() + "," +
1074 0 : source_.to_string();
1075 : }
1076 0 : return str;
1077 0 : }
1078 :
1079 0 : uint8_t EvpnPrefix::ip_address_length() const {
1080 0 : if (type_ == IpPrefixRoute)
1081 0 : return ip_prefixlen_;
1082 0 : if (family_ == Address::INET)
1083 0 : return 32;
1084 0 : if (family_ == Address::INET6)
1085 0 : return 128;
1086 0 : return 32;
1087 : }
1088 :
1089 0 : size_t EvpnPrefix::GetIpAddressSize() const {
1090 0 : if (family_ == Address::INET)
1091 0 : return kIp4AddrSize;
1092 0 : if (family_ == Address::INET6)
1093 0 : return kIp6AddrSize;
1094 0 : return 0;
1095 : }
1096 :
1097 0 : void EvpnPrefix::ReadSource(const BgpProtoPrefix &proto_prefix,
1098 : size_t ip_offset, size_t ip_size) {
1099 0 : if (ip_size == 0) {
1100 0 : family_ = Address::UNSPEC;
1101 0 : } else if (ip_size == kIp4AddrSize) {
1102 0 : family_ = Address::INET;
1103 0 : Ip4Address::bytes_type bytes = { { 0 } };
1104 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1105 0 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1106 0 : 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 0 : }
1115 :
1116 0 : void EvpnPrefix::ReadGroup(const BgpProtoPrefix &proto_prefix,
1117 : size_t ip_offset, size_t ip_size) {
1118 0 : if (ip_size == 0) {
1119 0 : family_ = Address::UNSPEC;
1120 0 : } else if (ip_size == kIp4AddrSize) {
1121 0 : family_ = Address::INET;
1122 0 : Ip4Address::bytes_type bytes = { { 0 } };
1123 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1124 0 : proto_prefix.prefix.begin() + ip_offset + ip_size, bytes.begin());
1125 0 : 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 0 : }
1134 :
1135 0 : void EvpnPrefix::ReadIpAddress(const BgpProtoPrefix &proto_prefix,
1136 : size_t ip_offset, size_t ip_size, size_t ip_psize) {
1137 0 : assert(ip_psize <= ip_size);
1138 0 : if (ip_size == 0) {
1139 0 : family_ = Address::UNSPEC;
1140 0 : } else if (ip_size == kIp4AddrSize) {
1141 0 : family_ = Address::INET;
1142 0 : Ip4Address::bytes_type bytes = { { 0 } };
1143 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1144 0 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1145 0 : ip_address_ = Ip4Address(bytes);
1146 0 : } else if (ip_size == kIp6AddrSize) {
1147 0 : family_ = Address::INET6;
1148 0 : Ip6Address::bytes_type bytes = { { 0 } };
1149 0 : copy(proto_prefix.prefix.begin() + ip_offset,
1150 0 : proto_prefix.prefix.begin() + ip_offset + ip_psize, bytes.begin());
1151 0 : ip_address_ = Ip6Address(bytes);
1152 : }
1153 0 : }
1154 :
1155 0 : void EvpnPrefix::WriteIpAddress(BgpProtoPrefix *proto_prefix,
1156 : size_t ip_offset) const {
1157 0 : if (family_ == Address::INET) {
1158 0 : const Ip4Address::bytes_type &bytes = ip_address_.to_v4().to_bytes();
1159 0 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1160 0 : proto_prefix->prefix.begin() + ip_offset);
1161 0 : } else if (family_ == Address::INET6) {
1162 0 : const Ip6Address::bytes_type &bytes = ip_address_.to_v6().to_bytes();
1163 0 : copy(bytes.begin(), bytes.begin() + kIp6AddrSize,
1164 0 : proto_prefix->prefix.begin() + ip_offset);
1165 : }
1166 0 : }
1167 :
1168 0 : void EvpnPrefix::WriteSource(BgpProtoPrefix *proto_prefix,
1169 : size_t ip_offset) const {
1170 0 : if (family_ == Address::INET) {
1171 0 : const Ip4Address::bytes_type &bytes = source_.to_v4().to_bytes();
1172 0 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1173 0 : 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 0 : }
1180 :
1181 0 : void EvpnPrefix::WriteGroup(BgpProtoPrefix *proto_prefix,
1182 : size_t ip_offset) const {
1183 0 : if (family_ == Address::INET) {
1184 0 : const Ip4Address::bytes_type &bytes = group_.to_v4().to_bytes();
1185 0 : copy(bytes.begin(), bytes.begin() + kIp4AddrSize,
1186 0 : 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 0 : }
1193 :
1194 0 : EvpnRoute::EvpnRoute(const EvpnPrefix &prefix)
1195 0 : : prefix_(prefix) {
1196 0 : }
1197 :
1198 0 : int EvpnRoute::CompareTo(const Route &rhs) const {
1199 0 : const EvpnRoute &evpn_rhs = static_cast<const EvpnRoute &>(rhs);
1200 0 : return prefix_.CompareTo(evpn_rhs.prefix_);
1201 : }
1202 :
1203 0 : string EvpnRoute::ToString() const {
1204 0 : return prefix_.ToString();
1205 : }
1206 :
1207 0 : string EvpnRoute::ToXmppIdString() const {
1208 0 : if (xmpp_id_str_.empty())
1209 0 : xmpp_id_str_ = prefix_.ToXmppIdString();
1210 0 : return xmpp_id_str_;
1211 : }
1212 :
1213 0 : bool EvpnRoute::IsValid() const {
1214 0 : if (!BgpRoute::IsValid())
1215 0 : return false;
1216 :
1217 0 : const BgpAttr *attr = BestPath()->GetAttr();
1218 0 : switch (prefix_.type()) {
1219 0 : case EvpnPrefix::AutoDiscoveryRoute: {
1220 0 : if (prefix_.tag() == EvpnPrefix::kMaxTag)
1221 0 : return true;
1222 0 : break;
1223 : }
1224 0 : case EvpnPrefix::MacAdvertisementRoute: {
1225 0 : return true;
1226 : }
1227 0 : case EvpnPrefix::InclusiveMulticastRoute: {
1228 0 : const PmsiTunnel *pmsi_tunnel = attr->pmsi_tunnel();
1229 0 : if (!pmsi_tunnel)
1230 0 : return false;
1231 0 : uint8_t tunnel_type = pmsi_tunnel->tunnel_type();
1232 0 : uint8_t tunnel_flags = pmsi_tunnel->tunnel_flags();
1233 0 : uint8_t ar_type =
1234 : tunnel_flags & PmsiTunnelSpec::AssistedReplicationType;
1235 0 : if (tunnel_type == PmsiTunnelSpec::IngressReplication) {
1236 0 : if (ar_type == PmsiTunnelSpec::RegularNVE)
1237 0 : return true;
1238 0 : if (ar_type == PmsiTunnelSpec::ARReplicator &&
1239 0 : (tunnel_flags & PmsiTunnelSpec::LeafInfoRequired)) {
1240 0 : return true;
1241 : }
1242 0 : return false;
1243 : }
1244 0 : if (tunnel_type == PmsiTunnelSpec::AssistedReplicationContrail &&
1245 : ar_type == PmsiTunnelSpec::ARLeaf) {
1246 0 : 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 0 : void EvpnRoute::SetKey(const DBRequestKey *reqkey) {
1268 0 : const EvpnTable::RequestKey *key =
1269 : static_cast<const EvpnTable::RequestKey *>(reqkey);
1270 0 : prefix_ = key->prefix;
1271 0 : }
1272 :
1273 0 : void EvpnRoute::BuildProtoPrefix(BgpProtoPrefix *proto_prefix,
1274 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
1275 0 : prefix_.BuildProtoPrefix(proto_prefix, attr, label, l3_label);
1276 0 : }
1277 :
1278 0 : void EvpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
1279 : IpAddress nexthop) const {
1280 0 : nh.resize(4);
1281 0 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
1282 0 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
1283 0 : }
1284 :
1285 0 : DBEntryBase::KeyPtr EvpnRoute::GetDBRequestKey() const {
1286 0 : EvpnTable::RequestKey *key = new EvpnTable::RequestKey(GetPrefix(), NULL);
1287 0 : return KeyPtr(key);
1288 : }
|