Ejemplo n.º 1
0
void
ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
{
  struct ospf6_as_external_lsa *external;
  struct prefix asbr_id;
  struct ospf6_route *asbr_entry, *route;
  char buf[64];
  int i;

  external = (struct ospf6_as_external_lsa *)
    OSPF6_LSA_HEADER_END (lsa->header);

  if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
    zlog_debug ("Calculate AS-External route for %s", lsa->name);

  if (lsa->header->adv_router == ospf6->router_id)
    {
      /*if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
        zlog_debug ("Ignore self-originated AS-External-LSA");*/
      return;
    }

  if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
    {
      if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
        zlog_debug ("Ignore LSA with LSInfinity Metric");
      return;
    }

  ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
  asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
  if (asbr_entry == NULL ||
      ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
    {
      if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
        {
          prefix2str (&asbr_id, buf, sizeof (buf));
          zlog_debug ("ASBR entry not found: %s", buf);
        }
      return;
    }

  route = ospf6_route_create ();
  route->type = OSPF6_DEST_TYPE_NETWORK;
  route->prefix.family = AF_INET6;
  route->prefix.prefixlen = external->prefix.prefix_length;
  ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);

  route->path.area_id = asbr_entry->path.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;

  route->path.prefix_options = external->prefix.prefix_options;
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
    {
      route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
      route->path.metric_type = 2;
      route->path.cost = asbr_entry->path.cost;
      route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
    }
  else
    {
      route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
      route->path.metric_type = 1;
      route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
      route->path.cost_e2 = 0;
    }

  for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
    ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);

  if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
    {
      prefix2str (&route->prefix, buf, sizeof (buf));
      zlog_debug ("AS-External route add: %s", buf);
    }

  ospf6_route_add (route, ospf6->route_table);
}
void
ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa)
{
  struct ospf6_lsa_as_external *external;
  struct prefix_ls asbr_id;
  struct ospf6_route_req asbr_entry;
  struct ospf6_route_req request;

  external = OSPF6_LSA_HEADER_END (lsa->header);

  if (IS_LSA_MAXAGE (lsa))
    return;

  if (IS_OSPF6_DUMP_ASBR)
    zlog_info ("ASBR: Calculate %s", lsa->str);

  if (lsa->header->adv_router == ospf6->router_id)
    {
      if (IS_OSPF6_DUMP_ASBR)
        zlog_info ("ASBR:   Self-originated, ignore");
      return;
    }

  if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
    {
      if (IS_OSPF6_DUMP_ASBR)
        zlog_info ("ASBR:   Metric is Infinity, ignore");
      return;
    }

  memset (&asbr_id, 0, sizeof (asbr_id));
  asbr_id.family = AF_UNSPEC;
  asbr_id.prefixlen = 64; /* xxx */
  asbr_id.adv_router.s_addr = lsa->header->adv_router;

  ospf6_route_lookup (&asbr_entry, (struct prefix *) &asbr_id,
                      ospf6->topology_table);

  if (ospf6_route_end (&asbr_entry))
    {
      if (IS_OSPF6_DUMP_ASBR)
        {
          char buf[64];
          inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf));
          zlog_info ("ASBR:   ASBR %s not found, ignore", buf);
        }
      return;
    }

  memset (&request, 0, sizeof (request));
  request.route.type = OSPF6_DEST_TYPE_NETWORK;
  request.route.prefix.family = AF_INET6;
  request.route.prefix.prefixlen = external->prefix.prefix_length;
  memcpy (&request.route.prefix.u.prefix6, (char *)(external + 1),
          OSPF6_PREFIX_SPACE (request.route.prefix.prefixlen));

  request.path.area_id = asbr_entry.path.area_id;
  request.path.origin.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
  request.path.origin.id = lsa->header->id;
  request.path.origin.adv_router = lsa->header->adv_router;
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
    {
      request.path.type = OSPF6_PATH_TYPE_EXTERNAL2;
      request.path.metric_type = 2;
      request.path.cost = asbr_entry.path.cost;
      request.path.cost_e2 = OSPF6_ASBR_METRIC (external);
    }
  else
    {
      request.path.type = OSPF6_PATH_TYPE_EXTERNAL1;
      request.path.metric_type = 1;
      request.path.cost = asbr_entry.path.cost
                          + OSPF6_ASBR_METRIC (external);
      request.path.cost_e2 = 0;
    }
  request.path.prefix_options = external->prefix.prefix_options;

  while (((struct prefix_ls *)&asbr_entry.route.prefix)->adv_router.s_addr ==
         asbr_id.adv_router.s_addr &&
         asbr_entry.route.type == OSPF6_DEST_TYPE_ROUTER)
    {
      memcpy (&request.nexthop, &asbr_entry.nexthop,
              sizeof (struct ospf6_nexthop));
      ospf6_route_add (&request, ospf6->route_table);
      ospf6_route_next (&asbr_entry);
    }
}