summaryrefslogtreecommitdiff
path: root/ospf6d/ospf6_lsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_lsa.c')
-rw-r--r--ospf6d/ospf6_lsa.c83
1 files changed, 80 insertions, 3 deletions
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 017751825f..622e5f9e0f 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -37,8 +37,85 @@ DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_HEADER, "OSPF6 LSA header");
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA_SUMMARY, "OSPF6 LSA summary");
+const uint8_t ospf6_lsa_min_size[OSPF6_LSTYPE_SIZE] = {
+ [OSPF6_LSTYPE_UNKNOWN] = 0,
+ [0x00ff & OSPF6_LSTYPE_ROUTER] = OSPF6_ROUTER_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_NETWORK] = OSPF6_NETWORK_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_INTER_PREFIX] = OSPF6_INTER_PREFIX_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_INTER_ROUTER] = OSPF6_INTER_ROUTER_LSA_FIX_SIZE,
+ [0x00ff & OSPF6_LSTYPE_AS_EXTERNAL] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_GROUP_MEMBERSHIP] = 0, /* Unused */
+ [0x00ff & OSPF6_LSTYPE_TYPE_7] = OSPF6_AS_EXTERNAL_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_LINK] = OSPF6_LINK_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_INTRA_PREFIX] = OSPF6_INTRA_PREFIX_LSA_MIN_SIZE,
+ [0x00ff & OSPF6_LSTYPE_GRACE_LSA] = 0
+};
+
+void *lsdesc_start_lsa_type(struct ospf6_lsa_header *header, int lsa_type)
+{
+ uint8_t t = (0x00ff & lsa_type);
+
+ if (t == OSPF6_LSTYPE_UNKNOWN || t >= OSPF6_LSTYPE_SIZE) {
+ zlog_debug("Cannot get descriptor offset for unknown lsa type 0x%x",
+ t);
+ return ospf6_lsa_end(header);
+ }
+ return (char *)lsa_after_header(header) + ospf6_lsa_min_size[t];
+}
+
+void *lsdesc_start(struct ospf6_lsa_header *header)
+{
+ return lsdesc_start_lsa_type(header, ntohs(header->type));
+}
+
static struct ospf6_lsa_handler *lsa_handlers[OSPF6_LSTYPE_SIZE];
+void *nth_lsdesc(struct ospf6_lsa_header *header, int pos)
+{
+ char *lsdesc = lsdesc_start(header);
+ char *lsa_end = ospf6_lsa_end(header);
+ char *nth;
+ int lsdesc_size;
+
+ if (ntohs(header->type) == OSPF6_LSTYPE_ROUTER)
+ lsdesc_size = OSPF6_ROUTER_LSDESC_FIX_SIZE;
+ else if (ntohs(header->type) == OSPF6_LSTYPE_NETWORK)
+ lsdesc_size = OSPF6_NETWORK_LSDESC_FIX_SIZE;
+ else
+ return NULL;
+
+ nth = lsdesc + (pos * lsdesc_size);
+
+ if (nth + lsdesc_size <= lsa_end)
+ return nth;
+
+ return NULL;
+}
+
+void *nth_prefix(struct ospf6_lsa_header *header, int pos)
+{
+ struct ospf6_prefix *prefix = lsdesc_start(header);
+ char *end = ospf6_lsa_end(header);
+ int i = 0;
+
+ if (ntohs(header->type) != OSPF6_LSTYPE_LINK &&
+ ntohs(header->type) != OSPF6_LSTYPE_INTRA_PREFIX)
+ return NULL;
+
+ if (pos == 0)
+ return prefix;
+
+ while ((char *)prefix < end &&
+ (char *)prefix + OSPF6_PREFIX_SIZE(prefix) <= end) {
+ if (i == pos)
+ return prefix;
+ i++;
+ prefix = OSPF6_PREFIX_NEXT(prefix);
+ }
+
+ return NULL;
+}
+
struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
{
struct ospf6 *ospf6 = NULL;
@@ -65,7 +142,7 @@ static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
{
char *start, *end, *current;
- start = ospf6_lsa_header_end(lsa->header);
+ start = lsa_after_header(lsa->header);
end = ospf6_lsa_end(lsa->header);
if (use_json) {
@@ -234,8 +311,8 @@ int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
if (length <= 0)
return 0;
- return memcmp(ospf6_lsa_header_end(lsa1->header),
- ospf6_lsa_header_end(lsa2->header), length);
+ return memcmp(lsa_after_header(lsa1->header),
+ lsa_after_header(lsa2->header), length);
}
/* ospf6 age functions */