Example #1
0
static char *
ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
                       caddr_t lsdesc, struct ospf6_vertex *v) 
{
  caddr_t backlink, found = NULL;
  int size;

  size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?
          sizeof (struct ospf6_router_lsdesc) :
          sizeof (struct ospf6_network_lsdesc));
  for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;
       backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)
  {   
    assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
               VERTEX_IS_TYPE (NETWORK, v)));

    if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
        NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
        == v->lsa->header->adv_router)
      found = backlink;
    else if (VERTEX_IS_TYPE (NETWORK, v) &&
             ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&
             ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)
             == v->lsa->header->adv_router &&
             ROUTER_LSDESC_GET_NBR_IFID (backlink)
             == ntohl (v->lsa->header->id))
      found = backlink;
    else
    {   
      if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
          ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
        continue;
      if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=
          ROUTER_LSDESC_GET_IFID (lsdesc) ||
          ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=
          ROUTER_LSDESC_GET_IFID (backlink))
        continue;
      if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=
          v->lsa->header->adv_router ||
          ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=
          lsa->header->adv_router)
        continue;
      found = backlink;
    }   
  }   

  if (IS_OSPF6_SIBLING_DEBUG_SPF)
    zlog_debug ("  Backlink %s", (found ? "OK" : "FAIL"));

  return found;
}
Example #2
0
/* RFC2740 3.8.1.  Calculating the shortest path tree for an area */
void
ospf6_spf_calculation (u_int32_t router_id,
                       struct ospf6_route_table *result_table,
                       struct ospf6_area *oa)
{
  struct pqueue *candidate_list;
  struct ospf6_vertex *root, *v, *w;
  int i;
  int size;
  caddr_t lsdesc;
  struct ospf6_lsa *lsa;

  ospf6_spf_table_finish (result_table);

  /* Install the calculating router itself as the root of the SPF tree */
  /* construct root vertex */
  lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
                           router_id, oa->lsdb);
  if (lsa == NULL)
    return;

  /* initialize */
  candidate_list = pqueue_create ();
  candidate_list->cmp = ospf6_vertex_cmp;

  root = ospf6_vertex_create (lsa);
  root->area = oa;
  root->cost = 0;
  root->hops = 0;
  root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */
  inet_pton (AF_INET6, "::1", &root->nexthop[0].address);

  /* Actually insert root to the candidate-list as the only candidate */
  pqueue_enqueue (root, candidate_list);

  /* Iterate until candidate-list becomes empty */
  while (candidate_list->size)
    {
      /* get closest candidate from priority queue */
      v = pqueue_dequeue (candidate_list);

      /* installing may result in merging or rejecting of the vertex */
      if (ospf6_spf_install (v, result_table) < 0)
        continue;

      /* Skip overloaded routers */
      if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
	   ospf6_router_is_stub_router (v->lsa)))
	continue;

      /* For each LS description in the just-added vertex V's LSA */
      size = (VERTEX_IS_TYPE (ROUTER, v) ?
              sizeof (struct ospf6_router_lsdesc) :
              sizeof (struct ospf6_network_lsdesc));
      for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
           lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
        {
          lsa = ospf6_lsdesc_lsa (lsdesc, v);
          if (lsa == NULL)
            continue;

          if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
            continue;

          w = ospf6_vertex_create (lsa);
          w->area = oa;
          w->parent = v;
          if (VERTEX_IS_TYPE (ROUTER, v))
            {
              w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
              w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
            }
          else /* NETWORK */
            {
              w->cost = v->cost;
              w->hops = v->hops + 1;
            }

          /* nexthop calculation */
          if (w->hops == 0)
            w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
          else if (w->hops == 1 && v->hops == 0)
            ospf6_nexthop_calc (w, v, lsdesc);
          else
            {
              for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
                   i < OSPF6_MULTI_PATH_LIMIT; i++)
                ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
            }

          /* add new candidate to the candidate_list */
          if (IS_OSPF6_DEBUG_SPF (PROCESS))
            zlog_debug ("  New candidate: %s hops %d cost %d",
			w->name, w->hops, w->cost);
          pqueue_enqueue (w, candidate_list);
        }
    }

  pqueue_delete (candidate_list);

  oa->spf_calculation++;
}