Beispiel #1
0
void
ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
{
  struct ospf6_lsa *lsa;
  u_int16_t type;
  u_int32_t router;

  if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST))
    {
      char buf[16];
      inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix),
                 buf, sizeof (buf));
       zlog_info ("ignore non-best path: lsentry %s add", buf);
      return;
    }

  type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
  router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
  for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa;
       lsa = ospf6_lsdb_type_router_next (type, router, lsa))
    {
      if (! OSPF6_LSA_IS_MAXAGE (lsa))
        ospf6_asbr_lsa_add (lsa);
    }
}
/* RFC 2328 16.2. Calculating the inter-area routes */
void
ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
{
  struct prefix prefix, abr_prefix;
  struct ospf6_route_table *table = NULL;
  struct ospf6_route *range, *route, *old = NULL;
  struct ospf6_route *abr_entry;
  u_char type = 0;
  char options[3] = {0, 0, 0};
  u_int8_t prefix_options = 0;
  u_int32_t cost = 0;
  u_char router_bits = 0;
  int i;
  char buf[64];
  int is_debug = 0;
  struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
  struct ospf6_inter_router_lsa *router_lsa = NULL;

  memset (&prefix, 0, sizeof (prefix));

  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
    {
      if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
        {
          is_debug++;
          zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        }

      prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        OSPF6_LSA_HEADER_END (lsa->header);
      prefix.family = AF_INET6;
      prefix.prefixlen = prefix_lsa->prefix.prefix_length;
      ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
      if (is_debug)
        prefix2str (&prefix, buf, sizeof (buf));
      table = oa->ospf6->route_table;
      type = OSPF6_DEST_TYPE_NETWORK;
      prefix_options = prefix_lsa->prefix.prefix_options;
      cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
    }
  else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
    {
      if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
        {
          is_debug++;
          zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        }

      router_lsa = (struct ospf6_inter_router_lsa *)
        OSPF6_LSA_HEADER_END (lsa->header);
      ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
      if (is_debug)
        inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
      table = oa->ospf6->brouter_table;
      type = OSPF6_DEST_TYPE_ROUTER;
      options[0] = router_lsa->options[0];
      options[1] = router_lsa->options[1];
      options[2] = router_lsa->options[2];
      cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
      SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
    }
  else
    assert (0);

  /* Find existing route */
  route = ospf6_route_lookup (&prefix, table);
  if (route)
    ospf6_route_lock (route);
  while (route && ospf6_route_is_prefix (&prefix, route))
    {
      if (route->path.area_id == oa->area_id &&
          route->path.origin.type == lsa->header->type &&
          route->path.origin.id == lsa->header->id &&
          route->path.origin.adv_router == lsa->header->adv_router &&
          ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED))
        old = route;
      route = ospf6_route_next (route);
    }

  /* (1) if cost == LSInfinity or if the LSA is MaxAge */
  if (cost == OSPF_LS_INFINITY)
    {
      if (is_debug)
        zlog_debug ("cost is LS_INFINITY, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }
  if (OSPF6_LSA_IS_MAXAGE (lsa))
    {
      if (is_debug)
        zlog_debug ("LSA is MaxAge, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* (2) if the LSA is self-originated, ignore */
  if (lsa->header->adv_router == oa->ospf6->router_id)
    {
      if (is_debug)
        zlog_debug ("LSA is self-originated, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* (3) if the prefix is equal to an active configured address range */
  /*     or if the NU bit is set in the prefix */
  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
    {
      range = ospf6_route_lookup (&prefix, oa->range_table);
      if (range)
        {
          if (is_debug)
            zlog_debug ("Prefix is equal to address range, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
        }

      if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
		      OSPF6_PREFIX_OPTION_NU) ||
	  CHECK_FLAG (prefix_lsa->prefix.prefix_options,
		      OSPF6_PREFIX_OPTION_LA))
	{
          if (is_debug)
            zlog_debug ("Prefix has NU/LA bit set, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
	}
    }

  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
    {
      /* To pass test suites */
      if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
	  ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
	{
          if (is_debug)
            zlog_debug ("Prefix has NU/LA bit set, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
	}
    }

  /* (4) if the routing table entry for the ABR does not exist */
  ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
  abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
  if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
      CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
      ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
    {
      if (is_debug)
        zlog_debug ("ABR router entry does not exist, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* Check import list */
  if (IMPORT_NAME (oa))
    {
      if (IMPORT_LIST (oa) == NULL)
        IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa));

      if (IMPORT_LIST (oa))
        if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY)
          {
            if (is_debug)
              zlog_debug ("Prefix was denied by import-list");
            if (old)
              ospf6_route_remove (old, table);
            return;
          }
    }

  /* Check input prefix-list */
  if (PREFIX_NAME_IN (oa))
    {
      if (PREFIX_LIST_IN (oa) == NULL)
        PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa));

      if (PREFIX_LIST_IN (oa))
        if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT)
          {
            if (is_debug)
              zlog_debug ("Prefix was denied by prefix-list");
            if (old)
              ospf6_route_remove (old, table);
            return;
          }
    }

  /* (5),(6),(7) the path preference is handled by the sorting
     in the routing table. Always install the path by substituting
     old route (if any). */
  if (old)
    route = ospf6_route_copy (old);
  else
    route = ospf6_route_create ();

  route->type = type;
  route->prefix = prefix;
  route->path.origin.type = lsa->header->type;
  route->path.origin.id = lsa->header->id;
  route->path.origin.adv_router = lsa->header->adv_router;
  route->path.router_bits = router_bits;
  route->path.options[0] = options[0];
  route->path.options[1] = options[1];
  route->path.options[2] = options[2];
  route->path.prefix_options = prefix_options;
  route->path.area_id = oa->area_id;
  route->path.type = OSPF6_PATH_TYPE_INTER;
  route->path.cost = abr_entry->path.cost + cost;
  for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
    route->nexthop[i] = abr_entry->nexthop[i];

  if (is_debug)
    zlog_debug ("Install route: %s", buf);
  ospf6_route_add (route, table);
}
Beispiel #3
0
int negotiation_done(struct thread * thread)
{
  struct ospf6_neighbor * on;
  struct ospf6_lsa * lsa;

  on = (struct ospf6_neighbor *) THREAD_ARG(thread);
  assert(on);

  if(on->state != OSPF6_NEIGHBOR_EXSTART)
    return 0;

  if(IS_OSPF6_SIBLING_DEBUG_NEIGHBOR)
    zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name);

  /* clear ls-list */
  ospf6_lsdb_remove_all(on->summary_list);
  ospf6_lsdb_remove_all(on->request_list);

  for(lsa = ospf6_lsdb_head(on->retrans_list); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    ospf6_decrement_retrans_count(lsa);
    ospf6_lsdb_remove(lsa, on->retrans_list);
  }

  /* Interface scoped LSAs */
  for(lsa = ospf6_lsdb_head(on->ospf6_if->lsdb); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    if (OSPF6_LSA_IS_MAXAGE (lsa))
    {
      ospf6_increment_retrans_count(lsa);
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
    }
    else
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
  }

  /* Area scoped LSAs - no area implemented yet */
//  LIST_FOR_EACH(lsa, struct ospf6_lsa, node, on-> )
//  {

//  }

  /* AS scoped LSAs */
  for(lsa = ospf6_lsdb_head(ospf6->lsdb); lsa;
      lsa = ospf6_lsdb_next(lsa))
  {
    if(OSPF6_LSA_IS_MAXAGE(lsa))
    {
      ospf6_increment_retrans_count(lsa);
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
    }
    else
      ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list);
  }
 

  UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT);
  ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on);

  return 0;
}
Beispiel #4
0
void
ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
{
  struct prefix_ipv6 key;
  struct route_node *current, *nextnode, *prevnode;
  struct ospf6_lsa *next, *prev, *old = NULL;

  memset (&key, 0, sizeof (key));
  ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
  ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
                      sizeof (lsa->header->adv_router));
  ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));

  current = route_node_get (lsdb->table, (struct prefix *) &key);
  old = current->info;
  current->info = lsa;
  ospf6_lsa_lock (lsa);

  if (old)
    {
      if (old->prev)
        old->prev->next = lsa;
      if (old->next)
        old->next->prev = lsa;
      lsa->next = old->next;
      lsa->prev = old->prev;
    }
  else
    {
      /* next link */
      nextnode = current;
      route_lock_node (nextnode);
      do {
        nextnode = route_next (nextnode);
      } while (nextnode && nextnode->info == NULL);
      if (nextnode == NULL)
        lsa->next = NULL;
      else
        {
          next = nextnode->info;
          lsa->next = next;
          next->prev = lsa;
          route_unlock_node (nextnode);
        }

      /* prev link */
      prevnode = current;
      route_lock_node (prevnode);
      do {
        prevnode = route_prev (prevnode);
      } while (prevnode && prevnode->info == NULL);
      if (prevnode == NULL)
        lsa->prev = NULL;
      else
        {
          prev = prevnode->info;
          lsa->prev = prev;
          prev->next = lsa;
          route_unlock_node (prevnode);
        }

      lsdb->count++;
    }

  if (old)
    {
      if (OSPF6_LSA_IS_CHANGED (old, lsa))
        {
          if (OSPF6_LSA_IS_MAXAGE (lsa))
            {
              if (lsdb->hook_remove)
                {
                  (*lsdb->hook_remove) (old);
                  (*lsdb->hook_remove) (lsa);
                }
            }
          else if (OSPF6_LSA_IS_MAXAGE (old))
            {
              if (lsdb->hook_add)
                (*lsdb->hook_add) (lsa);
            }
          else
            {
              if (lsdb->hook_remove)
                (*lsdb->hook_remove) (old);
              if (lsdb->hook_add)
                (*lsdb->hook_add) (lsa);
            }
        }
    }
  else if (OSPF6_LSA_IS_MAXAGE (lsa))
    {
      if (lsdb->hook_remove)
        (*lsdb->hook_remove) (lsa);
    }
  else
    {
      if (lsdb->hook_add)
        (*lsdb->hook_add) (lsa);
    }

  if (old)
    ospf6_lsa_unlock (old);

  ospf6_lsdb_count_assert (lsdb);
}