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/lsalib.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/lsalib.c')
-rw-r--r-- | proto/ospf/lsalib.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 7ddf64e3..7767700f 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -12,6 +12,9 @@ #include "lib/fletcher16.h" +#define HDRLEN sizeof(struct ospf_lsa_header) + + #ifndef CPU_BIG_ENDIAN void lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n) @@ -61,7 +64,6 @@ lsa_ntoh_body(void *n, void *h, u16 len) #endif /* little endian */ - int lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa) { @@ -147,11 +149,13 @@ static const u16 lsa_v2_types[] = { /* Maps OSPFv2 opaque types to OSPFv3 function codes */ static const u16 opaque_lsa_types[] = { + [LSA_OT_GR] = LSA_T_GR, [LSA_OT_RI] = LSA_T_RI_, }; /* Maps (subset of) OSPFv3 function codes to OSPFv2 opaque types */ static const u8 opaque_lsa_types_inv[] = { + [LSA_T_GR] = LSA_OT_GR, [LSA_T_RI_] = LSA_OT_RI, }; @@ -168,7 +172,13 @@ lsa_get_type_domain_(u32 type, u32 id, struct ospf_iface *ifa, u32 *otype, u32 * uint code; if (LSA_FUNCTION(type) == LSA_T_OPAQUE_) if (code = LOOKUP(opaque_lsa_types, id >> 24)) + { type = code | LSA_UBIT | LSA_SCOPE(type); + + /* Hack for Grace-LSA: It does not use U-bit for link-scoped LSAs */ + if (type == (LSA_T_GR | LSA_UBIT)) + type = LSA_T_GR; + } } else { @@ -196,6 +206,13 @@ lsa_get_type_domain_(u32 type, u32 id, struct ospf_iface *ifa, u32 *otype, u32 * } } +int +lsa_is_opaque(u32 type) +{ + u32 fn = LSA_FUNCTION(type); + return LOOKUP(opaque_lsa_types_inv, fn) || (fn == LSA_T_OPAQUE_); +} + u32 lsa_get_opaque_type(u32 type) { @@ -267,6 +284,51 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2) } +#define LSA_TLV_LENGTH(tlv) \ + (sizeof(struct ospf_tlv) + BIRD_ALIGN((tlv)->length, 4)) + +#define LSA_NEXT_TLV(tlv) \ + ((struct ospf_tlv *) ((byte *) (tlv) + LSA_TLV_LENGTH(tlv))) + +#define LSA_WALK_TLVS(tlv,buf,len) \ + for(struct ospf_tlv *tlv = (void *) (buf); \ + (byte *) tlv < (byte *) (buf) + (len); \ + tlv = LSA_NEXT_TLV(tlv)) + +struct ospf_tlv * +lsa_get_tlv(struct top_hash_entry *en, uint type) +{ + LSA_WALK_TLVS(tlv, en->lsa_body, en->lsa.length - HDRLEN) + if (tlv->type == type) + return tlv; + + return NULL; +} + +int +lsa_validate_tlvs(byte *buf, uint len) +{ + byte *pos = buf; + byte *end = buf + len; + + while (pos < end) + { + if ((pos + sizeof(struct ospf_tlv)) > end) + return 0; + + struct ospf_tlv *tlv = (void *) pos; + uint len = LSA_TLV_LENGTH(tlv); + + if ((pos + len) > end) + return 0; + + pos += len; + } + + return 1; +} + + static inline int lsa_walk_rt2(struct ospf_lsa_rt_walk *rt) { @@ -408,7 +470,6 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, int af, struct ospf_lsa_ext_ } } -#define HDRLEN sizeof(struct ospf_lsa_header) static int lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body) @@ -604,6 +665,12 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body) } static int +lsa_validate_gr(struct ospf_lsa_header *lsa, void *body) +{ + return lsa_validate_tlvs(body, lsa->length - HDRLEN); +} + +static int lsa_validate_ri(struct ospf_lsa_header *lsa UNUSED, struct ospf_lsa_net *body UNUSED) { /* @@ -643,6 +710,8 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body) case LSA_T_EXT: case LSA_T_NSSA: return lsa_validate_ext2(lsa, body); + case LSA_T_GR: + return lsa_validate_gr(lsa, body); case LSA_T_RI_LINK: case LSA_T_RI_AREA: case LSA_T_RI_AS: @@ -674,6 +743,8 @@ lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body) return lsa_validate_link(lsa, body); case LSA_T_PREFIX: return lsa_validate_prefix(lsa, body); + case LSA_T_GR: + return lsa_validate_gr(lsa, body); case LSA_T_RI_LINK: case LSA_T_RI_AREA: case LSA_T_RI_AS: |