LCOV - code coverage report
Current view: top level - bgp - bgp_proto.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 575 603 95.4 %
Date: 2026-11-09 02:10:49 Functions: 142 143 99.3 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14