📄 ospf_lsa.c
字号:
int length; if (ei == NULL) { if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_warn ("LSA[Type5]: External info is NULL, could not originated"); return NULL; } if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type5]: Originate AS-external-LSA instance"); /* If old Link State ID is specified, refresh LSA with same ID. */ if (old_id) id = *old_id; /* Get Link State with unique ID. */ else { id = ospf_lsa_unique_id (ospf, ospf->lsdb, OSPF_AS_EXTERNAL_LSA, &ei->p); if (id.s_addr == 0xffffffff) { /* Maybe Link State ID not available. */ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type5]: Link ID not available, can't originate"); return NULL; } } /* Create new stream for LSA. */ s = stream_new (OSPF_MAX_LSA_SIZE); lsah = (struct lsa_header *) STREAM_DATA (s); /* Set LSA common header fields. */ lsa_header_set (s, OSPF_OPTION_E, OSPF_AS_EXTERNAL_LSA, id, ospf->router_id); /* Set AS-external-LSA body fields. */ ospf_external_lsa_body_set (s, ei, ospf); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Now, create OSPF LSA instance. */ new = ospf_lsa_new (); new->area = NULL; SET_FLAG (new->flags, OSPF_LSA_SELF|OSPF_LSA_APPROVED); /* Copy LSA data to store, discard stream. */ new->data = ospf_lsa_data_new (length); memcpy (new->data, lsah, length); stream_free (s); return new;}#ifdef HAVE_NSSA/* As Type-7 */voidospf_install_flood_nssa (struct ospf *ospf, struct ospf_lsa *lsa, struct external_info *ei){ struct ospf_lsa *new2; struct as_external_lsa *extlsa; listnode node; /* NSSA Originate or Refresh (If anyNSSA) LSA is self-originated. And just installed as Type-5. Additionally, install as Type-7 LSDB for every attached NSSA. P-Bit controls which ABR performs translation to outside world; If we are an ABR....do not set the P-bit, because we send the Type-5, not as the ABR Translator, but as the ASBR owner within the AS! If we are NOT ABR, Flood through NSSA as Type-7 w/P-bit set. The elected ABR Translator will see the P-bit, Translate, and re-flood. Later, ABR_TASK and P-bit will scan Type-7 LSDB and translate to Type-5's to non-NSSA Areas. (it will also attempt a re-install) */ for (node = listhead (ospf->areas); node; nextnode (node)) { struct ospf_area *area = getdata (node); /* make lsa duplicate, lock=1 */ new2 = ospf_lsa_dup (lsa); new2->area = area; new2->data->type = OSPF_AS_NSSA_LSA; /* set P-bit if not ABR */ if (! IS_OSPF_ABR (ospf)) { SET_FLAG(new2->data->options, OSPF_OPTION_NP); /* set non-zero FWD ADDR draft-ietf-ospf-nssa-update-09.txt if the network between the NSSA AS boundary router and the adjacent AS is advertised into OSPF as an internal OSPF route, the forwarding address should be the next op address as is cu currently done with type-5 LSAs. If the intervening network is not adversited into OSPF as an internal OSPF route and the type-7 LSA's P-bit is set a forwarding address should be selected from one of the router's active OSPF inteface addresses which belong to the NSSA. If no such addresses exist, then no type-7 LSA's with the P-bit set should originate from this router. */ /* kevinm: not updating lsa anymore, just new2 */ extlsa = (struct as_external_lsa *)(new2->data); if (extlsa->e[0].fwd_addr.s_addr == 0) extlsa->e[0].fwd_addr = ospf_get_nssa_ip(area); /* this NSSA area in ifp */ if (extlsa->e[0].fwd_addr.s_addr == 0) { if (IS_DEBUG_OSPF_NSSA) zlog_info ("LSA[Type-7]: Could not build FWD-ADDR"); ospf_lsa_discard(new2); return; } } /* Re-calculate checksum. */ ospf_lsa_checksum (new2->data); /* install also as Type-7 */ ospf_lsa_install (ospf, NULL, new2); /* Remove Old, Lock New = 2 */ /* will send each copy, lock=2+n */ ospf_flood_through_as (ospf, NULL, new2); /* all attached NSSA's, no AS/STUBs */ }}#endif /* HAVE_NSSA */intis_prefix_default (struct prefix_ipv4 *p){ struct prefix_ipv4 q; q.family = AF_INET; q.prefix.s_addr = 0; q.prefixlen = 0; return prefix_same ((struct prefix *) p, (struct prefix *) &q);}/* Originate an AS-external-LSA, install and flood. */struct ospf_lsa *ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei){ struct ospf_lsa *new; /* Added for NSSA project.... External LSAs are originated in ASBRs as usual, but for NSSA systems. there is the global Type-5 LSDB and a Type-7 LSDB installed for every area. The Type-7's are flooded to every IR and every ABR; We install the Type-5 LSDB so that the normal "refresh" code operates as usual, and flag them as not used during ASE calculations. The Type-7 LSDB is used for calculations. Each Type-7 has a Forwarding Address of non-zero. If an ABR is the elected NSSA translator, following SPF and during the ABR task it will translate all the scanned Type-7's, with P-bit ON and not-self generated, and translate to Type-5's throughout the non-NSSA/STUB AS. A difference in operation depends whether this ASBR is an ABR or not. If not an ABR, the P-bit is ON, to indicate that any elected NSSA-ABR can perform its translation. If an ABR, the P-bit is OFF; No ABR will perform translation and this ASBR will flood the Type-5 LSA as usual. For the case where this ASBR is not an ABR, the ASE calculations are based on the Type-5 LSDB; The Type-7 LSDB exists just to demonstrate to the user that there are LSA's that belong to any attached NSSA. Finally, it just so happens that when the ABR is translating every Type-7 into Type-5, it installs it into the Type-5 LSDB as an approved Type-5 (translated from Type-7); at the end of translation if any Translated Type-5's remain unapproved, then they must be flushed from the AS. */ /* Check the AS-external-LSA should be originated. */ if (!ospf_redistribute_check (ospf, ei, NULL)) return NULL; /* Create new AS-external-LSA instance. */ if ((new = ospf_external_lsa_new (ospf, ei, NULL)) == NULL) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[Type5:%s]: Could not originate AS-external-LSA", inet_ntoa (ei->p.prefix)); return NULL; } /* Install newly created LSA into Type-5 LSDB, lock = 1. */ ospf_lsa_install (ospf, NULL, new); /* Update LSA origination count. */ ospf->lsa_originate_count++; /* Flooding new LSA. only to AS (non-NSSA/STUB) */ ospf_flood_through_as (ospf, NULL, new);#ifdef HAVE_NSSA /* If there is any attached NSSA, do special handling */ if (ospf->anyNSSA) ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood Type-7 to all NSSAs */#endif /* HAVE_NSSA */ /* Debug logging. */ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: Originate AS-external-LSA %p", new->data->type, inet_ntoa (new->data->id), new); ospf_lsa_header_dump (new->data); } return new;}/* Originate AS-external-LSA from external info with initial flag. */intospf_external_lsa_originate_timer (struct thread *thread){ struct ospf *ospf = THREAD_ARG (thread); struct route_node *rn; struct external_info *ei; struct route_table *rt; int type = THREAD_VAL (thread); ospf->t_external_lsa = NULL; /* Originate As-external-LSA from all type of distribute source. */ if ((rt = EXTERNAL_INFO (type))) for (rn = route_top (rt); rn; rn = route_next (rn)) if ((ei = rn->info) != NULL) if (!is_prefix_default ((struct prefix_ipv4 *)&ei->p)) if (!ospf_external_lsa_originate (ospf, ei)) zlog_warn ("LSA: AS-external-LSA was not originated."); return 0;}struct external_info *ospf_default_external_info (struct ospf *ospf){ int type; struct route_node *rn; struct prefix_ipv4 p; p.family = AF_INET; p.prefix.s_addr = 0; p.prefixlen = 0; /* First, lookup redistributed default route. */ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) if (EXTERNAL_INFO (type) && type != ZEBRA_ROUTE_OSPF) { rn = route_node_lookup (EXTERNAL_INFO (type), (struct prefix *) &p); if (rn != NULL) { route_unlock_node (rn); assert (rn->info); if (ospf_redistribute_check (ospf, rn->info, NULL)) return rn->info; } } return NULL;}intospf_default_originate_timer (struct thread *thread){ int *origin; struct prefix_ipv4 p; struct in_addr nexthop; struct external_info *ei; struct ospf *ospf; ospf = ospf_lookup (); /* Get originate flags. */ origin = THREAD_ARG (thread); p.family = AF_INET; p.prefix.s_addr = 0; p.prefixlen = 0; if (*origin == DEFAULT_ORIGINATE_ALWAYS) { /* If there is no default route via redistribute, then originate AS-external-LSA with nexthop 0 (self). */ nexthop.s_addr = 0; ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop); } if ((ei = ospf_default_external_info (ospf))) ospf_external_lsa_originate (ospf, ei); return 0;}#ifdef HAVE_NSSA/* Flush any NSSA LSAs for given prefix */voidospf_nssa_lsa_flush (struct ospf *ospf, struct prefix_ipv4 *p){ struct listnode *node; struct ospf_lsa *lsa; struct ospf_area *area; for (node = listhead (ospf->areas); node; nextnode (node)) { if (((area = getdata (node)) != NULL) && (area->external_routing == OSPF_AREA_NSSA)) { if (!(lsa = ospf_lsa_lookup (area, OSPF_AS_NSSA_LSA, p->prefix, ospf->router_id))) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_warn ("LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", inet_ntoa (p->prefix), p->prefixlen); continue; } ospf_ls_retransmit_delete_nbr_area (area, lsa); if (!IS_LSA_MAXAGE (lsa)) { ospf_refresher_unregister_lsa (ospf, lsa); ospf_lsa_flush_area (lsa, area); } } }}#endif /* HAVE_NSSA *//* Flush an AS-external-LSA from LSDB and routing domain. */voidospf_external_lsa_flush (struct ospf *ospf, u_char type, struct prefix_ipv4 *p, unsigned int ifindex, struct in_addr nexthop){ struct ospf_lsa *lsa; if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_info ("LSA: Flushing AS-external-LSA %s/%d", inet_ntoa (p->prefix), p->prefixlen); /* First lookup LSA from LSDB. */ if (!(lsa = ospf_external_info_find_lsa (ospf, p))) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_warn ("LSA: There is no such AS-external-LSA %s/%d in LSDB", inet_ntoa (p->prefix), p->prefixlen); return; }#ifdef HAVE_NSSA /* If LSA is selforiginated and there is NSSA area, flush * Type-7 LSA's at first. */ if (IS_LSA_SELF(lsa) && (ospf->anyNSSA)) ospf_nssa_lsa_flush (ospf, p);#endif /* HAVE_NSSA */ /* Sweep LSA from Link State Retransmit List. */ ospf_ls_retransmit_delete_nbr_as (ospf, lsa); /* There must be no self-originated LSA in rtrs_external. */#if 0 /* Remove External route from Zebra. */ ospf_zebra_delete ((struct prefix_ipv4 *) p, &nexthop);#endif if (!IS_LSA_MAXAGE (lsa)) { /* Unregister LSA from Refresh queue. */ ospf_refresher_unregister_lsa (ospf, lsa); /* Flush AS-external-LSA through AS. */ ospf_lsa_flush_as (ospf, lsa); } if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_info ("ospf_external_lsa_flush(): stop");}voidospf_external_lsa_refresh_default (struct ospf *ospf){ struct prefix_ipv4 p; struct external_info *ei; struct ospf_lsa *lsa; p.family = AF_INET; p.prefixlen = 0; p.prefix.s_addr = 0; ei = ospf_default_external_info (ospf); lsa = ospf_external_info_find_lsa (ospf, &p); if (ei) { if (lsa) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa); ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); } else { if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[Type5:0.0.0.0]: Originate AS-external-LSA"); ospf_external_lsa_originate (ospf, ei); } } else { if (lsa) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[Type5:0.0.0.0]: Flush AS-external-LSA"); ospf_lsa_flush_as (ospf, lsa); } }}voidospf_external_lsa_refresh_type (struct ospf *ospf, u_char type, int force){ struct route_node *rn; struct external_info *ei; if (type != DEFAULT_ROUTE) if (EXTERNAL_INFO(type)) /* Refresh each redistributed AS-external-LSAs. */ for (rn = route_top (EXTERNAL_INFO (type)); rn; rn = route_next (rn)) if ((ei = rn->info)) if (!is_prefix_default (&ei->p)) { struct ospf_lsa *lsa; if ((lsa = ospf_external_info_find_lsa (ospf, &ei->p))) ospf_external_lsa_refresh (ospf, lsa, ei, force); else ospf_external_lsa_originate (ospf, ei); }}/* Refresh AS-external-LSA. */voidospf_external_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa, struct external_info *ei, int force){ struct ospf_lsa *new; int changed; /* Check the AS-external-LSA should be originated. */ if (!ospf_redistribute_check (ospf, ei, &changed)) { ospf_external_lsa_flush (ospf, ei->type, &ei->p, ei->ifindex, ei->nexthop); return; } if (!changed && !force) return; /* Delete LSA from neighbor retransmit-list. */ ospf_ls_retransmit_delete_nbr_as (ospf, lsa); /* Unregister AS-external-LSA from refresh-list. */ ospf_refresher_unregister_lsa (ospf, lsa); new = ospf_external_lsa_new (ospf, ei, &lsa->data->id); if (new == NULL) { if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_warn ("LSA[Type%d:%s]: Could not be refreshed", lsa->data->type, inet_ntoa (lsa->data->id)); return; } new->data->ls_seqnum = lsa_seqnum_increment (lsa); /* Record timestamp. */ gettimeofday (&new->tv_orig, NULL); /* Re-calculate checksum. */ ospf_lsa_checksum (new->data); ospf_lsa_install (ospf, NULL, new); /* As type-5. */ /* Flood LSA through AS. */ ospf_flood_through_as (ospf, NULL, new);#ifdef HAVE_NSSA /* If any attached NSSA, install as Type-7, flood to all NSSA Areas */ if (ospf->anyNSSA) ospf_install_flood_nssa (ospf, new, ei); /* Install/Flood per new rules */#endif /* HAVE_NSSA */ /* Register slef-originated LSA to refresh queue. */ ospf_refresher_register_lsa (ospf, new); /* Debug logging. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -