/* 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; }