Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "bgp/bgp_proto.h"
6 :
7 : #include <boost/foreach.hpp>
8 :
9 : #include <algorithm>
10 : #include <list>
11 : #include <map>
12 : #include <utility>
13 :
14 : #include "base/proto.h"
15 : #include "bgp/bgp_log.h"
16 : #include "bgp/bgp_peer.h"
17 : #include "bgp/bgp_server.h"
18 : #include "net/bgp_af.h"
19 :
20 : using boost::system::error_code;
21 : using boost::tie;
22 : using std::cout;
23 : using std::endl;
24 : using std::string;
25 : using std::vector;
26 :
27 : namespace mpl = boost::mpl;
28 :
29 15553 : BgpProto::OpenMessage::OpenMessage()
30 15553 : : BgpMessage(OPEN), as_num(-1), holdtime(-1), identifier(-1) {
31 15552 : }
32 :
33 21814 : BgpProto::OpenMessage::~OpenMessage() {
34 15552 : STLDeleteValues(&opt_params);
35 21813 : }
36 :
37 : //
38 : // Validate the capabilities in an incoming Open Message.
39 : //
40 : // Return the capability code that's missing if a problem is detected.
41 : // Return 0 if capabilities in the message are OK.
42 : //
43 : // Note that we must not generate an error if we see a capability that we
44 : // do not support.
45 : //
46 : // Go through all the capabilities and make sure that there's at least one
47 : // MpExtension with an (afi, safi) pair that's also configured on the peer.
48 : //
49 : //
50 6188 : int BgpProto::OpenMessage::ValidateCapabilities(BgpPeer *peer) const {
51 6188 : bool mp_extension_ok = false;
52 :
53 : // Go through each OptParam in the OpenMessage.
54 6188 : for (vector<OptParam *>::const_iterator param_it = opt_params.begin();
55 12362 : param_it != opt_params.end(); ++param_it) {
56 6188 : const OptParam *param = *param_it;
57 :
58 : // Go through each Capability in the OptParam.
59 6188 : for (vector<Capability *>::const_iterator cap_it =
60 6188 : param->capabilities.begin();
61 29101 : cap_it != param->capabilities.end(); ++cap_it) {
62 22926 : const Capability *cap = *cap_it;
63 :
64 : // See if the (afi,safi) in the MpExtension is configured on peer.
65 22926 : if (cap->code == Capability::MpExtension) {
66 14850 : const uint8_t *data = cap->capability.data();
67 14850 : uint16_t afi = get_value(data, 2);
68 14850 : uint8_t safi = get_value(data + 3, 1);
69 14851 : Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
70 14852 : if (peer->LookupFamily(family))
71 14755 : mp_extension_ok = true;
72 : }
73 :
74 23112 : if (cap->code == Capability::AS4Support &&
75 184 : peer->server()->enable_4byte_as()) {
76 59 : const uint8_t *data = cap->capability.data();
77 59 : as_t asn = get_value(data, 4);
78 59 : if (asn != peer->peer_as()) {
79 14 : BGP_LOG_PEER_WARNING(Message, peer, BGP_LOG_FLAG_ALL,
80 : BGP_PEER_DIR_IN, "Bad Peer AS Number: " << asn <<
81 : ", Configured peer ASN: " << peer->peer_as());
82 14 : return BgpProto::Notification::BadPeerAS;
83 : }
84 : }
85 : }
86 : }
87 :
88 6174 : if (!mp_extension_ok) {
89 29 : BGP_LOG_PEER_WARNING(Message, peer, BGP_LOG_FLAG_ALL,
90 : BGP_PEER_DIR_IN, "Unsupported Capability: " <<
91 : Capability::CapabilityToString(Capability::MpExtension) <<
92 : " (" << Capability::MpExtension << ")");
93 29 : return BgpProto::Notification::UnsupportedCapability;
94 : }
95 :
96 6145 : return 0;
97 : }
98 :
99 : //
100 : // Validate an incoming Open Message.
101 : //
102 : // Return one of the values from BgpProto::Notification::OpenMsgSubCode if
103 : // an error is detected.
104 : // Return 0 if message is OK.
105 : //
106 6253 : int BgpProto::OpenMessage::Validate(BgpPeer *peer) const {
107 6253 : if (identifier == 0) {
108 0 : BGP_LOG_PEER_WARNING(Message, peer, BGP_LOG_FLAG_ALL,
109 : BGP_PEER_DIR_IN, "Bad BGP Identifier: " << 0);
110 0 : return BgpProto::Notification::BadBgpId;
111 : }
112 6253 : if (identifier == peer->server()->bgp_identifier()) {
113 5 : BGP_LOG_PEER_WARNING(Message, peer, BGP_LOG_FLAG_ALL,
114 : BGP_PEER_DIR_IN,
115 : "Bad (Same as mine) BGP Identifier: " <<
116 : Ip4Address(identifier).to_string());
117 5 : return BgpProto::Notification::BadBgpId;
118 : }
119 6248 : if (as_num != AS_TRANS && as_num != peer->peer_as()) {
120 60 : BGP_LOG_PEER_WARNING(Message, peer, BGP_LOG_FLAG_ALL,
121 : BGP_PEER_DIR_IN, "Bad Peer AS Number: " << as_num);
122 60 : return BgpProto::Notification::BadPeerAS;
123 : }
124 :
125 6188 : return ValidateCapabilities(peer);
126 : }
127 :
128 : BgpProto::OpenMessage::Capability *
129 205889 : BgpProto::OpenMessage::Capability::GR::Encode(
130 : uint16_t gr_time, bool restarted, bool notification,
131 : const vector<uint8_t> &gr_afi_flags,
132 : const vector<Address::Family> &gr_families) {
133 205889 : assert((gr_time & ~RestartTimeMask) == 0);
134 205889 : uint16_t restart_flags = restarted ? RestartedFlag : 0;
135 205889 : restart_flags |= notification ? NotificationFlag : 0;
136 205889 : const uint16_t gr_bytes = restart_flags | gr_time;
137 :
138 205889 : vector<uint8_t> restart_cap;
139 205893 : restart_cap.push_back(gr_bytes >> 8);
140 205889 : restart_cap.push_back(gr_bytes & 0xFF);
141 :
142 205891 : size_t i = 0;
143 826111 : BOOST_FOREACH(const Address::Family family, gr_families) {
144 : uint16_t afi;
145 : uint8_t safi;
146 310113 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
147 310112 : restart_cap.push_back(0);
148 310110 : restart_cap.push_back(afi);
149 310110 : restart_cap.push_back(safi);
150 310110 : restart_cap.push_back(gr_afi_flags[i++]);
151 : }
152 205889 : return new Capability(GracefulRestart, restart_cap.data(),
153 411780 : restart_cap.size());
154 205893 : }
155 :
156 791856 : void BgpProto::OpenMessage::Capability::GR::GetFamilies(const GR &gr_params,
157 : vector<string> *families) {
158 791856 : families->clear();
159 1979924 : BOOST_FOREACH(Capability::GR::Family gr_family, gr_params.families) {
160 : Address::Family family =
161 594033 : BgpAf::AfiSafiToFamily(gr_family.afi, gr_family.safi);
162 594033 : if (family == Address::UNSPEC) {
163 0 : families->push_back(BgpAf::ToString(gr_family.afi, gr_family.safi));
164 : } else {
165 594033 : families->push_back(Address::FamilyToString(family));
166 : }
167 : }
168 :
169 : // Keep the list sorted and unique.
170 791857 : sort(families->begin(), families->end());
171 791857 : families->erase(unique(families->begin(), families->end()),
172 791857 : families->end() );
173 791858 : }
174 :
175 798383 : bool BgpProto::OpenMessage::Capability::GR::Decode(GR *gr_params,
176 : const vector<Capability *> &capabilities) {
177 798383 : gr_params->Initialize();
178 :
179 : // Find and process all GR capabilities. We are expected to receive only
180 : // one. Otherwise, the only the last one should be taken into effect.
181 798383 : bool found = false;
182 798383 : for (vector<Capability *>::const_iterator cap_it = capabilities.begin();
183 1637108 : cap_it != capabilities.end(); ++cap_it) {
184 838724 : if ((*cap_it)->code != GracefulRestart)
185 433795 : continue;
186 404929 : found = true;
187 404929 : gr_params->Initialize();
188 :
189 404932 : uint8_t *data = (*cap_it)->capability.data();
190 404932 : uint16_t bytes = get_value(data, 2);
191 404932 : gr_params->set_flags(bytes);
192 404932 : gr_params->set_time(bytes);
193 :
194 404932 : size_t offset = 2;
195 1015325 : while (offset < (*cap_it)->capability.size()) {
196 610394 : uint16_t afi = get_value(data + offset, 2);
197 610394 : uint8_t safi = get_value(data + offset + 2, 1);
198 610394 : uint8_t flags = get_value(data + offset + 3, 1);
199 610394 : gr_params->families.push_back(Family(afi, safi, flags));
200 610393 : offset += 4;
201 : }
202 : }
203 798380 : return found;
204 : }
205 :
206 : BgpProto::OpenMessage::Capability *
207 200710 : BgpProto::OpenMessage::Capability::LLGR::Encode(uint32_t llgr_time,
208 : uint8_t llgr_afi_flags, const vector<Address::Family> &llgr_families) {
209 200710 : assert((llgr_time & ~RestartTimeMask) == 0);
210 200710 : vector<uint8_t> llgr_cap;
211 820896 : BOOST_FOREACH(const Address::Family family, llgr_families) {
212 : uint16_t afi;
213 : uint8_t safi;
214 310096 : tie(afi, safi) = BgpAf::FamilyToAfiSafi(family);
215 310097 : llgr_cap.push_back(0);
216 310096 : llgr_cap.push_back(afi);
217 310096 : llgr_cap.push_back(safi);
218 310095 : llgr_cap.push_back(llgr_afi_flags);
219 310095 : llgr_cap.push_back((llgr_time & 0x00FF0000) >> 16);
220 310093 : llgr_cap.push_back((llgr_time & 0x0000FF00) >> 8);
221 310092 : llgr_cap.push_back((llgr_time & 0x000000FF) >> 0);
222 : }
223 200710 : return new Capability(LongLivedGracefulRestart, llgr_cap.data(),
224 401421 : llgr_cap.size());
225 200711 : }
226 :
227 798380 : bool BgpProto::OpenMessage::Capability::LLGR::Decode(LLGR *llgr_params,
228 : const vector<Capability *> &capabilities) {
229 798380 : llgr_params->Initialize();
230 :
231 : // Find and process all LLGR capabilities. We are expected to receive only
232 : // one. Otherwise, the only the last one should be taken into effect.
233 798381 : bool found = false;
234 798381 : for (vector<Capability *>::const_iterator cap_it = capabilities.begin();
235 1637100 : cap_it != capabilities.end(); ++cap_it) {
236 838720 : if ((*cap_it)->code != LongLivedGracefulRestart)
237 439251 : continue;
238 399469 : found = true;
239 399469 : llgr_params->Initialize();
240 :
241 399469 : uint8_t *data = (*cap_it)->capability.data();
242 399469 : size_t offset = 0;
243 399469 : uint32_t max_time = 0;
244 1009840 : while (offset < (*cap_it)->capability.size()) {
245 610373 : uint16_t afi = get_value(data + offset, 2);
246 610372 : uint8_t safi = get_value(data + offset + 2, 1);
247 610372 : uint8_t flags = get_value(data + offset + 3, 1);
248 610372 : uint32_t time = get_value(data + offset + 4, 3);
249 610373 : llgr_params->families.push_back(Family(afi, safi, flags, time));
250 :
251 610371 : if (time > max_time)
252 178288 : max_time = time;
253 610371 : offset += 7;
254 : }
255 399468 : llgr_params->time = max_time;
256 : }
257 798380 : return found;
258 : }
259 :
260 791858 : void BgpProto::OpenMessage::Capability::LLGR::GetFamilies(
261 : const LLGR &llgr_params, vector<string> *families) {
262 791858 : families->clear();
263 1979896 : BOOST_FOREACH(Capability::LLGR::Family llgr_family, llgr_params.families) {
264 : Address::Family family =
265 594019 : BgpAf::AfiSafiToFamily(llgr_family.afi, llgr_family.safi);
266 594019 : if (family == Address::UNSPEC) {
267 0 : families->push_back(BgpAf::ToString(llgr_family.afi,
268 0 : llgr_family.safi));
269 : } else {
270 594019 : families->push_back(Address::FamilyToString(family));
271 : }
272 : }
273 :
274 : // Keep the list sorted and unique.
275 791857 : sort(families->begin(), families->end());
276 791857 : families->erase(unique(families->begin(), families->end()),
277 791857 : families->end() );
278 791858 : }
279 :
280 6522 : const string BgpProto::OpenMessage::ToString() const {
281 6522 : std::ostringstream os;
282 :
283 6522 : error_code ec;
284 6522 : os << "AS " << as_num;
285 6522 : os << ", Hold Time " << holdtime;
286 6522 : os << ", Identifier " << Ip4Address(identifier).to_string(ec);
287 :
288 : // Go through each OptParam in the OpenMessage.
289 6522 : for (vector<OptParam *>::const_iterator param_it = opt_params.begin();
290 13043 : param_it != opt_params.end(); ++param_it) {
291 6522 : const OptParam *param = *param_it;
292 :
293 : // Go through each Capability in the OptParam.
294 : vector<Capability *>::const_iterator cap_it =
295 6522 : param->capabilities.begin();
296 32234 : while (cap_it != param->capabilities.end()) {
297 32233 : const Capability *cap = *cap_it;
298 :
299 32233 : os << ", Code " << Capability::CapabilityToString(cap->code);
300 :
301 32234 : if (cap->code == Capability::MpExtension) {
302 20587 : const uint8_t *data = cap->capability.data();
303 20587 : uint16_t afi = get_value(data, 2);
304 20587 : uint8_t safi = get_value(data + 3, 1);
305 20587 : Address::Family family = BgpAf::AfiSafiToFamily(afi, safi);
306 20587 : os << " Family " << Address::FamilyToString(family);
307 : }
308 :
309 32234 : if (++cap_it == param->capabilities.end())
310 6522 : break;
311 : }
312 :
313 6522 : Capability::GR gr_params = Capability::GR();
314 6522 : if (Capability::GR::Decode(&gr_params, param->capabilities)) {
315 6400 : os << ", GR_Flags 0x" << std::hex << int(gr_params.flags);
316 6400 : os << ", GR_Time " << gr_params.time;
317 39102 : BOOST_FOREACH(Capability::GR::Family family, gr_params.families) {
318 16350 : os << ", GR_family " <<
319 16350 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
320 16351 : os << ", GR_family_flags 0x" << std::hex << int(family.flags);
321 : }
322 : }
323 :
324 6522 : Capability::LLGR llgr_params = Capability::LLGR();
325 6522 : if (Capability::LLGR::Decode(&llgr_params, param->capabilities)) {
326 37580 : BOOST_FOREACH(Capability::LLGR::Family family,
327 : llgr_params.families) {
328 16347 : os << ", LLGR_family " <<
329 16347 : BgpAf::AfiSafiToFamily(family.afi, family.safi);
330 16347 : os << ", LLGR_family_flags 0x" << std::hex << int(family.flags);
331 16351 : os << ", LLGR_Time " << family.time << " Seconds";
332 : }
333 : }
334 6521 : }
335 :
336 13042 : return os.str();
337 6521 : }
338 :
339 12074 : BgpProto::Notification::Notification()
340 12074 : : BgpMessage(NOTIFICATION), error(0), subcode(0) {
341 12073 : }
342 :
343 7259 : const string BgpProto::Notification::ToString() const {
344 7259 : return toString(static_cast<BgpProto::Notification::Code>(error), subcode);
345 : }
346 :
347 14318 : const string BgpProto::Notification::toString(
348 : BgpProto::Notification::Code code, int sub_code) {
349 14318 : string msg("");
350 14318 : switch (code) {
351 10 : case MsgHdrErr:
352 20 : msg += string("Message Header Error:") +
353 30 : MsgHdrSubcodeToString(static_cast<MsgHdrSubCode>(sub_code));
354 10 : break;
355 258 : case OpenMsgErr:
356 516 : msg += string("OPEN Message Error:") +
357 774 : OpenMsgSubcodeToString(static_cast<OpenMsgSubCode>(sub_code));
358 258 : break;
359 10 : case UpdateMsgErr:
360 20 : msg += string("UPDATE Message Error:") +
361 20 : UpdateMsgSubCodeToString(
362 10 : static_cast<UpdateMsgSubCode>(sub_code));
363 10 : break;
364 270 : case HoldTimerExp:
365 270 : msg += "Hold Timer Expired";
366 270 : break;
367 32 : case FSMErr:
368 64 : msg += string("Finite State Machine Error:") +
369 96 : FsmSubcodeToString(static_cast<FsmSubcode>(sub_code));
370 32 : break;
371 13659 : case Cease:
372 27316 : msg += string("Cease:") +
373 40977 : CeaseSubcodeToString(static_cast<CeaseSubCode>(sub_code));
374 13661 : break;
375 79 : default:
376 79 : msg += "Unknown";
377 79 : break;
378 : }
379 14320 : return msg;
380 0 : }
381 :
382 13727 : BgpProto::Keepalive::Keepalive()
383 13727 : : BgpMessage(KEEPALIVE) {
384 13727 : }
385 :
386 363819 : BgpProto::Update::Update()
387 363819 : : BgpMessage(UPDATE) {
388 363785 : }
389 :
390 538244 : BgpProto::Update::~Update() {
391 363824 : STLDeleteValues(&withdrawn_routes);
392 363817 : STLDeleteValues(&path_attributes);
393 363802 : STLDeleteValues(&nlri);
394 538209 : }
395 :
396 : struct BgpAttrCodeCompare {
397 974940 : bool operator()(BgpAttribute *lhs, BgpAttribute *rhs) const {
398 974940 : return lhs->code < rhs->code;
399 : }
400 : };
401 :
402 : //
403 : // Validate an incoming Update Message
404 : // Returns 0 if message is OK
405 : // Returns one of the values from enum UpdateMsgSubCode if an error is detected
406 : //
407 158260 : int BgpProto::Update::Validate(const BgpPeer *peer, string *data) {
408 : BgpAttrCodeCompare comp;
409 158260 : std::sort(path_attributes.begin(), path_attributes.end(), comp);
410 158247 : bool origin = false, nh = false, as_path = false, mp_reach_nlri = false,
411 158247 : local_pref = false;
412 :
413 158247 : bool ibgp = (peer->PeerType() == IBGP);
414 :
415 158250 : BgpAttrSpec::const_iterator it;
416 158250 : string rxed_attr("Path attributes : ");
417 715898 : for (it = path_attributes.begin(); it < path_attributes.end(); it++) {
418 557619 : if (it+1 < path_attributes.end() && (*it)->code == (*(it+1))->code) {
419 : // Duplicate attributes
420 0 : return BgpProto::Notification::MalformedAttributeList;
421 : }
422 :
423 557601 : rxed_attr += (*it)->ToString() + " ";
424 :
425 557640 : if ((*it)->code == BgpAttribute::Origin)
426 111204 : origin = true;
427 557635 : if ((*it)->code == BgpAttribute::LocalPref) {
428 24227 : local_pref = true;
429 533404 : } else if ((*it)->code == BgpAttribute::NextHop) {
430 3207 : nh = true;
431 530211 : } else if ((*it)->code == BgpAttribute::AsPath) {
432 111205 : as_path = true;
433 111205 : if (peer && peer->IsAs4Supported()) {
434 66 : AsPath4ByteSpec *asp = static_cast<AsPath4ByteSpec *>(*it);
435 : // Check segments size for ebgp.
436 : // IBGP can have empty path for routes that are originated.
437 66 : if (!ibgp) {
438 62 : if (!asp->path_segments.size() ||
439 31 : !asp->path_segments[0]->path_segment.size())
440 0 : return BgpProto::Notification::MalformedASPath;
441 : }
442 : } else {
443 111138 : AsPathSpec *asp = static_cast<AsPathSpec *>(*it);
444 : // Check segments size for ebgp.
445 : // IBGP can have empty path for routes that are originated.
446 111136 : if (!ibgp) {
447 173892 : if (!asp->path_segments.size() ||
448 86946 : !asp->path_segments[0]->path_segment.size())
449 0 : return BgpProto::Notification::MalformedASPath;
450 : }
451 : }
452 419007 : } else if ((*it)->code == BgpAttribute::MPReachNlri) {
453 111197 : mp_reach_nlri = true;
454 : }
455 : }
456 :
457 158249 : BGP_LOG_PEER(Message, const_cast<BgpPeer *>(peer),
458 : SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_TRACE,
459 : BGP_PEER_DIR_IN, rxed_attr);
460 158250 : if (nlri.size() > 0 && !nh) {
461 : // next-hop attribute must be present if IPv4 NLRI is present
462 0 : char attrib_type = BgpAttribute::NextHop;
463 0 : *data = string(&attrib_type, 1);
464 0 : return BgpProto::Notification::MissingWellKnownAttrib;
465 : }
466 158250 : if (nlri.size() > 0 || mp_reach_nlri) {
467 : // origin and as_path must be present if any NLRI is present
468 111197 : if (!origin) {
469 0 : char attrib_type = BgpAttribute::Origin;
470 0 : *data = string(&attrib_type, 1);
471 0 : return BgpProto::Notification::MissingWellKnownAttrib;
472 : }
473 111197 : if (!as_path) {
474 0 : char attrib_type = BgpAttribute::AsPath;
475 0 : *data = string(&attrib_type, 1);
476 0 : return BgpProto::Notification::MissingWellKnownAttrib;
477 : }
478 :
479 : // All validations for IBGP
480 111197 : if (ibgp && !local_pref) {
481 : // If IBGP, local_pref is mandatory
482 0 : char attrib_type = BgpAttribute::LocalPref;
483 0 : *data = string(&attrib_type, 1);
484 0 : return BgpProto::Notification::MissingWellKnownAttrib;
485 : }
486 : }
487 158250 : return 0;
488 158250 : }
489 :
490 9981 : int BgpProto::Update::CompareTo(const BgpProto::Update &rhs) const {
491 9981 : KEY_COMPARE(withdrawn_routes.size(), rhs.withdrawn_routes.size());
492 9989 : for (size_t i = 0; i < withdrawn_routes.size(); i++) {
493 8 : KEY_COMPARE(withdrawn_routes[i]->prefixlen,
494 : rhs.withdrawn_routes[i]->prefixlen);
495 8 : KEY_COMPARE(withdrawn_routes[i]->prefix,
496 : rhs.withdrawn_routes[i]->prefix);
497 : }
498 :
499 9981 : KEY_COMPARE(path_attributes.size(), rhs.path_attributes.size());
500 63551 : for (size_t i = 0; i < rhs.path_attributes.size(); i++) {
501 53570 : int ret = path_attributes[i]->CompareTo(*rhs.path_attributes[i]);
502 53570 : if (ret != 0) {
503 0 : cout << "Unequal " << TYPE_NAME(*path_attributes[i]) << endl;
504 0 : return ret;
505 : }
506 : }
507 :
508 9981 : KEY_COMPARE(nlri.size(), rhs.nlri.size());
509 9989 : for (size_t i = 0; i < rhs.nlri.size(); i++) {
510 8 : KEY_COMPARE(nlri[i]->prefixlen, rhs.nlri[i]->prefixlen);
511 8 : KEY_COMPARE(nlri[i]->prefix, rhs.nlri[i]->prefix);
512 : }
513 9981 : return 0;
514 : }
515 :
516 : class BgpMarker : public ProtoElement<BgpMarker> {
517 : public:
518 : static const int kSize = 16;
519 : static const int kErrorCode = BgpProto::Notification::MsgHdrErr;
520 : static const int kErrorSubcode = BgpProto::Notification::ConnNotSync;
521 196000 : static bool Verifier(const void *obj, const uint8_t *data, size_t size,
522 : ParseContext *context) {
523 3326255 : for (int i = 0; i < 16; i++) {
524 3131219 : if (data[i] != 0xff) return false;
525 : }
526 195036 : return true;
527 : }
528 212826 : static void Writer(const void *msg, uint8_t *data, size_t size) {
529 3618049 : for (int i = 0; i < 16; i++) {
530 3405223 : data[i] = 0xff;
531 : }
532 212826 : }
533 : };
534 :
535 : class BgpMsgLength : public ProtoElement<BgpMsgLength> {
536 : public:
537 : static const int kSize = 2;
538 : static const int kErrorCode = BgpProto::Notification::MsgHdrErr;
539 : static const int kErrorSubcode = BgpProto::Notification::BadMsgLength;
540 : struct Offset {
541 212834 : string operator()() {
542 212834 : return "BgpMsgLength";
543 : }
544 : };
545 : typedef Offset SaveOffset;
546 195037 : static bool Verifier(const void *obj, const uint8_t *data, size_t size,
547 : ParseContext *context) {
548 195037 : int value = get_short(data);
549 195037 : if (value < BgpProto::kMinMessageSize ||
550 : value > BgpProto::kMaxMessageSize) {
551 87 : return false;
552 : }
553 194950 : if ((size_t) value < context->offset() + size) {
554 2846 : return false;
555 : }
556 192104 : return true;
557 : }
558 : struct SetLength {
559 212712 : static void Callback(EncodeContext *context, uint8_t *data,
560 : int offset, int element_size) {
561 212712 : put_value(data, kSize, context->length());
562 212702 : }
563 : };
564 : typedef SetLength EncodingCallback;
565 : };
566 :
567 : // BGP OPEN
568 : class BgpOpenVersion : public ProtoElement<BgpOpenVersion> {
569 : public:
570 : static const int kSize = 1;
571 : static const int kErrorCode = BgpProto::Notification::OpenMsgErr;
572 : static const int kErrorSubcode = BgpProto::Notification::UnsupportedVersion;
573 6136 : static bool Verifier(const void * obj, const uint8_t *data, size_t size,
574 : ParseContext *context) {
575 6136 : return data[0] == 0x4;
576 : }
577 9278 : static void Writer(const void *msg, uint8_t *data, size_t size) {
578 9278 : *data = 0x4;
579 9278 : }
580 : };
581 :
582 : class BgpOpenAsNum : public ProtoElement<BgpOpenAsNum> {
583 : public:
584 : static const int kSize = 2;
585 : typedef Accessor<BgpProto::OpenMessage, uint32_t,
586 : &BgpProto::OpenMessage::as_num> Setter;
587 : };
588 :
589 : class BgpHoldTime : public ProtoElement<BgpHoldTime> {
590 : public:
591 : static const int kSize = 2;
592 : static const int kErrorCode = BgpProto::Notification::OpenMsgErr;
593 : static const int kErrorSubcode =
594 : BgpProto::Notification::UnacceptableHoldTime;
595 6132 : static bool Verifier(const BgpProto::OpenMessage *obj, const uint8_t *data,
596 : size_t size, ParseContext *context) {
597 6132 : uint16_t value = get_value(data, 2);
598 6132 : return (value == 0 || value >= 3);
599 : }
600 : typedef Accessor<BgpProto::OpenMessage, int32_t,
601 : &BgpProto::OpenMessage::holdtime> Setter;
602 : };
603 :
604 : class BgpIdentifier : public ProtoElement<BgpIdentifier> {
605 : public:
606 : static const int kSize = 4;
607 : typedef Accessor<BgpProto::OpenMessage, uint32_t,
608 : &BgpProto::OpenMessage::identifier> Setter;
609 : };
610 :
611 : class BgpOpenCapabilityCode : public ProtoElement<BgpOpenCapabilityCode> {
612 : public:
613 : static const int kSize = 1;
614 : typedef Accessor<BgpProto::OpenMessage::Capability, int,
615 : &BgpProto::OpenMessage::Capability::code> Setter;
616 : };
617 :
618 : class BgpOpenCapabilityLength : public ProtoElement<BgpOpenCapabilityLength> {
619 : public:
620 : static const int kSize = 1;
621 : typedef int SequenceLength;
622 : };
623 :
624 : class BgpOpenCapabilityValue : public ProtoElement<BgpOpenCapabilityValue> {
625 : public:
626 : static const int kSize = -1;
627 : typedef VectorAccessor<BgpProto::OpenMessage::Capability, uint8_t,
628 : &BgpProto::OpenMessage::Capability::capability> Setter;
629 : };
630 :
631 : class BgpOpenCapability : public ProtoSequence<BgpOpenCapability> {
632 : public:
633 : typedef mpl::list<BgpOpenCapabilityCode, BgpOpenCapabilityLength,
634 : BgpOpenCapabilityValue> Sequence;
635 : };
636 :
637 : class BgpOpenCapabilities : public ProtoSequence<BgpOpenCapabilities> {
638 : public:
639 : static const int kSize = 1;
640 : static const int kMinOccurs = 0;
641 : static const int kMaxOccurs = -1;
642 : typedef mpl::list<BgpOpenCapability> Sequence;
643 :
644 : typedef CollectionAccessor<BgpProto::OpenMessage::OptParam,
645 : vector<BgpProto::OpenMessage::Capability *>,
646 : &BgpProto::OpenMessage::OptParam::capabilities> ContextStorer;
647 :
648 : struct OptMatch {
649 9281 : bool match(const BgpProto::OpenMessage::OptParam *ctx) {
650 9281 : return !ctx->capabilities.empty();
651 : }
652 : };
653 : typedef OptMatch ContextMatch;
654 : };
655 :
656 : class BgpOpenOptParamChoice : public ProtoChoice<BgpOpenOptParamChoice> {
657 : public:
658 : static const int kSize = 1;
659 : static const int kErrorCode = BgpProto::Notification::OpenMsgErr;
660 : static const int kErrorSubcode =
661 : BgpProto::Notification::UnsupportedOptionalParam;
662 : typedef mpl::map<
663 : mpl::pair<mpl::int_<BgpProto::OpenMessage::OPEN_OPT_CAPABILITIES>,
664 : BgpOpenCapabilities>
665 : > Choice;
666 : };
667 :
668 : class BgpOpenOptParam : public ProtoSequence<BgpOpenOptParam> {
669 : public:
670 : static const int kSize = 1;
671 : static const int kMinOccurs = 0;
672 : static const int kMaxOccurs = -1;
673 : typedef CollectionAccessor<BgpProto::OpenMessage,
674 : vector<BgpProto::OpenMessage::OptParam *>,
675 : &BgpProto::OpenMessage::opt_params> ContextStorer;
676 : typedef mpl::list<BgpOpenOptParamChoice> Sequence;
677 : };
678 :
679 : class BgpOpenMessage : public ProtoSequence<BgpOpenMessage> {
680 : public:
681 : typedef mpl::list<BgpOpenVersion,
682 : BgpOpenAsNum,
683 : BgpHoldTime,
684 : BgpIdentifier,
685 : BgpOpenOptParam> Sequence;
686 : typedef BgpProto::OpenMessage ContextType;
687 : };
688 :
689 : class NotificationErrorCode : public ProtoElement<NotificationErrorCode> {
690 : public:
691 : static const int kSize = 1;
692 : typedef Accessor<BgpProto::Notification, int,
693 : &BgpProto::Notification::error> Setter;
694 : };
695 :
696 : class NotificationErrorSubcode : public ProtoElement<NotificationErrorSubcode> {
697 : public:
698 : static const int kSize = 1;
699 : typedef Accessor<BgpProto::Notification, int,
700 : &BgpProto::Notification::subcode> Setter;
701 : };
702 :
703 : class NotificationData : public ProtoElement<NotificationData> {
704 : public:
705 : static const int kSize = -1;
706 : typedef Accessor<BgpProto::Notification, string,
707 : &BgpProto::Notification::data> Setter;
708 : };
709 :
710 : class BgpNotificationMessage : public ProtoSequence<BgpNotificationMessage> {
711 : public:
712 : typedef mpl::list<NotificationErrorCode,
713 : NotificationErrorSubcode,
714 : NotificationData> Sequence;
715 : typedef BgpProto::Notification ContextType;
716 : };
717 :
718 : class BgpKeepaliveMessage : public ProtoSequence<BgpKeepaliveMessage> {
719 : public:
720 : typedef mpl::list<> Sequence;
721 : typedef BgpProto::Keepalive ContextType;
722 : };
723 :
724 : class BgpPrefixLen : public ProtoElement<BgpPrefixLen> {
725 : public:
726 : static const int kSize = 1;
727 : struct PrefixLen {
728 832572 : int operator()(BgpProtoPrefix *obj, const uint8_t *data, size_t size) {
729 832572 : int bits = data[0];
730 832572 : return (bits + 7) / 8;
731 : }
732 : };
733 : typedef PrefixLen SequenceLength;
734 : typedef Accessor<BgpProtoPrefix, int,
735 : &BgpProtoPrefix::prefixlen> Setter;
736 : };
737 :
738 : class BgpPrefixAddress : public ProtoElement<BgpPrefixAddress> {
739 : public:
740 : static const int kSize = -1;
741 : typedef VectorAccessor<BgpProtoPrefix, uint8_t,
742 : &BgpProtoPrefix::prefix> Setter;
743 : };
744 :
745 : class BgpUpdateWithdrawnRoutes :
746 : public ProtoSequence<BgpUpdateWithdrawnRoutes> {
747 : public:
748 : static const int kSize = 2;
749 : static const int kMinOccurs = 0;
750 : static const int kMaxOccurs = -1;
751 : static const int kErrorCode = BgpProto::Notification::UpdateMsgErr;
752 : static const int kErrorSubcode =
753 : BgpProto::Notification::MalformedAttributeList;
754 :
755 : typedef CollectionAccessor<BgpProto::Update,
756 : vector<BgpProtoPrefix *>,
757 : &BgpProto::Update::withdrawn_routes> ContextStorer;
758 :
759 : struct OptMatch {
760 : bool match(const BgpProto::Update *ctx) {
761 : return !ctx->withdrawn_routes.empty();
762 : }
763 : };
764 : typedef OptMatch ContextMatch;
765 :
766 : typedef mpl::list<BgpPrefixLen, BgpPrefixAddress> Sequence;
767 : };
768 :
769 : class BgpPathAttrLength : public ProtoElement<BgpPathAttrLength> {
770 : public:
771 : static const int kSize = -1;
772 : struct AttrLen {
773 627836 : int operator()(BgpAttribute *obj,
774 : const uint8_t *data, size_t &size) {
775 627836 : if (obj->flags & BgpAttribute::ExtendedLength) {
776 : // Extended Length: use 2 bytes to read
777 168967 : size = 2;
778 : } else {
779 458869 : size = 1;
780 : }
781 627836 : return get_value(data, size);
782 : }
783 : };
784 : typedef AttrLen SequenceLength;
785 : struct AttrSizeSet {
786 1303113 : static int get(const BgpAttribute *obj) {
787 1303113 : if (obj->GetEncodeFlags() & BgpAttribute::ExtendedLength) {
788 : // Extended Length: use 2 bytes to read
789 353553 : return 2;
790 : } else {
791 950014 : return 1;
792 : }
793 : }
794 : };
795 : typedef AttrSizeSet SizeSetter;
796 : };
797 :
798 : template <class Derived>
799 : struct BgpContextSwap {
800 627887 : Derived *operator()(const BgpAttribute *attr) {
801 627887 : return new Derived(*attr);
802 : }
803 : };
804 :
805 : template <class C>
806 : struct BgpAttributeVerifier {
807 631377 : static bool Verifier(const C *obj, const uint8_t *data, size_t size,
808 : ParseContext *context) {
809 631377 : int pre = (obj->flags & BgpAttribute::ExtendedLength) ? 4 : 3;
810 86261 : if (C::kSize > 0 &&
811 86257 : static_cast<int>(context->total_size()) != C::kSize) {
812 5 : int offset = pre + context->total_size() - context->size();
813 5 : context->SetError(BgpProto::Notification::UpdateMsgErr,
814 : BgpProto::Notification::AttribLengthError,
815 5 : TYPE_NAME(C), data - offset, context->total_size() + pre);
816 5 : return false;
817 : }
818 631376 : if ((obj->flags & BgpAttribute::FLAG_MASK) != C::kFlags) {
819 120 : int offset = pre + context->total_size() - context->size();
820 120 : context->SetError(BgpProto::Notification::UpdateMsgErr,
821 : BgpProto::Notification::AttribFlagsError,
822 120 : TYPE_NAME(C), data - offset, context->total_size() + pre);
823 120 : return false;
824 : }
825 631256 : return true;
826 : }
827 : };
828 :
829 : template <>
830 : struct BgpAttributeVerifier<BgpAttrOrigin> {
831 124241 : static bool Verifier(const BgpAttrOrigin *obj, const uint8_t *data,
832 : size_t size, ParseContext *context) {
833 124241 : int pre = (obj->flags & BgpAttribute::ExtendedLength) ? 4 : 3;
834 124241 : if (context->size() != 1) {
835 14 : context->SetError(BgpProto::Notification::UpdateMsgErr,
836 : BgpProto::Notification::AttribLengthError,
837 14 : "BgpAttrOrigin", data - pre, size + pre);
838 14 : return false;
839 : }
840 124227 : if ((obj->flags & BgpAttribute::FLAG_MASK) != BgpAttrOrigin::kFlags) {
841 24 : context->SetError(BgpProto::Notification::UpdateMsgErr,
842 : BgpProto::Notification::AttribFlagsError,
843 24 : "BgpAttrOrigin", data - pre, size + pre);
844 24 : return false;
845 : }
846 124203 : uint8_t value = data[0];
847 124203 : if (value != BgpAttrOrigin::IGP && value != BgpAttrOrigin::EGP &&
848 : value != BgpAttrOrigin::INCOMPLETE) {
849 16 : context->SetError(BgpProto::Notification::UpdateMsgErr,
850 : BgpProto::Notification::InvalidOrigin,
851 16 : "BgpAttrOrigin", data - pre, size + pre);
852 16 : return false;
853 : }
854 124187 : return true;
855 : }
856 : };
857 :
858 : template <>
859 : struct BgpAttributeVerifier<BgpAttrNextHop> {
860 16134 : static bool Verifier(const BgpAttrNextHop *obj, const uint8_t *data,
861 : size_t size, ParseContext *context) {
862 16134 : int pre = (obj->flags & BgpAttribute::ExtendedLength) ? 4 : 3;
863 16134 : if (static_cast<int>(context->size()) != BgpAttrNextHop::kSize) {
864 4 : context->SetError(BgpProto::Notification::UpdateMsgErr,
865 : BgpProto::Notification::AttribLengthError,
866 4 : "BgpAttrNextHop", data - pre, size + pre);
867 4 : return false;
868 : }
869 16130 : if ((obj->flags & BgpAttribute::FLAG_MASK) != BgpAttrNextHop::kFlags) {
870 16 : context->SetError(BgpProto::Notification::UpdateMsgErr,
871 : BgpProto::Notification::AttribFlagsError,
872 16 : "BgpAttrNextHop", data - pre, size + pre);
873 16 : return false;
874 : }
875 16114 : uint32_t value = get_value(data, size);
876 : // TODO(sbansal): More checks are needed
877 16114 : if (value == 0) {
878 0 : context->SetError(BgpProto::Notification::UpdateMsgErr,
879 : BgpProto::Notification::InvalidNH,
880 0 : "BgpAttrNextHop", data - pre, size + pre);
881 0 : return false;
882 : }
883 16114 : return true;
884 : }
885 : };
886 :
887 : template <>
888 : struct BgpAttributeVerifier<AsPathSpec::PathSegment> {
889 100776 : static bool Verifier(const AsPathSpec::PathSegment *obj,
890 : const uint8_t *data, size_t size,
891 : ParseContext *context) {
892 100776 : return true;
893 : }
894 : };
895 :
896 : template <>
897 : struct BgpAttributeVerifier<AsPath4ByteSpec::PathSegment> {
898 36 : static bool Verifier(const AsPath4ByteSpec::PathSegment *obj,
899 : const uint8_t *data, size_t size,
900 : ParseContext *context) {
901 36 : return true;
902 : }
903 : };
904 :
905 : template <>
906 : struct BgpAttributeVerifier<As4PathSpec::PathSegment> {
907 5 : static bool Verifier(const As4PathSpec::PathSegment *obj,
908 : const uint8_t *data, size_t size,
909 : ParseContext *context) {
910 5 : return true;
911 : }
912 : };
913 :
914 : template <int Size, class C, typename T, T C::*Member>
915 : class BgpAttributeValue :
916 : public ProtoElement<BgpAttributeValue<Size, C, T, Member> > {
917 : public:
918 : static const int kSize = Size;
919 658266 : static bool Verifier(const C *obj, const uint8_t *data, size_t size,
920 : ParseContext *context) {
921 658266 : return BgpAttributeVerifier<C>::Verifier(obj, data, size, context);
922 : }
923 : typedef Accessor<C, T, Member> Setter;
924 : };
925 :
926 : template <class C, int Size, typename T, T C::*M>
927 : class BgpAttrTemplate :
928 : public ProtoSequence<BgpAttrTemplate<C, Size, T, M> > {
929 : public:
930 : static const int kErrorCode = BgpProto::Notification::UpdateMsgErr;
931 : static const int kErrorSubcode = BgpProto::Notification::AttribLengthError;
932 : typedef C ContextType;
933 : typedef BgpContextSwap<C> ContextSwap;
934 : typedef mpl::list<BgpPathAttrLength, BgpAttributeValue<Size, C, T, M>
935 : > Sequence;
936 : };
937 :
938 : class BgpPathAttributeAtomicAggregate :
939 : public ProtoSequence<BgpPathAttributeAtomicAggregate> {
940 : public:
941 2674 : static bool Verifier(const BgpAttrAtomicAggregate * obj,
942 : const uint8_t *data, size_t size,
943 : ParseContext *context) {
944 2674 : if (data[0] != 0) {
945 6 : context->SetError(BgpProto::Notification::UpdateMsgErr,
946 : BgpProto::Notification::AttribLengthError,
947 6 : "BgpAttrAtomicAggregate", data - 2, data[0] + 3);
948 6 : return false;
949 : }
950 2668 : if (obj->flags != BgpAttrAtomicAggregate::kFlags) {
951 15 : context->SetError(BgpProto::Notification::UpdateMsgErr,
952 : BgpProto::Notification::AttribFlagsError,
953 : "BgpAttrAtomicAggregate", data - 2, 3);
954 15 : return false;
955 : }
956 2653 : return true;
957 : }
958 : typedef BgpAttrAtomicAggregate ContextType;
959 : typedef BgpContextSwap<BgpAttrAtomicAggregate> ContextSwap;
960 : typedef mpl::list<BgpPathAttrLength> Sequence;
961 : };
962 :
963 : class BgpPathAttributeAggregator :
964 : public ProtoSequence<BgpPathAttributeAggregator> {
965 : public:
966 : typedef BgpAttrAggregator ContextType;
967 : typedef BgpContextSwap<BgpAttrAggregator> ContextSwap;
968 : typedef mpl::list<BgpPathAttrLength,
969 : BgpAttributeValue<2, BgpAttrAggregator, as2_t,
970 : &BgpAttrAggregator::as_num>,
971 : BgpAttributeValue<4, BgpAttrAggregator, uint32_t,
972 : &BgpAttrAggregator::address>
973 : > Sequence;
974 : };
975 :
976 : class BgpPathAttributeAggregator4Byte :
977 : public ProtoSequence<BgpPathAttributeAggregator4Byte> {
978 : public:
979 : typedef BgpAttr4ByteAggregator ContextType;
980 : typedef BgpContextSwap<BgpAttr4ByteAggregator> ContextSwap;
981 : typedef mpl::list<BgpPathAttrLength,
982 : BgpAttributeValue<4, BgpAttr4ByteAggregator, as_t,
983 : &BgpAttr4ByteAggregator::as_num>,
984 : BgpAttributeValue<4, BgpAttr4ByteAggregator, uint32_t,
985 : &BgpAttr4ByteAggregator::address>
986 : > Sequence;
987 : };
988 :
989 : class BgpPathAttributeAs4Aggregator :
990 : public ProtoSequence<BgpPathAttributeAs4Aggregator> {
991 : public:
992 : typedef BgpAttrAs4Aggregator ContextType;
993 : typedef BgpContextSwap<BgpAttrAs4Aggregator> ContextSwap;
994 : typedef mpl::list<BgpPathAttrLength,
995 : BgpAttributeValue<4, BgpAttrAs4Aggregator, as_t,
996 : &BgpAttrAs4Aggregator::as_num>,
997 : BgpAttributeValue<4, BgpAttrAs4Aggregator, uint32_t,
998 : &BgpAttrAs4Aggregator::address>
999 : > Sequence;
1000 : };
1001 :
1002 : class BgpPathAttrAsPathSegmentLength :
1003 : public ProtoElement<BgpPathAttrAsPathSegmentLength> {
1004 : public:
1005 : static const int kSize = 1;
1006 : struct PathSegmentLength {
1007 100773 : int operator()(AsPathSpec::PathSegment *obj,
1008 : const uint8_t *data, size_t size) {
1009 100773 : return get_value(data, 1) * 2;
1010 : }
1011 : };
1012 : typedef PathSegmentLength SequenceLength;
1013 : struct SetLength {
1014 108916 : static void Callback(EncodeContext *context, uint8_t *data,
1015 : int offset, int element_size) {
1016 108916 : int len = get_value(data, kSize);
1017 108914 : put_value(data, kSize, len/2);
1018 108906 : }
1019 : };
1020 : typedef SetLength EncodingCallback;
1021 : };
1022 :
1023 : class BgpPathAttrAsPath4ByteSegmentLength :
1024 : public ProtoElement<BgpPathAttrAsPath4ByteSegmentLength> {
1025 : public:
1026 : static const int kSize = 1;
1027 : struct PathSegmentLength {
1028 36 : int operator()(AsPath4ByteSpec::PathSegment *obj,
1029 : const uint8_t *data, size_t size) {
1030 36 : return get_value(data, 1) * 4;
1031 : }
1032 : };
1033 : typedef PathSegmentLength SequenceLength;
1034 : struct SetLength {
1035 35 : static void Callback(EncodeContext *context, uint8_t *data,
1036 : int offset, int element_size) {
1037 35 : int len = get_value(data, kSize);
1038 35 : put_value(data, kSize, len/4);
1039 35 : }
1040 : };
1041 : typedef SetLength EncodingCallback;
1042 : };
1043 :
1044 : class BgpPathAttrAs4PathSegmentLength :
1045 : public ProtoElement<BgpPathAttrAs4PathSegmentLength> {
1046 : public:
1047 : static const int kSize = 1;
1048 : struct PathSegmentLength {
1049 5 : int operator()(As4PathSpec::PathSegment *obj,
1050 : const uint8_t *data, size_t size) {
1051 5 : return get_value(data, 1) * 4;
1052 : }
1053 : };
1054 : typedef PathSegmentLength SequenceLength;
1055 : struct SetLength {
1056 5 : static void Callback(EncodeContext *context, uint8_t *data,
1057 : int offset, int element_size) {
1058 5 : int len = get_value(data, kSize);
1059 5 : put_value(data, kSize, len/4);
1060 5 : }
1061 : };
1062 : typedef SetLength EncodingCallback;
1063 : };
1064 :
1065 :
1066 : class BgpPathAttrAsPathSegmentValue :
1067 : public ProtoElement<BgpPathAttrAsPathSegmentValue> {
1068 : public:
1069 : static const int kSize = -1;
1070 : typedef VectorAccessor<AsPathSpec::PathSegment, as2_t,
1071 : &AsPathSpec::PathSegment::path_segment> Setter;
1072 : };
1073 :
1074 : class BgpPathAttrAsPath4ByteSegmentValue :
1075 : public ProtoElement<BgpPathAttrAsPath4ByteSegmentValue> {
1076 : public:
1077 : static const int kSize = -1;
1078 : typedef VectorAccessor<AsPath4ByteSpec::PathSegment, as_t,
1079 : &AsPath4ByteSpec::PathSegment::path_segment> Setter;
1080 : };
1081 :
1082 : class BgpPathAttrAs4PathSegmentValue :
1083 : public ProtoElement<BgpPathAttrAs4PathSegmentValue> {
1084 : public:
1085 : static const int kSize = -1;
1086 : typedef VectorAccessor<As4PathSpec::PathSegment, as_t,
1087 : &As4PathSpec::PathSegment::path_segment> Setter;
1088 : };
1089 :
1090 : class BgpPathAttrAsPathSegmentList :
1091 : public ProtoSequence<BgpPathAttrAsPathSegmentList> {
1092 : public:
1093 : static const int kMinOccurs = 0;
1094 : static const int kMaxOccurs = -1;
1095 :
1096 100790 : static bool Verifier(const AsPathSpec *obj, const uint8_t *data,
1097 : size_t size, ParseContext *context) {
1098 100790 : return BgpAttributeVerifier<AsPathSpec>::Verifier(obj, data, size,
1099 100790 : context);
1100 : }
1101 :
1102 : typedef CollectionAccessor<AsPathSpec,
1103 : vector<AsPathSpec::PathSegment *>,
1104 : &AsPathSpec::path_segments> ContextStorer;
1105 :
1106 : typedef mpl::list<BgpAttributeValue<1, AsPathSpec::PathSegment, int,
1107 : &AsPathSpec::PathSegment::path_segment_type>,
1108 : BgpPathAttrAsPathSegmentLength,
1109 : BgpPathAttrAsPathSegmentValue
1110 : > Sequence;
1111 : };
1112 :
1113 : class BgpPathAttrAsPath4ByteSegmentList :
1114 : public ProtoSequence<BgpPathAttrAsPath4ByteSegmentList> {
1115 : public:
1116 : static const int kMinOccurs = 0;
1117 : static const int kMaxOccurs = -1;
1118 :
1119 36 : static bool Verifier(const AsPath4ByteSpec *obj, const uint8_t *data,
1120 : size_t size, ParseContext *context) {
1121 36 : return BgpAttributeVerifier<AsPath4ByteSpec>::Verifier(obj, data, size,
1122 36 : context);
1123 : }
1124 :
1125 : typedef CollectionAccessor<AsPath4ByteSpec,
1126 : vector<AsPath4ByteSpec::PathSegment *>,
1127 : &AsPath4ByteSpec::path_segments> ContextStorer;
1128 :
1129 : typedef mpl::list<BgpAttributeValue<1, AsPath4ByteSpec::PathSegment, int,
1130 : &AsPath4ByteSpec::PathSegment::path_segment_type>,
1131 : BgpPathAttrAsPath4ByteSegmentLength,
1132 : BgpPathAttrAsPath4ByteSegmentValue
1133 : > Sequence;
1134 : };
1135 :
1136 : class BgpPathAttrAs4PathSegmentList :
1137 : public ProtoSequence<BgpPathAttrAs4PathSegmentList> {
1138 : public:
1139 : static const int kMinOccurs = 0;
1140 : static const int kMaxOccurs = -1;
1141 :
1142 5 : static bool Verifier(const As4PathSpec *obj, const uint8_t *data,
1143 : size_t size, ParseContext *context) {
1144 5 : return BgpAttributeVerifier<As4PathSpec>::Verifier(obj, data, size,
1145 5 : context);
1146 : }
1147 :
1148 : typedef CollectionAccessor<As4PathSpec,
1149 : vector<As4PathSpec::PathSegment *>,
1150 : &As4PathSpec::path_segments> ContextStorer;
1151 :
1152 : typedef mpl::list<BgpAttributeValue<1, As4PathSpec::PathSegment, int,
1153 : &As4PathSpec::PathSegment::path_segment_type>,
1154 : BgpPathAttrAs4PathSegmentLength,
1155 : BgpPathAttrAs4PathSegmentValue
1156 : > Sequence;
1157 : };
1158 :
1159 : class BgpPathAttributeAsPath : public ProtoSequence<BgpPathAttributeAsPath> {
1160 : public:
1161 : typedef AsPathSpec ContextType;
1162 : typedef BgpContextSwap<AsPathSpec> ContextSwap;
1163 : typedef mpl::list<BgpPathAttrLength, BgpPathAttrAsPathSegmentList> Sequence;
1164 : };
1165 :
1166 : class BgpPathAttributeAsPath4Byte :
1167 : public ProtoSequence<BgpPathAttributeAsPath4Byte> {
1168 : public:
1169 : typedef AsPath4ByteSpec ContextType;
1170 : typedef BgpContextSwap<AsPath4ByteSpec> ContextSwap;
1171 : typedef mpl::list<BgpPathAttrLength,
1172 : BgpPathAttrAsPath4ByteSegmentList> Sequence;
1173 : };
1174 :
1175 : class BgpPathAttributeAs4Path : public ProtoSequence<BgpPathAttributeAs4Path> {
1176 : public:
1177 : typedef As4PathSpec ContextType;
1178 : typedef BgpContextSwap<As4PathSpec> ContextSwap;
1179 : typedef mpl::list<BgpPathAttrLength, BgpPathAttrAs4PathSegmentList> Sequence;
1180 : };
1181 :
1182 : class BgpPathAttributeFlags : public ProtoElement<BgpPathAttributeFlags> {
1183 : public:
1184 : static const int kSize = 1;
1185 : struct FlagsAccessor {
1186 627829 : static void set(BgpAttribute *obj, uint8_t value) {
1187 627829 : obj->flags = value;
1188 627829 : }
1189 675765 : static uint8_t get(const BgpAttribute *obj) {
1190 675765 : return obj->GetEncodeFlags();
1191 : }
1192 : };
1193 : typedef FlagsAccessor Setter;
1194 : };
1195 :
1196 : class BgpPathAttributeCommunityList :
1197 : public ProtoElement<BgpPathAttributeCommunityList> {
1198 : public:
1199 : static const int kSize = -1;
1200 6662 : static bool Verifier(const CommunitySpec *obj, const uint8_t *data,
1201 : size_t size, ParseContext *context) {
1202 6662 : return BgpAttributeVerifier<CommunitySpec>::Verifier(obj, data, size,
1203 6662 : context);
1204 : }
1205 :
1206 : typedef VectorAccessor<CommunitySpec, uint32_t,
1207 : &CommunitySpec::communities> Setter;
1208 : };
1209 :
1210 : class BgpPathAttributeCommunities :
1211 : public ProtoSequence<BgpPathAttributeCommunities> {
1212 : public:
1213 : typedef CommunitySpec ContextType;
1214 : typedef BgpContextSwap<CommunitySpec> ContextSwap;
1215 : typedef mpl::list<BgpPathAttrLength,
1216 : BgpPathAttributeCommunityList> Sequence;
1217 : };
1218 :
1219 : class BgpPathAttributeExtendedCommunityList :
1220 : public ProtoElement<BgpPathAttributeExtendedCommunityList> {
1221 : public:
1222 : static const int kSize = -1;
1223 92188 : static bool Verifier(const ExtCommunitySpec *obj, const uint8_t *data,
1224 : size_t size, ParseContext *context) {
1225 92188 : return BgpAttributeVerifier<ExtCommunitySpec>::Verifier(obj, data, size,
1226 92188 : context);
1227 : }
1228 :
1229 : typedef VectorAccessor<ExtCommunitySpec, uint64_t,
1230 : &ExtCommunitySpec::communities> Setter;
1231 : };
1232 :
1233 : class BgpPathAttributeExtendedCommunities :
1234 : public ProtoSequence<BgpPathAttributeExtendedCommunities> {
1235 : public:
1236 : typedef ExtCommunitySpec ContextType;
1237 : typedef BgpContextSwap<ExtCommunitySpec> ContextSwap;
1238 : typedef mpl::list<BgpPathAttrLength,
1239 : BgpPathAttributeExtendedCommunityList> Sequence;
1240 : };
1241 :
1242 : class BgpPathAttributeLargeCommunityList :
1243 : public ProtoElement<BgpPathAttributeLargeCommunityList> {
1244 : public:
1245 : static const int kSize = -1;
1246 6 : static bool Verifier(const LargeCommunitySpec *obj, const uint8_t *data,
1247 : size_t size, ParseContext *context) {
1248 6 : return BgpAttributeVerifier<LargeCommunitySpec>::Verifier(obj, data,
1249 : size,
1250 6 : context);
1251 : }
1252 :
1253 : typedef VectorAccessor<LargeCommunitySpec, uint32_t,
1254 : &LargeCommunitySpec::communities> Setter;
1255 : };
1256 :
1257 : class BgpPathAttributeLargeCommunities :
1258 : public ProtoSequence<BgpPathAttributeLargeCommunities> {
1259 : public:
1260 : typedef LargeCommunitySpec ContextType;
1261 : typedef BgpContextSwap<LargeCommunitySpec> ContextSwap;
1262 : typedef mpl::list<BgpPathAttrLength,
1263 : BgpPathAttributeLargeCommunityList> Sequence;
1264 : };
1265 :
1266 : class BgpPathAttributeClusterListData :
1267 : public ProtoElement<BgpPathAttributeClusterListData> {
1268 : public:
1269 : static const int kSize = -1;
1270 : typedef VectorAccessor<ClusterListSpec, uint32_t,
1271 : &ClusterListSpec::cluster_list> Setter;
1272 : };
1273 :
1274 : class BgpPathAttributeClusterList :
1275 : public ProtoSequence<BgpPathAttributeClusterList> {
1276 : public:
1277 : typedef ClusterListSpec ContextType;
1278 : typedef BgpContextSwap<ClusterListSpec> ContextSwap;
1279 : typedef mpl::list<BgpPathAttrLength,
1280 : BgpPathAttributeClusterListData> Sequence;
1281 : };
1282 :
1283 : class BgpPathAttributeOriginVnList :
1284 : public ProtoElement<BgpPathAttributeOriginVnList> {
1285 : public:
1286 : static const int kSize = -1;
1287 3254 : static bool Verifier(const OriginVnPathSpec *obj, const uint8_t *data,
1288 : size_t size, ParseContext *context) {
1289 3254 : return BgpAttributeVerifier<OriginVnPathSpec>::Verifier(obj, data, size,
1290 3254 : context);
1291 : }
1292 :
1293 : typedef VectorAccessor<OriginVnPathSpec, uint64_t,
1294 : &OriginVnPathSpec::origin_vns> Setter;
1295 : };
1296 :
1297 : class BgpPathAttributeOriginVnPath :
1298 : public ProtoSequence<BgpPathAttributeOriginVnPath> {
1299 : public:
1300 : typedef OriginVnPathSpec ContextType;
1301 : typedef BgpContextSwap<OriginVnPathSpec> ContextSwap;
1302 : typedef mpl::list<BgpPathAttrLength, BgpPathAttributeOriginVnList> Sequence;
1303 : };
1304 :
1305 : class BgpPathAttributePmsiTunnelIdentifier :
1306 : public ProtoElement<BgpPathAttributePmsiTunnelIdentifier> {
1307 : public:
1308 : static const int kSize = -1;
1309 2999 : static bool Verifier(const PmsiTunnelSpec *obj, const uint8_t *data,
1310 : size_t size, ParseContext *context) {
1311 2999 : return BgpAttributeVerifier<PmsiTunnelSpec>::Verifier(
1312 2999 : obj, data, size, context);
1313 : }
1314 :
1315 : typedef VectorAccessor<PmsiTunnelSpec, uint8_t,
1316 : &PmsiTunnelSpec::identifier> Setter;
1317 : };
1318 :
1319 : class BgpPathAttributePmsiTunnel :
1320 : public ProtoSequence<BgpPathAttributePmsiTunnel> {
1321 : public:
1322 : typedef PmsiTunnelSpec ContextType;
1323 : typedef BgpContextSwap<PmsiTunnelSpec> ContextSwap;
1324 : typedef mpl::list<BgpPathAttrLength,
1325 : BgpAttributeValue<1, PmsiTunnelSpec,
1326 : uint8_t, &PmsiTunnelSpec::tunnel_flags>,
1327 : BgpAttributeValue<1, PmsiTunnelSpec,
1328 : uint8_t, &PmsiTunnelSpec::tunnel_type>,
1329 : BgpAttributeValue<3, PmsiTunnelSpec,
1330 : uint32_t, &PmsiTunnelSpec::label>,
1331 : BgpPathAttributePmsiTunnelIdentifier> Sequence;
1332 : };
1333 :
1334 : class BgpPathAttributeDiscoveryEdgeAddressLen :
1335 : public ProtoElement<BgpPathAttributeDiscoveryEdgeAddressLen> {
1336 : public:
1337 : static const int kSize = 1;
1338 85955 : static bool Verifier(const void *obj, const uint8_t *data,
1339 : size_t size, ParseContext *context) {
1340 85955 : uint8_t value = get_value(data, 1);
1341 85955 : return (value == 4);
1342 : }
1343 : typedef int SequenceLength;
1344 : };
1345 :
1346 : class BgpPathAttributeDiscoveryEdgeAddressValue :
1347 : public ProtoElement<BgpPathAttributeDiscoveryEdgeAddressValue> {
1348 : public:
1349 : static const int kSize = -1;
1350 : typedef VectorAccessor<EdgeDiscoverySpec::Edge, uint8_t,
1351 : &EdgeDiscoverySpec::Edge::address> Setter;
1352 : };
1353 :
1354 : class BgpPathAttributeDiscoveryEdgeAddress :
1355 : public ProtoSequence<BgpPathAttributeDiscoveryEdgeAddress> {
1356 : public:
1357 : typedef mpl::list<BgpPathAttributeDiscoveryEdgeAddressLen,
1358 : BgpPathAttributeDiscoveryEdgeAddressValue> Sequence;
1359 : };
1360 :
1361 : class BgpPathAttributeDiscoveryEdgeLabelLen :
1362 : public ProtoElement<BgpPathAttributeDiscoveryEdgeLabelLen> {
1363 : public:
1364 : static const int kSize = 1;
1365 85920 : static bool Verifier(const void *obj, const uint8_t *data,
1366 : size_t size, ParseContext *context) {
1367 85920 : uint8_t value = get_value(data, 1);
1368 85920 : return (value > 0 && value % 8 == 0);
1369 : }
1370 : typedef int SequenceLength;
1371 : };
1372 :
1373 : class BgpPathAttributeDiscoveryEdgeLabelValues :
1374 : public ProtoElement<BgpPathAttributeDiscoveryEdgeLabelValues> {
1375 : public:
1376 : static const int kSize = -1;
1377 : typedef VectorAccessor<EdgeDiscoverySpec::Edge, uint32_t,
1378 : &EdgeDiscoverySpec::Edge::labels> Setter;
1379 : };
1380 :
1381 : class BgpPathAttributeDiscoveryEdgeLabels :
1382 : public ProtoSequence<BgpPathAttributeDiscoveryEdgeLabels> {
1383 : public:
1384 : typedef mpl::list<BgpPathAttributeDiscoveryEdgeLabelLen,
1385 : BgpPathAttributeDiscoveryEdgeLabelValues> Sequence;
1386 : };
1387 :
1388 : class BgpPathAttributeDiscoveryEdgeList :
1389 : public ProtoSequence<BgpPathAttributeDiscoveryEdgeList> {
1390 : public:
1391 : static const int kMinOccurs = 1;
1392 : static const int kMaxOccurs = -1;
1393 :
1394 3810 : static bool Verifier(const EdgeDiscoverySpec *obj, const uint8_t *data,
1395 : size_t size, ParseContext *context) {
1396 3810 : return BgpAttributeVerifier<EdgeDiscoverySpec>::Verifier(
1397 3810 : obj, data, size, context);
1398 : }
1399 :
1400 : typedef CollectionAccessor<EdgeDiscoverySpec,
1401 : vector<EdgeDiscoverySpec::Edge *>,
1402 : &EdgeDiscoverySpec::edge_list> ContextStorer;
1403 :
1404 : typedef mpl::list<BgpPathAttributeDiscoveryEdgeAddress,
1405 : BgpPathAttributeDiscoveryEdgeLabels> Sequence;
1406 : };
1407 :
1408 : class BgpPathAttributeEdgeDiscovery :
1409 : public ProtoSequence<BgpPathAttributeEdgeDiscovery> {
1410 : public:
1411 : typedef EdgeDiscoverySpec ContextType;
1412 : typedef BgpContextSwap<EdgeDiscoverySpec> ContextSwap;
1413 : typedef mpl::list<BgpPathAttrLength,
1414 : BgpPathAttributeDiscoveryEdgeList> Sequence;
1415 : };
1416 :
1417 : class BgpPathAttributeForwardingEdgeLen :
1418 : public ProtoElement<BgpPathAttributeForwardingEdgeLen> {
1419 : public:
1420 : static const int kSize = 1;
1421 81795 : static bool Verifier(const void *obj, const uint8_t *data,
1422 : size_t size, ParseContext *context) {
1423 81795 : uint8_t value = get_value(data, 1);
1424 81795 : return (value == 4);
1425 : }
1426 : struct GetLength {
1427 81767 : int operator()(EdgeForwardingSpec::Edge *obj,
1428 : const uint8_t *data, size_t size) {
1429 81767 : obj->address_len = get_value(data, 1) * 2 + 8;
1430 81767 : return obj->address_len;
1431 : }
1432 : };
1433 : typedef GetLength SequenceLength;
1434 : struct SetLength {
1435 126673 : static void Callback(EncodeContext *context, uint8_t *data,
1436 : int offset, int element_size) {
1437 126673 : int len = get_value(data, kSize);
1438 126673 : put_value(data, kSize, (len - 8) / 2);
1439 126673 : }
1440 : };
1441 : typedef SetLength EncodingCallback;
1442 : };
1443 :
1444 : class BgpPathAttributeForwardingEdgeAddressLen :
1445 : public ProtoElement<BgpPathAttributeForwardingEdgeAddressLen> {
1446 : public:
1447 : static const int kSize = 0;
1448 : struct GetLength {
1449 163534 : int operator()(EdgeForwardingSpec::Edge *obj,
1450 : const uint8_t *data, size_t size) {
1451 163534 : return (obj->address_len - 8) / 2;
1452 : }
1453 : };
1454 : typedef GetLength SequenceLength;
1455 : };
1456 :
1457 : class BgpPathAttributeForwardingEdgeInAddressValue :
1458 : public ProtoElement<BgpPathAttributeForwardingEdgeInAddressValue> {
1459 : public:
1460 : static const int kSize = -1;
1461 : typedef VectorAccessor<EdgeForwardingSpec::Edge, uint8_t,
1462 : &EdgeForwardingSpec::Edge::inbound_address> Setter;
1463 : };
1464 :
1465 : class BgpPathAttributeForwardingEdgeInAddress :
1466 : public ProtoSequence<BgpPathAttributeForwardingEdgeInAddress> {
1467 : public:
1468 : static const int kMinOccurs = 1;
1469 : static const int kMaxOccurs = 1;
1470 : typedef mpl::list<BgpPathAttributeForwardingEdgeAddressLen,
1471 : BgpPathAttributeForwardingEdgeInAddressValue> Sequence;
1472 : };
1473 :
1474 : class BgpPathAttributeForwardingEdgeInLabel :
1475 : public ProtoElement<BgpPathAttributeForwardingEdgeInLabel> {
1476 : public:
1477 : static const int kSize = 4;
1478 : typedef Accessor<EdgeForwardingSpec::Edge, uint32_t,
1479 : &EdgeForwardingSpec::Edge::inbound_label> Setter;
1480 : };
1481 :
1482 : class BgpPathAttributeForwardingEdgeOutAddressValue :
1483 : public ProtoElement<BgpPathAttributeForwardingEdgeOutAddressValue> {
1484 : public:
1485 : static const int kSize = -1;
1486 : typedef VectorAccessor<EdgeForwardingSpec::Edge, uint8_t,
1487 : &EdgeForwardingSpec::Edge::outbound_address> Setter;
1488 : };
1489 :
1490 : class BgpPathAttributeForwardingEdgeOutAddress :
1491 : public ProtoSequence<BgpPathAttributeForwardingEdgeOutAddress> {
1492 : public:
1493 : static const int kMinOccurs = 1;
1494 : static const int kMaxOccurs = 1;
1495 : typedef mpl::list<BgpPathAttributeForwardingEdgeAddressLen,
1496 : BgpPathAttributeForwardingEdgeOutAddressValue> Sequence;
1497 : };
1498 :
1499 : class BgpPathAttributeForwardingEdgeOutLabel :
1500 : public ProtoElement<BgpPathAttributeForwardingEdgeOutLabel> {
1501 : public:
1502 : static const int kSize = 4;
1503 : typedef Accessor<EdgeForwardingSpec::Edge, uint32_t,
1504 : &EdgeForwardingSpec::Edge::outbound_label> Setter;
1505 : };
1506 :
1507 : class BgpPathAttributeForwardingEdgeList :
1508 : public ProtoSequence<BgpPathAttributeForwardingEdgeList> {
1509 : public:
1510 : static const int kMinOccurs = 1;
1511 : static const int kMaxOccurs = -1;
1512 :
1513 4560 : static bool Verifier(const EdgeForwardingSpec *obj, const uint8_t *data,
1514 : size_t size, ParseContext *context) {
1515 4560 : return BgpAttributeVerifier<EdgeForwardingSpec>::Verifier(
1516 4560 : obj, data, size, context);
1517 : }
1518 :
1519 : typedef CollectionAccessor<EdgeForwardingSpec,
1520 : vector<EdgeForwardingSpec::Edge *>,
1521 : &EdgeForwardingSpec::edge_list> ContextStorer;
1522 :
1523 : typedef mpl::list<BgpPathAttributeForwardingEdgeLen,
1524 : BgpPathAttributeForwardingEdgeInAddress,
1525 : BgpPathAttributeForwardingEdgeInLabel,
1526 : BgpPathAttributeForwardingEdgeOutAddress,
1527 : BgpPathAttributeForwardingEdgeOutLabel> Sequence;
1528 : };
1529 :
1530 : class BgpPathAttributeEdgeForwarding :
1531 : public ProtoSequence<BgpPathAttributeEdgeForwarding> {
1532 : public:
1533 : typedef EdgeForwardingSpec ContextType;
1534 : typedef BgpContextSwap<EdgeForwardingSpec> ContextSwap;
1535 : typedef mpl::list<BgpPathAttrLength,
1536 : BgpPathAttributeForwardingEdgeList> Sequence;
1537 : };
1538 :
1539 : class BgpPathAttributeReserved : public ProtoElement<BgpPathAttributeReserved> {
1540 : public:
1541 : static const int kSize = 1;
1542 114953 : static void Writer(const void *msg, uint8_t *data, size_t size) {
1543 114953 : *data = 0;
1544 114953 : }
1545 : };
1546 :
1547 : class BgpPathAttributeMpNlriNextHopLength :
1548 : public ProtoElement<BgpPathAttributeMpNlriNextHopLength> {
1549 : public:
1550 : static const int kSize = 1;
1551 : static const int kErrorCode = BgpProto::Notification::UpdateMsgErr;
1552 : static const int kErrorSubcode =
1553 : BgpProto::Notification::OptionalAttribError;
1554 : typedef int SequenceLength;
1555 113864 : static bool Verifier(const BgpMpNlri *obj, const uint8_t *data, size_t size,
1556 : ParseContext *context) {
1557 113864 : uint8_t len = get_value(data, kSize);
1558 113864 : uint16_t afi = obj->afi;
1559 113864 : uint8_t safi = obj->safi;
1560 113864 : if (afi == BgpAf::IPv4 && safi == BgpAf::Unicast) {
1561 3207 : return (len == Address::kMaxV4Bytes);
1562 110657 : } else if (afi == BgpAf::IPv4 && safi == BgpAf::Mpls) {
1563 3 : return (len == Address::kMaxV4Bytes);
1564 110654 : } else if (afi == BgpAf::IPv4 && safi == BgpAf::Vpn) {
1565 45689 : return (len == RouteDistinguisher::kSize + Address::kMaxV4Bytes);
1566 64965 : } else if (afi == BgpAf::IPv6 && safi == BgpAf::Unicast) {
1567 2630 : return (len == Address::kMaxV6Bytes ||
1568 2630 : len == 2 * Address::kMaxV6Bytes);
1569 62335 : } else if (afi == BgpAf::IPv6 && safi == BgpAf::Vpn) {
1570 30012 : return (len == RouteDistinguisher::kSize + Address::kMaxV6Bytes);
1571 32323 : } else if (afi == BgpAf::L2Vpn && safi == BgpAf::EVpn) {
1572 12422 : return (len == Address::kMaxV4Bytes);
1573 19901 : } else if (afi == BgpAf::IPv4 && safi == BgpAf::RTarget) {
1574 15768 : return (len == Address::kMaxV4Bytes);
1575 4133 : } else if (afi == BgpAf::IPv4 && safi == BgpAf::ErmVpn) {
1576 3214 : return (len == Address::kMaxV4Bytes);
1577 919 : } else if (afi == BgpAf::IPv4 && safi == BgpAf::MVpn) {
1578 919 : return (len == Address::kMaxV4Bytes);
1579 : }
1580 0 : return false;
1581 : }
1582 : };
1583 :
1584 :
1585 : class BgpPathAttributeMpNlriNexthopAddr :
1586 : public ProtoElement<BgpPathAttributeMpNlriNexthopAddr> {
1587 : public:
1588 : static const int kSize = -1;
1589 : typedef VectorAccessor<BgpMpNlri, uint8_t, &BgpMpNlri::nexthop> Setter;
1590 : };
1591 :
1592 : class BgpPathAttributeMpNlriNextHop :
1593 : public ProtoSequence<BgpPathAttributeMpNlriNextHop> {
1594 : public:
1595 : typedef mpl::list<BgpPathAttributeMpNlriNextHopLength,
1596 : BgpPathAttributeMpNlriNexthopAddr> Sequence;
1597 : };
1598 :
1599 : class BgpPathAttributeMpNlri : public ProtoSequence<BgpPathAttributeMpNlri> {
1600 : public:
1601 : static const int kMinOccurs = 0;
1602 : static const int kMaxOccurs = -1;
1603 :
1604 : struct OptMatch {
1605 173204 : bool match(const BgpMpNlri *obj) {
1606 102407 : return ((obj->afi == BgpAf::IPv4 && obj->safi == BgpAf::Unicast) ||
1607 165058 : (obj->afi == BgpAf::IPv4 && obj->safi == BgpAf::Mpls) ||
1608 165040 : (obj->afi == BgpAf::IPv4 && obj->safi == BgpAf::Vpn) ||
1609 98092 : (obj->afi == BgpAf::IPv6 && obj->safi == BgpAf::Unicast) ||
1610 394607 : (obj->afi == BgpAf::IPv6 && obj->safi == BgpAf::Vpn) ||
1611 221403 : (obj->afi == BgpAf::IPv4 && obj->safi == BgpAf::RTarget));
1612 : }
1613 : };
1614 :
1615 : typedef OptMatch ContextMatch;
1616 : typedef CollectionAccessor<BgpMpNlri, vector<BgpProtoPrefix *>,
1617 : &BgpMpNlri::nlri> ContextStorer;
1618 : typedef mpl::list<BgpPrefixLen, BgpPrefixAddress> Sequence;
1619 : };
1620 :
1621 : class BgpMvpnNlriType : public ProtoElement<BgpMvpnNlriType> {
1622 : public:
1623 : static const int kSize = 1;
1624 : typedef Accessor<BgpProtoPrefix, uint8_t,
1625 : &BgpProtoPrefix::type> Setter;
1626 : };
1627 :
1628 : class BgpMvpnNlriLen : public ProtoElement<BgpMvpnNlriLen> {
1629 : public:
1630 : static const int kSize = 1;
1631 :
1632 : struct MvpnPrefixLen {
1633 1669 : static void set(BgpProtoPrefix *obj, int value) {
1634 1669 : obj->prefixlen = value * 8;
1635 1669 : }
1636 :
1637 1828 : static int get(const BgpProtoPrefix *obj) {
1638 1828 : return obj->prefixlen / 8;
1639 : }
1640 : };
1641 :
1642 :
1643 : typedef int SequenceLength;
1644 :
1645 : typedef MvpnPrefixLen Setter;
1646 : };
1647 :
1648 : class BgpPathAttributeMpMvpnNlri
1649 : : public ProtoSequence<BgpPathAttributeMpMvpnNlri> {
1650 : public:
1651 : static const int kMinOccurs = 0;
1652 : static const int kMaxOccurs = -1;
1653 :
1654 : struct OptMatch {
1655 14067 : bool match(const BgpMpNlri *obj) {
1656 14067 : return ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::MVpn));
1657 : }
1658 : };
1659 :
1660 : typedef OptMatch ContextMatch;
1661 :
1662 : typedef CollectionAccessor<BgpMpNlri, vector<BgpProtoPrefix *>,
1663 : &BgpMpNlri::nlri> ContextStorer;
1664 :
1665 : typedef mpl::list<BgpMvpnNlriType, BgpMvpnNlriLen,
1666 : BgpPrefixAddress> Sequence;
1667 : };
1668 :
1669 : class BgpErmVpnNlriType : public ProtoElement<BgpErmVpnNlriType> {
1670 : public:
1671 : static const int kSize = 1;
1672 : typedef Accessor<BgpProtoPrefix, uint8_t,
1673 : &BgpProtoPrefix::type> Setter;
1674 : };
1675 :
1676 : class BgpErmVpnNlriLen : public ProtoElement<BgpErmVpnNlriLen> {
1677 : public:
1678 : static const int kSize = 1;
1679 :
1680 : struct ErmVpnPrefixLen {
1681 4709 : static void set(BgpProtoPrefix *obj, int value) {
1682 4709 : obj->prefixlen = value * 8;
1683 4709 : }
1684 :
1685 4121 : static int get(const BgpProtoPrefix *obj) {
1686 4121 : return obj->prefixlen / 8;
1687 : }
1688 : };
1689 :
1690 :
1691 : typedef int SequenceLength;
1692 :
1693 : typedef ErmVpnPrefixLen Setter;
1694 : };
1695 :
1696 : class BgpPathAttributeMpErmVpnNlri
1697 : : public ProtoSequence<BgpPathAttributeMpErmVpnNlri> {
1698 : public:
1699 : static const int kMinOccurs = 0;
1700 : static const int kMaxOccurs = -1;
1701 :
1702 : struct OptMatch {
1703 17652 : bool match(const BgpMpNlri *obj) {
1704 17652 : return ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::ErmVpn));
1705 : }
1706 : };
1707 :
1708 : typedef OptMatch ContextMatch;
1709 :
1710 : typedef CollectionAccessor<BgpMpNlri, vector<BgpProtoPrefix *>,
1711 : &BgpMpNlri::nlri> ContextStorer;
1712 :
1713 : typedef mpl::list<BgpErmVpnNlriType, BgpErmVpnNlriLen,
1714 : BgpPrefixAddress> Sequence;
1715 : };
1716 :
1717 : class BgpEvpnNlriType : public ProtoElement<BgpEvpnNlriType> {
1718 : public:
1719 : static const int kSize = 1;
1720 : typedef Accessor<BgpProtoPrefix, uint8_t,
1721 : &BgpProtoPrefix::type> Setter;
1722 : };
1723 :
1724 : class BgpEvpnNlriLen : public ProtoElement<BgpEvpnNlriLen> {
1725 : public:
1726 : static const int kSize = 1;
1727 :
1728 : struct EvpnPrefixLen {
1729 25797 : static void set(BgpProtoPrefix *obj, int value) {
1730 25797 : obj->prefixlen = value * 8;
1731 25797 : }
1732 :
1733 29489 : static int get(const BgpProtoPrefix *obj) {
1734 29489 : return obj->prefixlen / 8;
1735 : }
1736 : };
1737 :
1738 :
1739 : typedef int SequenceLength;
1740 :
1741 : typedef EvpnPrefixLen Setter;
1742 : };
1743 :
1744 : class BgpPathAttributeMpEvpnNlri :
1745 : public ProtoSequence<BgpPathAttributeMpEvpnNlri> {
1746 : public:
1747 : static const int kMinOccurs = 0;
1748 : static const int kMaxOccurs = -1;
1749 :
1750 : struct OptMatch {
1751 37501 : bool match(const BgpMpNlri *obj) {
1752 37501 : return ((obj->afi == BgpAf::L2Vpn) && (obj->safi == BgpAf::EVpn));
1753 : }
1754 : };
1755 :
1756 : typedef OptMatch ContextMatch;
1757 : typedef CollectionAccessor<BgpMpNlri, vector<BgpProtoPrefix *>,
1758 : &BgpMpNlri::nlri> ContextStorer;
1759 : typedef mpl::list<BgpEvpnNlriType, BgpEvpnNlriLen,
1760 : BgpPrefixAddress> Sequence;
1761 : };
1762 :
1763 : class BgpPathAttributeMpNlriChoice :
1764 : public ProtoChoice<BgpPathAttributeMpNlriChoice> {
1765 : public:
1766 : static const int kSize = 0;
1767 : struct MpChoice {
1768 160898 : static void set(BgpMpNlri *obj, int &value) {
1769 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Unicast)) {
1770 6488 : value = 0;
1771 : }
1772 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Mpls)) {
1773 18 : value = 0;
1774 : }
1775 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Vpn)) {
1776 61780 : value = 0;
1777 : }
1778 160898 : if ((obj->afi == BgpAf::IPv6) && (obj->safi == BgpAf::Unicast)) {
1779 4376 : value = 0;
1780 : }
1781 160898 : if ((obj->afi == BgpAf::IPv6) && (obj->safi == BgpAf::Vpn)) {
1782 41761 : value = 0;
1783 : }
1784 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::RTarget)) {
1785 21267 : value = 0;
1786 : }
1787 160898 : if ((obj->afi == BgpAf::L2Vpn) && (obj->safi == BgpAf::EVpn)) {
1788 17821 : value = 1;
1789 : }
1790 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::ErmVpn)) {
1791 6150 : value = 2;
1792 : }
1793 160898 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::MVpn)) {
1794 1240 : value = 3;
1795 : }
1796 160898 : }
1797 :
1798 : static int get(BgpMpNlri *obj) {
1799 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Unicast)) {
1800 : return 0;
1801 : }
1802 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Mpls)) {
1803 : return 0;
1804 : }
1805 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::Vpn)) {
1806 : return 0;
1807 : }
1808 : if ((obj->afi == BgpAf::IPv6) && (obj->safi == BgpAf::Unicast)) {
1809 : return 0;
1810 : }
1811 : if ((obj->afi == BgpAf::IPv6) && (obj->safi == BgpAf::Vpn)) {
1812 : return 0;
1813 : }
1814 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::RTarget)) {
1815 : return 0;
1816 : }
1817 : if ((obj->afi == BgpAf::L2Vpn) && (obj->safi == BgpAf::EVpn)) {
1818 : return 1;
1819 : }
1820 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::ErmVpn)) {
1821 : return 2;
1822 : }
1823 : if ((obj->afi == BgpAf::IPv4) && (obj->safi == BgpAf::MVpn)) {
1824 : return 3;
1825 : }
1826 : return -1;
1827 : }
1828 : };
1829 :
1830 : typedef MpChoice Setter;
1831 : typedef mpl::map<
1832 : mpl::pair<mpl::int_<0>, BgpPathAttributeMpNlri>,
1833 : mpl::pair<mpl::int_<1>, BgpPathAttributeMpEvpnNlri>,
1834 : mpl::pair<mpl::int_<2>, BgpPathAttributeMpErmVpnNlri>,
1835 : mpl::pair<mpl::int_<3>, BgpPathAttributeMpMvpnNlri>
1836 : > Choice;
1837 : };
1838 :
1839 : class BgpPathAttributeMpReachNlriSequence :
1840 : public ProtoSequence<BgpPathAttributeMpReachNlriSequence> {
1841 : public:
1842 : struct Offset {
1843 114970 : string operator()() {
1844 114970 : return "MpReachUnreachNlri";
1845 : }
1846 : };
1847 : typedef Offset SaveOffset;
1848 : typedef BgpMpNlri ContextType;
1849 : typedef BgpContextSwap<BgpMpNlri> ContextSwap;
1850 : typedef mpl::list<BgpPathAttrLength,
1851 : BgpAttributeValue<2, BgpMpNlri, uint16_t, &BgpMpNlri::afi>,
1852 : BgpAttributeValue<1, BgpMpNlri, uint8_t, &BgpMpNlri::safi>,
1853 : BgpPathAttributeMpNlriNextHop,
1854 : BgpPathAttributeReserved,
1855 : BgpPathAttributeMpNlriChoice> Sequence;
1856 : };
1857 :
1858 : class BgpPathAttributeMpUnreachNlriSequence :
1859 : public ProtoSequence<BgpPathAttributeMpUnreachNlriSequence> {
1860 : public:
1861 : struct Offset {
1862 58214 : string operator()() {
1863 58214 : return "MpReachUnreachNlri";
1864 : }
1865 : };
1866 : typedef Offset SaveOffset;
1867 : typedef BgpMpNlri ContextType;
1868 : typedef BgpContextSwap<BgpMpNlri> ContextSwap;
1869 : typedef mpl::list<BgpPathAttrLength,
1870 : BgpAttributeValue<2, BgpMpNlri, uint16_t, &BgpMpNlri::afi>,
1871 : BgpAttributeValue<1, BgpMpNlri, uint8_t, &BgpMpNlri::safi>,
1872 : BgpPathAttributeMpNlriChoice> Sequence;
1873 : };
1874 :
1875 : class BgpPathAttrUnknownValue : public ProtoElement<BgpPathAttrUnknownValue> {
1876 : public:
1877 : static const int kSize = -1;
1878 2550 : static bool Verifier(BgpAttrUnknown *obj, const uint8_t *data, size_t size,
1879 : ParseContext *context) {
1880 2550 : int pre = (obj->flags & BgpAttribute::ExtendedLength) ? 4 : 3;
1881 2550 : if (!(obj->flags & BgpAttribute::Optional)) {
1882 80 : context->SetError(BgpProto::Notification::UpdateMsgErr,
1883 : BgpProto::Notification::UnrecognizedWellKnownAttrib,
1884 80 : "BgpAttrUnknown", data - pre, context->size() + pre);
1885 80 : return false;
1886 : }
1887 2470 : return true;
1888 : }
1889 : typedef VectorAccessor<BgpAttrUnknown, uint8_t,
1890 : &BgpAttrUnknown::value> Setter;
1891 : };
1892 :
1893 : class BgpPathAttributeUnknown : public ProtoSequence<BgpPathAttributeUnknown> {
1894 : public:
1895 : typedef BgpAttrUnknown ContextType;
1896 : typedef BgpContextSwap<BgpAttrUnknown> ContextSwap;
1897 : typedef mpl::list<BgpPathAttrLength, BgpPathAttrUnknownValue> Sequence;
1898 : };
1899 :
1900 : class BgpPathAttribute : public ProtoChoice<BgpPathAttribute> {
1901 : public:
1902 : static const int kSize = 1;
1903 :
1904 : typedef Accessor<BgpAttribute, uint8_t, &BgpAttribute::code> Setter;
1905 : typedef mpl::map<
1906 : mpl::pair<mpl::int_<BgpAttribute::Origin>,
1907 : BgpAttrTemplate<BgpAttrOrigin, 1, int,
1908 : &BgpAttrOrigin::origin> >,
1909 : mpl::pair<mpl::int_<BgpAttribute::AsPath>, BgpPathAttributeAsPath>,
1910 : mpl::pair<mpl::int_<BgpAttribute::As4Path>, BgpPathAttributeAs4Path>,
1911 : mpl::pair<mpl::int_<BgpAttribute::NextHop>,
1912 : BgpAttrTemplate<BgpAttrNextHop, 4, uint32_t,
1913 : &BgpAttrNextHop::nexthop> >,
1914 : mpl::pair<mpl::int_<BgpAttribute::MultiExitDisc>,
1915 : BgpAttrTemplate<BgpAttrMultiExitDisc, 4, uint32_t,
1916 : &BgpAttrMultiExitDisc::med> >,
1917 : mpl::pair<mpl::int_<BgpAttribute::LocalPref>,
1918 : BgpAttrTemplate<BgpAttrLocalPref, 4, uint32_t,
1919 : &BgpAttrLocalPref::local_pref> >,
1920 : mpl::pair<mpl::int_<BgpAttribute::AtomicAggregate>,
1921 : BgpPathAttributeAtomicAggregate>,
1922 : mpl::pair<mpl::int_<BgpAttribute::Aggregator>,
1923 : BgpPathAttributeAggregator>,
1924 : mpl::pair<mpl::int_<BgpAttribute::As4Aggregator>,
1925 : BgpPathAttributeAs4Aggregator>,
1926 : mpl::pair<mpl::int_<BgpAttribute::Communities>,
1927 : BgpPathAttributeCommunities>,
1928 : mpl::pair<mpl::int_<BgpAttribute::OriginatorId>,
1929 : BgpAttrTemplate<BgpAttrOriginatorId, 4, uint32_t,
1930 : &BgpAttrOriginatorId::originator_id> >,
1931 : mpl::pair<mpl::int_<BgpAttribute::ClusterList>,
1932 : BgpPathAttributeClusterList>,
1933 : mpl::pair<mpl::int_<BgpAttribute::MPReachNlri>,
1934 : BgpPathAttributeMpReachNlriSequence>,
1935 : mpl::pair<mpl::int_<BgpAttribute::MPUnreachNlri>,
1936 : BgpPathAttributeMpUnreachNlriSequence>,
1937 : mpl::pair<mpl::int_<BgpAttribute::ExtendedCommunities>,
1938 : BgpPathAttributeExtendedCommunities>,
1939 : mpl::pair<mpl::int_<BgpAttribute::LargeCommunities>,
1940 : BgpPathAttributeLargeCommunities>,
1941 : mpl::pair<mpl::int_<BgpAttribute::PmsiTunnel>,
1942 : BgpPathAttributePmsiTunnel>,
1943 : mpl::pair<mpl::int_<BgpAttribute::McastEdgeDiscovery>,
1944 : BgpPathAttributeEdgeDiscovery>,
1945 : mpl::pair<mpl::int_<BgpAttribute::McastEdgeForwarding>,
1946 : BgpPathAttributeEdgeForwarding>,
1947 : mpl::pair<mpl::int_<BgpAttribute::OriginVnPath>,
1948 : BgpPathAttributeOriginVnPath>,
1949 : mpl::pair<mpl::int_<-1>, BgpPathAttributeUnknown>
1950 : > Choice;
1951 : };
1952 :
1953 : class BgpPathAttributeAs4 : public ProtoChoice<BgpPathAttributeAs4> {
1954 : public:
1955 : static const int kSize = 1;
1956 :
1957 : typedef Accessor<BgpAttribute, uint8_t, &BgpAttribute::code> Setter;
1958 : typedef mpl::map<
1959 : mpl::pair<mpl::int_<BgpAttribute::Origin>,
1960 : BgpAttrTemplate<BgpAttrOrigin, 1, int,
1961 : &BgpAttrOrigin::origin> >,
1962 : mpl::pair<mpl::int_<BgpAttribute::AsPath>,
1963 : BgpPathAttributeAsPath4Byte>,
1964 : mpl::pair<mpl::int_<BgpAttribute::As4Path>, BgpPathAttributeAs4Path>,
1965 : mpl::pair<mpl::int_<BgpAttribute::NextHop>,
1966 : BgpAttrTemplate<BgpAttrNextHop, 4, uint32_t,
1967 : &BgpAttrNextHop::nexthop> >,
1968 : mpl::pair<mpl::int_<BgpAttribute::MultiExitDisc>,
1969 : BgpAttrTemplate<BgpAttrMultiExitDisc, 4, uint32_t,
1970 : &BgpAttrMultiExitDisc::med> >,
1971 : mpl::pair<mpl::int_<BgpAttribute::LocalPref>,
1972 : BgpAttrTemplate<BgpAttrLocalPref, 4, uint32_t,
1973 : &BgpAttrLocalPref::local_pref> >,
1974 : mpl::pair<mpl::int_<BgpAttribute::AtomicAggregate>,
1975 : BgpPathAttributeAtomicAggregate>,
1976 : mpl::pair<mpl::int_<BgpAttribute::Aggregator>,
1977 : BgpPathAttributeAggregator4Byte>,
1978 : mpl::pair<mpl::int_<BgpAttribute::As4Aggregator>,
1979 : BgpPathAttributeAs4Aggregator>,
1980 : mpl::pair<mpl::int_<BgpAttribute::Communities>,
1981 : BgpPathAttributeCommunities>,
1982 : mpl::pair<mpl::int_<BgpAttribute::OriginatorId>,
1983 : BgpAttrTemplate<BgpAttrOriginatorId, 4, uint32_t,
1984 : &BgpAttrOriginatorId::originator_id> >,
1985 : mpl::pair<mpl::int_<BgpAttribute::ClusterList>,
1986 : BgpPathAttributeClusterList>,
1987 : mpl::pair<mpl::int_<BgpAttribute::MPReachNlri>,
1988 : BgpPathAttributeMpReachNlriSequence>,
1989 : mpl::pair<mpl::int_<BgpAttribute::MPUnreachNlri>,
1990 : BgpPathAttributeMpUnreachNlriSequence>,
1991 : mpl::pair<mpl::int_<BgpAttribute::ExtendedCommunities>,
1992 : BgpPathAttributeExtendedCommunities>,
1993 : mpl::pair<mpl::int_<BgpAttribute::LargeCommunities>,
1994 : BgpPathAttributeLargeCommunities>,
1995 : mpl::pair<mpl::int_<BgpAttribute::PmsiTunnel>,
1996 : BgpPathAttributePmsiTunnel>,
1997 : mpl::pair<mpl::int_<BgpAttribute::McastEdgeDiscovery>,
1998 : BgpPathAttributeEdgeDiscovery>,
1999 : mpl::pair<mpl::int_<BgpAttribute::McastEdgeForwarding>,
2000 : BgpPathAttributeEdgeForwarding>,
2001 : mpl::pair<mpl::int_<BgpAttribute::OriginVnPath>,
2002 : BgpPathAttributeOriginVnPath>,
2003 : mpl::pair<mpl::int_<-1>, BgpPathAttributeUnknown>
2004 : > Choice;
2005 : };
2006 :
2007 : class BgpPathAttributeList : public ProtoSequence<BgpPathAttributeList> {
2008 : public:
2009 : static const int kSize = 2;
2010 : static const int kMinOccurs = 0;
2011 : static const int kMaxOccurs = -1;
2012 : static const int kErrorCode = BgpProto::Notification::UpdateMsgErr;
2013 : static const int kErrorSubcode =
2014 : BgpProto::Notification::MalformedAttributeList;
2015 : struct Offset {
2016 189191 : string operator()() {
2017 189191 : return "BgpPathAttribute";
2018 : }
2019 : };
2020 : typedef Offset SaveOffset;
2021 : typedef CollectionAccessor<BgpProto::Update,
2022 : vector<BgpAttribute *>,
2023 : &BgpProto::Update::path_attributes> ContextStorer;
2024 : typedef mpl::list<BgpPathAttributeFlags, BgpPathAttribute> Sequence;
2025 : };
2026 :
2027 : class BgpPathAttributeAs4List : public ProtoSequence<BgpPathAttributeAs4List> {
2028 : public:
2029 : static const int kSize = 2;
2030 : static const int kMinOccurs = 0;
2031 : static const int kMaxOccurs = -1;
2032 : static const int kErrorCode = BgpProto::Notification::UpdateMsgErr;
2033 : static const int kErrorSubcode =
2034 : BgpProto::Notification::MalformedAttributeList;
2035 : struct Offset {
2036 140 : string operator()() {
2037 140 : return "BgpPathAttribute";
2038 : }
2039 : };
2040 : typedef Offset SaveOffset;
2041 : typedef CollectionAccessor<BgpProto::Update,
2042 : vector<BgpAttribute *>,
2043 : &BgpProto::Update::path_attributes> ContextStorer;
2044 : typedef mpl::list<BgpPathAttributeFlags, BgpPathAttributeAs4> Sequence;
2045 : };
2046 :
2047 : class BgpUpdateNlri : public ProtoSequence<BgpUpdateNlri> {
2048 : public:
2049 : static const int kMinOccurs = 0;
2050 : static const int kMaxOccurs = -1;
2051 :
2052 : typedef CollectionAccessor<BgpProto::Update,
2053 : vector<BgpProtoPrefix *>,
2054 : &BgpProto::Update::nlri> ContextStorer;
2055 :
2056 : struct OptMatch {
2057 : bool match(const BgpProto::Update *ctx) {
2058 : return !ctx->nlri.empty();
2059 : }
2060 : };
2061 : typedef OptMatch ContextMatch;
2062 : typedef mpl::list<BgpPrefixLen, BgpPrefixAddress> Sequence;
2063 : };
2064 :
2065 : class BgpUpdateMessageAs4 : public ProtoSequence<BgpUpdateMessageAs4> {
2066 : public:
2067 : typedef mpl::list<BgpUpdateWithdrawnRoutes, BgpPathAttributeAs4List,
2068 : BgpUpdateNlri> Sequence;
2069 : typedef BgpProto::Update ContextType;
2070 : };
2071 :
2072 : class BgpUpdateMessage : public ProtoSequence<BgpUpdateMessage> {
2073 : public:
2074 : typedef mpl::list<BgpUpdateWithdrawnRoutes, BgpPathAttributeList,
2075 : BgpUpdateNlri> Sequence;
2076 : typedef BgpProto::Update ContextType;
2077 : };
2078 :
2079 : class BgpMsgType : public ProtoChoice<BgpMsgType> {
2080 : public:
2081 : static const int kSize = 1;
2082 : static const int kErrorCode = BgpProto::Notification::MsgHdrErr;
2083 : static const int kErrorSubcode = BgpProto::Notification::BadMsgType;
2084 : typedef mpl::map<
2085 : mpl::pair<mpl::int_<BgpProto::OPEN>, BgpOpenMessage>,
2086 : mpl::pair<mpl::int_<BgpProto::NOTIFICATION>, BgpNotificationMessage>,
2087 : mpl::pair<mpl::int_<BgpProto::KEEPALIVE>, BgpKeepaliveMessage>,
2088 : mpl::pair<mpl::int_<BgpProto::UPDATE>, BgpUpdateMessage>
2089 : > Choice;
2090 : };
2091 :
2092 : class BgpMsgTypeAs4 : public ProtoChoice<BgpMsgTypeAs4> {
2093 : public:
2094 : static const int kSize = 1;
2095 : static const int kErrorCode = BgpProto::Notification::MsgHdrErr;
2096 : static const int kErrorSubcode = BgpProto::Notification::BadMsgType;
2097 : typedef mpl::map<
2098 : mpl::pair<mpl::int_<BgpProto::OPEN>, BgpOpenMessage>,
2099 : mpl::pair<mpl::int_<BgpProto::NOTIFICATION>, BgpNotificationMessage>,
2100 : mpl::pair<mpl::int_<BgpProto::KEEPALIVE>, BgpKeepaliveMessage>,
2101 : mpl::pair<mpl::int_<BgpProto::UPDATE>, BgpUpdateMessageAs4>
2102 : > Choice;
2103 : };
2104 :
2105 : class BgpProtocol : public ProtoSequence<BgpProtocol> {
2106 : public:
2107 : typedef mpl::list<BgpMarker, BgpMsgLength, BgpMsgType> Sequence;
2108 : };
2109 :
2110 : class BgpProtocolAs4 : public ProtoSequence<BgpProtocolAs4> {
2111 : public:
2112 : typedef mpl::list<BgpMarker, BgpMsgLength, BgpMsgTypeAs4> Sequence;
2113 : };
2114 :
2115 196006 : BgpProto::BgpMessage *BgpProto::Decode(const uint8_t *data, size_t size,
2116 : ParseErrorContext *ec, bool as4) {
2117 196006 : ParseContext context;
2118 : int result;
2119 196007 : if (as4) {
2120 230 : result = BgpProtocolAs4::Parse(data, size, &context,
2121 : reinterpret_cast<void *>(NULL));
2122 : } else {
2123 195777 : result = BgpProtocol::Parse(data, size, &context,
2124 : reinterpret_cast<void *>(NULL));
2125 : }
2126 195998 : if (result < 0) {
2127 7540 : if (ec) {
2128 139 : *ec = context.error_context();
2129 : }
2130 7540 : return NULL;
2131 : }
2132 188458 : return static_cast<BgpMessage *>(context.release());
2133 196006 : }
2134 :
2135 212851 : int BgpProto::Encode(const BgpMessage *msg, uint8_t *data, size_t size,
2136 : EncodeOffsets *offsets, bool as4) {
2137 212851 : EncodeContext ctx;
2138 : int result;
2139 212848 : if (as4) {
2140 140 : result = BgpProtocolAs4::Encode(&ctx, msg, data, size);
2141 : } else {
2142 212708 : result = BgpProtocol::Encode(&ctx, msg, data, size);
2143 : }
2144 212869 : if (offsets) {
2145 156529 : *offsets = ctx.encode_offsets();
2146 : }
2147 212865 : return result;
2148 212861 : }
2149 :
2150 60950 : int BgpProto::Encode(const BgpMpNlri *msg, uint8_t *data, size_t size,
2151 : EncodeOffsets *offsets) {
2152 60950 : EncodeContext ctx;
2153 60949 : int result = 0;
2154 60949 : if ((msg->afi == BgpAf::L2Vpn) && (msg->safi == BgpAf::EVpn)) {
2155 9640 : result = BgpPathAttributeMpEvpnNlri::Encode(&ctx, msg, data, size);
2156 51309 : } else if ((msg->afi == BgpAf::IPv4) && (msg->safi == BgpAf::ErmVpn)) {
2157 536 : result = BgpPathAttributeMpErmVpnNlri::Encode(&ctx, msg, data, size);
2158 50773 : } else if ((msg->afi == BgpAf::IPv4) && (msg->safi == BgpAf::MVpn)) {
2159 615 : result = BgpPathAttributeMpMvpnNlri::Encode(&ctx, msg, data, size);
2160 : } else {
2161 50158 : result = BgpPathAttributeMpNlri::Encode(&ctx, msg, data, size);
2162 : }
2163 60953 : if (offsets) {
2164 0 : *offsets = ctx.encode_offsets();
2165 : }
2166 60954 : return result;
2167 60953 : }
|