Exemplo n.º 1
0
void
ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
                             u_int nexthop_num, struct in6_addr *nexthop)
{
  int ret;
  struct ospf6_route troute;
  struct ospf6_external_info tinfo;
  struct ospf6_route *route, *match;
  struct ospf6_external_info *info;
  struct prefix prefix_id;
  struct route_node *node;
  char pbuf[64], ibuf[16];
  struct listnode *lnode, *lnnode;
  struct ospf6_area *oa;

  if (! ospf6_zebra_is_redistribute (type))
    return;

  if (IS_OSPF6_DEBUG_ASBR)
    {
      prefix2str (prefix, pbuf, sizeof (pbuf));
      zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
    }

  /* if route-map was specified but not found, do not advertise */
  if (ospf6->rmap[type].name)
    {
      if (ospf6->rmap[type].map == NULL)
        ospf6_asbr_routemap_update (NULL);
      if (ospf6->rmap[type].map == NULL)
        {
          zlog_warn ("route-map \"%s\" not found, suppress redistributing",
                     ospf6->rmap[type].name);
          return;
        }
    }

  /* apply route-map */
  if (ospf6->rmap[type].map)
    {
      memset (&troute, 0, sizeof (troute));
      memset (&tinfo, 0, sizeof (tinfo));
      troute.route_option = &tinfo;

      ret = route_map_apply (ospf6->rmap[type].map, prefix,
                             RMAP_OSPF6, &troute);
      if (ret == RMAP_DENYMATCH)
        {
          if (IS_OSPF6_DEBUG_ASBR)
            zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
          return;
        }
    }

  match = ospf6_route_lookup (prefix, ospf6->external_table);
  if (match)
    {
      info = match->route_option;

      /* copy result of route-map */
      if (ospf6->rmap[type].map)
        {
          if (troute.path.metric_type)
            match->path.metric_type = troute.path.metric_type;
          if (troute.path.cost)
            match->path.cost = troute.path.cost;
          if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
            memcpy (&info->forwarding, &tinfo.forwarding,
                    sizeof (struct in6_addr));
        }

      info->type = type;
      match->nexthop[0].ifindex = ifindex;
      if (nexthop_num && nexthop)
        memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));

      /* create/update binding in external_id_table */
      prefix_id.family = AF_INET;
      prefix_id.prefixlen = 32;
      prefix_id.u.prefix4.s_addr = htonl (info->id);
      node = route_node_get (ospf6->external_id_table, &prefix_id);
      node->info = match;

      if (IS_OSPF6_DEBUG_ASBR)
        {
          inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
          zlog_debug ("Advertise as AS-External Id:%s", ibuf);
        }

      match->path.origin.id = htonl (info->id);
      ospf6_as_external_lsa_originate (match);
      return;
    }

  /* create new entry */
  route = ospf6_route_create ();
  route->type = OSPF6_DEST_TYPE_NETWORK;
  memcpy (&route->prefix, prefix, sizeof (struct prefix));

  info = (struct ospf6_external_info *)
    XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
  route->route_option = info;
  info->id = ospf6->external_id++;

  /* copy result of route-map */
  if (ospf6->rmap[type].map)
    {
      if (troute.path.metric_type)
        route->path.metric_type = troute.path.metric_type;
      if (troute.path.cost)
        route->path.cost = troute.path.cost;
      if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
        memcpy (&info->forwarding, &tinfo.forwarding,
                sizeof (struct in6_addr));
    }

  info->type = type;
  route->nexthop[0].ifindex = ifindex;
  if (nexthop_num && nexthop)
    memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));

  /* create/update binding in external_id_table */
  prefix_id.family = AF_INET;
  prefix_id.prefixlen = 32;
  prefix_id.u.prefix4.s_addr = htonl (info->id);
  node = route_node_get (ospf6->external_id_table, &prefix_id);
  node->info = route;

  route = ospf6_route_add (route, ospf6->external_table);
  route->route_option = info;

  if (IS_OSPF6_DEBUG_ASBR)
    {
      inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
      zlog_debug ("Advertise as AS-External Id:%s", ibuf);
    }

  route->path.origin.id = htonl (info->id);
  ospf6_as_external_lsa_originate (route);

  /* Router-Bit (ASBR Flag) may have to be updated */
  for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
    OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
