📄 ospf6_intra.c
字号:
o6i->interface->name); adv_list = list_new (); /* foreach Link-LSA associated with this Link */ for (ospf6_lsdb_type (&n, htons (OSPF6_LSA_TYPE_LINK), o6i->lsdb); ! ospf6_lsdb_is_end (&n); ospf6_lsdb_next (&n)) { if (IS_LSA_MAXAGE (n.lsa)) continue; if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): Checking %s", n.lsa->str); /* Check status of the advertising router */ if (n.lsa->header->adv_router != o6i->area->ospf6->router_id) { o6n = ospf6_neighbor_lookup (n.lsa->header->adv_router, o6i); if (! o6n) { if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): neighbor not found"); continue; } if (o6n->state != NBS_FULL) { if (IS_OSPF6_DUMP_PREFIX) zlog_info ("Update Intra-Prefix (Transit): %s not FULL", o6n->str); continue; } } /* For each Prefix in this Link-LSA */ link = (struct ospf6_link_lsa *) (n.lsa->header + 1); prefix_num = ntohl (link->llsa_prefix_num); if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Prefix #%d", prefix_num); start = (char *) (link + 1); end = (char *) (n.lsa->header) + ntohs (n.lsa->header->length); prefix = (struct ospf6_prefix *) start; for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) { prefix = (struct ospf6_prefix *) current; ospf6_prefix_string (prefix, buf, sizeof (buf)); /* Check duplicate prefix */ dup = ospf6_prefix_lookup (adv_list, prefix); if (dup) { if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Duplicate %s", buf); dup->prefix_options |= prefix->prefix_options; continue; } if (prefix_num <= 0) { zlog_warn (" Wong prefix number ..."); break; } if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Prefix %s", buf); /* copy prefix to advertise list */ ospf6_prefix_add (adv_list, prefix); prefix_num --; } } /* if no prefix to advertise, return */ if (listcount (adv_list) == 0) { if (IS_OSPF6_DUMP_PREFIX) zlog_info (" No Prefix to advertise"); if (old) ospf6_lsa_premature_aging (old); return; } /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); size = sizeof (struct ospf6_intra_area_prefix_lsa); iap = (struct ospf6_intra_area_prefix_lsa *) buffer; /* Set Referenced LSA field */ iap->refer_lstype = htons (OSPF6_LSA_TYPE_NETWORK); iap->refer_lsid = htonl (o6i->if_id); iap->refer_advrtr = o6i->area->ospf6->router_id; dst = (struct ospf6_prefix *) (iap + 1); for (node = listhead (adv_list); node; nextnode (node)) { src = (struct ospf6_prefix *) getdata (node); memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); size += OSPF6_PREFIX_SIZE (dst); dst = OSPF6_NEXT_PREFIX (dst); } iap->prefix_number = htons (listcount (adv_list)); while ((node = listhead (adv_list)) != NULL) { prefix = getdata (node); ospf6_prefix_delete (prefix); listnode_delete (adv_list, prefix); } list_delete (adv_list); ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), htonl (o6i->if_id), ospf6->router_id, buffer, size, o6i->area);}voidospf6_lsa_intra_prefix_update_stub (u_int32_t area_id){ char buffer [MAXLSASIZE]; u_int16_t size; struct ospf6_lsa *old; struct ospf6_area *o6a; int count; struct ospf6_intra_area_prefix_lsa *iap; listnode i,j; struct ospf6_interface *o6i = NULL; struct ospf6_prefix *prefix, *dst, *src; struct connected *c; char buf[128]; list adv_list; listnode node; char prefix_buf[sizeof (struct ospf6_prefix) + sizeof (struct in6_addr)]; o6a = ospf6_area_lookup (area_id, ospf6); if (! o6a) { char tmp[16]; inet_ntop (AF_INET, &area_id, tmp, sizeof (tmp)); zlog_warn ("Update Intra-Prefix (Stub): No such area: %s", tmp); return; } else if (IS_OSPF6_DUMP_PREFIX) { zlog_info ("Update Intra-Prefix (Stub): area: %s", o6a->str); } /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), htonl (0), ospf6->router_id, o6a); /* xxx, ls-id */ adv_list = list_new (); /* Examin for each interface */ for (i = listhead (o6a->if_list); i; nextnode (i)) { o6i = (struct ospf6_interface *) getdata (i); if (o6i->state == IFS_DOWN) { if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Interface %s: down", o6i->interface->name); continue; } count = 0; o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); if (o6i->state != IFS_LOOPBACK && o6i->state != IFS_PTOP && count != 0) { /* This interface's prefix will be included in DR's */ if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Interface %s: not stub", o6i->interface->name); continue; } if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Interface %s:", o6i->interface->name); /* copy foreach address prefix */ for (j = listhead (o6i->interface->connected); j; nextnode (j)) { c = (struct connected *) getdata (j); /* filter prefix not IPv6 */ if (c->address->family != AF_INET6) continue; /* for log */ prefix2str (c->address, buf, sizeof (buf)); CONTINUE_IF_ADDRESS_LINKLOCAL (c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address); CONTINUE_IF_ADDRESS_LOOPBACK (c->address); CONTINUE_IF_ADDRESS_V4COMPAT (c->address); CONTINUE_IF_ADDRESS_V4MAPPED (c->address); /* filter prefix specified by configuration */ if (o6i->plist_name) { struct prefix_list *plist; enum prefix_list_type result = PREFIX_PERMIT; plist = prefix_list_lookup (AFI_IP6, o6i->plist_name); if (plist) result = prefix_list_apply (plist, c->address); else zlog_warn ("Update Intra-Prefix (Stub): " "Prefix list \"%s\" not found", o6i->plist_name); if (result == PREFIX_DENY) { if (IS_OSPF6_DUMP_PREFIX) zlog_info (" %s: Filtered by %s", buf, o6i->plist_name); continue; } } /* initialize buffer for ospf6 prefix */ memset (prefix_buf, 0, sizeof (prefix_buf)); prefix = (struct ospf6_prefix *) prefix_buf; /* set ospf6 prefix according to its state */ /* xxx, virtual links */ if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX) && (o6i->state == IFS_LOOPBACK || o6i->state == IFS_PTOP /* xxx, PoinToMultiPoint I/F type */ )) { prefix->prefix_length = 128; prefix->prefix_options = OSPF6_PREFIX_OPTION_LA; prefix->prefix_metric = htons (0); memcpy (prefix + 1, &c->address->u.prefix6, OSPF6_PREFIX_SPACE (prefix->prefix_length)); } else { struct prefix_ipv6 prefix_ipv6; /* apply mask */ prefix_copy ((struct prefix *) &prefix_ipv6, c->address); apply_mask_ipv6 (&prefix_ipv6); prefix->prefix_length = prefix_ipv6.prefixlen; prefix->prefix_options = 0; /* xxx, no options yet */ prefix->prefix_metric = htons (o6i->cost); memcpy (prefix + 1, &prefix_ipv6.prefix, OSPF6_PREFIX_SPACE (prefix->prefix_length)); } ospf6_prefix_string (prefix, buf, sizeof (buf)); if (IS_OSPF6_DUMP_PREFIX) zlog_info (" Advertise %s", buf); /* check in the prefix to advertising prefix list */ ospf6_prefix_add (adv_list, prefix); } } /* If no prefix to advertise */ if (listcount (adv_list) == 0) { if (IS_OSPF6_DUMP_PREFIX) zlog_info (" No prefix to advertise"); if (old) ospf6_lsa_premature_aging (old); return; } /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); size = sizeof (struct ospf6_intra_area_prefix_lsa); iap = (struct ospf6_intra_area_prefix_lsa *) buffer; /* Set Referenced LSA field */ iap->refer_lstype = htons (OSPF6_LSA_TYPE_ROUTER); iap->refer_lsid = htonl (0); iap->refer_advrtr = o6a->ospf6->router_id; dst = (struct ospf6_prefix *) (iap + 1); for (node = listhead (adv_list); node; nextnode (node)) { src = (struct ospf6_prefix *) getdata (node); memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); size += OSPF6_PREFIX_SIZE (dst); dst = OSPF6_NEXT_PREFIX (dst); } iap->prefix_number = htons (listcount (adv_list)); while ((node = listhead (adv_list)) != NULL) { prefix = getdata (node); ospf6_prefix_delete (prefix); listnode_delete (adv_list, prefix); } list_delete (adv_list); ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), htonl (0) /* xxx */, ospf6->router_id, buffer, size, o6a);}intospf6_lsa_intra_prefix_hook_interface (void *interface){ struct ospf6_interface *o6i = interface; if (o6i->area) { ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id); } return 0;}intospf6_lsa_intra_prefix_hook_neighbor (void *neighbor){ struct ospf6_neighbor *o6n = neighbor; if (o6n->ospf6_interface->area) { ospf6_lsa_intra_prefix_update_transit (o6n->ospf6_interface->interface->name); ospf6_lsa_intra_prefix_update_stub (o6n->ospf6_interface->area->area_id); } return 0;}intospf6_intra_prefix_link_database_hook (void *new){ struct ospf6_lsa *lsa = new; struct ospf6_interface *o6i; if (lsa->header->type != htons (OSPF6_LSA_TYPE_LINK)) return 0; o6i = lsa->scope; if (o6i->state != IFS_DR) return 0; ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id); return 0;}intospf6_lsa_intra_prefix_refresh (void *old){ struct ospf6_lsa *lsa = old; struct ospf6_interface *o6i; struct ospf6_area *o6a; u_int32_t id; id = ntohl (lsa->header->id); if (id) { o6i = ospf6_interface_lookup_by_index (id); if (o6i) ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); else ospf6_lsa_premature_aging (lsa); } else { o6a = lsa->scope; ospf6_lsa_intra_prefix_update_stub (o6a->area_id); } return 0;}voidospf6_intra_prefix_register (){ struct ospf6_lsa_slot slot, *sp; struct ospf6_hook hook; memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); slot.type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX); slot.name = "Intra-Prefix"; slot.func_show = ospf6_lsa_intra_prefix_show; slot.func_refresh = ospf6_lsa_intra_prefix_refresh; ospf6_lsa_slot_register (&slot); memset (&hook, 0, sizeof (hook)); hook.name = "OriginateIntraPrefix"; hook.hook_add = ospf6_lsa_intra_prefix_hook_interface; hook.hook_change = ospf6_lsa_intra_prefix_hook_interface; hook.hook_remove = NULL; /* XXX */ ospf6_hook_register (&hook, &interface_hook); memset (&hook, 0, sizeof (hook)); hook.name = "OriginateIntraPrefix"; hook.hook_add = ospf6_lsa_intra_prefix_hook_neighbor; hook.hook_change = ospf6_lsa_intra_prefix_hook_neighbor; hook.hook_remove = ospf6_lsa_intra_prefix_hook_neighbor; ospf6_hook_register (&hook, &neighbor_hook); sp = ospf6_lsa_slot_get (htons (OSPF6_LSA_TYPE_INTRA_PREFIX)); hook.name = "CalculateIntraPrefix"; hook.hook_add = ospf6_intra_prefix_database_hook_add; hook.hook_change = ospf6_intra_prefix_database_hook_add; hook.hook_remove = ospf6_intra_prefix_database_hook_remove; ospf6_hook_register (&hook, &sp->database_hook);}voidospf6_intra_database_hook_intra_prefix (struct ospf6_lsa *old, struct ospf6_lsa *new){ if (old) ospf6_intra_prefix_database_hook_remove (old); if (new && ! IS_LSA_MAXAGE (new)) ospf6_intra_prefix_database_hook_add (new);}voidospf6_intra_database_hook_link (struct ospf6_lsa *old, struct ospf6_lsa *new){ ospf6_intra_prefix_link_database_hook (new); ospf6_spf_database_hook (old, new);}voidospf6_intra_init (){ ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTRA_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook = ospf6_intra_database_hook_intra_prefix; ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook = ospf6_intra_database_hook_link; intra_index = ospf6_dump_install ("intra-area", "Intra-area calculation\n"); ospf6_intra_prefix_register ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -