diff options
Diffstat (limited to 'proto/ospf/topology.c')
-rw-r--r-- | proto/ospf/topology.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index e58f1375..f9ca7bfc 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -224,12 +224,17 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa /* * lsa.type_raw is initialized by ospf_hash_get() to OSPFv3 LSA type. * lsa_set_options() implicitly converts it to OSPFv2 LSA type, assuming that - * old type is just new type masked by 0xff. That is not universally true, - * but it holds for all OSPFv2 types currently supported by BIRD. + * old type is just new type masked by 0xff. That holds for most OSPFv2 types, + * but we have to fix it for opaque LSAs. */ if (ospf_is_v2(p)) + { + if (lsa_is_opaque(en->lsa_type)) + en->lsa.type_raw = LSA_T_V2_OPAQUE_ + LSA_SCOPE_ORDER(en->lsa_type); + lsa_set_options(&en->lsa, lsa_opts); + } mb_free(en->lsa_body); en->lsa_body = lsa_body; @@ -273,6 +278,10 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa) u16 lsa_blen = p->lsab_used; u16 lsa_length = sizeof(struct ospf_lsa_header) + lsa_blen; + /* For OSPFv2 Opaque LSAs, LS ID consists of Opaque Type and Opaque ID */ + if (ospf_is_v2(p) && lsa_is_opaque(lsa->type)) + lsa->id |= (u32) lsa_get_opaque_type(lsa->type) << 24; + en = ospf_hash_get(p->gr, lsa->dom, lsa->id, p->router_id, lsa->type); if (!SNODE_VALID(en)) @@ -1658,6 +1667,41 @@ ospf_originate_prefix_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa) ifa->pxn_lsa = ospf_originate_lsa(p, &lsa); } + +/* + * Router Information LSA handling + * Type = LSA_T_RI_AREA, opaque type = LSA_OT_RI + */ + +void +ospf_add_ric_tlv(struct ospf_proto *p) +{ + struct ospf_tlv *ri = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32)); + ri->type = LSA_RI_RIC; + ri->length = sizeof(struct ospf_tlv) + sizeof(u32); + + BIT32R_SET(ri->data, LSA_RIC_STUB_ROUTER); +} + +void +ospf_originate_ri_lsa(struct ospf_proto *p, struct ospf_area *oa) +{ + struct ospf_new_lsa lsa = { + .type = LSA_T_RI_AREA, + .dom = oa->areaid, + .id = p->instance_id + }; + + ospf_add_ric_tlv(p); + + ospf_originate_lsa(p, &lsa); +} + + +/* + * Generic topology code + */ + static inline int breaks_minlsinterval(struct top_hash_entry *en) { return en && (en->lsa.age < LSA_MAXAGE) && (lsa_inst_age(en) < MINLSINTERVAL); } @@ -1692,6 +1736,7 @@ ospf_update_topology(struct ospf_proto *p) ospf_originate_rt_lsa(p, oa); ospf_originate_prefix_rt_lsa(p, oa); + ospf_originate_ri_lsa(p, oa); oa->update_rt_lsa = 0; } } |