--- proto/ospf/topology.c | 165 +++++++++++++++++++++++++++++++------------------- 1 file changed, 104 insertions(+), 61 deletions(-) diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 4af5afa..6498585 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -24,6 +24,9 @@ void originate_prefix_rt_lsa(struct ospf_area *oa); void originate_prefix_net_lsa(struct ospf_iface *ifa); void flush_prefix_net_lsa(struct ospf_iface *ifa); +static void fill_lsa_header(struct proto_ospf *po, struct ospf_area *oa, + struct ospf_lsa_header *lsa, struct fib_node *fn, struct ospf_iface *ifa); + #ifdef OSPFv2 #define ipa_to_rid(x) _I(x) #else /* OSPFv3 */ @@ -485,17 +488,8 @@ originate_rt_lsa(struct ospf_area *oa) OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid); - lsa.age = 0; lsa.type = LSA_T_RT; - -#ifdef OSPFv2 - lsa.options = oa->options; - lsa.id = po->router_id; -#else /* OSPFv3 */ - lsa.id = 0; -#endif - - lsa.rt = po->router_id; + fill_lsa_header(po, oa, &lsa, NULL, NULL); lsa.sn = get_seqnum(oa->rt); u32 dom = oa->areaid; @@ -598,17 +592,8 @@ originate_net_lsa(struct ospf_iface *ifa) OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s", ifa->ifname); - lsa.age = 0; lsa.type = LSA_T_NET; - -#ifdef OSPFv2 - lsa.options = ifa->oa->options; - lsa.id = ipa_to_u32(ifa->addr->ip); -#else /* OSPFv3 */ - lsa.id = ifa->iface_id; -#endif - - lsa.rt = po->router_id; + fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa); lsa.sn = get_seqnum(ifa->net_lsa); body = originate_net_lsa_body(ifa, &lsa.length, po); @@ -781,14 +766,8 @@ originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric) OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)", fn->prefix, fn->pxlen, metric); - /* options argument is used in ORT_NET and OSPFv3 only */ - lsa.age = 0; -#ifdef OSPFv2 - lsa.options = oa->options; -#endif lsa.type = LSA_T_SUM_NET; - lsa.id = fibnode_to_lsaid(po, fn); - lsa.rt = po->router_id; + fill_lsa_header(po, oa, &lsa, fn, NULL); if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL) { @@ -824,16 +803,11 @@ originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)", rid, metric); - lsa.age = 0; -#ifdef OSPFv2 - lsa.options = oa->options; -#endif lsa.type = LSA_T_SUM_RT; - /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */ - lsa.id = rid; - lsa.rt = po->router_id; + fill_lsa_header(po, oa, &lsa, fn, NULL); options &= OPTIONS_MASK; + if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL) { if (check_sum_rt_lsa_same(en, lsa.id, metric, options)) @@ -855,18 +829,8 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) struct top_hash_entry *en; struct ospf_lsa_header lsa; - lsa.rt = po->router_id; - if (type == ORT_NET) - { - lsa.id = fibnode_to_lsaid(po, fn); - lsa.type = LSA_T_SUM_NET; - } - else - { - /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */ - lsa.id = ipa_to_rid(fn->prefix); - lsa.type = LSA_T_SUM_RT; - } + lsa.type = (type == ORT_NET) ? LSA_T_SUM_NET : LSA_T_SUM_RT; + fill_lsa_header(po, oa, &lsa, fn, NULL); if ((en = ospf_hash_find_header(po->gr, oa->areaid, &lsa)) != NULL) { @@ -1083,13 +1047,9 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d", nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen); - lsa.age = 0; -#ifdef OSPFv2 - lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E; -#endif + lsa.type = nssa ? LSA_T_NSSA : LSA_T_EXT; - lsa.id = fibnode_to_lsaid(po, fn); - lsa.rt = po->router_id; + fill_lsa_header(po, oa, &lsa, fn, NULL); if (nssa && pbit && ipa_zero(fwaddr)) { @@ -1104,6 +1064,10 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, } } +#ifdef OSPFv2 + lsa.options = nssa ? (pbit ? OPT_P : 0) : OPT_E; +#endif + if ((en = ospf_hash_find_header(po->gr, dom, &lsa)) != NULL) { int rv = check_ext_lsa(en, fn, metric, fwaddr, tag); @@ -1167,6 +1131,91 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int nssa) } +/** + * fill_lsa_header - fills in initial values for an LSA + * @po: OSPF protocol + * @oa: Area + * @lsa: LSA header pointer + * @fn: prefix if any + * @ida: OSPF interface if any + */ +static void +fill_lsa_header(struct proto_ospf *po, struct ospf_area *oa, struct ospf_lsa_header *lsa, + struct fib_node *fn, struct ospf_iface *ifa) +{ + u32 lsid = 0; + + /* + * Determine LSID for given LSA + * + * LSType#, used, scope, key identifier[, used identifier] + * + * OSPFv2: RFC2328 (A4.2+, 12.4.1+) + * + * Type1: singleton, area: [0001][RTRID], + * Type2: per-prefix, area: [0002][prefix][/cidr], [iface IP] + * Type3: per-prefix, area: [0003][prefix][/cidr], fibnode_to_lsaid() + * Type4: per-ASBR, area: [0004][ASBRID][/32], fibnode_to_lsaid() + * Type5: per-prefix, AS: [0005][prefix][/cidr], fibnode_to_lsaid() + * Type7: per-prefix, NSSA: [0007][prefix][/cidr], fibnode_to_lsaid() + * + * OSPFv3 mappings: RFC 5340 (4.4.3+) + * 0x2001: one/many, area: [0x2001][RTRID][/128], [0.0.0.0] + * 0x2002: per-link, area: [0x2002][link#][/128] + * 0x2003: per-prefix, area: [0x2003][prefix][/cidr], hash(prefix) + * 0x2004: per-ASBR, area: [0x2004][ASBRID][/128], RID(/128 route) + * 0x4005: per-prefix, AS: [0x4005][prefix][/cidr], hash(prefix) + * 0x2007: per-prefix, NSSA: [0x2007][prefix][/cidr], hash(prefix) + * 0x0008: per-link, link: [0x0008][iface#] + * 0x2009: one/many(RTR), area: [0x2009][??], [0.0.0.0] + * 0x2009: one/many(PX), area: [0x2009][iface#] + */ + + lsa->age = 0; +#ifdef OSPFv2 + lsa->options = oa->options; +#endif + lsa->rt = po->router_id; + + switch (lsa->type) + { +#ifdef OSPFv2 + case LSA_T_RT: + /* Singleton, LS id is router ID */ + lsid = po->router_id; + break; + case LSA_T_NET: + lsid = ipa_to_u32(ifa->addr->ip); + break; +#else + case LSA_T_RT: + lsid = 0; + break; + case LSA_T_PREFIX: + if (ifa != NULL) + lsid = ifa->iface_id; /* network prefix-LSA */ + else + lsid = 0; /* router prefix-LSA */ + break; + case LSA_T_NET: + case LSA_T_LINK: + lsid = ifa->iface_id; + break; +#endif + case LSA_T_SUM_NET: + case LSA_T_EXT: + case LSA_T_NSSA: + lsid = fibnode_to_lsaid(po, fn); + break; + case LSA_T_SUM_RT: + /* In OSPFv3, LSA ID is meaningless, but we still use Router ID of ASBR */ + lsid = ipa_to_rid(fn->prefix); + break; + } + + lsa->id = lsid; +} + #ifdef OSPFv3 static void * @@ -1216,10 +1265,8 @@ originate_link_lsa(struct ospf_iface *ifa) OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->ifname); - lsa.age = 0; lsa.type = LSA_T_LINK; - lsa.id = ifa->iface_id; - lsa.rt = po->router_id; + fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa); lsa.sn = get_seqnum(ifa->link_lsa); u32 dom = ifa->iface_id; @@ -1362,10 +1409,8 @@ originate_prefix_rt_lsa(struct ospf_area *oa) OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid); - lsa.age = 0; lsa.type = LSA_T_PREFIX; - lsa.id = 0; - lsa.rt = po->router_id; + fill_lsa_header(po, oa, &lsa, NULL, NULL); lsa.sn = get_seqnum(oa->pxr_lsa); u32 dom = oa->areaid; @@ -1501,10 +1546,8 @@ originate_prefix_net_lsa(struct ospf_iface *ifa) OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s", ifa->ifname); - lsa.age = 0; lsa.type = LSA_T_PREFIX; - lsa.id = ifa->iface_id; - lsa.rt = po->router_id; + fill_lsa_header(po, ifa->oa, &lsa, NULL, ifa); lsa.sn = get_seqnum(ifa->pxn_lsa); u32 dom = ifa->oa->areaid; -- 1.7.11.5 --------------000206050504040902070200 Content-Type: text/x-patch; name="0002-Remember-sequence-number-for-LSAs.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0002-Remember-sequence-number-for-LSAs.patch"