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); }
/* assumes static lock is held */ static inline bool quark_init_if_needed() { if (quark_string_hash == NULL) { quark_string_hash = create_hashtable(31, string_hash, string_eq); quark_string_index = ptr_array_new(10); ptr_array_append(quark_string_index, NULL); return true; } return false; }
void str_grid_cell_filler_insert(str_grid_cell_filler_t* cell_filler, int i, int j, int k, str_grid_patch_filler_t* patch_filler) { int index = patch_index(cell_filler, i, j, k); ASSERT(str_grid_has_patch(cell_filler->grid, i, j, k)); ptr_array_t** fillers_p = (ptr_array_t**)int_ptr_unordered_map_get(cell_filler->patch_fillers, index); ptr_array_t* fillers; if (fillers_p != NULL) fillers = *fillers_p; else { fillers = ptr_array_new(); int_ptr_unordered_map_insert_with_v_dtor(cell_filler->patch_fillers, index, fillers, DTOR(ptr_array_free)); } ptr_array_append(fillers, patch_filler); }
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; }
void create_boundary_generators(ptr_array_t* surface_points, ptr_array_t* surface_normals, ptr_array_t* surface_tags, point_t** boundary_generators, int* num_boundary_generators, char*** tag_names, int_array_t*** tags, int* num_tags) { ASSERT(surface_points->size >= 4); // surface must be closed! ASSERT(surface_points->size == surface_normals->size); ASSERT(surface_points->size == surface_tags->size); int num_surface_points = surface_points->size; // Compute the minimum distance from each surface point to its neighbors. real_t* h_min = polymec_malloc(sizeof(real_t) * num_surface_points); { // Dump the surface points into a kd-tree. point_t* surf_points = polymec_malloc(sizeof(point_t) * num_surface_points); for (int i = 0; i < num_surface_points; ++i) surf_points[i] = *((point_t*)surface_points->data[i]); kd_tree_t* tree = kd_tree_new(surf_points, num_surface_points); int neighbors[2]; for (int i = 0; i < num_surface_points; ++i) { // Find the "nearest 2" points to the ith surface point--the first is // the point itself, and the second is its nearest neighbor. // FIXME: Serious memory error within here. We work around it for // FIXME: the moment by freshing the tree pointer, which is // FIXME: corrupted. ICK! kd_tree_t* tree_p = tree; kd_tree_nearest_n(tree, &surf_points[i], 2, neighbors); tree = tree_p; ASSERT(neighbors[0] == i); ASSERT(neighbors[1] >= 0); ASSERT(neighbors[1] < num_surface_points); h_min[i] = point_distance(&surf_points[i], &surf_points[neighbors[1]]); } // Clean up. kd_tree_free(tree); polymec_free(surf_points); } // Generate boundary points for each surface point based on how many // surfaces it belongs to. ptr_array_t* boundary_points = ptr_array_new(); string_int_unordered_map_t* tag_indices = string_int_unordered_map_new(); ptr_array_t* boundary_tags = ptr_array_new(); for (int i = 0; i < num_surface_points; ++i) { // Add any tags from this point to the set of existing boundary tags. string_slist_t* tags = surface_tags->data[i]; for (string_slist_node_t* t_iter = tags->front; t_iter != NULL; t_iter = t_iter->next) string_int_unordered_map_insert(tag_indices, t_iter->value, tag_indices->size); // Retrieve the surface point. point_t* x_surf = surface_points->data[i]; // Retrieve the list of normal vectors for this surface point. ptr_slist_t* normal_list = surface_normals->data[i]; int num_normals = normal_list->size; vector_t normals[num_normals]; int n_offset = 0; for (ptr_slist_node_t* n_iter = normal_list->front; n_iter != NULL; n_iter = n_iter->next) normals[n_offset++] = *((vector_t*)n_iter->value); // For now, let's keep things relatively simple. if (num_normals > 2) { polymec_error("create_boundary_generators: Too many normal vectors (%d) for surface point %d at (%g, %g, %g)", num_normals, i, x_surf->x, x_surf->y, x_surf->z); } // Create boundary points based on this list of normals. if (num_normals == 1) { // This point only belongs to one surface, so we create boundary points // on either side of it. point_t* x_out = polymec_malloc(sizeof(point_t)); x_out->x = x_surf->x + h_min[i]*normals[0].x; x_out->y = x_surf->y + h_min[i]*normals[0].y; x_out->z = x_surf->z + h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x_out, polymec_free); point_t* x_in = polymec_malloc(sizeof(point_t)); x_in->x = x_surf->x - h_min[i]*normals[0].x; x_in->y = x_surf->y - h_min[i]*normals[0].y; x_in->z = x_surf->z - h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x_in, polymec_free); } else if (num_normals == 2) { // This point appears at the interface between two surfaces. // (Or so it seems.) ASSERT(vector_dot(&normals[0], &normals[1]) < 0.0); point_t* x1 = polymec_malloc(sizeof(point_t)); x1->x = x_surf->x + h_min[i]*normals[0].x; x1->y = x_surf->y + h_min[i]*normals[0].y; x1->z = x_surf->z + h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x1, polymec_free); point_t* x2 = polymec_malloc(sizeof(point_t)); x2->x = x_surf->x - h_min[i]*normals[1].x; x2->y = x_surf->y - h_min[i]*normals[1].y; x2->z = x_surf->z - h_min[i]*normals[1].z; ptr_array_append_with_dtor(boundary_points, x2, polymec_free); } // Tag the boundary point appropriately. ptr_array_append(boundary_tags, tags); // Borrowed ref to tags. } // Move the surface points into a contiguous array. *boundary_generators = polymec_malloc(sizeof(point_t) * boundary_points->size); *num_boundary_generators = boundary_points->size; for (int i = 0; i < boundary_points->size; ++i) { (*boundary_generators)[i] = *((point_t*)boundary_points->data[i]); } // Transcribe the tags. *tag_names = polymec_malloc(sizeof(char*) * tag_indices->size); *tags = polymec_malloc(sizeof(int_array_t*) * tag_indices->size); *num_tags = tag_indices->size; char* tag_name; int pos = 0, tag_index; while (string_int_unordered_map_next(tag_indices, &pos, &tag_name, &tag_index)) { (*tag_names)[tag_index] = string_dup(tag_name); (*tags)[tag_index] = int_array_new(); for (int j = 0; j < *num_boundary_generators; ++j) int_array_append((*tags)[tag_index], tag_index); } // Clean up. string_int_unordered_map_free(tag_indices); polymec_free(h_min); }
static void _add_object(OBJECT obj, struct marshal_state *ms) { ptr_array_append(ms->objects, (xpointer)obj); }
/** * 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; }