diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-06-30 20:12:59 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2019-06-30 21:30:41 +0200 |
commit | 1a2ad348f660b150265f6df759a07de8a2b6de2f (patch) | |
tree | d64846d56a79178a34e865440b3b87d970c13fd4 /proto/ospf/topology.c | |
parent | 8a68316eb96be1fecf91ca395f3321aa99997ad2 (diff) |
OSPF: Support for graceful restart
Implement OSPFv2 (RFC 3623) and OSPFv3 (RFC 5187) graceful restart,
for both restarting and helper sides. Graceful restart is initiated
by 'graceful down' command.
Diffstat (limited to 'proto/ospf/topology.c')
-rw-r--r-- | proto/ospf/topology.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 1579f496..efd03b54 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -83,7 +83,10 @@ ospf_install_lsa(struct ospf_proto *p, struct ospf_lsa_header *lsa, u32 type, u3 en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age); if (change) + { + ospf_neigh_lsadb_changed(p, en); ospf_schedule_rtcalc(p); + } return en; } @@ -243,6 +246,7 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa en->lsa.age = 0; en->init_age = 0; en->inst_time = current_time(); + en->dirty = 0; lsa_generate_checksum(&en->lsa, en->lsa_body); OSPF_TRACE(D_EVENTS, "Originating LSA: Type: %04x, Id: %R, Rt: %R, Seq: %08x", @@ -251,7 +255,10 @@ ospf_do_originate_lsa(struct ospf_proto *p, struct top_hash_entry *en, void *lsa ospf_flood_lsa(p, en, NULL); if (en->mode == LSA_M_BASIC) + { + ospf_neigh_lsadb_changed(p, en); ospf_schedule_rtcalc(p); + } return 1; } @@ -321,7 +328,8 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa) if ((en->lsa.age < LSA_MAXAGE) && (lsa_length == en->lsa.length) && !memcmp(lsa_body, en->lsa_body, lsa_blen) && - (!ospf_is_v2(p) || (lsa->opts == lsa_get_options(&en->lsa)))) + (!ospf_is_v2(p) || (lsa->opts == lsa_get_options(&en->lsa))) && + !en->dirty) goto drop; lsa_body = lsab_flush(p); @@ -433,7 +441,10 @@ ospf_flush_lsa(struct ospf_proto *p, struct top_hash_entry *en) ospf_flood_lsa(p, en, NULL); if (en->mode == LSA_M_BASIC) + { + ospf_neigh_lsadb_changed(p, en); ospf_schedule_rtcalc(p); + } en->mode = LSA_M_BASIC; } @@ -509,6 +520,12 @@ ospf_update_lsadb(struct ospf_proto *p) continue; } + if (en->dirty) + { + ospf_flush_lsa(p, en); + continue; + } + if ((en->lsa.rt == p->router_id) && (real_age >= LSREFRESHTIME)) { ospf_refresh_lsa(p, en); @@ -525,6 +542,16 @@ ospf_update_lsadb(struct ospf_proto *p) } } +void +ospf_mark_lsadb(struct ospf_proto *p) +{ + struct top_hash_entry *en; + + /* Mark all local LSAs as dirty */ + WALK_SLIST(en, p->lsal) + if (en->lsa.rt == p->router_id) + en->dirty = 1; +} static u32 ort_to_lsaid(struct ospf_proto *p, ort *nf) @@ -1676,6 +1703,59 @@ ospf_originate_prefix_net_lsa(struct ospf_proto *p, struct ospf_iface *ifa) /* + * Grace LSA handling + * Type = LSA_T_GR, opaque type = LSA_OT_GR + */ + +static inline void +ospf_add_gr_period_tlv(struct ospf_proto *p, uint period) +{ + struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32)); + tlv->type = LSA_GR_PERIOD; + tlv->length = 4; + tlv->data[0] = period; +} + +static inline void +ospf_add_gr_reason_tlv(struct ospf_proto *p, uint reason) +{ + struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32)); + tlv->type = LSA_GR_REASON; + tlv->length = 1; + tlv->data[0] = reason << 24; +} + +static inline void +ospf_add_gr_address_tlv(struct ospf_proto *p, ip4_addr addr) +{ + struct ospf_tlv *tlv = lsab_allocz(p, sizeof(struct ospf_tlv) + sizeof(u32)); + tlv->type = LSA_GR_ADDRESS; + tlv->length = 4; + tlv->data[0] = ip4_to_u32(addr); +} + +void +ospf_originate_gr_lsa(struct ospf_proto *p, struct ospf_iface *ifa) +{ + struct ospf_new_lsa lsa = { + .type = LSA_T_GR, + .dom = ifa->iface_id, + .id = ospf_is_v2(p) ? 0 : ifa->iface_id, + .ifa = ifa + }; + + ospf_add_gr_period_tlv(p, p->gr_time); + ospf_add_gr_reason_tlv(p, 0); + + uint t = ifa->type; + if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) + ospf_add_gr_address_tlv(p, ipa_to_ip4(ifa->addr->ip)); + + ospf_originate_lsa(p, &lsa); +} + + +/* * Router Information LSA handling * Type = LSA_T_RI_AREA, opaque type = LSA_OT_RI */ @@ -1718,6 +1798,10 @@ ospf_update_topology(struct ospf_proto *p) struct ospf_area *oa; struct ospf_iface *ifa; + /* No LSA reorigination during GR recovery */ + if (p->gr_recovery) + return; + WALK_LIST(oa, p->area_list) { if (oa->update_rt_lsa) |