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