mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
add BGP update commands
This commit is contained in:
@@ -16,7 +16,6 @@ import os
|
||||
import json
|
||||
import ast
|
||||
|
||||
|
||||
def error(*args, **kwargs):
|
||||
"""print error and exit"""
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user