add support for the first few OSPF messages

This commit is contained in:
Hannes Gredler
2023-09-01 08:28:47 +00:00
committed by Christian Giese
parent de843be48b
commit b8e1b9c955
6 changed files with 338 additions and 50 deletions
+14 -15
View File
@@ -557,9 +557,9 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
if (node->node_name) {
lsdb_reset_attr_template(&attr_template);
attr_template.key.ordinal = 1;
attr_template.key.msg[0] = OSPF_MSG_LSUPDATE;
attr_template.key.msg[1] = OSPF_LSA_OPAQUE_AREA;
attr_template.key.msg[2] = OSPF_TLV_HOSTNAME;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI;
attr_template.key.attr_cp[2] = OSPF_TLV_HOSTNAME;
strncpy(attr_template.key.hostname, node->node_name, sizeof(attr_template.key.hostname)-1);
lsdb_add_node_attr(node, &attr_template);
}
@@ -576,9 +576,9 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
}
attr_template.key.prefix.node_flag = true;
attr_template.key.msg[0] = OSPF_MSG_LSUPDATE;
attr_template.key.msg[1] = OSPF_LSA_ROUTER;
attr_template.key.msg[2] = OSPF_ROUTER_LSA_LINK_STUB;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB;
lsdb_add_node_attr(node, &attr_template);
/* external prefixes */
@@ -590,9 +590,8 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
attr_template.key.prefix.ipv4_prefix.len = ctx->ipv4_ext_prefix.len;
attr_template.key.prefix.metric = 100;
attr_template.key.msg[0] = OSPF_MSG_LSUPDATE;
attr_template.key.msg[1] = OSPF_LSA_EXTERNAL;
attr_template.key.msg[2] = OSPF_EXTERNAL_PREFIX;;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_EXTERNAL;
lsdb_add_node_attr(node, &attr_template);
ext_addr4 += ext_incr4;
}
@@ -625,9 +624,9 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
* TODO Type-2 LSA handling.
*/
lsdb_reset_attr_template(&attr_template);
attr_template.key.msg[0] = OSPF_MSG_LSUPDATE;
attr_template.key.msg[1] = OSPF_LSA_ROUTER;
attr_template.key.msg[2] = OSPF_ROUTER_LSA_LINK_PTP;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_PTP;
memcpy(attr_template.key.link.remote_node_id, link->key.remote_node_id, 4);
attr_template.key.link.metric = link->link_metric; /* TODO clip metric */
lsdb_add_node_attr(node, &attr_template);
@@ -641,9 +640,9 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx)
attr_template.key.prefix.ipv4_prefix.len = ctx->ipv4_link_prefix.len;
attr_template.key.prefix.metric = link->link_metric; /* TODO clip metric */
attr_template.key.msg[0] = OSPF_MSG_LSUPDATE;
attr_template.key.msg[1] = OSPF_LSA_ROUTER;
attr_template.key.msg[2] = OSPF_ROUTER_LSA_LINK_STUB;
attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE;
attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER;
attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB;
lsdb_add_node_attr(node, &attr_template);
}
+1
View File
@@ -58,6 +58,7 @@ extern struct keyval_ isis_level_names[];
/* lspgen_packet.c */
void lspgen_serialize_attr(lsdb_ctx_t *, lsdb_attr_t *, lsdb_packet_t *);
void lspgen_gen_packet(lsdb_ctx_t *);
void lspgen_reset_packet_buffer(struct lsdb_packet_ *);
/* lspgen_seq_cache.c */
void lspgen_read_seq_cache(lsdb_ctx_t *);
+63 -17
View File
@@ -748,8 +748,22 @@ lsdb_format_isis_attr(struct lsdb_attr_ *attr)
return buf;
}
struct keyval_ ospf_attr_names[] = {
{ OSPF_TLV_HOSTNAME, "Hostname" },
struct keyval_ ospf_attr_l0_names[] = {
{ OSPF_MSG_LSUPDATE, "LS-Update" },
{ 0, NULL}
};
struct keyval_ ospf_attr_l1_names[] = {
{ OSPF_LSA_ROUTER, "Router-LSA" },
{ OSPF_LSA_EXTERNAL, "External-LSA" },
{ OSPF_LSA_OPAQUE_AREA_RI, "Opaque-LSA-RI" },
{ 0, NULL}
};
struct keyval_ ospf_attr_l2_names[] = {
{ OSPF_ROUTER_LSA_LINK_PTP, "ptp-link" },
{ OSPF_ROUTER_LSA_LINK_STUB, "ptp-stub" },
{ OSPF_TLV_HOSTNAME, "Hostname" },
{ 0, NULL}
};
@@ -758,16 +772,42 @@ lsdb_format_ospf2_attr(struct lsdb_attr_ *attr)
{
static char buf[128];
int len;
uint attr_cp;
len = snprintf(buf, sizeof(buf), "%s (%u)", val2key(ospf_attr_names, attr->key.attr_type), attr->key.attr_type);
switch(attr->key.attr_type) {
case OSPF_TLV_HOSTNAME:
len += snprintf(buf+len, sizeof(buf)-len, " '%s'", attr->key.hostname);
break;
default:
break;
attr_cp = attr->key.attr_cp[0];
len = snprintf(buf, sizeof(buf), "%s", val2key(ospf_attr_l0_names, attr_cp));
attr_cp = attr->key.attr_cp[1];
if (attr_cp) {
len += snprintf(buf+len, sizeof(buf)-len, " %s", val2key(ospf_attr_l1_names, attr_cp));
}
attr_cp = attr->key.attr_cp[2];
if (attr_cp) {
len += snprintf(buf+len, sizeof(buf)-len, " %s", val2key(ospf_attr_l2_names, attr_cp));
}
switch(attr->key.attr_cp[1]) {
case OSPF_LSA_EXTERNAL:
len += snprintf(buf+len, sizeof(buf)-len, " %s, metric %u",
format_ipv4_prefix(&attr->key.prefix.ipv4_prefix),
attr->key.prefix.metric);
break;
default:
break;
}
switch(attr->key.attr_cp[2]) {
case OSPF_ROUTER_LSA_LINK_STUB:
len += snprintf(buf+len, sizeof(buf)-len, " %s, metric %u",
format_ipv4_prefix(&attr->key.prefix.ipv4_prefix),
attr->key.prefix.metric);
break;
case OSPF_TLV_HOSTNAME:
len += snprintf(buf+len, sizeof(buf)-len, ": %s", attr->key.hostname);
break;
default:
break;
}
return buf;
}
@@ -856,6 +896,7 @@ lsdb_add_node_attr(lsdb_node_t *node, lsdb_attr_t *attr_template)
struct lsdb_attr_ *attr;
void **p;
lsdb_packet_t packet;
int idx;
if (!node) {
return NULL;
@@ -911,20 +952,25 @@ lsdb_add_node_attr(lsdb_node_t *node, lsdb_attr_t *attr_template)
/*
* Calculate the size, by serializing the data into a dummy packet buffer.
*/
packet.buf.data = packet.data;
//buf.data = data;
packet.buf.idx = 0;
//buf.idx = 0;
packet.buf.size = sizeof(packet.data);
//buf.size = sizeof(data);
lspgen_reset_packet_buffer(&packet);
lspgen_serialize_attr(ctx, attr, &packet);
attr->size = packet.buf.idx;
//attr->size = buf.idx;
/*
* Find lowest level size.
*/
for (idx = MAX_MSG_LEVEL-1; idx; idx--) {
if (packet.bufX[idx].idx) {
attr->size += packet.bufX[idx].idx;
break;
}
}
/*
* Book keeping.
*/
node->attr_count++;
attr->parent = node;
LOG(LSDB, " Add attr %s to node %s (%s), size %u\n",
lsdb_format_attr(ctx, attr),
+6 -2
View File
@@ -262,6 +262,8 @@ typedef struct msg_stack_ {
struct io_buffer_ buf[1]; /* variable length */
} msg_stack_t;
#define MAX_MSG_LEVEL 4
/*
* An Attribute hanging off a node or link
*/
@@ -272,7 +274,7 @@ typedef struct lsdb_attr_ {
*/
struct {
uint8_t ordinal; /* Used for ordering message generation */
uint8_t msg[4]; /* code points for multiple levels */
uint8_t attr_cp[MAX_MSG_LEVEL]; /* code points for multiple levels */
uint8_t attr_type; /* Type */
bool start_tlv; /* Always start a fresh TLV */
union {
@@ -289,6 +291,7 @@ typedef struct lsdb_attr_ {
} key;
uint32_t size; /* on-the wire space required in bytes */
struct lsdb_node_ *parent;
} lsdb_attr_t;
/*
@@ -309,10 +312,11 @@ typedef struct lsdb_packet_ {
} key;
struct io_buffer_ buf;
struct io_buffer_ bufX[MAX_MSG_LEVEL];
uint8_t data[1500]; /* fixed buffer */
uint8_t redzone[8]; /* Overwrite detection */
uint8_t prev_attr_cp[4]; /* cached code points for previous attr */
uint8_t prev_attr_cp[MAX_MSG_LEVEL]; /* cached code points for previous attr */
} lsdb_packet_t;
+1 -4
View File
@@ -17,7 +17,7 @@
#define OSPF_LSA_EXTERNAL 5
#define OSPF_LSA_OPAQUE_LINK 9
#define OSPF_LSA_OPAQUE_AREA 10
#define OSPF_LSA_OPAQUE_AREA_RI 104
#define OSPF_LSA_OPAQUE_DOMAIN 11
#define OSPF_TLV_HOSTNAME 7
@@ -26,7 +26,4 @@ enum {
/* Router LSA */
OSPF_ROUTER_LSA_LINK_PTP,
OSPF_ROUTER_LSA_LINK_STUB,
/* External LSA */
OSPF_EXTERNAL_PREFIX,
};
+253 -12
View File
@@ -18,6 +18,8 @@
*/
void lspgen_gen_packet_node(lsdb_node_t *);
#define PAD4(X) ((X+3)&(~3)) /* 32-Bit padding */
void
lspgen_gen_isis_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet)
{
@@ -114,7 +116,7 @@ lspgen_gen_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *pack
lspgen_gen_isis_packet_header(ctx, node, packet);
break;
case PROTO_OSPF2:
lspgen_gen_ospf2_packet_header(ctx, node, packet);
//lspgen_gen_ospf2_packet_header(ctx, node, packet);
break;
default:
LOG_NOARG(ERROR, "Unknown protocol\n");
@@ -597,26 +599,243 @@ lspgen_serialize_isis_attr(lsdb_attr_t *attr, lsdb_packet_t *packet)
}
}
/*
* Inititialize a next level buffer to the remnants of the passed in buffer.
* This gives us nice hierarchical buffers with vboundary protection.
*/
void
lspgen_propagate_buffer_down (lsdb_packet_t *packet, uint level)
{
struct io_buffer_ *cur, *next;
/* boundary protection */
if (level >= MAX_MSG_LEVEL - 1) {
return;
}
cur = &packet->bufX[level];
next = &packet->bufX[level+1];
next->data = cur->data + cur->idx;
next->size = cur->size - cur->idx;
next->idx = 0;
next->start_idx = 0;
}
void
lspgen_propagate_buffer_up (lsdb_packet_t *packet, uint level)
{
struct io_buffer_ *cur, *prev;
/* boundary protection */
if (level == 0) {
return;
}
cur = &packet->bufX[level];
prev = &packet->bufX[level-1];
prev->idx += cur->idx;
}
/*
* Serialize an OSPFv2 attribute into a packet buffer.
*/
void
lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet)
{
io_buffer_t *buf;
uint16_t attr_len;
lsdb_node_t *node;
io_buffer_t *buf0, *buf1, *buf2;
uint16_t attr_len, checksum;
uint32_t router_id, mask;
buf = &packet->buf;
node = packet->parent;
switch (attr->key.attr_type) {
case OSPF_TLV_HOSTNAME:
attr_len = strnlen(attr->key.hostname, sizeof(attr->key.hostname));
push_data(buf, (uint8_t *)attr->key.hostname, attr_len);
break;
buf0 = &packet->bufX[0];
buf1 = &packet->bufX[1];
buf2 = &packet->bufX[2];
/*
* New Level 0 message ?
*/
if (packet->prev_attr_cp[0] != attr->key.attr_cp[0]) {
/* close Level 0 */
switch (packet->prev_attr_cp[0]) {
case OSPF_MSG_LSUPDATE:
write_be_uint(buf0->data+2, 2, buf0->idx); /* Packet length */
write_be_uint(buf0->data+12, 2, calculate_cksum(buf0->data, buf0->idx)); /* Checksum */
break;
default:
break;
}
/* open Level 0 */
switch(attr->key.attr_cp[0]) {
case OSPF_MSG_LSUPDATE:
push_be_uint(buf0, 1, 2); /* Version */
push_be_uint(buf0, 1, OSPF_MSG_LSUPDATE); /* Msg */
push_be_uint(buf0, 2, 0); /* Packet length - will be overwritten later */
router_id = read_be_uint(node->key.node_id, 4);
push_be_uint(buf0, 4, router_id); /* Router ID */
push_be_uint(buf0, 4, node->ctx->topology_id.area); /* Area ID */
push_be_uint(buf0, 2, 0); /* Checksum - will be overwritten later */
push_be_uint(buf0, 2, 0); /* Authentication Type */
push_be_uint(buf0, 8, 0); /* Authentication */
push_be_uint(buf0, 4, 0); /* # LSAs - will be overwritten later */
lspgen_propagate_buffer_down(packet, 0);
break;
default:
LOG(ERROR, "No Level 0 open packet serializer for attr %d\n", attr->key.attr_cp[0]);
return;
}
}
/*
* New Level 1 message ?
*/
if (packet->prev_attr_cp[1] != attr->key.attr_cp[1]) {
/* close Level 1 */
switch (packet->prev_attr_cp[1]) {
case OSPF_LSA_ROUTER:
case OSPF_LSA_EXTERNAL:
case OSPF_LSA_OPAQUE_AREA_RI:
inc_be_uint(buf0->data+24, 4); /* Update #LSAs */
write_be_uint(buf1->data+16, 2, 0); /* reset checksum field */
checksum = calculate_fletcher_cksum(buf1->data, 16, buf1->idx);
write_be_uint(packet->data+16, 2, checksum); /* LSA Checksum */
lspgen_propagate_buffer_up(packet, 1);
break;
}
/* open Level 1 */
switch(attr->key.attr_cp[1]) {
case OSPF_LSA_ROUTER:
push_be_uint(buf1, 2, 1); /* LS-age */
push_be_uint(buf1, 1, 0); /* Options */
push_be_uint(buf1, 1, OSPF_LSA_ROUTER); /* LS-Type */
router_id = read_be_uint(node->key.node_id, 4);
push_be_uint(buf1, 4, router_id); /* Link State ID */
push_be_uint(buf1, 4, router_id); /* Advertising Router */
push_be_uint(&packet->buf, 4, node->sequence); /* Sequence */
push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */
push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */
push_be_uint(buf1, 1, 0x02); /* Flags, E */
push_be_uint(buf1, 1, 0);
push_be_uint(buf1, 2, 0); /* # links - will be overwritten later */
lspgen_propagate_buffer_down(packet, 1);
break;
case OSPF_LSA_EXTERNAL:
push_be_uint(buf1, 2, 1); /* LS-age */
push_be_uint(buf1, 1, 0); /* Options */
push_be_uint(buf1, 1, 5); /* LS-Type */
push_data(buf1, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Link State ID */
router_id = read_be_uint(node->key.node_id, 4);
push_be_uint(buf1, 4, router_id); /* Advertising Router */
push_be_uint(&packet->buf, 4, node->sequence); /* Sequence */
push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */
push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */
mask = 0xffffffff;
/* convert prefix length to mask */
mask &= ~((1 << ((32 - attr->key.prefix.ipv4_prefix.len)))-1);
push_be_uint(buf1, 4, mask); /* Network Mask */
push_be_uint(buf1, 1, 0x80); /* E2 */
push_be_uint(buf1, 1, 0); /* Options */
push_be_uint(buf1, 3, attr->key.prefix.metric); /* Metric */
push_be_uint(buf1, 4, 0); /* Forwarding Address */
push_be_uint(buf1, 4, 0); /* External Route Tag */
lspgen_propagate_buffer_down(packet, 1);
break;
case OSPF_LSA_OPAQUE_AREA_RI:
push_be_uint(buf1, 2, 1); /* LS-age */
push_be_uint(buf1, 1, 0); /* Options */
push_be_uint(buf1, 1, 10); /* LS-Type */
push_be_uint(buf1, 1, 4); /* Opaque Type: Router-Information */
push_be_uint(buf1, 3, 0); /* Opaque subtype */
router_id = read_be_uint(node->key.node_id, 4);
push_be_uint(buf1, 4, router_id); /* Advertising Router */
push_be_uint(&packet->buf, 4, node->sequence); /* Sequence */
push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */
push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */
lspgen_propagate_buffer_down(packet, 1);
break;
default:
LOG(ERROR, "No Level 1 open packet serializer for attr %d\n", attr->key.attr_cp[1]);
return;
}
}
/*
* New Level 2 message ?
*/
if (packet->prev_attr_cp[2] != attr->key.attr_cp[2]) {
/* close Level 2 */
switch (packet->prev_attr_cp[2]) {
case OSPF_ROUTER_LSA_LINK_PTP:
case OSPF_ROUTER_LSA_LINK_STUB:
inc_be_uint(buf1->data+22, 1); /* Update #links */
lspgen_propagate_buffer_up(packet, 2);
break;
}
/* open Level 2 */
switch(attr->key.attr_cp[2]) {
case OSPF_ROUTER_LSA_LINK_PTP:
push_be_uint(buf2, 4, 0); /* Link ID */
push_be_uint(buf2, 4, 0); /* Link Data */
push_be_uint(buf2, 1, 1); /* Type ptp */
push_be_uint(buf2, 1, 0); /* #TOS */
push_be_uint(buf2, 2, 100); /* metric */
lspgen_propagate_buffer_down(packet, 2);
break;
case OSPF_ROUTER_LSA_LINK_STUB:
push_be_uint(buf2, 4, 1); /* Link ID */
push_be_uint(buf2, 4, 0xffffffff); /* Link Data */
push_be_uint(buf2, 1, 3); /* Type stub */
push_be_uint(buf2, 1, 0); /* #TOS */
push_be_uint(buf2, 2, 100); /* metric */
lspgen_propagate_buffer_down(packet, 2);
break;
case OSPF_TLV_HOSTNAME:
attr_len = strnlen(attr->key.hostname, sizeof(attr->key.hostname));
if (attr_len) {
push_be_uint(buf2, 2, 7); /* Type */
push_be_uint(buf2, 2, attr_len); /* Length */
push_data(buf2, (uint8_t *)attr->key.hostname, attr_len);
push_be_uint(buf2, PAD4(attr_len), 0); /* Padding zeros */
}
lspgen_propagate_buffer_down(packet, 2);
break;
default:
LOG(ERROR, "No Level 2 open packet serializer for attr %d\n", attr->key.attr_cp[2]);
return;
}
default:
LOG(ERROR, "No packet serializer for attr %d\n", attr->key.attr_type);
break;
}
}
@@ -666,6 +885,23 @@ lspgen_calculate_tlv_space(io_buffer_t *buf, uint32_t tlv_start_idx)
return 255 - tlv_len;
}
/*
* Reset all packet buffers.
*/
void
lspgen_reset_packet_buffer (struct lsdb_packet_ *packet)
{
uint idx;
packet->buf.data = packet->data;
packet->buf.start_idx = 0;
packet->buf.idx = 0;
packet->buf.size = sizeof(packet->data);
for (idx = 0; idx < MAX_MSG_LEVEL; idx++) {
memcpy(&packet->bufX[idx], &packet->buf, sizeof(struct io_buffer_));
}
}
/*
* Lookup / Create a fresh packet based on the id.
*/
@@ -711,6 +947,11 @@ lspgen_add_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, uint32_t id)
*/
packet->parent = node;
/*
* Reset buffers.
*/
lspgen_reset_packet_buffer(packet);
/*
* Write header for link-state packet.
*/