void ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry) { struct ospf6_lsa *lsa; u_int16_t type; u_int32_t router; if (! CHECK_FLAG (asbr_entry->flag, OSPF6_ROUTE_BEST)) { char buf[16]; inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&asbr_entry->prefix), buf, sizeof (buf)); zlog_info ("ignore non-best path: lsentry %s add", buf); return; } type = htons (OSPF6_LSTYPE_AS_EXTERNAL); router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix); for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb); lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa)) { if (! OSPF6_LSA_IS_MAXAGE (lsa)) ospf6_asbr_lsa_add (lsa); } }
/* 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); }
int negotiation_done(struct thread * thread) { struct ospf6_neighbor * on; struct ospf6_lsa * lsa; on = (struct ospf6_neighbor *) THREAD_ARG(thread); assert(on); if(on->state != OSPF6_NEIGHBOR_EXSTART) return 0; if(IS_OSPF6_SIBLING_DEBUG_NEIGHBOR) zlog_debug("Neighbor Event %s: *NegotiationDone*", on->name); /* clear ls-list */ ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); for(lsa = ospf6_lsdb_head(on->retrans_list); lsa; lsa = ospf6_lsdb_next(lsa)) { ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } /* Interface scoped LSAs */ for(lsa = ospf6_lsdb_head(on->ospf6_if->lsdb); lsa; lsa = ospf6_lsdb_next(lsa)) { if (OSPF6_LSA_IS_MAXAGE (lsa)) { ospf6_increment_retrans_count(lsa); ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); } else ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); } /* Area scoped LSAs - no area implemented yet */ // LIST_FOR_EACH(lsa, struct ospf6_lsa, node, on-> ) // { // } /* AS scoped LSAs */ for(lsa = ospf6_lsdb_head(ospf6->lsdb); lsa; lsa = ospf6_lsdb_next(lsa)) { if(OSPF6_LSA_IS_MAXAGE(lsa)) { ospf6_increment_retrans_count(lsa); ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list); } else ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->summary_list); } UNSET_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT); ospf6_neighbor_state_change(OSPF6_NEIGHBOR_EXCHANGE, on); return 0; }
void ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) { struct prefix_ipv6 key; struct route_node *current, *nextnode, *prevnode; struct ospf6_lsa *next, *prev, *old = NULL; memset (&key, 0, sizeof (key)); ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); ospf6_lsdb_set_key (&key, &lsa->header->adv_router, sizeof (lsa->header->adv_router)); ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id)); current = route_node_get (lsdb->table, (struct prefix *) &key); old = current->info; current->info = lsa; ospf6_lsa_lock (lsa); if (old) { if (old->prev) old->prev->next = lsa; if (old->next) old->next->prev = lsa; lsa->next = old->next; lsa->prev = old->prev; } else { /* next link */ nextnode = current; route_lock_node (nextnode); do { nextnode = route_next (nextnode); } while (nextnode && nextnode->info == NULL); if (nextnode == NULL) lsa->next = NULL; else { next = nextnode->info; lsa->next = next; next->prev = lsa; route_unlock_node (nextnode); } /* prev link */ prevnode = current; route_lock_node (prevnode); do { prevnode = route_prev (prevnode); } while (prevnode && prevnode->info == NULL); if (prevnode == NULL) lsa->prev = NULL; else { prev = prevnode->info; lsa->prev = prev; prev->next = lsa; route_unlock_node (prevnode); } lsdb->count++; } if (old) { if (OSPF6_LSA_IS_CHANGED (old, lsa)) { if (OSPF6_LSA_IS_MAXAGE (lsa)) { if (lsdb->hook_remove) { (*lsdb->hook_remove) (old); (*lsdb->hook_remove) (lsa); } } else if (OSPF6_LSA_IS_MAXAGE (old)) { if (lsdb->hook_add) (*lsdb->hook_add) (lsa); } else { if (lsdb->hook_remove) (*lsdb->hook_remove) (old); if (lsdb->hook_add) (*lsdb->hook_add) (lsa); } } } else if (OSPF6_LSA_IS_MAXAGE (lsa)) { if (lsdb->hook_remove) (*lsdb->hook_remove) (lsa); } else { if (lsdb->hook_add) (*lsdb->hook_add) (lsa); } if (old) ospf6_lsa_unlock (old); ospf6_lsdb_count_assert (lsdb); }