LCOV - code coverage report
Current view: top level - bgp - bgp_show_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 371 0.0 %
Date: 2026-09-21 02:11:39 Functions: 0 23 0.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/bgp_sandesh.h"
       6             : #include "bgp/bgp_show_route.h"
       7             : 
       8             : #include <boost/assign/list_of.hpp>
       9             : #include <sandesh/request_pipeline.h>
      10             : 
      11             : #include "base/regex.h"
      12             : #include "bgp/bgp_peer_internal_types.h"
      13             : #include "bgp/bgp_route.h"
      14             : #include "bgp/bgp_server.h"
      15             : #include "bgp/bgp_table.h"
      16             : #include "bgp/routing-instance/routing_instance.h"
      17             : 
      18             : using boost::assign::list_of;
      19             : using std::unique_ptr;
      20             : using std::string;
      21             : using std::vector;
      22             : 
      23           0 : static bool IsLess(const ShowRoute &lhs, const ShowRoute &rhs,
      24             :                    const BgpSandeshContext *bsc, const string &table_name) {
      25             :     BgpTable *table = static_cast<BgpTable *>
      26           0 :         (bsc->bgp_server->database()->FindTable(table_name));
      27           0 :     if (!table) {
      28           0 :         return false;
      29             :     }
      30           0 :     unique_ptr<DBEntry> lhs_entry = table->AllocEntryStr(lhs.get_prefix());
      31           0 :     unique_ptr<DBEntry> rhs_entry = table->AllocEntryStr(rhs.get_prefix());
      32             : 
      33           0 :     Route *lhs_route = static_cast<Route *>(lhs_entry.get());
      34           0 :     Route *rhs_route = static_cast<Route *>(rhs_entry.get());
      35             : 
      36           0 :     return lhs_route->IsLess(*rhs_route);
      37           0 : }
      38             : 
      39           0 : static bool IsLess(const ShowRouteTable &lhs, const ShowRouteTable &rhs,
      40             :                    const BgpSandeshContext *bsc, const string &table_name) {
      41           0 :     if (lhs.get_routing_instance() < rhs.get_routing_instance()) {
      42           0 :         return true;
      43             :     }
      44           0 :     if (lhs.get_routing_instance() == rhs.get_routing_instance()) {
      45           0 :         return lhs.get_routing_table_name() < rhs.get_routing_table_name();
      46             :     }
      47           0 :     return false;
      48             : }
      49             : 
      50             : template <class T>
      51             : void MergeSort(vector<T> *result, vector<const vector<T> *> *input, int limit,
      52             :                const BgpSandeshContext *bsc, const string &table_name);
      53             : 
      54           0 : int MergeValues(ShowRoute *result, vector<const ShowRoute *> *input,
      55             :                 int limit, const BgpSandeshContext *bsc) {
      56           0 :     assert(input->size() == 1);
      57           0 :     *result = *input->at(0);
      58           0 :     return 1;
      59             : }
      60             : 
      61           0 : int MergeValues(ShowRouteTable *result, vector<const ShowRouteTable *> *input,
      62             :                 int limit, const BgpSandeshContext *bsc) {
      63           0 :     vector<const vector<ShowRoute> *> list;
      64           0 :     result->set_routing_instance(input->at(0)->get_routing_instance());
      65           0 :     result->set_routing_table_name(input->at(0)->get_routing_table_name());
      66           0 :     result->set_deleted(input->at(0)->get_deleted());
      67           0 :     result->set_deleted_at(input->at(0)->get_deleted_at());
      68           0 :     result->set_prefixes(input->at(0)->get_prefixes());
      69           0 :     result->set_primary_paths(input->at(0)->get_primary_paths());
      70           0 :     result->set_secondary_paths(input->at(0)->get_secondary_paths());
      71           0 :     result->set_infeasible_paths(input->at(0)->get_infeasible_paths());
      72           0 :     result->set_stale_paths(input->at(0)->get_stale_paths());
      73           0 :     result->set_llgr_stale_paths(input->at(0)->get_llgr_stale_paths());
      74           0 :     result->set_paths(input->at(0)->get_paths());
      75           0 :     result->set_listeners(input->at(0)->get_listeners());
      76             : 
      77           0 :     int count = 0;
      78           0 :     for (size_t i = 0; i < input->size(); ++i) {
      79           0 :         if (input->at(i)->get_routes().size())
      80           0 :             list.push_back(&input->at(i)->get_routes());
      81             :     }
      82           0 :     MergeSort(const_cast<vector<ShowRoute> *>(&result->get_routes()), &list,
      83             :               limit ? limit - count : 0, bsc,
      84           0 :               input->at(0)->get_routing_table_name());
      85           0 :     count += result->get_routes().size();
      86           0 :     return count;
      87           0 : }
      88             : 
      89             : //
      90             : // Merge n number of vectors in result.
      91             : // Input is a vector of pointers to vector.
      92             : //
      93             : template <class T>
      94           0 : void MergeSort(vector<T> *result, vector<const vector<T> *> *input, int limit,
      95             :                const BgpSandeshContext *bsc, const string &table_name) {
      96           0 :     size_t size = input->size();
      97           0 :     vector<size_t> index(size, 0);
      98           0 :     int count = 0;
      99           0 :     while (limit == 0 || count < limit) {
     100           0 :         size_t best_index = size;
     101           0 :         const T *best = NULL;
     102           0 :         for (size_t i = 0; i < size; ++i) {
     103           0 :             if (index[i] == input->at(i)->size())
     104           0 :                 continue;
     105           0 :             if (best == NULL ||
     106           0 :                 IsLess(input->at(i)->at(index[i]), *best, bsc, table_name)) {
     107           0 :                 best = &input->at(i)->at(index[i]);
     108           0 :                 best_index = i;
     109           0 :                 continue;
     110             :             }
     111             :         }
     112           0 :         if (best_index >= size)
     113           0 :             break;
     114           0 :         T table;
     115           0 :         vector<const T *> list;
     116           0 :         for (size_t j = best_index; j < size; ++j) {
     117           0 :             if (index[j] == input->at(j)->size())
     118           0 :                 continue;
     119           0 :             if (IsLess(input->at(j)->at(index[j]), *best, bsc, table_name) ||
     120           0 :                 IsLess(*best, input->at(j)->at(index[j]), bsc, table_name)) {
     121           0 :                 continue;
     122             :             }
     123           0 :             list.push_back(&input->at(j)->at(index[j]));
     124           0 :             index[j]++;
     125             :         }
     126           0 :         count += MergeValues(&table, &list, limit ? limit - count : 0, bsc);
     127           0 :         result->push_back(table);
     128             :     }
     129           0 : }
     130             : 
     131             : char ShowRouteHandler::kIterSeparator[] = "||";
     132           0 : uint32_t ShowRouteHandler::GetMaxCount(bool test_mode) {
     133           0 :     if (test_mode) {
     134           0 :         return kUnitTestMaxCount;
     135             :     } else {
     136           0 :         return kMaxCount;
     137             :     }
     138             : }
     139             : 
     140           0 : ShowRouteHandler::ShowRouteHandler(const ShowRouteReq *req, int inst_id) :
     141           0 :         req_(req), inst_id_(inst_id), prefix_expr_(req->get_prefix()) {
     142           0 : }
     143             : 
     144             : // Search for interesting prefixes in a given table for given partition
     145           0 : void ShowRouteHandler::BuildShowRouteTable(BgpTable *table,
     146             :         vector<ShowRoute> *route_list, int count) {
     147           0 :     if (inst_id_ >= table->PartitionCount())
     148           0 :         return;
     149             :     DBTablePartition *partition =
     150           0 :         static_cast<DBTablePartition *>(table->GetTablePartition(inst_id_));
     151           0 :     BgpRoute *route = NULL;
     152             : 
     153           0 :     if (table->name() == req_->get_start_routing_table()) {
     154             :         unique_ptr<DBEntry> key =
     155           0 :             table->AllocEntryStr(req_->get_start_prefix());
     156           0 :         route = static_cast<BgpRoute *>(partition->lower_bound(key.get()));
     157           0 :     } else {
     158           0 :         route = static_cast<BgpRoute *>(partition->GetFirst());
     159             :     }
     160           0 :     for (int i = 0; route && (!count || i < count);
     161           0 :          route = static_cast<BgpRoute *>(partition->GetNext(route)), ++i) {
     162           0 :         if (!MatchPrefix(req_->get_prefix(), route,
     163           0 :                          req_->get_longer_match(),
     164           0 :                          req_->get_shorter_match()))
     165           0 :             continue;
     166           0 :         ShowRoute show_route;
     167           0 :         route->FillRouteInfo(table, &show_route, req_->get_source(),
     168           0 :                              req_->get_protocol());
     169           0 :         if (!show_route.get_paths().empty())
     170           0 :             route_list->push_back(show_route);
     171           0 :     }
     172             : }
     173             : 
     174           0 : bool ShowRouteHandler::MatchPrefix(const string &expected_prefix,
     175             :                                    BgpRoute *route, bool longer_match,
     176             :                                    bool shorter_match) {
     177           0 :     if (expected_prefix.empty())
     178           0 :         return true;
     179           0 :     if (!longer_match && !shorter_match)
     180           0 :         return regex_search(route->ToString(), prefix_expr_);
     181             : 
     182             :     // Do longer match.
     183           0 :     if (longer_match && route->IsMoreSpecific(expected_prefix))
     184           0 :         return true;
     185             : 
     186             :     // Do shorter match.
     187           0 :     if (shorter_match && route->IsLessSpecific(expected_prefix))
     188           0 :         return true;
     189             : 
     190           0 :     return false;
     191             : }
     192             : 
     193           0 : bool ShowRouteHandler::match(const string &expected, const string &actual) {
     194           0 :     if (expected == "")
     195           0 :         return true;
     196           0 :     return expected == actual;
     197             : }
     198             : 
     199           0 : RequestPipeline::InstData *ShowRouteHandler::CreateData(int stage) {
     200           0 :     return static_cast<RequestPipeline::InstData *>(new ShowRouteData);
     201             : }
     202             : 
     203           0 : uint32_t ShowRouteHandler::GetMaxRouteCount(const ShowRouteReq *req) {
     204             :     BgpSandeshContext *bsc =
     205           0 :         static_cast<BgpSandeshContext *>(req->client_context());
     206             :     uint32_t max_count =
     207           0 :         ShowRouteHandler::GetMaxCount(bsc->test_mode());
     208             : 
     209           0 :     uint32_t route_count = req->get_count() + 1;
     210           0 :     if (!req->get_count() || (req->get_count() > max_count)) {
     211             :         // Set the count to our default if input is zero or too high
     212           0 :         route_count = max_count + 1;
     213             :     }
     214           0 :     return route_count;
     215             : }
     216             : 
     217             : // Get the information from req_iterate and fill into req
     218           0 : bool ShowRouteHandler::ConvertReqIterateToReq(
     219             :     const ShowRouteReqIterate *req_iterate, ShowRouteReq *req) {
     220             :     // First, set the context from the original request since we might return
     221             :     // due to parsing errors.
     222           0 :     req->set_context(req_iterate->context());
     223             : 
     224             :     // Format of route_info:
     225             :     // UserRI||UserRT||UserPfx||NextRI||NextRT||NextPfx||count||longer_match||
     226             :     // shorter_match
     227             :     //
     228             :     // User* values were entered by the user and Next* values indicate 'where'
     229             :     // we need to start this iteration.
     230           0 :     string route_info = req_iterate->get_route_info();
     231           0 :     size_t sep_size = strlen(kIterSeparator);
     232             : 
     233           0 :     size_t pos1 = route_info.find(kIterSeparator);
     234           0 :     if (pos1 == string::npos) {
     235           0 :         return false;
     236             :     }
     237           0 :     string user_ri = route_info.substr(0, pos1);
     238             : 
     239           0 :     size_t pos2 = route_info.find(kIterSeparator, (pos1 + sep_size));
     240           0 :     if (pos2 == string::npos) {
     241           0 :         return false;
     242             :     }
     243             :     string user_rt = route_info.substr((pos1 + sep_size),
     244           0 :                                        pos2 - (pos1 + sep_size));
     245             : 
     246           0 :     size_t pos3 = route_info.find(kIterSeparator, (pos2 + sep_size));
     247           0 :     if (pos3 == string::npos) {
     248           0 :         return false;
     249             :     }
     250             :     string user_prefix = route_info.substr((pos2 + sep_size),
     251           0 :                                            pos3 - (pos2 + sep_size));
     252             : 
     253           0 :     size_t pos4 = route_info.find(kIterSeparator, (pos3 + sep_size));
     254           0 :     if (pos4 == string::npos) {
     255           0 :         return false;
     256             :     }
     257             :     string next_ri = route_info.substr((pos3 + sep_size),
     258           0 :                                        pos4 - (pos3 + sep_size));
     259             : 
     260           0 :     size_t pos5 = route_info.find(kIterSeparator, (pos4 + sep_size));
     261           0 :     if (pos5 == string::npos) {
     262           0 :         return false;
     263             :     }
     264             :     string next_rt = route_info.substr((pos4 + sep_size),
     265           0 :                                        pos5 - (pos4 + sep_size));
     266             : 
     267           0 :     size_t pos6 = route_info.find(kIterSeparator, (pos5 + sep_size));
     268           0 :     if (pos6 == string::npos) {
     269           0 :         return false;
     270             :     }
     271             :     string next_prefix = route_info.substr((pos5 + sep_size),
     272           0 :                                            pos6 - (pos5 + sep_size));
     273             : 
     274           0 :     size_t pos7 = route_info.find(kIterSeparator, (pos6 + sep_size));
     275           0 :     if (pos7 == string::npos) {
     276           0 :         return false;
     277             :     }
     278             :     string count_str = route_info.substr((pos6 + sep_size),
     279           0 :                                          pos7 - (pos6 + sep_size));
     280             : 
     281           0 :     size_t pos8 = route_info.find(kIterSeparator, (pos7 + sep_size));
     282           0 :     if (pos8 == string::npos) {
     283           0 :         return false;
     284             :     }
     285             :     string user_source = route_info.substr((pos7 + sep_size),
     286           0 :                                            pos8 - (pos7 + sep_size));
     287             : 
     288           0 :     size_t pos9 = route_info.find(kIterSeparator, (pos8 + sep_size));
     289           0 :     if (pos9 == string::npos) {
     290           0 :         return false;
     291             :     }
     292             :     string user_protocol = route_info.substr((pos8 + sep_size),
     293           0 :                                              pos9 - (pos8 + sep_size));
     294             : 
     295           0 :     size_t pos10 = route_info.find(kIterSeparator, (pos9 + sep_size));
     296           0 :     if (pos10 == string::npos) {
     297           0 :         return false;
     298             :     }
     299             :     string user_family = route_info.substr((pos9 + sep_size),
     300           0 :                                            pos10 - (pos9 + sep_size));
     301             : 
     302           0 :     size_t pos11 = route_info.find(kIterSeparator, (pos10 + sep_size));
     303           0 :     if (pos11 == string::npos) {
     304           0 :         return false;
     305             :     }
     306             :     string longer_match = route_info.substr((pos10 + sep_size),
     307           0 :                                             pos11 - (pos10 + sep_size));
     308             : 
     309           0 :     string shorter_match = route_info.substr(pos11 + sep_size);
     310             : 
     311           0 :     req->set_routing_instance(user_ri);
     312           0 :     req->set_routing_table(user_rt);
     313           0 :     req->set_prefix(user_prefix);
     314           0 :     req->set_start_routing_instance(next_ri);
     315           0 :     req->set_start_routing_table(next_rt);
     316           0 :     req->set_start_prefix(next_prefix);
     317           0 :     req->set_count(atoi(count_str.c_str()));
     318           0 :     req->set_source(user_source);
     319           0 :     req->set_protocol(user_protocol);
     320           0 :     req->set_family(user_family);
     321           0 :     req->set_longer_match(StringToBool(longer_match));
     322           0 :     req->set_shorter_match(StringToBool(shorter_match));
     323             : 
     324           0 :     return true;
     325           0 : }
     326             : 
     327           0 : bool ShowRouteHandler::CallbackS1Common(const ShowRouteReq *req, int inst_id,
     328             :                                         ShowRouteData *mydata) {
     329           0 :     uint32_t max_count = ShowRouteHandler::GetMaxRouteCount(req);
     330             : 
     331           0 :     ShowRouteHandler handler(req, inst_id);
     332             :     BgpSandeshContext *bsc =
     333           0 :         static_cast<BgpSandeshContext *>(req->client_context());
     334           0 :     RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr();
     335             : 
     336           0 :     string exact_routing_table = req->get_routing_table();
     337           0 :     string exact_routing_instance;
     338           0 :     string start_routing_instance;
     339           0 :     if (exact_routing_table.empty()) {
     340           0 :         exact_routing_instance = req->get_routing_instance();
     341             :     } else {
     342             :         exact_routing_instance =
     343           0 :             RoutingInstance::GetVrfFromTableName(exact_routing_table);
     344             :     }
     345           0 :     if (exact_routing_instance.empty()) {
     346           0 :         start_routing_instance = req->get_start_routing_instance();
     347             :     } else {
     348           0 :         start_routing_instance = exact_routing_instance;
     349             :     }
     350             : 
     351             :     RoutingInstanceMgr::name_iterator i =
     352           0 :         rim->name_lower_bound(start_routing_instance);
     353           0 :     uint32_t count = 0;
     354           0 :     while (i != rim->name_end()) {
     355           0 :         if (!handler.match(exact_routing_instance, i->first)) {
     356           0 :             break;
     357             :         }
     358           0 :         RoutingInstance::RouteTableList::const_iterator j;
     359           0 :         if (req->get_start_routing_instance() == i->first) {
     360           0 :             j = i->second->GetTables().
     361           0 :                                 lower_bound(req->get_start_routing_table());
     362             :         } else {
     363           0 :             j = i->second->GetTables().begin();
     364             :         }
     365           0 :         for (; j != i->second->GetTables().end(); ++j) {
     366           0 :             BgpTable *table = j->second;
     367           0 :             if (!req->get_family().empty() && req->get_family() !=
     368           0 :                     Address::FamilyToTableString(table->family())) {
     369           0 :                 continue;
     370             :             }
     371           0 :             if (!handler.match(req->get_routing_table(), table->name())) {
     372           0 :                 continue;
     373             :             }
     374           0 :             ShowRouteTable srt;
     375           0 :             srt.set_routing_instance(i->first);
     376           0 :             srt.set_routing_table_name(table->name());
     377           0 :             srt.set_deleted(table->IsDeleted());
     378           0 :             srt.set_deleted_at(
     379           0 :                 UTCUsecToString(table->deleter()->delete_time_stamp_usecs()));
     380             : 
     381             :             // Encode routing-table stats.
     382           0 :             srt.set_prefixes(table->Size());
     383           0 :             srt.set_primary_paths(table->GetPrimaryPathCount());
     384           0 :             srt.set_secondary_paths(table->GetSecondaryPathCount());
     385           0 :             srt.set_infeasible_paths(table->GetInfeasiblePathCount());
     386           0 :             srt.set_stale_paths(table->GetStalePathCount());
     387           0 :             srt.set_llgr_stale_paths(table->GetLlgrStalePathCount());
     388           0 :             srt.set_paths(srt.get_primary_paths() + srt.get_secondary_paths());
     389             : 
     390           0 :             vector<ShowTableListener> listeners;
     391           0 :             table->FillListeners(&listeners);
     392           0 :             srt.set_listeners(listeners);
     393             : 
     394           0 :             vector<ShowRoute> route_list;
     395           0 :             handler.BuildShowRouteTable(table, &route_list,
     396           0 :                                         max_count ? max_count - count : 0);
     397           0 :             if (route_list.size() || table->IsDeleted()) {
     398           0 :                 srt.set_routes(route_list);
     399           0 :                 mydata->route_table_list.push_back(srt);
     400             :             }
     401           0 :             count += route_list.size();
     402           0 :             if (count >= max_count) {
     403           0 :                 break;
     404             :             }
     405           0 :         }
     406           0 :         if (count >= max_count) {
     407           0 :             break;
     408             :         }
     409             : 
     410           0 :         i++;
     411             :     }
     412             : 
     413           0 :     return true;
     414           0 : }
     415             : 
     416           0 : bool ShowRouteHandler::CallbackS1(const Sandesh *sr,
     417             :             const RequestPipeline::PipeSpec ps,
     418             :             int stage, int instNum, RequestPipeline::InstData *data) {
     419           0 :     ShowRouteData *mydata = static_cast<ShowRouteData *>(data);
     420           0 :     int inst_id = ps.stages_[stage].instances_[instNum];
     421             :     const ShowRouteReq *req =
     422           0 :         static_cast<const ShowRouteReq *>(ps.snhRequest_.get());
     423             : 
     424           0 :     return CallbackS1Common(req, inst_id, mydata);
     425             : }
     426             : 
     427           0 : bool ShowRouteHandler::CallbackS1Iterate(const Sandesh *sr,
     428             :             const RequestPipeline::PipeSpec ps,
     429             :             int stage, int instNum, RequestPipeline::InstData *data) {
     430           0 :     ShowRouteData *mydata = static_cast<ShowRouteData *>(data);
     431           0 :     int inst_id = ps.stages_[stage].instances_[instNum];
     432             :     const ShowRouteReqIterate *req_iterate =
     433           0 :         static_cast<const ShowRouteReqIterate *>(ps.snhRequest_.get());
     434             : 
     435           0 :     ShowRouteReq *req = new ShowRouteReq;
     436           0 :     bool success = ConvertReqIterateToReq(req_iterate, req);
     437           0 :     if (success) {
     438           0 :         CallbackS1Common(req, inst_id, mydata);
     439             :     }
     440           0 :     req->Release();
     441           0 :     return true;
     442             : }
     443             : 
     444           0 : string ShowRouteHandler::SaveContextAndPopLast(const ShowRouteReq *req,
     445             :         vector<ShowRouteTable> *route_table_list) {
     446             :     // If there are no output results for the input parameters, we dont need to
     447             :     // save anything since there will be no subsequent iteration and there is
     448             :     // nothing to pop off.
     449           0 :     if (route_table_list->empty()) {
     450           0 :         return string("");
     451             :     }
     452             : 
     453             :     // Get the total number of routes that we have collected in this iteration
     454             :     // after the mergesort.
     455           0 :     uint32_t total_count = 0;
     456           0 :     for (size_t i = 0; i < route_table_list->size(); ++i) {
     457           0 :         total_count += route_table_list->at(i).get_routes().size();
     458             :     }
     459             : 
     460             :     ShowRouteTable *last_route_table =
     461           0 :         &route_table_list->at(route_table_list->size() - 1);
     462           0 :     string next_batch;
     463             : 
     464             :     // We always attempt to read one extra entry (GetMaxRouteCount() adds 1).
     465             :     // Case 1: (total_count > GetMaxRouteCount())
     466             :     // This cannot happen since the merge sort has already trimmed the list to
     467             :     // GetMaxRouteCount
     468             : 
     469             :     // Case 2: (total_count < GetMaxRouteCount())
     470             :     // There are no more entries matching the input criteria and we are done.
     471           0 :     if (total_count < ShowRouteHandler::GetMaxRouteCount(req)) {
     472           0 :         return next_batch;
     473             :     }
     474             : 
     475             :     // Case 3: (total_count == GetMaxRouteCount())
     476             :     // If total_count is equal to GetMaxRouteCount(), we have at least 1 entry
     477             :     // for the next round i.e. we are not done and we need to init next_batch
     478             :     // with the right values from the extra entry and we also need to pop off
     479             :     // the extra entry.
     480             : 
     481             :     int new_count;
     482           0 :     bool next_round = true;
     483           0 :     if (req->get_count()) {
     484             :         // This is required for the last round if the user gave a count. Even
     485             :         // though we have read an extra entry, we are done and we do not want
     486             :         // to display any 'next_batch' http links.
     487           0 :         new_count = req->get_count() - total_count + 1;
     488           0 :         if (!new_count) {
     489           0 :             next_round = false;
     490             :         }
     491             :     } else {
     492             :         // If the user did not fill in the count, keep using zero.
     493           0 :         new_count = req->get_count();
     494             :     }
     495             : 
     496           0 :     if (next_round) {
     497             :         ShowRoute last_route =
     498           0 :             last_route_table->get_routes().at(
     499           0 :                     last_route_table->get_routes().size() - 1);
     500             :         next_batch =
     501           0 :             req->get_routing_instance() + kIterSeparator +
     502           0 :             req->get_routing_table() + kIterSeparator +
     503           0 :             req->get_prefix() + kIterSeparator +
     504           0 :             last_route_table->get_routing_instance() + kIterSeparator +
     505           0 :             last_route_table->get_routing_table_name() + kIterSeparator +
     506           0 :             last_route.get_prefix() + kIterSeparator +
     507           0 :             integerToString(new_count) + kIterSeparator +
     508           0 :             req->get_source() + kIterSeparator +
     509           0 :             req->get_protocol() + kIterSeparator +
     510           0 :             req->get_family() + kIterSeparator +
     511           0 :             BoolToString(req->get_longer_match()) + kIterSeparator +
     512           0 :             BoolToString(req->get_shorter_match());
     513           0 :     }
     514             : 
     515             :     // Pop off the last entry only after we have captured its values in
     516             :     // 'next_batch' above.
     517             :     const_cast<vector<ShowRoute> *>(
     518           0 :             &last_route_table->get_routes())->pop_back();
     519           0 :     if (last_route_table->get_routes().empty()) {
     520           0 :         route_table_list->pop_back();
     521             :     }
     522             : 
     523           0 :     return next_batch;
     524           0 : }
     525             : 
     526           0 : void ShowRouteHandler::CallbackS2Common(const ShowRouteReq *req,
     527             :                                         const RequestPipeline::PipeSpec ps,
     528             :                                         ShowRouteResp *resp) {
     529             :     BgpSandeshContext *bsc =
     530           0 :         static_cast<BgpSandeshContext *>(req->client_context());
     531           0 :     const RequestPipeline::StageData *sd = ps.GetStageData(0);
     532           0 :     vector<ShowRouteTable> route_table_list;
     533           0 :     vector<const vector<ShowRouteTable> *> table_lists;
     534           0 :     for (size_t i = 0; i < sd->size(); ++i) {
     535             :         const ShowRouteData &old_data =
     536           0 :             static_cast<const ShowRouteData &>(sd->at(i));
     537           0 :         if (old_data.route_table_list.size()) {
     538           0 :             table_lists.push_back(&old_data.route_table_list);
     539             :         }
     540             :     }
     541           0 :     MergeSort(&route_table_list, &table_lists,
     542           0 :               ShowRouteHandler::GetMaxRouteCount(req), bsc, "");
     543             : 
     544           0 :     string next_batch = SaveContextAndPopLast(req, &route_table_list);
     545           0 :     resp->set_next_batch(next_batch);
     546             : 
     547             :     // Save the table in the message *after* popping the last entry above.
     548           0 :     resp->set_tables(route_table_list);
     549           0 : }
     550             : 
     551           0 : bool ShowRouteHandler::CallbackS2(const Sandesh *sr,
     552             :         const RequestPipeline::PipeSpec &ps, int stage, int instNum,
     553             :         RequestPipeline::InstData *data) {
     554             :     const ShowRouteReq *req =
     555           0 :         static_cast<const ShowRouteReq *>(ps.snhRequest_.get());
     556             : 
     557           0 :     ShowRouteResp *resp = new ShowRouteResp;
     558           0 :     CallbackS2Common(req, ps, resp);
     559           0 :     resp->set_context(req->context());
     560           0 :     resp->Response();
     561           0 :     return true;
     562             : }
     563             : 
     564           0 : bool ShowRouteHandler::CallbackS2Iterate(const Sandesh *sr,
     565             :         const RequestPipeline::PipeSpec ps, int stage, int instNum,
     566             :         RequestPipeline::InstData *data) {
     567             :     const ShowRouteReqIterate *req_iterate =
     568           0 :         static_cast<const ShowRouteReqIterate *>(ps.snhRequest_.get());
     569             : 
     570           0 :     ShowRouteResp *resp = new ShowRouteResp;
     571           0 :     ShowRouteReq *req = new ShowRouteReq;
     572           0 :     bool success = ConvertReqIterateToReq(req_iterate, req);
     573           0 :     if (success) {
     574           0 :         CallbackS2Common(req, ps, resp);
     575             :     }
     576           0 :     resp->set_context(req->context());
     577           0 :     resp->Response();
     578           0 :     req->Release();
     579           0 :     return true;
     580             : }
     581             : 
     582             : // handler for 'show route'
     583           0 : void ShowRouteReq::HandleRequest() const {
     584           0 :     BgpSandeshContext *bsc = static_cast<BgpSandeshContext *>(client_context());
     585             : 
     586           0 :     RequestPipeline::PipeSpec ps(this);
     587             : 
     588             :     // Request pipeline has 2 stages. In first stage, we spawn one task per
     589             :     // partition and generate the list of routes. In second stage, we look
     590             :     // at the generated list and merge it so that we can send it back.
     591           0 :     RequestPipeline::StageSpec s1, s2;
     592           0 :     TaskScheduler *scheduler = TaskScheduler::GetInstance();
     593           0 :     s1.taskId_ = scheduler->GetTaskId("db::DBTable");
     594           0 :     s1.allocFn_ = ShowRouteHandler::CreateData;
     595             : 
     596           0 :     s1.cbFn_ = ShowRouteHandler::CallbackS1;
     597           0 :     for (int i = 0; i < bsc->bgp_server->database()->PartitionCount(); ++i) {
     598           0 :         s1.instances_.push_back(i);
     599             :     }
     600             : 
     601           0 :     s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
     602           0 :     s2.allocFn_ = ShowRouteHandler::CreateData;
     603           0 :     s2.cbFn_ = ShowRouteHandler::CallbackS2;
     604           0 :     s2.instances_.push_back(0);
     605             : 
     606           0 :     ps.stages_= list_of(s1)(s2)
     607           0 :         .convert_to_container<vector<RequestPipeline::StageSpec> >();
     608           0 :     RequestPipeline rp(ps);
     609           0 : }
     610             : 
     611             : // handler for 'show route' that shows batches of routes, iteratively
     612           0 : void ShowRouteReqIterate::HandleRequest() const {
     613           0 :     BgpSandeshContext *bsc = static_cast<BgpSandeshContext *>(client_context());
     614             : 
     615           0 :     RequestPipeline::PipeSpec ps(this);
     616             : 
     617             :     // Request pipeline has 2 stages. In first stage, we spawn one task per
     618             :     // partition and generate the list of routes. In second stage, we look
     619             :     // at the generated list and merge it so that we can send it back.
     620           0 :     RequestPipeline::StageSpec s1, s2;
     621           0 :     TaskScheduler *scheduler = TaskScheduler::GetInstance();
     622             : 
     623           0 :     s1.taskId_ = scheduler->GetTaskId("db::DBTable");
     624           0 :     s1.allocFn_ = ShowRouteHandler::CreateData;
     625           0 :     s1.cbFn_ = ShowRouteHandler::CallbackS1Iterate;
     626           0 :     for (int i = 0; i < bsc->bgp_server->database()->PartitionCount(); ++i) {
     627           0 :         s1.instances_.push_back(i);
     628             :     }
     629             : 
     630           0 :     s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand");
     631           0 :     s2.allocFn_ = ShowRouteHandler::CreateData;
     632           0 :     s2.cbFn_ = ShowRouteHandler::CallbackS2Iterate;
     633           0 :     s2.instances_.push_back(0);
     634             : 
     635           0 :     ps.stages_= list_of(s1)(s2)
     636           0 :         .convert_to_container<vector<RequestPipeline::StageSpec> >();
     637           0 :     RequestPipeline rp(ps);
     638           0 : }

Generated by: LCOV version 1.14