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

Generated by: LCOV version 1.14