void ospf6_abr_disable_area (struct ospf6_area *area) { struct ospf6_area *oa; struct ospf6_route *ro; struct ospf6_lsa *old; struct listnode *node, *nnode; /* Withdraw all summary prefixes previously originated */ for (ro = ospf6_route_head (area->summary_prefix); ro; ro = ospf6_route_next (ro)) { old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, area->ospf6->router_id, area->lsdb); if (old) ospf6_lsa_purge (old); ospf6_route_remove (ro, area->summary_prefix); } /* Withdraw all summary router-routes previously originated */ for (ro = ospf6_route_head (area->summary_router); ro; ro = ospf6_route_next (ro)) { old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, area->ospf6->router_id, area->lsdb); if (old) ospf6_lsa_purge (old); ospf6_route_remove (ro, area->summary_router); } /* Schedule Router-LSA for each area (ABR status may change) */ for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa)) /* update B bit for each area */ OSPF6_ROUTER_LSA_SCHEDULE (oa); }
void ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa) { struct ospf6_as_external_lsa *external; struct prefix prefix; struct ospf6_route *route; char buf[64]; external = (struct ospf6_as_external_lsa *) OSPF6_LSA_HEADER_END (lsa->header); if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) zlog_debug ("Withdraw 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; } memset (&prefix, 0, sizeof (struct prefix)); prefix.family = AF_INET6; prefix.prefixlen = external->prefix.prefix_length; ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix); route = ospf6_route_lookup (&prefix, ospf6->route_table); if (route == NULL) { if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) { prefix2str (&prefix, buf, sizeof (buf)); zlog_debug ("AS-External route %s not found", buf); } return; } for (ospf6_route_lock (route); route && ospf6_route_is_prefix (&prefix, route); route = ospf6_route_next (route)) { if (route->type != OSPF6_DEST_TYPE_NETWORK) continue; if (route->path.origin.type != lsa->header->type) continue; if (route->path.origin.id != lsa->header->id) continue; if (route->path.origin.adv_router != lsa->header->adv_router) continue; if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL)) { prefix2str (&route->prefix, buf, sizeof (buf)); zlog_debug ("AS-External route remove: %s", buf); } ospf6_route_remove (route, ospf6->route_table); } if (route != NULL) ospf6_route_unlock (route); }
static void ospf6_area_route_hook_remove (struct ospf6_route *route) { struct ospf6_route *copy; copy = ospf6_route_lookup_identical (route, ospf6->route_table); if (copy) ospf6_route_remove (copy, ospf6->route_table); }
void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa) { struct ospf6_lsa_as_external *external; struct prefix dest; char buf[64]; struct ospf6_route_req request; if (IS_OSPF6_DUMP_ASBR) zlog_info ("ASBR: Withdraw route of %s", lsa->str); if (lsa->header->adv_router == ospf6->router_id) { if (IS_OSPF6_DUMP_ASBR) zlog_info ("ASBR: Self-originated, ignore"); return; } external = OSPF6_LSA_HEADER_END (lsa->header); memset (&dest, 0, sizeof (dest)); dest.family = AF_INET6; dest.prefixlen = external->prefix.prefix_length; memcpy (&dest.u.prefix6, (char *)(external + 1), OSPF6_PREFIX_SPACE (dest.prefixlen)); prefix2str (&dest, buf, sizeof (buf)); if (IS_OSPF6_DUMP_ASBR) zlog_info ("ASBR: route: %s", buf); ospf6_route_lookup (&request, &dest, ospf6->route_table); if (ospf6_route_end (&request)) { zlog_info ("ASBR: route not found"); return; } while (request.path.origin.id != lsa->header->id || request.path.origin.adv_router != lsa->header->adv_router) { if (prefix_same (&request.route.prefix, &dest) != 1) { zlog_info ("ASBR: Can't find the entry matches the origin"); return; } ospf6_route_next (&request); } assert (request.path.origin.id == lsa->header->id); assert (request.path.origin.adv_router == request.path.origin.adv_router); while (request.path.origin.id == lsa->header->id && request.path.origin.adv_router == lsa->header->adv_router && prefix_same (&request.route.prefix, &dest) == 1) { ospf6_route_remove (&request, ospf6->route_table); ospf6_route_next (&request); } }
void ospf6_spf_table_finish (struct ospf6_route_table *result_table) { struct ospf6_route *route; struct ospf6_vertex *v; for (route = ospf6_route_head (result_table); route; route = ospf6_route_next (route)) { v = (struct ospf6_vertex *) route->route_option; ospf6_vertex_delete (v); ospf6_route_remove (route, result_table); } }
void ospf6_area_route_remove (void *data) { struct ospf6_route_req *route = data; struct in6_addr local; inet_pton (AF_INET6, "::1", &local); if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) { if (IS_OSPF6_DUMP_AREA) zlog_info ("AREA: Self-originated route remove, ignore"); return; } ospf6_route_remove (route, ospf6->route_table); }
void ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix) { struct ospf6_route *match; struct ospf6_external_info *info = NULL; struct route_node *node; struct ospf6_lsa *lsa; struct prefix prefix_id; char pbuf[64], ibuf[16]; struct listnode *lnode, *lnnode; struct ospf6_area *oa; match = ospf6_route_lookup (prefix, ospf6->external_table); if (match == NULL) { if (IS_OSPF6_DEBUG_ASBR) { prefix2str (prefix, pbuf, sizeof (pbuf)); zlog_debug ("No such route %s to withdraw", pbuf); } return; } info = match->route_option; assert (info); if (info->type != type) { if (IS_OSPF6_DEBUG_ASBR) { prefix2str (prefix, pbuf, sizeof (pbuf)); zlog_debug ("Original protocol mismatch: %s", pbuf); } return; } if (IS_OSPF6_DEBUG_ASBR) { prefix2str (prefix, pbuf, sizeof (pbuf)); inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf)); zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf); } lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), htonl (info->id), ospf6->router_id, ospf6->lsdb); if (lsa) ospf6_lsa_purge (lsa); /* remove 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_lookup (ospf6->external_id_table, &prefix_id); assert (node); node->info = NULL; route_unlock_node (node); ospf6_route_remove (match, ospf6->external_table); XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info); /* Router-Bit (ASBR Flag) may have to be updated */ for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa)) OSPF6_ROUTER_LSA_SCHEDULE (oa); }
/* 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); }
/* RFC 2328 12.4.3. Summary-LSAs */ void ospf6_abr_originate_summary_to_area (struct ospf6_route *route, struct ospf6_area *area) { struct ospf6_lsa *lsa, *old = NULL; struct ospf6_interface *oi; struct ospf6_route *summary, *range = NULL; struct ospf6_area *route_area; char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; caddr_t p; struct ospf6_inter_prefix_lsa *prefix_lsa; struct ospf6_inter_router_lsa *router_lsa; struct ospf6_route_table *summary_table = NULL; u_int16_t type; char buf[64]; int is_debug = 0; if (route->type == OSPF6_DEST_TYPE_ROUTER) { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER)) { is_debug++; inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof (buf)); zlog_debug ("Originating summary in area %s for ASBR %s", area->name, buf); } summary_table = area->summary_router; } else { if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX)) { is_debug++; prefix2str (&route->prefix, buf, sizeof (buf)); zlog_debug ("Originating summary in area %s for %s", area->name, buf); } summary_table = area->summary_prefix; } summary = ospf6_route_lookup (&route->prefix, summary_table); if (summary) old = ospf6_lsdb_lookup (summary->path.origin.type, summary->path.origin.id, area->ospf6->router_id, area->lsdb); /* if this route has just removed, remove corresponding LSA */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) { if (is_debug) zlog_debug ("The route has just removed, purge previous LSA"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Only destination type network, range or ASBR are considered */ if (route->type != OSPF6_DEST_TYPE_NETWORK && route->type != OSPF6_DEST_TYPE_RANGE && (route->type != OSPF6_DEST_TYPE_ROUTER || ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) { if (is_debug) zlog_debug ("Route type is none of network, range nor ASBR, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* AS External routes are never considered */ if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { if (is_debug) zlog_debug ("Path type is external, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the path's area is the same as target area */ if (route->path.area_id == area->area_id) { if (is_debug) zlog_debug ("The route is in the area itself, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the nexthops belongs to the target area */ oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); if (oi && oi->area && oi->area == area) { if (is_debug) zlog_debug ("The route's nexthop is in the same area, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* do not generate if the route cost is greater or equal to LSInfinity */ if (route->path.cost >= OSPF_LS_INFINITY) { if (is_debug) zlog_debug ("The cost exceeds LSInfinity, withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* if this is a route to ASBR */ if (route->type == OSPF6_DEST_TYPE_ROUTER) { /* Only the prefered best path is considered */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) { if (is_debug) zlog_debug ("This is the secondary path to the ASBR, ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Do not generate if the area is stub */ /* XXX */ } /* if this is an intra-area route, this may be suppressed by aggregation */ if (route->type == OSPF6_DEST_TYPE_NETWORK && route->path.type == OSPF6_PATH_TYPE_INTRA) { /* search for configured address range for the route's area */ route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); assert (route_area); range = ospf6_route_lookup_bestmatch (&route->prefix, route_area->range_table); /* ranges are ignored when originate backbone routes to transit area. Otherwise, if ranges are configured, the route is suppressed. */ if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && (route->path.area_id != OSPF_AREA_BACKBONE || ! IS_AREA_TRANSIT (area))) { if (is_debug) { prefix2str (&range->prefix, buf, sizeof (buf)); zlog_debug ("Suppressed by range %s of area %s", buf, route_area->name); } if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* If this is a configured address range */ if (route->type == OSPF6_DEST_TYPE_RANGE) { /* If DoNotAdvertise is set */ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) { if (is_debug) zlog_debug ("This is the range with DoNotAdvertise set. ignore"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } /* Whether the route have active longer prefix */ if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) { if (is_debug) zlog_debug ("The range is not active. withdraw"); if (summary) ospf6_route_remove (summary, summary_table); if (old) ospf6_lsa_purge (old); return; } } /* Check export list */ if (EXPORT_NAME (area)) { if (EXPORT_LIST (area) == NULL) EXPORT_LIST (area) = access_list_lookup (AFI_IP6, EXPORT_NAME (area)); if (EXPORT_LIST (area)) if (access_list_apply (EXPORT_LIST (area), &route->prefix) == FILTER_DENY) { if (is_debug) { inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof(buf)); zlog_debug ("prefix %s was denied by export list", buf); } return; } } /* Check filter-list */ if (PREFIX_NAME_OUT (area)) { if (PREFIX_LIST_OUT (area) == NULL) PREFIX_LIST_OUT (area) = prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area)); if (PREFIX_LIST_OUT (area)) if (prefix_list_apply (PREFIX_LIST_OUT (area), &route->prefix) != PREFIX_PERMIT) { if (is_debug) { inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, sizeof (buf)); zlog_debug ("prefix %s was denied by filter-list out", buf); } return; } } /* the route is going to be originated. store it in area's summary_table */ if (summary == NULL) { summary = ospf6_route_copy (route); if (route->type == OSPF6_DEST_TYPE_NETWORK || route->type == OSPF6_DEST_TYPE_RANGE) summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); else summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); summary->path.origin.adv_router = area->ospf6->router_id; summary->path.origin.id = ospf6_new_ls_id (summary->path.origin.type, summary->path.origin.adv_router, area->lsdb); summary = ospf6_route_add (summary, summary_table); } else { summary->type = route->type; quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed); } summary->path.router_bits = route->path.router_bits; summary->path.options[0] = route->path.options[0]; summary->path.options[1] = route->path.options[1]; summary->path.options[2] = route->path.options[2]; summary->path.prefix_options = route->path.prefix_options; summary->path.area_id = area->area_id; summary->path.type = OSPF6_PATH_TYPE_INTER; summary->path.cost = route->path.cost; summary->nexthop[0] = route->nexthop[0]; /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); lsa_header = (struct ospf6_lsa_header *) buffer; if (route->type == OSPF6_DEST_TYPE_ROUTER) { router_lsa = (struct ospf6_inter_router_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); /* Fill Inter-Area-Router-LSA */ router_lsa->options[0] = route->path.options[0]; router_lsa->options[1] = route->path.options[1]; router_lsa->options[2] = route->path.options[2]; OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix); type = htons (OSPF6_LSTYPE_INTER_ROUTER); } else { prefix_lsa = (struct ospf6_inter_prefix_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); /* Fill Inter-Area-Prefix-LSA */ OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; prefix_lsa->prefix.prefix_options = route->path.prefix_options; /* set Prefix */ memcpy (p, &route->prefix.u.prefix6, OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); ospf6_prefix_apply_mask (&prefix_lsa->prefix); p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); type = htons (OSPF6_LSTYPE_INTER_PREFIX); } /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = type; lsa_header->id = summary->path.origin.id; lsa_header->adv_router = area->ospf6->router_id; lsa_header->seqnum = ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, lsa_header->adv_router, area->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_area (lsa, area); }