Example #1
0
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);
}
Example #2
0
/* 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);
}
Example #4
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;
}
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);
}
Example #6
0
static void _add_object(OBJECT obj, struct marshal_state *ms) {
  ptr_array_append(ms->objects, (xpointer)obj);
}
Example #7
0
/**
 * 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;
}