// ----- check_deflection_in_area ------------------------------------------- int check_deflection_in_area(uint16_t uOspfDomain, ospf_area_t tArea) { int iIndexI, iIndexJ; /* Builds the set of BR that belongs to area and are on the backbone */ SPtrArray * pBRList = ospf_domain_get_br_on_bb_in_area(uOspfDomain, tArea); net_node_t * pBR, * pER; /* Build all possibile couple of border router in the set. * For each couple build RSPT on ER * */ for(iIndexI = 0; iIndexI < ptr_array_length(pBRList); iIndexI++) { ptr_array_get_at(pBRList, iIndexI, &pBR); for(iIndexJ = 0; iIndexJ < ptr_array_length(pBRList); iIndexJ++) { if (iIndexI == iIndexJ) continue; ptr_array_get_at(pBRList, iIndexJ, &pER); fprintf(stdout, "BR "); ip_address_dump(stdout, pBR->tAddr); fprintf(stdout, " - ER "); ip_address_dump(stdout, pER->tAddr); fprintf(stdout, "\n Computing rspt on ER\n"); SRadixTree * pRspt = ospf_node_compute_rspt(pER, uOspfDomain, tArea); assert(pRspt != NULL); SSptVertex * pBRVertex = radix_tree_get_exact(pRspt, pBR->tAddr, 32); assert(pBRVertex != NULL); radix_tree_destroy(&pRspt); } } return 0; }
/** * Aggregate N routes. The announced delay is the best route's delay. * The aggregated route has all the attribute (Next-Hop, * Communities, ...) of the best routes except the AS-Path which is an * AS-SET containing the AS-Num of all the ASes traversed by one of * the aggregated routes. */ SRoute * qos_route_aggregate(SRoutes * pRoutes, SRoute * pBestRoute) { SRoute * pAggrRoute; int iIndex; SRoute * pRoute; SPath ** ppPaths= (SPath **) MALLOC(sizeof(SPath *)* ptr_array_length(pRoutes)); qos_delay_t tDelay; assert(routes_list_get_num(pRoutes) >= 1); // Aggregate Delay tDelay.tMean= 0; tDelay.uWeight= 0; for (iIndex= 0; iIndex < routes_list_get_num(pRoutes); iIndex++) { pRoute= (SRoute *) pRoutes->data[iIndex]; tDelay.tMean+= pRoute->tDelay.uWeight*pRoute->tDelay.tMean; tDelay.uWeight+= pRoute->tDelay.uWeight; ppPaths[iIndex]= pRoute->pASPath; } tDelay.tMean= (int) (tDelay.tMean/tDelay.uWeight); // Aggregate Bandwidth: NOT YET IMPLEMENTED // Aggregate Paths pAggrRoute= route_copy(pBestRoute); pAggrRoute->tDelay= tDelay; pAggrRoute->tDelay.tDelay= pBestRoute->tDelay.tDelay; path_destroy(&pAggrRoute->pASPath); pAggrRoute->pASPath= path_aggregate(ppPaths, routes_list_get_num(pRoutes)); FREE(ppPaths); return pAggrRoute; }
// ----- check_deflection ---------------------------------------------- int check_deflection(uint16_t IGPDomainNumber, cr_info_list_t tList) { LOG_DEBUG("check actual deflection in domain %d\n", IGPDomainNumber); int iIndex; SCRouterInfo * pCRInfo; for (iIndex = 0; iIndex < ptr_array_length(tList); iIndex++){ ptr_array_get_at(tList, iIndex, &pCRInfo); fprintf(stdout, "CRInfo BR: "); ip_address_dump(stdout, pCRInfo->pBR->tAddr); fprintf(stdout, "\n"); fprintf(stdout, "ERInfo ER: "); ip_address_dump(stdout, pCRInfo->pER->tAddr); fprintf(stdout, "Compute RSPT on ER\n"); SRadixTree * pRspt = ospf_node_compute_rspt(pCRInfo->pER, IGPDomainNumber, pCRInfo->tArea); assert(pRspt != NULL); SSptVertex * pBRVertex = radix_tree_get_exact(pRspt, pCRInfo->pBR->tAddr, 32); assert(pBRVertex != NULL); csource_check_deflection(pBRVertex, pCRInfo); radix_tree_destroy(&pRspt); //fprintf(stdout, "--- Per ogni dest in CRInfo\n"); //fprintf(stdout, "------- Trova route in routing table in foglia\n"); //fprintf(stdout, "------- if (advRouter(route) == ER(CRInfo) deflection!\n"); } return 0; }
// -----[ cli_enum_as_level_domains ]-------------------------------- as_level_domain_t * cli_enum_as_level_domains(const char * text, int state) { static as_level_topo_t * topo= NULL; static unsigned int index= 0; char str_asn[ASN_STR_LEN]; as_level_domain_t * domain; if (state == 0) { topo= aslevel_get_topo(); if (topo == NULL) return NULL; index= 0; } while (index < ptr_array_length(topo->domains)) { domain= (as_level_domain_t *) topo->domains->data[index]; assert(snprintf(str_asn, ASN_STR_LEN, "%u", domain->asn) >= 0); index++; if (!strncmp(text, str_asn, strlen(text))) return domain; } return NULL; }
void _qos_test() { SRoute * pRoute1; SRoute * pRoute2; SRoute * pRoute3; SRoutes * pRoutes; SRoute * pAggrRoute; SPrefix sPrefix; int iIndex; sPrefix.tNetwork= 256; sPrefix.uMaskLen= 24; pRoute1= route_create(sPrefix, NULL, 1, ROUTE_ORIGIN_IGP); pRoute2= route_create(sPrefix, NULL, 2, ROUTE_ORIGIN_IGP); pRoute3= route_create(sPrefix, NULL, 3, ROUTE_ORIGIN_IGP); pRoute1->tDelay.tDelay= 5; pRoute1->tDelay.tMean= 5; pRoute1->tDelay.uWeight= 1; pRoute2->tDelay.tDelay= 5; pRoute2->tDelay.tMean= 7.5; pRoute2->tDelay.uWeight= 2; pRoute3->tDelay.tDelay= 10; pRoute3->tDelay.tMean= 10; pRoute3->tDelay.uWeight= 1; fprintf(stdout, "route-delay-compare: %d\n", qos_route_compare_delay(&pRoute1, &pRoute2, 0)); route_path_append(pRoute1, 1); route_path_append(pRoute2, 2); route_path_append(pRoute3, 3); pRoutes= ptr_array_create_ref(0); ptr_array_append(pRoutes, pRoute1); ptr_array_append(pRoutes, pRoute2); ptr_array_append(pRoutes, pRoute3); _array_sort((SArray *) pRoutes, qos_route_compare_delay); for (iIndex= 0; iIndex < ptr_array_length(pRoutes); iIndex++) { fprintf(stdout, "*** "); route_dump(stdout, (SRoute *) pRoutes->data[iIndex]); fprintf(stdout, "\n"); } pAggrRoute= qos_route_aggregate(pRoutes, pRoute1); route_dump(stdout, pAggrRoute); fprintf(stdout, "\n"); routes_list_destroy(&pRoutes); route_destroy(&pRoute1); route_destroy(&pRoute2); route_destroy(&pRoute3); route_destroy(&pAggrRoute); }
// -----[ aslevel_topo_num_edges ]--------------------------------- unsigned int aslevel_topo_num_edges(as_level_topo_t * topo) { unsigned int num_edges= 0; unsigned int index; as_level_domain_t * domain; ASLEVEL_TOPO_FOREACH_DOMAIN(topo, index, domain) { num_edges+= ptr_array_length(domain->neighbors); }
static int _find_object(OBJECT obj, struct marshal_state *ms) { int i; return -1; for(i = 0; i < ptr_array_length(ms->objects); i++) { if(obj == (OBJECT)ptr_array_get_index(ms->objects, i)) { return i; } } return -1; }
// ----- build_critical_destination_list --------------------------------------- int build_critical_destination_list(SCRouterInfo * pCRInfo) { LOG_DEBUG("bcdl on ER "); ip_address_dump(stdout, pCRInfo->pER->tAddr); fprintf(stdout, " area %d BR ", pCRInfo->tArea); ip_address_dump(stdout, pCRInfo->pBR->tAddr); fprintf(stdout, "\n"); if (OSPF_rt_for_each(pCRInfo->pER->pOspfRT, build_cd_for_each, pCRInfo) == OSPF_SUCCESS) return ptr_array_length(pCRInfo->tCDList); return 0; }
/** * Visit the revers shorthes path tree starting from pVertex to its soon. * */ void csource_check_deflection(SSptVertex * pVertex, SCRouterInfo * pCRInfo){ SSptVertex * pSon; int iLeafIdx; if (spt_vertex_is_router(pVertex) && (spt_vertex_to_router(pVertex)->tAddr != pCRInfo->pBR->tAddr)) { SCDestInfo * pCDInfo; int iDestIdx; SPrefix vertex_id = spt_vertex_get_id(pVertex); fprintf(stdout, "Visit "); ip_prefix_dump(stdout, vertex_id); fprintf(stdout, "\nCritical dest list: \n"); for (iDestIdx = 0; iDestIdx < ptr_array_length(pCRInfo->tCDList); iDestIdx++){ SOSPFRouteInfo * pCDRoute; ptr_array_get_at(pCRInfo->tCDList, iDestIdx, &pCDInfo); ip_prefix_dump(stdout, *pCDInfo); fprintf(stdout, "\n"); pCDRoute = OSPF_rt_find_exact(spt_vertex_to_router(pVertex)->pOspfRT, *pCDInfo, NET_ROUTE_IGP, OSPF_NO_AREA); assert(pCDRoute != NULL); int iNHIdx; SOSPFNextHop * pNH; for (iNHIdx = 0; iNHIdx < ptr_array_length(pCDRoute->aNextHops); iNHIdx++) { ptr_array_get_at(pCDRoute->aNextHops, iNHIdx, &pNH); if (pNH->tAdvRouterAddr != 0) ip_prefix_dump(stdout, pCDRoute->sPrefix); if (pNH->tAdvRouterAddr == pCRInfo->pER->tAddr) fprintf(stdout, "Trovata route con deflection!"); } } } //visit children for (iLeafIdx = 0; iLeafIdx < ptr_array_length(pVertex->sons); iLeafIdx++){ ptr_array_get_at(pVertex->sons, iLeafIdx, &pSon); csource_check_deflection(pSon, pCRInfo); } }
const char * quark_to_string(quark q) { const char *retval; if (q == 0) return NULL; mutex_lock(); if (quark_init_if_needed() || q >= ptr_array_length(quark_string_index)) { mutex_unlock(); return NULL; } retval = ptr_array_get_index(quark_string_index, q); mutex_unlock(); return retval; }
/** * Check if the given route is * - learned through an iBGP session * or * - has an aggregate which contains a route learned through an iBGP * session */ int qos_route_is_ibgp(SBGPRouter * pRouter, SRoute * pRoute) { int iIndex; // Best route learned from iBGP ? if (route_peer_get(pRoute)->uRemoteAS == pRouter->uNumber) return 1; // Route in the aggregate learned from iBGP ? if (pRoute->pAggrRoute != NULL) { for (iIndex= 0; iIndex < ptr_array_length(pRoute->pAggrRoutes); iIndex++) if (route_peer_get((SRoute *) pRoute->pAggrRoutes->data[iIndex])->uRemoteAS == pRouter->uNumber) return 1; } return 0; }
quark quark_from_static_string(const char *string) { if (string == NULL) return 0; mutex_lock(); if (!quark_init_if_needed()) { uintptr_t value = (uintptr_t)hashtable_search(quark_string_hash, string); if (value != 0) { mutex_unlock(); return value; } } if (!ptr_array_append(quark_string_index, string)) { mutex_unlock(); return QUARK_NOT_FOUND; } size_t index = ptr_array_length(quark_string_index) - 1; hashtable_insert(quark_string_hash, (char *)string, (void*) index); mutex_unlock(); return index; }
// ----- ospf_build_cd_for_each --------------------------------------------- int build_cd_for_each(uint32_t uKey, uint8_t uKeyLen, void * pItem, void * pContext){ SCRouterInfo * pCtx = (SCRouterInfo *) pContext; SOSPFRouteInfoList * pRIList = (SOSPFRouteInfoList *) pItem; SOSPFRouteInfo * pRIExitRouter = NULL;// = ospf_ri_list_get_route(pRIList); SOSPFRouteInfo * pRIBorderRouter; SPrefix sRoutePrefix; sRoutePrefix.tNetwork = (net_addr_t) uKey; sRoutePrefix.uMaskLen = uKeyLen; int iIndex; for (iIndex = 0; iIndex < ptr_array_length(pRIList); iIndex++){ ptr_array_get_at(pRIList, iIndex, &pRIExitRouter); if (ospf_ri_route_type_is(pRIExitRouter, NET_ROUTE_IGP)) break; else{ pRIExitRouter = NULL; } } if (pRIExitRouter != NULL && ospf_route_is_adver_in_area(pRIExitRouter, pCtx->tArea)) { pRIBorderRouter = OSPF_rt_find_exact(pCtx->pBR->pOspfRT, sRoutePrefix, NET_ROUTE_ANY, pCtx->tArea); if (pRIBorderRouter == NULL){ _cd_list_add(pCtx->tCDList, sRoutePrefix); } else if (ospf_ri_get_cost(pRIExitRouter) + pCtx->tRCost_BR_ER < ospf_ri_get_cost(pRIBorderRouter)){ _cd_list_add(pCtx->tCDList, sRoutePrefix); } } return OSPF_SUCCESS; }
/** * Select one route with the following rules: * * - prefer largest Delay-interval * - prefer shortest AS-PATH * - final tie-break * * Must go to the end of the function to select a unique best route, * but keep N good routes to aggregate */ void qos_decision_process_tie_break(SBGPRouter * pRouter, SRoutes * pRoutes, unsigned int uNumRoutes) { int iIndex; SRoute * pCurrentRoute, * pRoute; // *** lowest delay, then largest interval *** if (ptr_array_length(pRoutes) < 1) return; pCurrentRoute= (SRoute *) pRoutes->data[0]; for (iIndex= 0; iIndex < ptr_array_length(pRoutes)-1; iIndex++) { pRoute= (SRoute *) pRoutes->data[iIndex+1]; if ((pCurrentRoute->tDelay.tDelay != pRoute->tDelay.tDelay) || (_qos_delay_interval(pCurrentRoute->tDelay) != _qos_delay_interval(pRoute->tDelay))) { iIndex++; while (ptr_array_length(pRoutes) > iIndex) { ptr_array_remove_at(pRoutes, iIndex); } } pCurrentRoute= pRoute; } // *** shortest AS-PATH *** dp_rule_shortest_path(pRoutes); if (ptr_array_length(pRoutes) <= uNumRoutes) return; // *** eBGP over iBGP *** dp_rule_ebgp_over_ibgp(pRouter, pRoutes); if (ptr_array_length(pRoutes) <= uNumRoutes) return; // *** nearest NEXT-HOP (lowest IGP-cost) *** dp_rule_nearest_next_hop(pRouter, pRoutes); if (ptr_array_length(pRoutes) <= uNumRoutes) return; dp_rule_final(pRouter, pRoutes); }
// -----[ aslevel_topo_num_nodes ]--------------------------------- unsigned int aslevel_topo_num_nodes(as_level_topo_t * topo) { return ptr_array_length(topo->domains); }
/** * Let M be the number of routes which we want to keep for * aggregation (M = BGP_OPTIONS_QOS_AGGR_LIMIT). * * Order the routes lexicographically: * - first, lowest delay * - then longest interval * * Find the highest P < M such that * delay(R[P]) != delay(R[P+1]) * or such that * (delay(R[P]) == delay(R[P+1])) and (interval(R[P]) < interval(R[P+1])) * * Select the P first routes as candidates for aggregation * * Use the remaining tie-break rules to select at most M-P additional * routes as candidates for aggregation * * Run the decision process on the P first rules to find which one is * the best one. */ int qos_decision_process_delay(SBGPRouter * pRouter, SRoutes * pRoutes, unsigned int uNumRoutes) { int iIndex, iIndexLast; SRoute * pRoute, * pCurrentRoute; SRoutes * pAggrRoutes/*, * pOthRoutes*/; AS_LOG_DEBUG(pRouter, " > qos_decision_process_delay\n"); assert(uNumRoutes >= 1); // Sort routes based on (delay, delay_interval) _array_sort((SArray *) pRoutes, qos_route_compare_delay); // If there are more routes than can be aggregated, select a subset if (routes_list_get_num(pRoutes) > uNumRoutes) { // Find the higher P < M... iIndexLast= 0; pCurrentRoute= (SRoute *) pRoutes->data[0]; for (iIndex= 0; (iIndex < ptr_array_length(pRoutes)-1) && (iIndex < uNumRoutes); iIndex++) { pRoute= (SRoute *) pRoutes->data[iIndex+1]; if ((pCurrentRoute->tDelay.tDelay != pRoute->tDelay.tDelay) || (_qos_delay_interval(pCurrentRoute->tDelay) != _qos_delay_interval(pRoute->tDelay))) iIndexLast= iIndex; pCurrentRoute= pRoute; } _array_trim((SArray *) pRoutes, iIndexLast+1); // Tie-break for the N-P last routes in order to find additional // aggregatable routes (optional) /* pOthRoutes= (SPtrArray *) _array_sub((SArray *) pRoutes, iIndexLast+1, ptr_array_length(pRoutes)-1); qos_decision_process_tie_break(pAS, pOthRoutes, uNumRoutes-iIndexLast-1); _array_add_all((SArray *) pAggrRoutes, (SArray *) pOthRoutes); _array_destroy((SArray **) &pOthRoutes); */ } pAggrRoutes= (SRoutes *) _array_copy((SArray *) pRoutes); // Find best route qos_decision_process_tie_break(pRouter, pRoutes, 1); assert(ptr_array_length(pRoutes) <= 1); // Attach the list of aggregatable routes to the best route if (ptr_array_length(pRoutes) == 1) { ((SRoute *) pRoutes->data[0])->pAggrRoutes= pAggrRoutes; ((SRoute *) pRoutes->data[0])->pAggrRoute= qos_route_aggregate(pAggrRoutes, (SRoute *) pRoutes->data[0]); } else routes_list_destroy(&pAggrRoutes); AS_LOG_DEBUG(pRouter, " < qos_decision_process_delay\n"); return 0; }
/** * Disseminate route to Adj-RIB-Outs. * * If there is no best route, then * - if a route was previously announced, send an explicit withdraw * - otherwise do nothing * * If there is one best route, then send an update. If a route was * previously announced, it will be implicitly withdrawn. */ void qos_decision_process_disseminate(SBGPRouter * pRouter, SPrefix sPrefix, SRoute * pRoute) { #define QOS_REDISTRIBUTE_NOT 0 #define QOS_REDISTRIBUTE_BEST 1 #define QOS_REDISTRIBUTE_EBGP 2 int iIndex, iIndex2; SPeer * pPeer; SRoutes * pAggrRoutes= NULL; SRoute * pEBGPRoute= NULL; int iRedistributionType; int iAggregateIBGP; AS_LOG_DEBUG(pRouter, " > qos_decision_process_disseminate.begin\n"); iAggregateIBGP= qos_route_is_ibgp(pRouter, pRoute); if (pRoute->pAggrRoute != NULL) { pAggrRoutes= pRoute->pAggrRoutes; pEBGPRoute= pRoute->pEBGPRoute; pRoute= pRoute->pAggrRoute; } for (iIndex= 0; iIndex < ptr_array_length(pRouter->pPeers); iIndex++) { pPeer= (SPeer *) pRouter->pPeers->data[iIndex]; iRedistributionType= QOS_REDISTRIBUTE_BEST; // If one route of the aggregate was learned through the iBGP, // prevent the redistribution to all the iBGP peer. // Announce the eBGP route if it exists if ((pPeer->uRemoteAS == pRouter->uNumber) && (iAggregateIBGP)) { if (pEBGPRoute != NULL) iRedistributionType= QOS_REDISTRIBUTE_EBGP; else iRedistributionType= QOS_REDISTRIBUTE_NOT; } // If the route is an aggregate, check every peer which has // announced a route in the aggregate and prevent the // redistribution if ((iRedistributionType != QOS_REDISTRIBUTE_NOT) && (pAggrRoutes != NULL)) { for (iIndex2= 0; iIndex2 < ptr_array_length(pAggrRoutes); iIndex2++) if (((SRoute *) pAggrRoutes->data[iIndex2])->tNextHop == pPeer->tAddr) { iRedistributionType= QOS_REDISTRIBUTE_NOT; break; } } switch (iRedistributionType) { case QOS_REDISTRIBUTE_BEST: LOG_DEBUG("\tredistribution allowed to %d:", pPeer->uRemoteAS); LOG_ENABLED_DEBUG() ip_address_dump(log_get_stream(pMainLog), pPeer->tAddr); LOG_DEBUG("\n"); qos_decision_process_disseminate_to_peer(pRouter, sPrefix, pRoute, pPeer); break; case QOS_REDISTRIBUTE_EBGP: LOG_DEBUG("\tredistribution of eBGP allowed to %d:", pPeer->uRemoteAS); LOG_ENABLED_DEBUG() ip_address_dump(log_get_stream(pMainLog), pPeer->tAddr); LOG_DEBUG("\n"); qos_decision_process_disseminate_to_peer(pRouter, sPrefix, pEBGPRoute, pPeer); break; default: LOG_DEBUG("\tredistribution refused to %d:", pPeer->uRemoteAS); LOG_ENABLED_DEBUG() ip_address_dump(log_get_stream(pMainLog), pPeer->tAddr); LOG_DEBUG("\n"); qos_decision_process_disseminate_to_peer(pRouter, sPrefix, NULL, pPeer); } } AS_LOG_DEBUG(pRouter, " < qos_decision_process_disseminate.end\n"); }
// ----- build_critical_routers_list ------------------------------------------- int build_critical_routers_list(uint16_t uOspfDomain, ospf_area_t tArea, cr_info_list_t * tCRList) { int iIndexI, iIndexJ; SOSPFRouteInfo * pRouteIJArea, * pRouteIJBackbone; *tCRList = _cr_info_list_create(); SCRouterInfo * pCRInfo; /* Builds the set of BR that belongs to area and are on the backbone */ SPtrArray * pBRList = ospf_domain_get_br_on_bb_in_area(uOspfDomain, tArea); net_node_t * pBRI, *pBRJ; SPrefix sPrefix; /* Build all possibile couple of border router in the set. * For each couple check if condition 1 is verified * If is verified check condition 2, too. * */ for(iIndexI = 0; iIndexI < ptr_array_length(pBRList); iIndexI++){ ptr_array_get_at(pBRList, iIndexI, &pBRI); for(iIndexJ = 0; iIndexJ < ptr_array_length(pBRList); iIndexJ++){ if (iIndexI == iIndexJ) continue; ptr_array_get_at(pBRList, iIndexJ, &pBRJ); sPrefix.tNetwork = ospf_node_get_id(pBRJ); sPrefix.uMaskLen = 32; pRouteIJArea = OSPF_rt_find_exact(pBRI->pOspfRT, sPrefix, NET_ROUTE_IGP, tArea); /* If BR1 has not a route towards BR2 in area tArea this wants * to say that there is a partition in the area. In this case no * deflection is possibile because there not will be a source that * has BR1 on its path towards BR2, if BR2. * */ if (pRouteIJArea == NULL) continue; pRouteIJBackbone = OSPF_rt_find_exact(pBRI->pOspfRT, sPrefix, NET_ROUTE_IGP, BACKBONE_AREA); /* If BR1 has not a route towards BR2 in backbone this wants * to say that there is a partition in backbone. * Deflection can be possibile if BR2 will be choosen * as exit router to exit area for some couple source-destination * where source has BR1 on the path towards BR2. * This happends because BR2 announces destination in area tArea * but BR1 has not a route towards it because he does not consider * summary in area != backbone. * * If we assume that when a route does not exist in a routing table * it has a cost infinite, condition 1 we try to verify is still * verified. * */ if (pRouteIJBackbone == NULL) { fprintf(stdout, "partizione nel backbone - verificata la cond 1\n"); pCRInfo = _crouter_info_create(pBRI, pBRJ, ospf_ri_get_cost(pRouteIJArea), tArea); int iRes =build_critical_destination_list(pCRInfo); fprintf(stdout, "Returned %d", iRes); if (iRes) _cr_info_list_add(*tCRList, pCRInfo); else _crouter_info_destroy(&pCRInfo); continue; } /* Checking condition 2. * If it's true computing critical destination list for this * couple of routers and adding them to critical routers list. * */ if (ospf_ri_get_cost(pRouteIJArea) < ospf_ri_get_cost(pRouteIJBackbone)) fprintf(stdout, "Verificata condizione 1\n"); pCRInfo = _crouter_info_create(pBRI, pBRJ, ospf_ri_get_cost(pRouteIJArea), tArea); int iRes =build_critical_destination_list(pCRInfo); fprintf(stdout, "Returned %d", iRes); if (iRes) _cr_info_list_add(*tCRList, pCRInfo); else _crouter_info_destroy(&pCRInfo); } } return ptr_array_length(*tCRList); }
/** * Phase I - Calculate degree of preference (LOCAL_PREF) for each * single route. Operate on separate Adj-RIB-Ins. * This phase is carried by 'peer_handle_message' (peer.c). * * Phase II - Selection of best route on the basis of the degree of * preference and then on tie-breaking rules (AS-Path * length, Origin, MED, ...). * * Phase III - Dissemination of routes. * * In our implementation, we distinguish two main cases: * - a withdraw has been received from a peer for a given prefix. In * this case, if the best route towards this prefix was received by * the given peer, the complete decision process has to be * run. Otherwise, nothing more is done (the route has been removed * from the peer's Adj-RIB-In by 'peer_handle_message'); * - an update has been received. The complete decision process has to * be run. */ int qos_decision_process(SBGPRouter * pRouter, SPeer * pOriginPeer, SPrefix sPrefix) { #ifndef __EXPERIMENTAL_WALTON__ SRoutes * pRoutes= routes_list_create(); SRoutes * pEBGPRoutes= routes_list_create(); int iIndex; SPeer * pPeer; SRoute * pRoute, * pOldRoute; AS_LOG_DEBUG(pRouter, " > qos_decision_process.begin\n"); LOG_DEBUG("\t<-peer: AS%d\n", pOriginPeer->uRemoteAS); pOldRoute= rib_find_exact(pRouter->pLocRIB, sPrefix); LOG_DEBUG("\tbest: "); LOG_ENABLED_DEBUG() route_dump(log_get_stream(pMainLog), pOldRoute); LOG_DEBUG("\n"); // *** lock all Adj-RIB-Ins *** // Build list of eligible routes and list of eligible eBGP routes for (iIndex= 0; iIndex < ptr_array_length(pRouter->pPeers); iIndex++) { pPeer= (SPeer*) pRouter->pPeers->data[iIndex]; pRoute= rib_find_exact(pPeer->pAdjRIBIn, sPrefix); if ((pRoute != NULL) && (route_flag_get(pRoute, ROUTE_FLAG_FEASIBLE))) { assert(ptr_array_append(pRoutes, pRoute) >= 0); LOG_DEBUG("\teligible: "); LOG_ENABLED_DEBUG() route_dump(log_get_stream(pMainLog), pRoute); LOG_DEBUG("\n"); if (route_peer_get(pRoute)->uRemoteAS != pRouter->uNumber) assert(ptr_array_append(pEBGPRoutes, pRoute) >= 0); } } // Keep routes with highest degree of preference if (ptr_array_length(pRoutes) > 1) as_decision_process_dop(pRouter, pRoutes); // Tie-break if (ptr_array_length(pRoutes) > 1) qos_decision_process_delay(pRouter, pRoutes, BGP_OPTIONS_QOS_AGGR_LIMIT); assert(ptr_array_length(pRoutes) <= 1); if (ptr_array_length(pRoutes) == 1) { LOG_DEBUG("\tselected: "); LOG_ENABLED_DEBUG() route_dump(log_get_stream(pMainLog), (SRoute *) pRoutes->data[0]); LOG_DEBUG("\n"); // Carry aggregated route ? if (((SRoute *) pRoutes->data[0])->pAggrRoute != NULL) { LOG_DEBUG("\taggregated: "); LOG_ENABLED_DEBUG() route_dump(log_get_stream(pMainLog), ((SRoute *) pRoutes->data[0])->pAggrRoute); LOG_DEBUG("\n"); } // If best route is iBGP or aggregate contains an iBGP route, then // find the best eBGP route (and aggregate: optional) if (qos_route_is_ibgp(pRouter, (SRoute *) pRoutes->data[0])) { // Keep eBGP routes with highest degree of preference if (ptr_array_length(pEBGPRoutes) > 1) as_decision_process_dop(pRouter, pEBGPRoutes); // Tie-break for eBGP routes if (ptr_array_length(pEBGPRoutes) > 1) qos_decision_process_delay(pRouter, pEBGPRoutes, BGP_OPTIONS_QOS_AGGR_LIMIT); assert(ptr_array_length(pRoutes) <= 1); if (ptr_array_length(pEBGPRoutes) == 1) ((SRoute *) pRoutes->data[0])->pEBGPRoute= (SRoute *) pEBGPRoutes->data[0]; } route_copy_count++; pRoute= route_copy((SRoute *) pRoutes->data[0]); route_flag_set(pRoute, ROUTE_FLAG_BEST, 1); LOG_DEBUG("\tnew best: "); LOG_ENABLED_DEBUG() route_dump(log_get_stream(pMainLog), pRoute); LOG_DEBUG("\n"); // New/updated route // => install in Loc-RIB // => advertise to peers if ((pOldRoute == NULL) || !route_equals(pOldRoute, pRoute)) { if (pOldRoute != NULL) route_flag_set(pOldRoute, ROUTE_FLAG_BEST, 0); assert(rib_add_route(pRouter->pLocRIB, pRoute) == 0); qos_decision_process_disseminate(pRouter, sPrefix, pRoute); } else { route_destroy(&pRoute); pRoute= pOldRoute; } } else if (ptr_array_length(pRoutes) == 0) { LOG_DEBUG("no best\n"); // If a route towards this prefix was previously installed, then // withdraw it. Otherwise, do nothing... if (pOldRoute != NULL) { //LOG_DEBUG("there was a previous best-route\n"); rib_remove_route(pRouter->pLocRIB, sPrefix); //LOG_DEBUG("previous best-route removed\n"); route_flag_set(pOldRoute, ROUTE_FLAG_BEST, 0); // Withdraw should ideally only be sent to peers that already // have received this route. Since we do not maintain // Adj-RIB-Outs, the 'withdraw' message is sent to all peers... qos_decision_process_disseminate(pRouter, sPrefix, NULL); } } // *** unlock all Adj-RIB-Ins *** routes_list_destroy(&pRoutes); routes_list_destroy(&pEBGPRoutes); AS_LOG_DEBUG(pRouter, " < qos_decision_process.end\n"); #endif return 0; }