add BGP update commands

This commit is contained in:
Christian Giese
2022-03-24 20:54:02 +01:00
parent 83bf11bdb4
commit 9d1fbffca0
15 changed files with 390 additions and 170 deletions
-1
View File
@@ -16,7 +16,6 @@ import os
import json
import ast
def error(*args, **kwargs):
"""print error and exit"""
print(*args, file=sys.stderr, **kwargs)
+17
View File
@@ -772,6 +772,9 @@ json_parse_bgp_config(bbl_ctx_s *ctx, json_t *bgp, bgp_config_t *bgp_config) {
if (json_unpack(bgp, "{s:s}", "raw-update-file", &s) == 0) {
bgp_config->raw_update_file = strdup(s);
if(!bgp_raw_update_load(ctx, bgp_config->raw_update_file, true)) {
return false;
}
}
return true;
}
@@ -1707,6 +1710,20 @@ json_parse_config(json_t *root, bbl_ctx_s *ctx) {
}
}
/* Pre-Load BGP RAW update files */
sub = json_object_get(root, "bgp-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(!bgp_raw_update_load(ctx, s, true)) {
return false;
}
}
}
}
/* IS-IS Configuration */
sub = json_object_get(root, "isis");
if (json_is_array(sub)) {
+4 -38
View File
@@ -1471,42 +1471,6 @@ bbl_ctrl_isis_teardown(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
ssize_t
bbl_ctrl_bgp_sessions(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused))) {
ssize_t result = 0;
json_t *root, *sessions, *session;
bgp_session_t *bgp_session = ctx->bgp_sessions;
sessions = json_array();
while(bgp_session) {
session = bgp_ctrl_session(bgp_session);
if(session) {
json_array_append(sessions, session);
}
bgp_session = bgp_session->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"bgp-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;
}
ssize_t
bbl_ctrl_bgp_teardown(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused))) {
bgp_teardown(ctx);
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
struct action {
char *name;
callback_function *fn;
@@ -1557,8 +1521,10 @@ struct action actions[] = {
{"isis-load-mrt", bbl_ctrl_isis_load_mrt},
{"isis-lsp-update", bbl_ctrl_isis_lsp_update},
{"isis-teardown", bbl_ctrl_isis_teardown},
{"bgp-sessions", bbl_ctrl_bgp_sessions},
{"bgp-teardown", bbl_ctrl_bgp_teardown},
{"bgp-sessions", bgp_ctrl_sessions},
{"bgp-teardown", bgp_ctrl_teardown},
{"bgp-raw-update", bgp_ctrl_raw_update},
{"bgp-raw-update-list", bgp_ctrl_raw_update_list},
{NULL, NULL},
};
+3
View File
@@ -10,6 +10,9 @@
#ifndef __BBL_CTRL_H__
#define __BBL_CTRL_H__
ssize_t
bbl_ctrl_status(int fd, const char *status, uint32_t code, const char *message);
bool
bbl_ctrl_socket_open (bbl_ctx_s *ctx);
+1
View File
@@ -102,6 +102,7 @@ typedef struct bbl_ctx_
} interfaces;
bgp_session_t *bgp_sessions;
bgp_raw_update_t *bgp_raw_updates;
isis_instance_t *isis_instances;
/* Scratchpad memory */
+4 -104
View File
@@ -8,91 +8,6 @@
*/
#include "bgp.h"
static bgp_raw_update_t *
bgp_raw_update_load(char *file, bool decode_file) {
bgp_raw_update_t *raw_update = NULL;
long fsize;
double fsize_kb;
uint8_t *buf = NULL;
uint32_t len = 0;
uint16_t msg_len;
uint8_t msg_type;
/* Open file */
FILE *f = fopen(file, "rb");
if (f == NULL) {
LOG(ERROR, "Failed to open BGP RAW update file %s\n", file);
return NULL;
}
/* Get file size */
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fsize_kb = fsize/1024;
fseek(f, 0, SEEK_SET);
/* Load file into memory */
raw_update = malloc(sizeof(bgp_raw_update_t));
raw_update->file = 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 BGP 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 < BGP_MIN_MESSAGE_SIZE) {
goto DECODE_ERROR;
}
if(*(uint64_t*)buf != UINT64_MAX) {
goto DECODE_ERROR;
}
BUMP_BUFFER(buf, len, sizeof(uint64_t));
if(*(uint64_t*)buf != UINT64_MAX) {
goto DECODE_ERROR;
}
BUMP_BUFFER(buf, len, sizeof(uint64_t));
msg_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
msg_type = *buf;
BUMP_BUFFER(buf, len, sizeof(uint8_t));
if(msg_len < BGP_MIN_MESSAGE_SIZE ||
msg_len > BGP_MAX_MESSAGE_SIZE) {
goto DECODE_ERROR;
}
if((msg_len - BGP_MIN_MESSAGE_SIZE) > len) {
goto DECODE_ERROR;
}
if(msg_type == BGP_MSG_UPDATE) {
raw_update->updates++;
}
BUMP_BUFFER(buf, len, (msg_len - BGP_MIN_MESSAGE_SIZE));
}
}
LOG(INFO, "Loaded BGP RAW update file %s (%.2f KB, %u updates)\n",
file, fsize_kb, raw_update->updates);
return raw_update;
DECODE_ERROR:
LOG(ERROR, "Failed to decode BGP RAW update file %s\n", file);
ERROR:
if(raw_update) {
if(raw_update->buf) {
free(raw_update->buf);
}
free(raw_update);
}
return NULL;
}
/**
* bgp_init
*
@@ -107,9 +22,6 @@ bgp_init(bbl_ctx_s *ctx) {
bgp_session_t *session = NULL;
bbl_interface_s *network_if;
bgp_raw_update_t *raw_update_root = NULL;
bgp_raw_update_t *raw_update = NULL;
while(config) {
if(session) {
session->next = calloc(1, sizeof(bgp_session_t));
@@ -147,23 +59,11 @@ bgp_init(bbl_ctx_s *ctx) {
/* Init RAW update file */
if(config->raw_update_file) {
raw_update = raw_update_root;
while(raw_update){
if (strcmp(config->raw_update_file, raw_update->file) == 0) {
session->raw_update = raw_update;
break;
}
raw_update = raw_update->next;
}
if(!session->raw_update) {
session->raw_update = bgp_raw_update_load(config->raw_update_file, true);
if(session->raw_update) {
session->raw_update->next = raw_update_root;
raw_update_root = session->raw_update;
} else {
return false;
}
session->raw_update_start = bgp_raw_update_load(ctx, config->raw_update_file, true);
if(!session->raw_update_start) {
return false;
}
session->raw_update = session->raw_update_start;
}
LOG(BGP, "BGP (%s %s - %s) init session\n",
+1 -1
View File
@@ -14,7 +14,7 @@
#include "bgp_session.h"
#include "bgp_message.h"
#include "bgp_receive.h"
#include "bgp_mrt.h"
#include "bgp_raw_update.h"
#include "bgp_ctrl.h"
bool
+204 -3
View File
@@ -7,16 +7,40 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bgp.h"
#include "../bbl_ctrl.h"
json_t *
bgp_ctrl_session(bgp_session_t *session) {
static const char *
raw_update_state(bgp_session_t *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;
}
static json_t *
bgp_ctrl_session_json(bgp_session_t *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}",
"messages-rx", session->stats.message_rx,
"messages-tx", session->stats.message_tx,
@@ -29,7 +53,7 @@ bgp_ctrl_session(bgp_session_t *session) {
return NULL;
}
root = json_pack("{ss ss ss si si ss ss si si ss so}",
root = json_pack("{ss ss ss si si ss ss si si ss ss* ss* so*}",
"interface", session->interface->name,
"local-address", format_ipv4_address(&session->ipv4_local_address),
"local-id", format_ipv4_address(&session->config->id),
@@ -40,10 +64,187 @@ bgp_ctrl_session(bgp_session_t *session) {
"peer-as", session->peer.as,
"peer-holdtime", session->peer.holdtime,
"state", bgp_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;
}
ssize_t
bgp_ctrl_sessions(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments) {
ssize_t result = 0;
json_t *root, *sessions, *session;
bgp_session_t *bgp_session = ctx->bgp_sessions;
const char *s;
uint32_t ipv4_local_address = 0;
uint32_t ipv4_peer_address = 0;
/* Unpack further arguments */
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(bgp_session) {
if(ipv4_local_address && bgp_session->ipv4_local_address != ipv4_local_address) {
bgp_session = bgp_session->next;
continue;
}
if(ipv4_peer_address && bgp_session->ipv4_peer_address != ipv4_peer_address) {
bgp_session = bgp_session->next;
continue;
}
session = bgp_ctrl_session_json(bgp_session);
if(session) {
json_array_append(sessions, session);
}
bgp_session = bgp_session->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"bgp-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;
}
ssize_t
bgp_ctrl_teardown(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused))) {
bgp_teardown(ctx);
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
ssize_t
bgp_ctrl_raw_update(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments) {
ssize_t result = 0;
json_t *root;
bgp_session_t *bgp_session = ctx->bgp_sessions;
bgp_raw_update_t *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;
/* Unpack further arguments */
if (json_unpack(arguments, "{s:s}", "file", &file_path) != 0) {
return bbl_ctrl_status(fd, "error", 400, "missing argument file");
}
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 = bgp_raw_update_load(ctx, file_path, true);
if(!raw_update) {
return bbl_ctrl_status(fd, "error", 400, "failed to load file");
}
while(bgp_session) {
if(ipv4_local_address && bgp_session->ipv4_local_address != ipv4_local_address) {
bgp_session = bgp_session->next;
filtered++;
continue;
}
if(ipv4_peer_address && bgp_session->ipv4_peer_address != ipv4_peer_address) {
bgp_session = bgp_session->next;
filtered++;
continue;
}
if(bgp_session->raw_update_sending) {
bgp_session = bgp_session->next;
skipped++;
continue;
}
bgp_session->raw_update = raw_update;
timer_add(&ctx->timer_root, &bgp_session->update_timer,
"BGP UPDATE", 0, 0, bgp_session,
&bgp_session_update_job);
started++;
bgp_session = bgp_session->next;
}
root = json_pack("{ss si s{si si}}",
"status", "ok",
"code", 200,
"bgp-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;
}
ssize_t
bgp_ctrl_raw_update_list(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused))) {
ssize_t result = 0;
bgp_raw_update_t *raw_update = ctx->bgp_raw_updates;
json_t *root, *updates, *update;
updates = json_array();
while(raw_update){
update = json_pack("{ss* si si}",
"file", raw_update->file,
"len", raw_update->len,
"updates", raw_update->updates);
if(update) {
json_array_append(updates, update);
}
raw_update = raw_update->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"bgp-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;
}
+11 -2
View File
@@ -9,7 +9,16 @@
#ifndef __BBL_BGP_CTRL_H__
#define __BBL_BGP_CTRL_H__
json_t *
bgp_ctrl_session(bgp_session_t *session);
ssize_t
bgp_ctrl_sessions(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
ssize_t
bgp_ctrl_teardown(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
ssize_t
bgp_ctrl_raw_update(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments);
ssize_t
bgp_ctrl_raw_update_list(int fd, bbl_ctx_s *ctx, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
#endif
+3 -2
View File
@@ -39,7 +39,7 @@ typedef enum bgp_state_ {
* BGP RAW Update File
*/
typedef struct bgp_raw_update_ {
char *file;
const char *file;
uint8_t *buf;
uint32_t len;
@@ -115,8 +115,9 @@ typedef struct bgp_session_ {
uint32_t update_tx;
} stats;
bgp_raw_update_t *raw_update_start;
bgp_raw_update_t *raw_update;
bool raw_update_send;
bool raw_update_sending;
struct timespec established_timestamp;
struct timespec update_start_timestamp;
-12
View File
@@ -1,12 +0,0 @@
/*
* BNG Blaster (BBL) - BGP MRT Files
*
* Christian Giese, March 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_BGP_MRT_H__
#define __BBL_BGP_MRT_H__
#endif
+116
View File
@@ -0,0 +1,116 @@
/*
* BNG Blaster (BBL) - BGP RAW Update Functions
*
* Christian Giese, March 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bgp.h"
static bgp_raw_update_t *
bgp_raw_update_load_file(const char *file, bool decode_file) {
bgp_raw_update_t *raw_update = NULL;
long fsize;
double fsize_kb;
uint8_t *buf = NULL;
uint32_t len = 0;
uint16_t msg_len;
uint8_t msg_type;
/* Open file */
FILE *f = fopen(file, "rb");
if (f == NULL) {
LOG(ERROR, "Failed to open BGP 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(bgp_raw_update_t));
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 BGP 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 < BGP_MIN_MESSAGE_SIZE) {
goto DECODE_ERROR;
}
BUMP_BUFFER(buf, len, 16);
msg_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
msg_type = *buf;
BUMP_BUFFER(buf, len, sizeof(uint8_t));
if(msg_len < BGP_MIN_MESSAGE_SIZE ||
msg_len > BGP_MAX_MESSAGE_SIZE) {
goto DECODE_ERROR;
}
if((msg_len - BGP_MIN_MESSAGE_SIZE) > len) {
goto DECODE_ERROR;
}
if(msg_type == BGP_MSG_UPDATE) {
raw_update->updates++;
}
BUMP_BUFFER(buf, len, (msg_len - BGP_MIN_MESSAGE_SIZE));
}
}
LOG(INFO, "Loaded BGP RAW update file %s (%.2f KB, %u updates)\n",
file, fsize_kb, raw_update->updates);
return raw_update;
DECODE_ERROR:
LOG(ERROR, "Failed to decode BGP RAW update file %s\n", file);
ERROR:
if(raw_update) {
if(raw_update->buf) {
free(raw_update->buf);
}
free(raw_update);
}
return NULL;
}
/**
* bgp_raw_update_load
*
* @param ctx global context
* @param file update file
* @param decode_file decode/parse file content if true
* @return BGP RAW update structure
*/
bgp_raw_update_t *
bgp_raw_update_load(bbl_ctx_s *ctx, const char *file, bool decode_file) {
bgp_raw_update_t *raw_update = ctx->bgp_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 = bgp_raw_update_load_file(file, decode_file);
if(raw_update) {
raw_update->next = ctx->bgp_raw_updates;
ctx->bgp_raw_updates = raw_update;
return raw_update;
} else {
return NULL;
}
}
+15
View File
@@ -0,0 +1,15 @@
/*
* BNG Blaster (BBL) - BGP RAW Update Functions
*
* Christian Giese, March 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_BGP_RAW_UPDATE_H__
#define __BBL_BGP_RAW_UPDATE_H__
bgp_raw_update_t *
bgp_raw_update_load(bbl_ctx_s *ctx, const char *file, bool decode_file);
#endif
+8 -7
View File
@@ -94,10 +94,11 @@ bgp_raw_update_stop_cb(void *arg) {
timespec_sub(&time_diff,
&session->update_stop_timestamp,
&session->update_start_timestamp);
session->raw_update_sending = false;
session->stats.message_tx += session->raw_update->updates;
session->stats.update_tx += session->raw_update->updates;
LOG(BGP, "BGP (%s %s - %s) raw update stop after %lds\n",
session->interface->name,
format_ipv4_address(&session->ipv4_local_address),
@@ -115,9 +116,9 @@ bgp_session_update_job(timer_s *timer) {
bbl_ctx_s *ctx = session->interface->ctx;
if(session->state == BGP_ESTABLISHED) {
if(session->raw_update && !session->raw_update_send) {
if(session->raw_update && !session->raw_update_sending) {
if(bbl_tcp_send(session->tcpc, session->raw_update->buf, session->raw_update->len)) {
session->raw_update_send = true;
session->raw_update_sending = true;
LOG(BGP, "BGP (%s %s - %s) raw update start\n",
session->interface->name,
@@ -126,7 +127,6 @@ bgp_session_update_job(timer_s *timer) {
clock_gettime(CLOCK_MONOTONIC, &session->update_start_timestamp);
session->tcpc->idle_cb = bgp_raw_update_stop_cb;
} else {
goto RETRY;
}
@@ -317,8 +317,9 @@ bgp_session_connect(bgp_session_t *session, time_t delay) {
session->stats.keepalive_tx = 0;
session->stats.update_rx = 0;
session->stats.update_tx = 0;
session->raw_update_send = false;
session->raw_update = session->raw_update_start;
session->raw_update_sending = false;
session->established_timestamp.tv_sec = 0;
session->established_timestamp.tv_nsec = 0;
+3
View File
@@ -12,6 +12,9 @@
const char *
bgp_session_state_string(bgp_state_t state);
void
bgp_session_update_job(timer_s *timer);
void
bgp_session_state_change(bgp_session_t *session, bgp_state_t new_state);