LDP commands

This commit is contained in:
Christian Giese
2023-01-03 13:12:52 +01:00
committed by Christian Giese
parent 29fb098c97
commit 86fdbe5f13
14 changed files with 629 additions and 14 deletions
+24 -3
View File
@@ -1381,11 +1381,11 @@ json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
return false;
}
value = json_object_get(ldp, "keepalive-interval");
value = json_object_get(ldp, "keepalive-time");
if(json_is_number(value)) {
ldp_config->keepalive_interval = json_number_value(value);
ldp_config->keepalive_time = json_number_value(value);
} else {
ldp_config->keepalive_interval = LDP_DEFAULT_KEEPALIVE_INTERVAL;
ldp_config->keepalive_time = LDP_DEFAULT_KEEPALIVE_TIME;
}
value = json_object_get(ldp, "hold-time");
@@ -1425,6 +1425,13 @@ json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
} else {
ldp_config->ipv4_transport_address = ldp_config->lsr_id;
}
if(json_unpack(ldp, "{s:s}", "raw-update-file", &s) == 0) {
ldp_config->raw_update_file = strdup(s);
if(!ldp_raw_update_load(ldp_config->raw_update_file, true)) {
return false;
}
}
return true;
}
@@ -2333,6 +2340,20 @@ json_parse_config(json_t *root)
}
}
/* Pre-Load LDP RAW update files */
sub = json_object_get(root, "ldp-raw-update-files");
if(json_is_array(sub)) {
size = json_array_size(sub);
for(i = 0; i < size; i++) {
s = json_string_value(json_array_get(sub, i));
if(s) {
if(!ldp_raw_update_load(s, true)) {
return false;
}
}
}
}
/* Interface Configuration */
section = json_object_get(root, "interfaces");
if(json_is_object(section)) {
+6
View File
@@ -156,6 +156,12 @@ struct action actions[] = {
{"bgp-teardown", bgp_ctrl_teardown, true},
{"bgp-raw-update-list", bgp_ctrl_raw_update_list, true},
{"bgp-raw-update", bgp_ctrl_raw_update, false},
{"ldp-adjacencies", ldp_ctrl_adjacencies, true},
{"ldp-sessions", ldp_ctrl_sessions, true},
{"ldp-disconnect", ldp_ctrl_disconnect, false},
{"ldp-teardown", ldp_ctrl_teardown, true},
{"ldp-raw-update-list", ldp_ctrl_raw_update_list, true},
{"ldp-raw-update", ldp_ctrl_raw_update, false},
{"monkey-start", bbl_session_ctrl_monkey_start, false},
{"monkey-stop", bbl_session_ctrl_monkey_stop, false},
{"lag-info", bbl_lag_ctrl_info, true},
+1
View File
@@ -96,6 +96,7 @@ typedef struct bbl_ctx_
bgp_raw_update_s *bgp_raw_updates;
isis_instance_s *isis_instances;
ldp_instance_s *ldp_instances;
ldp_raw_update_s *ldp_raw_updates;
/* Scratchpad memory */
uint8_t *sp;
+1 -1
View File
@@ -1384,7 +1384,7 @@ bbl_session_ctrl_terminate(int fd, uint32_t session_id, json_t *arguments)
/* Terminate single matching session ... */
session = bbl_session_get(session_id);
if(session) {
json_unpack(arguments, "{s:i}", "reconnect-delay", &session->reconnect_delay);
json_unpack(arguments, "{s:i}", "reconnect-delay", &reconnect_delay);
if(reconnect_delay > 0) {
session->reconnect_delay = reconnect_delay;
}
-1
View File
@@ -65,7 +65,6 @@ typedef struct bgp_config_ {
bool start_traffic;
char *network_interface;
char *mrt_file;
char *raw_update_file;
/* Pointer to next instance */
+4 -2
View File
@@ -11,11 +11,13 @@
#include "../bbl.h"
#include "ldp_def.h"
#include "ldp_message.h"
#include "ldp_hello.h"
#include "ldp_interface.h"
#include "ldp_receive.h"
#include "ldp_session.h"
#include "ldp_message.h"
#include "ldp_receive.h"
#include "ldp_raw_update.h"
#include "ldp_ctrl.h"
bool
ldp_init();
+407
View File
@@ -0,0 +1,407 @@
/*
* BNG Blaster (BBL) - LDP CTRL (Control Commands)
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
#include "../bbl_ctrl.h"
static const char *
raw_update_state(ldp_session_s *session)
{
if(session->raw_update) {
if(session->update_start_timestamp.tv_sec) {
if(session->raw_update_sending) {
return "sending";
}
if(session->update_stop_timestamp.tv_sec) {
return "done";
}
} else {
return "wait";
}
}
return NULL;
}
int
ldp_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root, *adjacencies, *adjacency;
ldp_instance_s *ldp_instance = g_ctx->ldp_instances;
ldp_adjacency_s *ldp_adjacency;
int ldp_instance_id = 0;
/* Unpack further arguments */
json_unpack(arguments, "{s:i}", "ldp-instance-id", &ldp_instance_id);
adjacencies = json_array();
while(ldp_instance) {
if(ldp_instance_id > 0 && ldp_instance_id != ldp_instance->config->id) {
ldp_instance = ldp_instance->next;
continue;
}
ldp_adjacency = ldp_instance->adjacencies;
while(ldp_adjacency) {
adjacency = json_pack("{si ss ss}",
"ldp-instance-id", ldp_adjacency->instance->config->id,
"interface", ldp_adjacency->interface->name,
"state", ldp_adjacency->state == LDP_ADJACENCY_STATE_UP ? "up" : "down");
if(adjacency) {
json_array_append(adjacencies, adjacency);
}
ldp_adjacency = ldp_adjacency->next;
}
ldp_instance = ldp_instance->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"ldp-adjacencies", adjacencies);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(adjacencies);
}
return result;
}
static json_t *
ldp_ctrl_session_json(ldp_session_s *session)
{
json_t *root = NULL;
json_t *stats = NULL;
const char *raw_update_file = NULL;
if(!session) {
return NULL;
}
if(session->raw_update) {
raw_update_file = session->raw_update->file;
}
stats = json_pack("{si si si si si si}",
"pdu-rx", session->stats.pdu_rx,
"pdu-tx", session->stats.pdu_tx,
"messages-rx", session->stats.message_rx,
"messages-tx", session->stats.message_tx,
"keepalive-rx", session->stats.keepalive_rx,
"keepalive-tx", session->stats.keepalive_tx);
if(!stats) {
return NULL;
}
root = json_pack("{si ss ss ss si ss ss si ss ss* ss* so*}",
"ldp-instance-id", session->instance->config->id,
"interface", session->interface->name,
"local-address", format_ipv4_address(&session->local.ipv4_address),
"local-lsr-id", format_ipv4_address(&session->local.lsr_id),
"local-label-space-id", session->local.label_space_id,
"peer-address", format_ipv4_address(&session->peer.ipv4_address),
"peer-lsr-id", format_ipv4_address(&session->peer.lsr_id),
"peer-label-space-id", session->peer.label_space_id,
"state", ldp_session_state_string(session->state),
"raw-update-state", raw_update_state(session),
"raw-update-file", raw_update_file,
"stats", stats);
if(!root) {
if(stats) json_decref(stats);
}
return root;
}
int
ldp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root, *sessions, *session;
ldp_instance_s *ldp_instance = g_ctx->ldp_instances;
ldp_session_s *ldp_session;
const char *s;
uint32_t ipv4_local_address = 0;
uint32_t ipv4_peer_address = 0;
int ldp_instance_id = 0;
/* Unpack further arguments */
json_unpack(arguments, "{s:i}", "ldp-instance-id", &ldp_instance_id);
if(json_unpack(arguments, "{s:s}", "local-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_local_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid local-ipv4-address");
}
}
if(json_unpack(arguments, "{s:s}", "peer-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_peer_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid peer-ipv4-address");
}
}
sessions = json_array();
while(ldp_instance) {
if(ldp_instance_id > 0 && ldp_instance_id != ldp_instance->config->id) {
ldp_instance = ldp_instance->next;
continue;
}
ldp_session = ldp_instance->sessions;
while(ldp_session) {
if(ipv4_local_address && ldp_session->local.ipv4_address != ipv4_local_address) {
ldp_session = ldp_session->next;
continue;
}
if(ipv4_peer_address && ldp_session->peer.ipv4_address != ipv4_peer_address) {
ldp_session = ldp_session->next;
continue;
}
session = ldp_ctrl_session_json(ldp_session);
if(session) {
json_array_append(sessions, session);
}
ldp_session = ldp_session->next;
}
ldp_instance = ldp_instance->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"ldp-sessions", sessions);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(sessions);
}
return result;
}
int
ldp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
ldp_teardown();
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
ldp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root;
ldp_instance_s *ldp_instance = g_ctx->ldp_instances;
ldp_session_s *ldp_session;
ldp_raw_update_s *raw_update;
const char *s;
const char *file_path;
uint16_t started = 0;
uint16_t skipped = 0;
uint16_t filtered = 0;
uint32_t ipv4_local_address = 0;
uint32_t ipv4_peer_address = 0;
int ldp_instance_id = 0;
/* Unpack further arguments */
if(json_unpack(arguments, "{s:s}", "file", &file_path) != 0) {
return bbl_ctrl_status(fd, "error", 400, "missing argument file");
}
json_unpack(arguments, "{s:i}", "ldp-instance-id", &ldp_instance_id);
if(json_unpack(arguments, "{s:s}", "local-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_local_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid local-ipv4-address");
}
}
if(json_unpack(arguments, "{s:s}", "peer-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_peer_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid peer-ipv4-address");
}
}
/* Load file. */
raw_update = ldp_raw_update_load(file_path, true);
if(!raw_update) {
return bbl_ctrl_status(fd, "error", 400, "failed to load file");
}
while(ldp_instance) {
ldp_session = ldp_instance->sessions;
while(ldp_session) {
if(ldp_instance_id > 0 && ldp_instance_id != ldp_instance->config->id) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ipv4_local_address && ldp_session->local.ipv4_address != ipv4_local_address) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ipv4_peer_address && ldp_session->peer.ipv4_address != ipv4_peer_address) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ldp_session->raw_update_sending) {
ldp_session = ldp_session->next;
skipped++;
continue;
}
ldp_session->raw_update = raw_update;
timer_add(&g_ctx->timer_root, &ldp_session->update_timer,
"LDP UPDATE", 0, 0, ldp_session,
&ldp_session_update_job);
started++;
ldp_session = ldp_session->next;
}
ldp_instance = ldp_instance->next;
}
root = json_pack("{ss si s{si si si}}",
"status", "ok",
"code", 200,
"ldp-raw-update",
"started", started,
"skipped", skipped,
"filtered", filtered);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
}
return result;
}
int
ldp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
ldp_raw_update_s *raw_update = g_ctx->ldp_raw_updates;
json_t *root, *updates, *update;
updates = json_array();
while(raw_update){
update = json_pack("{ss* si si si}",
"file", raw_update->file,
"len", raw_update->len,
"pdu", raw_update->pdu,
"messages", raw_update->messages);
if(update) {
json_array_append(updates, update);
}
raw_update = raw_update->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"ldp-raw-update-list", updates);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(updates);
}
return result;
}
int
ldp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root;
ldp_instance_s *ldp_instance = g_ctx->ldp_instances;
ldp_session_s *ldp_session;
const char *s;
uint16_t disconnected = 0;
uint16_t skipped = 0;
uint16_t filtered = 0;
uint32_t ipv4_local_address = 0;
uint32_t ipv4_peer_address = 0;
int ldp_instance_id = 0;
/* Unpack further arguments */
json_unpack(arguments, "{s:i}", "ldp-instance-id", &ldp_instance_id);
if(json_unpack(arguments, "{s:s}", "local-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_local_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid local-ipv4-address");
}
}
if(json_unpack(arguments, "{s:s}", "peer-ipv4-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ipv4_peer_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid peer-ipv4-address");
}
}
while(ldp_instance) {
ldp_session = ldp_instance->sessions;
while(ldp_session) {
if(ldp_instance_id > 0 && ldp_instance_id != ldp_instance->config->id) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ipv4_local_address && ldp_session->local.ipv4_address != ipv4_local_address) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ipv4_peer_address && ldp_session->peer.ipv4_address != ipv4_peer_address) {
ldp_session = ldp_session->next;
filtered++;
continue;
}
if(ldp_session->state == LDP_CLOSED || ldp_session->state == LDP_CLOSING) {
ldp_session = ldp_session->next;
skipped++;
continue;
}
if(!ldp_session->error_code) {
ldp_session->error_code = LDP_STATUS_SHUTDOWN;
}
ldp_session_close(ldp_session);
disconnected++;
ldp_session = ldp_session->next;
}
ldp_instance = ldp_instance->next;
}
root = json_pack("{ss si s{si si si}}",
"status", "ok",
"code", 200,
"ldp-disconnect",
"disconnected", disconnected,
"skipped", skipped,
"filtered", filtered);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
}
return result;
}
+30
View File
@@ -0,0 +1,30 @@
/*
* BNG Blaster (BBL) - LDP CTRL (Control Commands)
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_CTRL_H__
#define __BBL_LDP_CTRL_H__
int
ldp_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
ldp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
ldp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
ldp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
ldp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
ldp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
#endif
+4 -2
View File
@@ -62,7 +62,7 @@
#define LDP_STATUS_SHUTDOWN 0x0000000A
#define LDP_STATUS_INTERNAL_ERROR 0x00000019
#define LDP_DEFAULT_KEEPALIVE_INTERVAL 15
#define LDP_DEFAULT_KEEPALIVE_TIME 15
#define LDP_DEFAULT_HOLD_TIME 15
#define LDP_DEFAULT_TEARDOWN_TIME 5
@@ -120,10 +120,12 @@ typedef struct ldp_config_ {
const char *lsr_id_str;
const char *hostname;
uint16_t keepalive_interval;
uint16_t keepalive_time;
uint16_t hold_time;
uint16_t teardown_time;
char *raw_update_file;
/* Pointer to next instance. */
struct ldp_config_ *next;
} ldp_config_s;
+123
View File
@@ -0,0 +1,123 @@
/*
* BNG Blaster (BBL) - LDP RAW Update Functions
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
static ldp_raw_update_s *
ldp_raw_update_load_file(const char *file, bool decode_file)
{
ldp_raw_update_s *raw_update = NULL;
long fsize;
double fsize_kb;
uint8_t *buf = NULL;
uint32_t len = 0;
uint16_t pdu_length;
uint16_t msg_len;
/* Open file */
FILE *f = fopen(file, "rb");
if(f == NULL) {
LOG(ERROR, "Failed to open LDP RAW update file %s\n", file);
return NULL;
}
/* Get file size */
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fsize_kb = fsize/1024.0;
fseek(f, 0, SEEK_SET);
/* Load file into memory */
raw_update = calloc(1, sizeof(ldp_raw_update_s));
raw_update->file = strdup(file);
raw_update->buf = malloc(fsize);
raw_update->len = fsize;
if(fread(raw_update->buf, fsize, 1, f) != 1) {
fclose(f);
LOG(ERROR, "Failed to read LDP RAW update file %s\n", file);
goto ERROR;
}
fclose(f);
if(decode_file) {
/* Decode update stream */
buf = raw_update->buf;
len = raw_update->len;
while(len) {
if(len < LDP_MIN_PDU_LEN) {
goto DECODE_ERROR;
}
raw_update->pdu++;
BUMP_BUFFER(buf, len, sizeof(uint16_t));
pdu_length = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
if(pdu_length > len) {
goto DECODE_ERROR;
}
BUMP_BUFFER(buf, len, LDP_IDENTIFIER_LEN);
while(pdu_length > LDP_MIN_MSG_LEN) {
BUMP_BUFFER(buf, len, sizeof(uint16_t));
msg_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
pdu_length -= 4;
if(msg_len > pdu_length) {
goto DECODE_ERROR;
}
BUMP_BUFFER(buf, len, msg_len);
pdu_length -= msg_len;
raw_update->messages++;
}
}
}
LOG(INFO, "Loaded LDP RAW update file %s (%.2f KB, %u pdu, %u messages)\n",
file, fsize_kb, raw_update->pdu, raw_update->messages);
return raw_update;
DECODE_ERROR:
LOG(ERROR, "Failed to decode LDP RAW update file %s\n", file);
ERROR:
if(raw_update) {
if(raw_update->buf) {
free(raw_update->buf);
}
free(raw_update);
}
return NULL;
}
/**
* ldp_raw_update_load
*
* @param file update file
* @param decode_file decode/parse file content if true
* @return LDP RAW update structure
*/
ldp_raw_update_s *
ldp_raw_update_load(const char *file, bool decode_file)
{
ldp_raw_update_s *raw_update = g_ctx->ldp_raw_updates;
/* Check if file is already loaded */
while(raw_update){
if(strcmp(file, raw_update->file) == 0) {
return raw_update;
}
raw_update = raw_update->next;
}
raw_update = ldp_raw_update_load_file(file, decode_file);
if(raw_update) {
raw_update->next = g_ctx->ldp_raw_updates;
g_ctx->ldp_raw_updates = raw_update;
return raw_update;
} else {
return NULL;
}
}
+15
View File
@@ -0,0 +1,15 @@
/*
* BNG Blaster (BBL) - LDP RAW Update Functions
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_RAW_UPDATE_H__
#define __BBL_LDP_RAW_UPDATE_H__
ldp_raw_update_s *
ldp_raw_update_load(const char *file, bool decode_file);
#endif
+1 -1
View File
@@ -2,7 +2,7 @@
/*
* BNG Blaster (BBL) - LDP Receive Functions
*
* Christian Giese, March 2022
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
+7 -4
View File
@@ -241,7 +241,8 @@ ldp_session_fsm(ldp_session_s *session, ldp_event_t event)
ldp_push_init_message(session, true);
if(ldp_session_send(session)) {
session->stats.pdu_tx++;
session->stats.message_tx++;
session->stats.message_tx += 2;
session->stats.keepalive_tx++;
ldp_session_state_change(session, LDP_OPENREC);
}
} else if(session->state == LDP_OPENSENT) {
@@ -250,6 +251,7 @@ ldp_session_fsm(ldp_session_s *session, ldp_event_t event)
if(ldp_session_send(session)) {
session->stats.pdu_tx++;
session->stats.message_tx++;
session->stats.keepalive_tx++;
ldp_session_state_change(session, LDP_OPENREC);
}
} else {
@@ -449,13 +451,14 @@ ldp_session_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
if(!session) {
session = calloc(1, sizeof(ldp_session_s));
session->next = instance->sessions;
instance->sessions = session;
session->instance = instance;
session->local.ipv4_address = config->ipv4_transport_address;
session->local.lsr_id = config->lsr_id;
session->local.label_space_id = 0;
session->local.keepalive_time = config->keepalive_interval;
session->local.keepalive_time = config->keepalive_time;
session->local.max_pdu_len = LDP_MAX_PDU_LEN_INIT;
session->next = instance->sessions;
instance->sessions = session;
}
session->interface = adjacency->interface;
session->max_pdu_len = session->local.max_pdu_len;
+6
View File
@@ -9,6 +9,12 @@
#ifndef __BBL_LDP_SESSION_H__
#define __BBL_LDP_SESSION_H__
const char *
ldp_session_state_string(ldp_state_t state);
void
ldp_session_update_job(timer_s *timer);
void
ldp_session_restart_keepalive_timeout(ldp_session_s *session);