static int
ospf6_spf_install (struct ospf6_vertex *v,
                       struct ospf6_route_table *result_table, 
                       unsigned int hostnum)
{
  struct ospf6_route *route;
  int i, j;
  struct ospf6_vertex *prev, *w;
  struct listnode *node, *nnode;

  if(IS_OSPF6_SIBLING_DEBUG_SPF)
    zlog_debug ("SPF install %s hops %d cost %d",
                v->name, v->hops, v->cost);

  route = ospf6_route_lookup (&v->vertex_id, result_table);
  if (route && route->path.cost < v->cost)
  {
    if (IS_OSPF6_SIBLING_DEBUG_SPF)
      zlog_debug ("  already installed with lower cost (%d), ignore",
                  route->path.cost);
    ospf6_vertex_delete (v);
    return -1;
  }
  else if (route && route->path.cost == v->cost)
  {
    if (IS_OSPF6_SIBLING_DEBUG_SPF)
      zlog_debug ("  another path found, merge");

    for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
         i < OSPF6_MULTI_PATH_LIMIT; i++)
    {
      for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)
      {
        if (ospf6_nexthop_is_set (&route->nexthop[j]))
        {
          if (ospf6_nexthop_is_same (&route->nexthop[j],
                                     &v->nexthop[i]))
            break;
          else
            continue;
        }
        ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);
        break;
      }
    }

    prev = (struct ospf6_vertex *) route->route_option;
    assert (prev->hops <= v->hops);
    ospf6_vertex_delete (v);

    return -1;
  }

  /* There should be no case where candidate being installed (variable
     "v") is closer than the one in the SPF tree (variable "route").
     In the case something has gone wrong with the behavior of
     Priority-Queue. */

  /* the case where the route exists already is handled and returned
     up to here. */
  assert (route == NULL);

  route = ospf6_route_create ();
  memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
  route->type = OSPF6_DEST_TYPE_LINKSTATE;
  route->path.type = OSPF6_PATH_TYPE_INTRA;
  route->path.origin.type = v->lsa->header->type;
  route->path.origin.id = v->lsa->header->id;
  route->path.origin.adv_router = v->lsa->header->adv_router;
  route->path.metric_type = 1;
  route->path.cost = v->cost;
  route->path.cost_e2 = v->hops;
  route->path.router_bits = v->capability;
  route->path.options[0] = v->options[0];
  route->path.options[1] = v->options[1];
  route->path.options[2] = v->options[2];
  route->hostnum = hostnum; // number corresponding to host, 0 if hostnum is unknown

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

  if (v->parent)
    alt_listnode_add_sort (v->parent->child_list, v);
  route->route_option = v;

  ospf6_route_add (route, result_table);
  return 0;
}
Exemplo n.º 4
0
void
ospf6_interface_connected_route_update (struct interface *ifp)
{
  struct ospf6_interface *oi;
  struct ospf6_route *route;
  struct connected *c;
  struct listnode *node, *nnode;

  oi = (struct ospf6_interface *) ifp->info;
  if (oi == NULL)
    return;

  /* reset linklocal pointer */
  oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp);

  /* if area is null, do not make connected-route list */
  if (oi->area == NULL)
    return;

  /* update "route to advertise" interface route table */
  ospf6_route_remove_all (oi->route_connected);

  for (ALL_LIST_ELEMENTS (oi->interface->connected, node, nnode, c))
    {
      if (c->address->family != AF_INET6)
        continue;

      CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address);
      CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address);
      CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address);
      CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address);
      CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address);

      /* apply filter */
      if (oi->plist_name)
        {
          struct prefix_list *plist;
          enum prefix_list_type ret;
          char buf[128];

          prefix2str (c->address, buf, sizeof (buf));
          plist = prefix_list_lookup (AFI_IP6, oi->plist_name);
          ret = prefix_list_apply (plist, (void *) c->address);
          if (ret == PREFIX_DENY)
            {
              if (IS_OSPF6_DEBUG_INTERFACE)
                zlog_debug ("%s on %s filtered by prefix-list %s ",
			    buf, oi->interface->name, oi->plist_name);
              continue;
            }
        }

      route = ospf6_route_create ();
      memcpy (&route->prefix, c->address, sizeof (struct prefix));
      apply_mask (&route->prefix);
      route->type = OSPF6_DEST_TYPE_NETWORK;
      route->path.area_id = oi->area->area_id;
      route->path.type = OSPF6_PATH_TYPE_INTRA;
      route->path.cost = oi->cost;
      route->nexthop[0].ifindex = oi->interface->ifindex;
      inet_pton (AF_INET6, "::1", &route->nexthop[0].address);
      ospf6_route_add (route, oi->route_connected);
    }

  /* create new Link-LSA */
  OSPF6_LINK_LSA_SCHEDULE (oi);
  OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
  OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
}
Exemplo n.º 5
0
/* 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);
}