📄 ospf6_lsa.c
字号:
ospf6_lsa_network_update (char *ifname){ char buffer [MAXLSASIZE]; u_int16_t size; struct ospf6_lsa *old; struct interface *ifp; struct ospf6_interface *o6i; int count; struct ospf6_network_lsa *network_lsa; struct ospf6_neighbor *o6n; u_int32_t *router_id; listnode node; ifp = if_lookup_by_name (ifname); if (! ifp) { if (IS_OSPF6_DUMP_LSA) zlog_warn ("Update Network: No such Interface: %s", ifname); return; } o6i = (struct ospf6_interface *) ifp->info; if (! o6i || ! o6i->area) { if (IS_OSPF6_DUMP_LSA) zlog_warn ("Update Network: Interface not enabled: %s", ifname); return; } /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_NETWORK), htonl (o6i->if_id), o6i->area->ospf6->router_id, o6i->area); /* Don't originate Network-LSA if not DR */ if (o6i->state != IFS_DR) { if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Network: Interface %s is not DR", o6i->interface->name); if (old) ospf6_lsa_premature_aging (old); return; } /* If none of neighbor is adjacent to us */ count = 0; o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state); if (count == 0) { if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Network: Interface %s is Stub", o6i->interface->name); if (old) ospf6_lsa_premature_aging (old); return; } if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Network: Interface %s", o6i->interface->name); /* prepare buffer */ memset (buffer, 0, sizeof (buffer)); size = sizeof (struct ospf6_network_lsa); network_lsa = (struct ospf6_network_lsa *) buffer; router_id = (u_int32_t *)(network_lsa + 1); /* set fields of myself */ *router_id++ = o6i->area->ospf6->router_id; size += sizeof (u_int32_t); network_lsa->options[0] |= o6i->area->options[0]; network_lsa->options[1] |= o6i->area->options[1]; network_lsa->options[2] |= o6i->area->options[2]; /* Walk through neighbors */ for (node = listhead (o6i->neighbor_list); node; nextnode (node)) { o6n = (struct ospf6_neighbor *) getdata (node); if (o6n->state != NBS_FULL) continue; /* set this neighbor's Router-ID to LSA */ *router_id++ = o6n->router_id; size += sizeof (u_int32_t); /* options field is logical OR */ network_lsa->options[0] |= o6n->options[0]; network_lsa->options[1] |= o6n->options[1]; network_lsa->options[2] |= o6n->options[2]; } ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_NETWORK), htonl (o6i->if_id), o6i->area->ospf6->router_id, (char *) network_lsa, size, o6i->area);}intospf6_lsa_network_hook_neighbor (void *neighbor){ struct ospf6_neighbor *o6n = neighbor; ospf6_lsa_network_update (o6n->ospf6_interface->interface->name); return 0;}intospf6_lsa_network_hook_interface (void *interface){ struct ospf6_interface *o6i = interface; if (o6i->area) ospf6_lsa_network_update (o6i->interface->name); return 0;}intospf6_lsa_network_refresh (void *old){ struct ospf6_lsa *lsa = old; struct interface *ifp; ifp = if_lookup_by_index (ntohl (lsa->header->id)); if (! ifp) ospf6_lsa_premature_aging (old); else ospf6_lsa_network_update (ifp->name); return 0;}voidospf6_lsa_slot_register_network (){ struct ospf6_lsa_slot slot; struct ospf6_hook hook; memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); slot.type = htons (OSPF6_LSA_TYPE_NETWORK); slot.name = "Network"; slot.func_show = ospf6_lsa_network_show; slot.func_refresh = ospf6_lsa_network_refresh; ospf6_lsa_slot_register (&slot); ospf6_lsdb_hook[OSPF6_LSA_TYPE_NETWORK & OSPF6_LSTYPE_CODE_MASK].hook = ospf6_spf_database_hook; memset (&hook, 0, sizeof (hook)); hook.name = "OriginateNetwork"; hook.hook_change = ospf6_lsa_network_hook_neighbor; ospf6_hook_register (&hook, &neighbor_hook); memset (&hook, 0, sizeof (hook)); hook.name = "OriginateNetwork"; hook.hook_change = ospf6_lsa_network_hook_interface; ospf6_hook_register (&hook, &interface_hook);}/****************************//* RFC2740 3.4.3.6 Link-LSA *//****************************/intospf6_lsa_link_show (struct vty *vty, struct ospf6_lsa *lsa){ char *start, *end, *current; struct ospf6_link_lsa *link_lsa; int prefixnum; struct ospf6_prefix *prefix; char buf[128]; struct in6_addr in6; assert (lsa->header); link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1); prefixnum = ntohl (link_lsa->llsa_prefix_num); inet_ntop (AF_INET6, (void *)&link_lsa->llsa_linklocal, buf, sizeof (buf)); vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE); vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE); start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); end = (char *) lsa->header + ntohs (lsa->header->length); for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) { prefix = (struct ospf6_prefix *) current; if (current + OSPF6_PREFIX_SIZE (prefix) > end) { vty_out (vty, " Trailing %d byte garbage ... Malformed%s", end - current, VTY_NEWLINE); return -1; } ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf)); vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE); ospf6_prefix_in6_addr (prefix, &in6); inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); vty_out (vty, " Prefix: %s/%d%s", buf, prefix->prefix_length, VTY_NEWLINE); } return 0;}voidospf6_lsa_link_update (char *ifname){ char *cp, buffer [MAXLSASIZE], buf[32]; u_int16_t size; struct ospf6_lsa *old; struct interface *ifp; struct ospf6_interface *o6i; struct ospf6_link_lsa *link_lsa; struct ospf6_prefix *p; list prefix_connected; listnode node; struct connected *c; ifp = if_lookup_by_name (ifname); if (! ifp) { if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Link: No such Interface: %s", ifname); return; } o6i = (struct ospf6_interface *) ifp->info; if (! o6i || ! o6i->area) { if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Link: Interface not enabled: %s", ifname); return; }#if 0 /* Link-LSA is on Broadcast or NBMA */ if (! if_is_broadcast (o6i->interface) /* && ! NBMA xxx */) { return; }#endif /*0*/ /* find previous LSA */ old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id), ospf6->router_id, o6i->area); /* can't make Link-LSA if linklocal address not set */ if (! o6i->lladdr) { if (IS_OSPF6_DUMP_LSA) zlog_warn ("Update Link: No Linklocal Address: %s", o6i->interface->name); if (old) ospf6_lsa_premature_aging (old); return; } if (IS_OSPF6_DUMP_LSA) zlog_info ("Update Link: Interface %s", o6i->interface->name); if (! ospf6_interface_is_enabled (o6i->interface->ifindex)) { if (IS_OSPF6_DUMP_LSA) zlog_info (" Interface %s not enabled", o6i->interface->name); if (old) ospf6_lsa_premature_aging (old); return; } /* check connected prefix */ prefix_connected = list_new (); for (node = listhead (o6i->interface->connected); node; nextnode (node)) { c = (struct connected *) getdata (node); /* 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 if (IS_OSPF6_DUMP_LSA) zlog_warn ("Update Intra-Prefix (Stub): " "Prefix list \"%s\" not found", o6i->plist_name); if (result == PREFIX_DENY) { if (IS_OSPF6_DUMP_LSA) zlog_info (" Filter out Prefix-list %s: %s", o6i->plist_name, buf); continue; } } if (IS_OSPF6_DUMP_LSA) zlog_info (" Advertise %s", buf); /* hold prefix in list. duplicate is filtered in ospf6_prefix_add() */ p = ospf6_prefix_create (0, 0, (struct prefix_ipv6 *) c->address); ospf6_prefix_add (prefix_connected, p); } /* Note: even if no prefix configured, still we have to create Link-LSA for next-hop resolution */ memset (buffer, 0, sizeof (buffer)); size = sizeof (struct ospf6_link_lsa); link_lsa = (struct ospf6_link_lsa *) buffer; /* fill Link LSA and calculate size */ link_lsa->llsa_rtr_pri = o6i->priority; link_lsa->llsa_options[0] = o6i->area->options[0]; link_lsa->llsa_options[1] = o6i->area->options[1]; link_lsa->llsa_options[2] = o6i->area->options[2]; /* linklocal address */ memcpy (&link_lsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr));#ifdef KAME /* clear ifindex */ if (link_lsa->llsa_linklocal.s6_addr[3] & 0x0f) link_lsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f);#endif /* KAME */ link_lsa->llsa_prefix_num = htonl (listcount (prefix_connected)); cp = (char *)(link_lsa + 1); for (node = listhead (prefix_connected); node; nextnode (node)) { p = (struct ospf6_prefix *) getdata (node); size += OSPF6_PREFIX_SIZE (p); memcpy (cp, p, OSPF6_PREFIX_SIZE (p)); cp += OSPF6_PREFIX_SIZE (p); } for (node = listhead (prefix_connected); node; nextnode (node)) { p = (struct ospf6_prefix *) getdata (node); ospf6_prefix_delete (p); } list_delete (prefix_connected); ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id), o6i->area->ospf6->router_id, (char *) link_lsa, size, o6i);}intospf6_lsa_link_hook_interface (void *interface){ struct ospf6_interface *o6i = interface; if (o6i->area) ospf6_lsa_link_update (o6i->interface->name); return 0;}intospf6_lsa_link_refresh (void *old){ struct ospf6_lsa *lsa = old; struct interface *ifp; ifp = if_lookup_by_index (ntohl (lsa->header->id)); if (! ifp) ospf6_lsa_premature_aging (old); else ospf6_lsa_link_update (ifp->name); return 0;}voidospf6_lsa_slot_register_link (){ struct ospf6_lsa_slot slot; memset (&slot, 0, sizeof (struct ospf6_lsa_slot)); slot.type = htons (OSPF6_LSA_TYPE_LINK); slot.name = "Link"; slot.func_show = ospf6_lsa_link_show; slot.func_refresh = ospf6_lsa_link_refresh; slot.hook_interface.name = "OriginateLink"; slot.hook_interface.hook_change = ospf6_lsa_link_hook_interface; ospf6_lsa_slot_register (&slot); /* * Link LSA handling will be shift in ospf6_intra.c * Currently, only database hook only moved to ospf6_intra.c */#if 0 ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook = ospf6_spf_database_hook;#endif /*0*/}intospf6_lsa_add_hook (void *data){ struct ospf6_lsa *lsa = data; struct ospf6_lsa_slot *sp; sp = ospf6_lsa_slot_get (lsa->header->type); if (sp) { CALL_CHANGE_HOOK (&sp->database_hook, lsa); } else zlog_warn ("Unknown LSA added to database: %s", lsa->str); return 0;}intospf6_lsa_change_hook (void *data){ struct ospf6_lsa *lsa = data; struct ospf6_lsa_slot *sp; sp = ospf6_lsa_slot_get (lsa->header->type); if (sp) { CALL_CHANGE_HOOK (&sp->database_hook, lsa); } else zlog_warn ("Unknown LSA changed in database: %s", lsa->str); return 0;}intospf6_lsa_remove_hook (void *data){ struct ospf6_lsa *lsa = data; struct ospf6_lsa_slot *sp; sp = ospf6_lsa_slot_get (lsa->header->type); if (sp) { CALL_REMOVE_HOOK (&sp->database_hook, lsa); } else zlog_warn ("Unknown LSA removed from database: %s", lsa->str); return 0;}/* Initialize LSA slots */voidospf6_lsa_init (){ struct ospf6_hook hook; slot_head = NULL; ospf6_lsa_slot_register_router (); ospf6_lsa_slot_register_network (); ospf6_lsa_slot_register_link ();#if 0 ospf6_lsa_slot_register_intra_prefix (); ospf6_lsa_slot_register_as_external ();#endif /*0*/ hook.name = "LSADatabaseHook"; hook.hook_add = ospf6_lsa_add_hook; hook.hook_change = ospf6_lsa_change_hook; hook.hook_remove = ospf6_lsa_remove_hook; ospf6_hook_register (&hook, &database_hook);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -