Пример #1
0
/* AS External LSA origination */
static void
ospf6_as_external_lsa_originate (struct ospf6_route *route)
{
  char buffer[OSPF6_MAX_LSASIZE];
  struct ospf6_lsa_header *lsa_header;
  struct ospf6_lsa *old, *lsa;
  struct ospf6_external_info *info = route->route_option;

  struct ospf6_as_external_lsa *as_external_lsa;
  char buf[64];
  caddr_t p;
  /*restarter 不产生 lsa*/
  if(ospf6->restart)
  {
    return ;
  }

  /* find previous LSA */
  old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
                           route->path.origin.id, ospf6->router_id,
                           ospf6->lsdb);

  if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
    {
      prefix2str (&route->prefix, buf, sizeof (buf));
      zlog_debug ("Originate AS-External-LSA for %s", buf);
    }

  /* prepare buffer */
  memset (buffer, 0, sizeof (buffer));
  lsa_header = (struct ospf6_lsa_header *) buffer;
  as_external_lsa = (struct ospf6_as_external_lsa *)
    ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
  p = (caddr_t)
    ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));

  /* Fill AS-External-LSA */
  /* Metric type */
  if (route->path.metric_type == 2)
    SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
  else
    UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);

  /* forwarding address */
  if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
    SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
  else
    UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);

  /* external route tag */
  UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);

  /* Set metric */
  OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);

  /* prefixlen */
  as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;

  /* PrefixOptions */
  as_external_lsa->prefix.prefix_options = route->path.prefix_options;

  /* don't use refer LS-type */
  as_external_lsa->prefix.prefix_refer_lstype = htons (0);

  /* set Prefix */
  memcpy (p, &route->prefix.u.prefix6,
          OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
  ospf6_prefix_apply_mask (&as_external_lsa->prefix);
  p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);

  /* Forwarding address */
  if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
    {
      memcpy (p, &info->forwarding, sizeof (struct in6_addr));
      p += sizeof (struct in6_addr);
    }

  /* External Route Tag */
  if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
    {
      /* xxx */
    }

  /* Fill LSA Header */
  lsa_header->age = 0;
  lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
  lsa_header->id = route->path.origin.id;
  lsa_header->adv_router = ospf6->router_id;
  lsa_header->seqnum =
    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
                         lsa_header->adv_router, ospf6->lsdb);
  lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);

  /* LSA checksum */
  ospf6_lsa_checksum (lsa_header);

  /* create LSA */
  lsa = ospf6_lsa_create (lsa_header);

  /* Originate */
  ospf6_lsa_originate_process (lsa, ospf6);
}
void
ospf6_asbr_external_lsa_update (struct ospf6_route_req *request)
{
  char buffer [MAXLSASIZE];
  u_int16_t size;
  struct ospf6_lsa_as_external *external;
  char *p;
  struct ospf6_route_req route;
  char pbuf[BUFSIZ];

  /* assert this is best path; if not, return */
  ospf6_route_lookup (&route, &request->route.prefix, request->table);
  if (memcmp (&route.path, &request->path, sizeof (route.path)))
    return;

  if (IS_OSPF6_DUMP_LSA)
    zlog_info ("Update AS-External: ID: %lu",
               (u_long) ntohl (request->path.origin.id));

  /* prepare buffer */
  memset (buffer, 0, sizeof (buffer));
  size = sizeof (struct ospf6_lsa_as_external);
  external = (struct ospf6_lsa_as_external *) buffer;
  p = (char *) (external + 1);

  if (route.path.metric_type == 2)
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E);   /* type2 */
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */

  /* forwarding address */
  if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address))
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);

  /* external route tag */
  UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T);

  /* set metric. note: related to E bit */
  OSPF6_ASBR_METRIC_SET (external, route.path.cost);

  /* prefixlen */
  external->prefix.prefix_length = route.route.prefix.prefixlen;

  /* PrefixOptions */
  external->prefix.prefix_options = route.path.prefix_options;

  /* don't use refer LS-type */
  external->prefix.prefix_refer_lstype = htons (0);

  if (IS_OSPF6_DUMP_LSA)
    {
      prefix2str (&route.route.prefix, pbuf, sizeof (pbuf));
      zlog_info ("  Prefix: %s", pbuf);
    }

  /* set Prefix */
  memcpy (p, &route.route.prefix.u.prefix6,
          OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen));
  ospf6_prefix_apply_mask (&external->prefix);
  size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);
  p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);

  /* Forwarding address */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
    {
      memcpy (p, &route.nexthop.address, sizeof (struct in6_addr));
      size += sizeof (struct in6_addr);
      p += sizeof (struct in6_addr);
    }

  /* External Route Tag */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
    {
      /* xxx */
    }

  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
                       route.path.origin.id, ospf6->router_id,
                       (char *) external, size, ospf6);
  return;
}