LCOV - code coverage report
Current view: top level - bgp - xmpp_message_builder.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 397 413 96.1 %
Date: 2026-06-08 02:02:55 Functions: 31 31 100.0 %
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/xmpp_message_builder.h"
       6             : 
       7             : #include <boost/foreach.hpp>
       8             : 
       9             : #include <algorithm>
      10             : 
      11             : #include "bgp/ipeer.h"
      12             : #include "bgp/bgp_server.h"
      13             : #include "bgp/bgp_table.h"
      14             : #include "bgp/extended-community/etree.h"
      15             : #include "bgp/extended-community/mac_mobility.h"
      16             : #include "bgp/ermvpn/ermvpn_route.h"
      17             : #include "bgp/evpn/evpn_route.h"
      18             : #include "bgp/mvpn/mvpn_route.h"
      19             : #include "bgp/routing-instance/routing_instance.h"
      20             : #include "bgp/security_group/security_group.h"
      21             : #include "db/db.h"
      22             : #include "net/community_type.h"
      23             : #include "schema/xmpp_multicast_types.h"
      24             : #include "schema/xmpp_mvpn_types.h"
      25             : #include "schema/xmpp_enet_types.h"
      26             : #include "xmpp/xmpp_init.h"
      27             : 
      28             : using pugi::xml_attribute;
      29             : using pugi::xml_document;
      30             : using pugi::xml_node;
      31             : using std::ostringstream;
      32             : using std::copy;
      33             : using std::fill;
      34             : using std::string;
      35             : using std::stringstream;
      36             : using std::vector;
      37             : 
      38      467749 : static inline const char *AfiName(uint16_t afi) {
      39      467749 :     switch (afi) {
      40      263621 :     case BgpAf::IPv4:
      41      263621 :         return "1";
      42             :         break;
      43      193802 :     case BgpAf::IPv6:
      44      193802 :         return "2";
      45             :         break;
      46       10348 :     case BgpAf::L2Vpn:
      47       10348 :         return "25";
      48             :         break;
      49             :     }
      50           0 :     assert(false);
      51             :     return NULL;
      52             : }
      53             : 
      54      467752 : static inline const char *XmppSafiName(uint8_t safi) {
      55      467752 :     switch (safi) {
      56      448203 :     case BgpAf::Unicast:
      57      448203 :         return "1";
      58             :         break;
      59           6 :     case BgpAf::Mpls:
      60           6 :         return "4";
      61             :         break;
      62        6479 :     case BgpAf::MVpn:
      63        6479 :         return "5";
      64             :         break;
      65        2732 :     case BgpAf::Mcast:
      66        2732 :         return "241";
      67             :         break;
      68       10348 :     case BgpAf::Enet:
      69       10348 :         return "242";
      70             :         break;
      71             :     }
      72           0 :     assert(false);
      73             :     return NULL;
      74             : }
      75             : 
      76         144 : BgpXmppMessage::BgpXmppMessage()
      77         144 :     : table_(NULL),
      78         144 :       writer_(XmlWriter(&repr_)),
      79         144 :       is_reachable_(false),
      80         144 :       cache_routes_(false),
      81         144 :       repr_valid_(false),
      82         143 :       mobility_(0, false),
      83         287 :       etree_leaf_(false) {
      84         144 :     msg_begin_.reserve(kMaxFromToLength);
      85         144 : }
      86             : 
      87         288 : BgpXmppMessage::~BgpXmppMessage() {
      88         288 : }
      89             : 
      90      467677 : void BgpXmppMessage::Reset() {
      91      467677 :     Message::Reset();
      92      467679 :     table_ = NULL;
      93      467679 :     is_reachable_ = false;
      94      467679 :     cache_routes_ = false;
      95      467679 :     repr_valid_ = false;
      96      467679 :     repr_.clear();
      97      467671 : }
      98             : 
      99      467673 : bool BgpXmppMessage::Start(const RibOut *ribout, bool cache_routes,
     100             :     const RibOutAttr *roattr, const BgpRoute *route) {
     101      467673 :     Reset();
     102      467668 :     table_ = ribout->table();
     103      467658 :     is_reachable_ = roattr->IsReachable();
     104      467651 :     cache_routes_ = cache_routes;
     105      467651 :     Address::Family family = table_->family();
     106             : 
     107      467650 :     if (is_reachable_) {
     108      316231 :         const BgpAttr *attr = roattr->attr();
     109      316224 :         ProcessCommunity(attr->community());
     110      316224 :         ProcessExtCommunity(attr->ext_community());
     111             :     }
     112             : 
     113             :     // Reserve space for the begin line that contains the message opening tag
     114             :     // with from and to attributes. Actual value gets patched in when GetData
     115             :     // is called.
     116      467671 :     repr_.append(kMaxFromToLength, ' ');
     117             : 
     118             :     // Add opening tags for event and items. The closing tags are added when
     119             :     // GetData is called.
     120      467688 :     repr_ += "\n\t<event xmlns=\"http://jabber.org/protocol/pubsub\">";
     121      467704 :     repr_ += "\n\t\t<items node=\"";
     122      467738 :     repr_ += AfiName(BgpAf::FamilyToAfi(family));
     123      467758 :     repr_ += "/";
     124      467779 :     repr_ += XmppSafiName(BgpAf::FamilyToXmppSafi(family));
     125      467762 :     repr_ += "/";
     126      467763 :     repr_ += table_->routing_instance()->name();
     127      467757 :     repr_ += "\">\n";
     128             : 
     129      467760 :     if (table_->family() == Address::ERMVPN) {
     130        2732 :         AddMcastRoute(route, roattr);
     131      465020 :     } else if (table_->family() == Address::EVPN) {
     132       10348 :         AddEnetRoute(route, roattr);
     133      454668 :     } else if (table_->family() == Address::INET6) {
     134      193798 :         AddInet6Route(route, roattr);
     135      260866 :     } else if (table_->family() == Address::MVPN) {
     136        6479 :         AddMvpnRoute(route, roattr);
     137             :     } else {
     138      254397 :         AddInetRoute(route, roattr);
     139             :     }
     140      467810 :     return true;
     141             : }
     142             : 
     143      467794 : void BgpXmppMessage::Finish() {
     144      467794 : }
     145             : 
     146      623081 : bool BgpXmppMessage::AddRoute(const BgpRoute *route, const RibOutAttr *roattr) {
     147      623081 :     assert(is_reachable_ == roattr->IsReachable());
     148      623079 :     if (is_reachable_ && num_reach_route_ >= kMaxReachCount)
     149         181 :         return false;
     150      622898 :     if (!is_reachable_ && num_unreach_route_ >= kMaxUnreachCount)
     151           8 :         return false;
     152             : 
     153      622890 :     if (is_reachable_) {
     154      521325 :         const BgpAttr *attr = roattr->attr();
     155      521320 :         ProcessCommunity(attr->community());
     156      521323 :         ProcessExtCommunity(attr->ext_community());
     157             :     }
     158             : 
     159      622909 :     if (table_->family() == Address::ERMVPN) {
     160         154 :         return AddMcastRoute(route, roattr);
     161      622751 :     } else if (table_->family() == Address::EVPN) {
     162        2258 :         return AddEnetRoute(route, roattr);
     163      620492 :     } else if (table_->family() == Address::INET6) {
     164      127083 :         return AddInet6Route(route, roattr);
     165      493411 :     } else if (table_->family() == Address::MVPN) {
     166      190464 :         return AddMvpnRoute(route, roattr);
     167             :     } else {
     168      302990 :         return AddInetRoute(route, roattr);
     169             :     }
     170             : }
     171             : 
     172      531675 : void BgpXmppMessage::EncodeNextHop(const BgpRoute *route,
     173             :                                    const RibOutAttr::NextHop &nexthop,
     174             :                                    autogen::ItemType *item) {
     175      531675 :     autogen::NextHopType item_nexthop;
     176             : 
     177      531684 :     const IpAddress &address = nexthop.address();
     178      531688 :     if (address.is_v4()) {
     179      528403 :         item_nexthop.af = BgpAf::IPv4;
     180      528403 :         item_nexthop.address = address.to_v4().to_string();
     181             :     } else {
     182        3285 :         item_nexthop.af = BgpAf::IPv6;
     183        3285 :         item_nexthop.address = address.to_v6().to_string();
     184             :     }
     185      531968 :     item_nexthop.label = nexthop.label();
     186      531963 :     item_nexthop.virtual_network = GetVirtualNetwork(nexthop);
     187      531960 :     item_nexthop.tag_list.tag = nexthop.tag_list();
     188      531787 :     item_nexthop.is_new_tags_list = true;
     189             : 
     190             :     // If there's a non-zero label and encap list is empty use mpls over gre
     191             :     // as default encap.
     192      531787 :     if (item_nexthop.label) {
     193      522832 :         vector<string> &encap_list =
     194             :             item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation;
     195      522832 :         if (nexthop.encap().empty()) {
     196      100614 :             encap_list.push_back(string("gre"));
     197             :         } else {
     198      422233 :             encap_list = nexthop.encap();
     199             :         }
     200             :     }
     201             : 
     202      531724 :     item->entry.next_hops.next_hop.push_back(item_nexthop);
     203      531781 : }
     204             : 
     205      627754 : void BgpXmppMessage::AddIpReach(const BgpRoute *route,
     206             :                                 const RibOutAttr *roattr) {
     207      627754 :     if (!roattr->repr().empty()) {
     208       98208 :         repr_ += roattr->repr();
     209       98208 :         return;
     210             :     }
     211      529557 :     Address::Family family = table_->family();
     212             : 
     213      529550 :     autogen::ItemType item;
     214      529501 :     item.entry.nlri.af = BgpAf::FamilyToAfi(family);
     215      529508 :     item.entry.nlri.safi = BgpAf::FamilyToXmppSafi(family);
     216      529502 :     item.entry.nlri.address = route->ToString();
     217      529595 :     item.entry.version = 1;
     218      529595 :     item.entry.virtual_network = GetVirtualNetwork(route, roattr);
     219      529610 :     item.entry.local_preference = roattr->attr()->local_pref();
     220      529578 :     item.entry.med = roattr->attr()->med();
     221      529547 :     item.entry.sequence_number = mobility_.sequence_number;
     222      529547 :     item.entry.mobility.seqno = mobility_.sequence_number;
     223      529547 :     item.entry.mobility.sticky = mobility_.sticky;
     224             : 
     225      529547 :     assert(!roattr->nexthop_list().empty());
     226             : 
     227             :     // Encode all next-hops in the list.
     228     1593008 :     BOOST_FOREACH(const RibOutAttr::NextHop &nexthop, roattr->nexthop_list()) {
     229      531697 :         EncodeNextHop(route, nexthop, &item);
     230             :     }
     231             : 
     232      529479 :     for (vector<int>::const_iterator it = security_group_list_.begin();
     233      852515 :          it != security_group_list_.end(); ++it) {
     234      323076 :         item.entry.security_group_list.security_group.push_back(*it);
     235             :     }
     236             : 
     237      529450 :     for (vector<string>::const_iterator it = community_list_.begin();
     238      541291 :          it != community_list_.end(); ++it) {
     239       11852 :         item.entry.community_tag_list.community_tag.push_back(*it);
     240             :     }
     241             : 
     242             :     // Encode load balance attribute.
     243      529432 :     if (!load_balance_attribute_.IsDefault())
     244           4 :         load_balance_attribute_.Encode(&item.entry.load_balance);
     245             : 
     246      529432 :     xml_node node = doc_.append_child("item");
     247      529378 :     node.append_attribute("id") = route->ToXmppIdString().c_str();
     248             : 
     249             :     // Remember the previous size.
     250             :     // Using remove_child instead of reset allows memory pages allocated for
     251             :     // the xml_document to be reused during the lifetime of the xml_document.
     252      529464 :     size_t pos = repr_.size();
     253      529468 :     item.Encode(&node);
     254      529435 :     doc_.print(writer_, "\t", pugi::format_default, pugi::encoding_auto, 3);
     255      529601 :     doc_.remove_child(node);
     256             : 
     257             :     // Cache the substring starting at the previous size.
     258      529606 :     if (cache_routes_)
     259       28519 :         roattr->set_repr(repr_, pos);
     260      529607 : }
     261             : 
     262      250441 : void BgpXmppMessage::AddIpUnreach(const BgpRoute *route) {
     263      250441 :     repr_ += "\t\t\t<retract id=\"" + route->ToXmppIdString() + "\" />\n";
     264      250534 : }
     265             : 
     266      557381 : bool BgpXmppMessage::AddInetRoute(const BgpRoute *route,
     267             :                                   const RibOutAttr *roattr) {
     268      557381 :     if (is_reachable_) {
     269      425147 :         num_reach_route_++;
     270      425147 :         AddIpReach(route, roattr);
     271             :     } else {
     272      132234 :         num_unreach_route_++;
     273      132234 :         AddIpUnreach(route);
     274             :     }
     275      557443 :     return true;
     276             : }
     277             : 
     278      320865 : bool BgpXmppMessage::AddInet6Route(const BgpRoute *route,
     279             :                                    const RibOutAttr *roattr) {
     280      320865 :     if (is_reachable_) {
     281      202642 :         num_reach_route_++;
     282      202642 :         AddIpReach(route, roattr);
     283             :     } else {
     284      118223 :         num_unreach_route_++;
     285      118223 :         AddIpUnreach(route);
     286             :     }
     287      320911 :     return true;
     288             : }
     289             : 
     290        9101 : void BgpXmppMessage::EncodeEnetNextHop(const BgpRoute *route,
     291             :                                        const RibOutAttr::NextHop &nexthop,
     292             :                                        autogen::EnetItemType *item) {
     293        9101 :     autogen::EnetNextHopType item_nexthop;
     294             : 
     295        9101 :     item_nexthop.af = BgpAf::IPv4;
     296        9101 :     item_nexthop.address = nexthop.address().to_v4().to_string();
     297        9101 :     item_nexthop.label = nexthop.label();
     298        9101 :     item_nexthop.l3_label = nexthop.l3_label();
     299        9101 :     if (!nexthop.mac().IsZero())
     300          20 :         item_nexthop.mac = nexthop.mac().ToString();
     301             : 
     302             :     // If encap list is empty use mpls over gre as default encap.
     303        9101 :     vector<string> &encap_list =
     304             :         item_nexthop.tunnel_encapsulation_list.tunnel_encapsulation;
     305        9101 :     if (nexthop.encap().empty()) {
     306           0 :         encap_list.push_back(string("gre"));
     307             :     } else {
     308        9101 :         encap_list = nexthop.encap();
     309             :     }
     310        9101 :     item_nexthop.tag_list.tag = nexthop.tag_list();
     311        9101 :     item_nexthop.is_new_tags_list = true;
     312        9101 :     item->entry.next_hops.next_hop.push_back(item_nexthop);
     313        9101 : }
     314             : 
     315       10614 : void BgpXmppMessage::AddEnetReach(const BgpRoute *route,
     316             :                                   const RibOutAttr *roattr) {
     317       10614 :     if (!roattr->repr().empty()) {
     318           0 :         repr_ += roattr->repr();
     319           0 :         return;
     320             :     }
     321       10614 :     Address::Family family = table_->family();
     322             : 
     323       10614 :     autogen::EnetItemType item;
     324       10614 :     item.entry.nlri.af = BgpAf::FamilyToAfi(family);
     325       10614 :     item.entry.nlri.safi = BgpAf::FamilyToXmppSafi(family);
     326             : 
     327       10614 :     EvpnRoute *evpn_route =
     328             :         static_cast<EvpnRoute *>(const_cast<BgpRoute *>(route));
     329       10614 :     const EvpnPrefix &evpn_prefix = evpn_route->GetPrefix();
     330       10614 :     item.entry.nlri.ethernet_tag = evpn_prefix.tag();
     331       10614 :     item.entry.nlri.mac = evpn_prefix.mac_addr().ToString();
     332       21228 :     item.entry.nlri.address = evpn_prefix.ip_address().to_string() + "/" +
     333       31842 :         integerToString(evpn_prefix.ip_address_length());
     334       10614 :     item.entry.nlri.source = evpn_prefix.source().to_string();
     335       10614 :     item.entry.nlri.group = evpn_prefix.group().to_string();
     336             : 
     337       10614 :     item.entry.virtual_network = GetVirtualNetwork(route, roattr);
     338       10614 :     item.entry.local_preference = roattr->attr()->local_pref();
     339       10614 :     item.entry.med = roattr->attr()->med();
     340       10614 :     item.entry.sequence_number = mobility_.sequence_number;
     341       10614 :     item.entry.mobility.seqno = mobility_.sequence_number;
     342       10614 :     item.entry.mobility.sticky = mobility_.sticky;
     343       10614 :     item.entry.etree_leaf = etree_leaf_;
     344             : 
     345       10614 :     for (vector<int>::const_iterator it = security_group_list_.begin();
     346       21236 :          it != security_group_list_.end(); ++it) {
     347       10622 :         item.entry.security_group_list.security_group.push_back(*it);
     348             :     }
     349             : 
     350       10614 :     const BgpOList *olist = roattr->attr()->olist().get();
     351       10614 :     assert((olist == NULL) != roattr->nexthop_list().empty());
     352             : 
     353       10614 :     if (olist) {
     354        1641 :         assert(olist->olist().subcode == BgpAttribute::OList);
     355       15125 :         BOOST_FOREACH(const BgpOListElem *elem, olist->elements()) {
     356        6742 :             autogen::EnetNextHopType nh;
     357        6742 :             nh.af = BgpAf::IPv4;
     358        6742 :             nh.address = elem->address.to_string();
     359        6742 :             nh.label = elem->label;
     360        6742 :             nh.tunnel_encapsulation_list.tunnel_encapsulation = elem->encap;
     361        6742 :             item.entry.olist.next_hop.push_back(nh);
     362        6742 :         }
     363             :     }
     364             : 
     365       10614 :     const BgpOList *leaf_olist = roattr->attr()->leaf_olist().get();
     366       10614 :     assert((leaf_olist == NULL) != roattr->nexthop_list().empty());
     367             : 
     368       10614 :     if (leaf_olist) {
     369        1641 :         assert(leaf_olist->olist().subcode == BgpAttribute::LeafOList);
     370        1641 :         BOOST_FOREACH(const BgpOListElem *elem, leaf_olist->elements()) {
     371           0 :             autogen::EnetNextHopType nh;
     372           0 :             nh.af = BgpAf::IPv4;
     373           0 :             nh.address = elem->address.to_string();
     374           0 :             nh.label = elem->label;
     375           0 :             nh.tunnel_encapsulation_list.tunnel_encapsulation = elem->encap;
     376           0 :             item.entry.leaf_olist.next_hop.push_back(nh);
     377           0 :         }
     378             :     }
     379             : 
     380       28816 :     BOOST_FOREACH(const RibOutAttr::NextHop &nexthop, roattr->nexthop_list()) {
     381        9101 :         EncodeEnetNextHop(route, nexthop, &item);
     382             :     }
     383             : 
     384       11534 :     for (const auto &peer_name : route->peer_sources()) {
     385         920 :         item.entry.peers.peer.push_back(peer_name);
     386             :     }
     387             : 
     388       10614 :     xml_node node = doc_.append_child("item");
     389       10614 :     node.append_attribute("id") = route->ToXmppIdString().c_str();
     390             : 
     391             :     // Remember the previous size.
     392             :     // Using remove_child instead of reset allows memory pages allocated for
     393             :     // the xml_document to be reused during the lifetime of the xml_document.
     394       10614 :     size_t pos = repr_.size();
     395       10614 :     item.Encode(&node);
     396       10613 :     doc_.print(writer_, "\t", pugi::format_default, pugi::encoding_auto, 3);
     397       10614 :     doc_.remove_child(node);
     398             : 
     399             :     // Cache the substring starting at the previous size.
     400       10614 :     if (cache_routes_)
     401        1917 :         roattr->set_repr(repr_, pos);
     402       10614 : }
     403             : 
     404        1992 : void BgpXmppMessage::AddEnetUnreach(const BgpRoute *route) {
     405        1992 :     repr_ += "\t\t\t<retract id=\"" + route->ToXmppIdString() + "\" />\n";
     406        1992 : }
     407             : 
     408       12606 : bool BgpXmppMessage::AddEnetRoute(const BgpRoute *route,
     409             :     const RibOutAttr *roattr) {
     410       12606 :     if (is_reachable_) {
     411       10614 :         num_reach_route_++;
     412       10614 :         AddEnetReach(route, roattr);
     413             :     } else {
     414        1992 :         num_unreach_route_++;
     415        1992 :         AddEnetUnreach(route);
     416             :     }
     417       12606 :     return true;
     418             : }
     419             : 
     420             : //
     421             : // Note that there's no need to cache the string representation since a given
     422             : // mcast route is sent to exactly one xmpp peer.
     423             : //
     424        2420 : void BgpXmppMessage::AddMcastReach(const BgpRoute *route,
     425             :                                    const RibOutAttr *roattr) {
     426        2420 :     Address::Family family = table_->family();
     427        2420 :     autogen::McastItemType item;
     428        2420 :     item.entry.nlri.af = BgpAf::FamilyToAfi(family);
     429        2420 :     item.entry.nlri.safi = BgpAf::FamilyToXmppSafi(family);
     430             : 
     431        2420 :     ErmVpnRoute *ermvpn_route =
     432             :         static_cast<ErmVpnRoute *>(const_cast<BgpRoute *>(route));
     433        2420 :     item.entry.nlri.group = ermvpn_route->GetPrefix().group().to_string();
     434        2420 :     item.entry.nlri.source =  ermvpn_route->GetPrefix().source().to_string();
     435        2420 :     item.entry.nlri.source_label = roattr->label();
     436        2420 :     if (!roattr->source_address().is_unspecified()) {
     437             :         item.entry.nlri.source_address =
     438         146 :            roattr->source_address().to_string();
     439             :     }
     440             : 
     441        2420 :     const BgpOList *olist = roattr->attr()->olist().get();
     442        2420 :     assert(olist->olist().subcode == BgpAttribute::OList);
     443        7586 :     BOOST_FOREACH(const BgpOListElem *elem, olist->elements()) {
     444        2583 :         autogen::McastNextHopType nh;
     445        2583 :         nh.af = BgpAf::IPv4;
     446        2583 :         nh.address = elem->address.to_string();
     447        2583 :         nh.label = integerToString(elem->label);
     448        2583 :         nh.tunnel_encapsulation_list.tunnel_encapsulation = elem->encap;
     449        2583 :         item.entry.olist.next_hop.push_back(nh);
     450        2583 :     }
     451             : 
     452             :     // Using remove_child instead of reset allows memory pages allocated for
     453             :     // the xml_document to be reused during the lifetime of the xml_document.
     454        2420 :     xml_node node = doc_.append_child("item");
     455        2420 :     node.append_attribute("id") = route->ToXmppIdString().c_str();
     456        2420 :     item.Encode(&node);
     457        2420 :     doc_.print(writer_, "\t", pugi::format_default, pugi::encoding_auto, 3);
     458        2420 :     doc_.remove_child(node);
     459        2420 : }
     460             : 
     461         466 : void BgpXmppMessage::AddMcastUnreach(const BgpRoute *route) {
     462         466 :     repr_ += "\t\t\t<retract id=\"" + route->ToXmppIdString() + "\" />\n";
     463         466 : }
     464             : 
     465        2886 : bool BgpXmppMessage::AddMcastRoute(const BgpRoute *route,
     466             :                                    const RibOutAttr *roattr) {
     467        2886 :     if (is_reachable_) {
     468        2420 :         num_reach_route_++;
     469        2420 :         AddMcastReach(route, roattr);
     470             :     } else {
     471         466 :         num_unreach_route_++;
     472         466 :         AddMcastUnreach(route);
     473             :     }
     474        2886 :     return true;
     475             : }
     476             : 
     477      196818 : void BgpXmppMessage::AddMvpnReach(const BgpRoute *route,
     478             :                                   const RibOutAttr *roattr) {
     479      196818 :     Address::Family family = table_->family();
     480      196818 :     autogen::MvpnItemType item;
     481      196818 :     item.entry.nlri.af = BgpAf::FamilyToAfi(family);
     482      196818 :     item.entry.nlri.safi = BgpAf::FamilyToXmppSafi(family);
     483             : 
     484      196818 :     MvpnRoute *mvpn_route =
     485             :         static_cast<MvpnRoute *>(const_cast<BgpRoute *>(route));
     486      196818 :     item.entry.nlri.group = mvpn_route->GetPrefix().group().to_string();
     487      196818 :     item.entry.nlri.source =  mvpn_route->GetPrefix().source().to_string();
     488      196818 :     item.entry.nlri.route_type = mvpn_route->GetPrefix().type();
     489      196818 :     assert((item.entry.nlri.route_type == MvpnPrefix::SourceActiveADRoute) ||
     490             :             (item.entry.nlri.route_type == MvpnPrefix::SourceTreeJoinRoute));
     491             : 
     492      196818 :     if (item.entry.nlri.route_type == MvpnPrefix::SourceActiveADRoute) {
     493      196724 :         const BgpOList *olist = roattr->attr()->olist().get();
     494      196724 :         assert(olist->olist().subcode == BgpAttribute::OList);
     495      590172 :         BOOST_FOREACH(const BgpOListElem *elem, olist->elements()) {
     496      196724 :             autogen::MvpnNextHopType nh;
     497      196724 :             nh.af = BgpAf::IPv4;
     498      196724 :             nh.address = elem->address.to_string();
     499      196724 :             nh.label = elem->label;
     500      196724 :             nh.tunnel_encapsulation_list.tunnel_encapsulation = elem->encap;
     501      196724 :             item.entry.olist.next_hop.push_back(nh);
     502      196724 :         }
     503             :     }
     504             : 
     505             :     // Using remove_child instead of reset allows memory pages allocated for
     506             :     // the xml_document to be reused during the lifetime of the xml_document.
     507      196818 :     xml_node node = doc_.append_child("item");
     508      196818 :     node.append_attribute("id") = route->ToXmppIdString().c_str();
     509      196818 :     item.Encode(&node);
     510      196818 :     doc_.print(writer_, "\t", pugi::format_default, pugi::encoding_auto, 3);
     511      196818 :     doc_.remove_child(node);
     512      196818 : }
     513             : 
     514         125 : void BgpXmppMessage::AddMvpnUnreach(const BgpRoute *route) {
     515         125 :     repr_ += "\t\t\t<retract id=\"" + route->ToXmppIdString() + "\" />\n";
     516         125 : }
     517             : 
     518      196943 : bool BgpXmppMessage::AddMvpnRoute(const BgpRoute *route,
     519             :                                    const RibOutAttr *roattr) {
     520      196943 :     if (is_reachable_) {
     521      196818 :         num_reach_route_++;
     522      196818 :         AddMvpnReach(route, roattr);
     523             :     } else {
     524         125 :         num_unreach_route_++;
     525         125 :         AddMvpnUnreach(route);
     526             :     }
     527      196943 :     return true;
     528             : }
     529             : 
     530    14147018 : const uint8_t *BgpXmppMessage::GetData(IPeerUpdate *peer, size_t *lenp,
     531             :     const string **msg_str, string *temp) {
     532             :     // Build begin line that contains message opening tag with from and to
     533             :     // attributes.
     534    14147018 :     msg_begin_.clear();
     535    14147081 :     msg_begin_ += "\n<message from=\"";
     536    14147158 :     msg_begin_ += XmppInit::kControlNodeJID;
     537    14147211 :     msg_begin_ += "\" to=\"";
     538    14147281 :     msg_begin_ += peer->ToString();
     539    14147360 :     msg_begin_ += "/";
     540    14147367 :     msg_begin_ += XmppInit::kBgpPeer;
     541    14147327 :     msg_begin_ += "\">";
     542             : 
     543             :     // Add closing tags if this is the first peer to which the message will
     544             :     // be sent.
     545    14147353 :     if (!repr_valid_) {
     546      467827 :         repr_ += "\t\t</items>\n\t</event>\n</message>\n";
     547      467826 :         repr_valid_ = true;
     548             :     }
     549             : 
     550             :     // Replace the begin line if it fits in the space reserved at the start
     551             :     // of repr_. Use fill and copy instead of string::replace as the latter
     552             :     // seems to construct a new temporary string to hold the input data to
     553             :     // be copied.
     554             :     // Otherwise build a new string with the begin line and the rest of the
     555             :     // message in repr_.
     556    14147352 :     size_t begin_size = msg_begin_.size();
     557    14147273 :     if (begin_size <= kMaxFromToLength) {
     558     9952998 :         size_t extra = kMaxFromToLength - begin_size;
     559     9952998 :         char *data = const_cast<char *>(repr_.c_str());
     560     9953009 :         fill(data, data + extra, ' ');
     561     9953026 :         copy(msg_begin_.c_str(), msg_begin_.c_str() + begin_size, data + extra);
     562     9952818 :         *lenp = repr_.size() - extra;
     563     9952783 :         *msg_str = &repr_;
     564     9952783 :         return reinterpret_cast<const uint8_t *>(repr_.c_str()) + extra;
     565             :     } else {
     566     4194275 :         *temp = msg_begin_ + string(repr_, kMaxFromToLength);
     567     4194304 :         *lenp = temp->size();
     568     4194304 :         *msg_str = NULL;
     569     4194304 :         return reinterpret_cast<const uint8_t *>(temp->c_str());
     570             :     }
     571             : }
     572             : 
     573      837527 : void BgpXmppMessage::ProcessCommunity(const Community *community) {
     574      837527 :     community_list_.clear();
     575      837545 :     if (community == NULL)
     576      825712 :         return;
     577       35538 :     BOOST_FOREACH(uint32_t value, community->communities()) {
     578       11854 :         community_list_.push_back(CommunityType::CommunityToString(value));
     579             :     }
     580             : }
     581             : 
     582      837527 : void BgpXmppMessage::ProcessExtCommunity(const ExtCommunity *ext_community) {
     583      837527 :     mobility_.sequence_number = 0;
     584      837527 :     mobility_.sticky = false;
     585      837527 :     etree_leaf_ = false;
     586      837527 :     security_group_list_.clear();
     587      837539 :     load_balance_attribute_ = LoadBalance::LoadBalanceAttribute();
     588      837723 :     if (ext_community == NULL)
     589      208094 :         return;
     590             : 
     591      629629 :     as_t as_number =  table_->server()->autonomous_system();
     592      629596 :     bool sg_asn_match = true;
     593      629567 :     for (ExtCommunity::ExtCommunityList::const_iterator iter =
     594      629596 :         ext_community->communities().begin();
     595     3680460 :         iter != ext_community->communities().end(); ++iter) {
     596     3050942 :         if (ExtCommunity::is_security_group(*iter)) {
     597      432042 :             SecurityGroup sg(*iter);
     598      432036 :             if (as_number <= AS2_MAX)
     599      235428 :                 if (sg.as_number() != as_number && !sg.IsGlobal())
     600           2 :                     continue;
     601      432041 :             security_group_list_.push_back(sg.security_group_id());
     602     2618978 :         } else if (ExtCommunity::is_security_group4(*iter)) {
     603      196608 :             SecurityGroup4ByteAs sg(*iter);
     604      196608 :             if (sg.as_number() != as_number)
     605           0 :                 sg_asn_match = false;
     606     2422382 :         } else if (ExtCommunity::is_mac_mobility(*iter)) {
     607        1079 :             MacMobility mm(*iter);
     608        1079 :             mobility_.sequence_number = mm.sequence_number();
     609        1079 :             mobility_.sticky = mm.sticky();
     610     2421227 :         } else if (ExtCommunity::is_load_balance(*iter)) {
     611           4 :             LoadBalance load_balance(*iter);
     612           4 :             load_balance.FillAttribute(&load_balance_attribute_);
     613     2421211 :         } else if (ExtCommunity::is_etree(*iter)) {
     614        9470 :             ETree etree(*iter);
     615        9470 :             etree_leaf_ = etree.leaf();
     616             :         }
     617             :     }
     618      629474 :     if (!sg_asn_match)
     619           0 :         security_group_list_.clear();
     620             : }
     621             : 
     622     1070229 : string BgpXmppMessage::GetVirtualNetwork(
     623             :     const RibOutAttr::NextHop &nexthop) const {
     624     1070229 :     int index = nexthop.origin_vn_index();
     625     1070365 :     if (index > 0) {
     626             :         const RoutingInstanceMgr *manager =
     627       68956 :             table_->routing_instance()->manager();
     628       68971 :         return manager->GetVirtualNetworkByVnIndex(index);
     629     1001409 :     } else if (index == 0) {
     630       61488 :         return table_->routing_instance()->GetVirtualNetworkName();
     631             :     } else {
     632      939921 :         return "unresolved";
     633             :     }
     634             : }
     635             : 
     636      540196 : string BgpXmppMessage::GetVirtualNetwork(const BgpRoute *route,
     637             :     const RibOutAttr *roattr) const {
     638      540196 :     if (!is_reachable_) {
     639           0 :         return "unresolved";
     640      540196 :     } else if (roattr->nexthop_list().empty()) {
     641        1641 :         if (roattr->vrf_originated()) {
     642        1641 :             return table_->routing_instance()->GetVirtualNetworkName();
     643             :         } else {
     644           0 :             return "unresolved";
     645             :         }
     646             :     } else {
     647      538483 :         return GetVirtualNetwork(roattr->nexthop_list().front());
     648             :     }
     649             : }
     650             : 
     651          50 : BgpXmppMessageBuilder::BgpXmppMessageBuilder() {
     652          51 : }
     653             : 
     654         143 : Message *BgpXmppMessageBuilder::Create() const {
     655         143 :     return new BgpXmppMessage;
     656             : }

Generated by: LCOV version 1.14