From 4e341fc354a6f41bf957dd87547cee60a9a6958b Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Tue, 15 Mar 2022 15:13:19 +0100 Subject: [PATCH] BGP ctrl commands, config, docu ... --- code/bngblaster/src/bbl_config.c | 24 ++++++----- code/bngblaster/src/bbl_ctrl.c | 31 ++++++++++++++ code/bngblaster/src/bgp/bgp.c | 16 ++++---- code/bngblaster/src/bgp/bgp.h | 1 + code/bngblaster/src/bgp/bgp_ctrl.c | 32 +++++++++++++++ code/bngblaster/src/bgp/bgp_ctrl.h | 15 +++++++ code/bngblaster/src/bgp/bgp_def.h | 8 ++-- code/bngblaster/src/bgp/bgp_receive.c | 40 +++++++++--------- code/bngblaster/src/bgp/bgp_session.c | 58 ++++++++++++++------------- code/bngblaster/src/bgp/bgp_session.h | 3 ++ code/bngblaster/src/isis/isis_ctrl.c | 1 - docs/bgp.md | 45 +++++++++++++++++++++ docs/config.md | 17 ++++++++ docs/index.md | 1 + 14 files changed, 221 insertions(+), 71 deletions(-) create mode 100644 code/bngblaster/src/bgp/bgp_ctrl.c create mode 100644 code/bngblaster/src/bgp/bgp_ctrl.h create mode 100644 docs/bgp.md diff --git a/code/bngblaster/src/bbl_config.c b/code/bngblaster/src/bbl_config.c index 0744c245..9657733c 100644 --- a/code/bngblaster/src/bbl_config.c +++ b/code/bngblaster/src/bbl_config.c @@ -698,21 +698,25 @@ json_parse_bgp_config(bbl_ctx_s *ctx, json_t *bgp, bgp_config_t *bgp_config) { ctx->tcp = true; - if (json_unpack(bgp, "{s:s}", "source-ipv4-address", &s) == 0) { - if (!inet_pton(AF_INET, s, &bgp_config->ipv4_src_address)) { - fprintf(stderr, "JSON config error: Invalid value for bgp->source-ipv4-address\n"); - return false; - } - add_secondary_ipv4(ctx, bgp_config->ipv4_src_address); + if (json_unpack(bgp, "{s:s}", "network-interface", &s) == 0) { + bgp_config->network_interface = strdup(s); } - if (json_unpack(bgp, "{s:s}", "destination-ipv4-address", &s) == 0) { - if (!inet_pton(AF_INET, s, &bgp_config->ipv4_dst_address)) { - fprintf(stderr, "JSON config error: Invalid value for bgp->destination-ipv4-address\n"); + if (json_unpack(bgp, "{s:s}", "local-ipv4-address", &s) == 0) { + if (!inet_pton(AF_INET, s, &bgp_config->ipv4_local_address)) { + fprintf(stderr, "JSON config error: Invalid value for bgp->local-ipv4-address\n"); + return false; + } + add_secondary_ipv4(ctx, bgp_config->ipv4_local_address); + } + + if (json_unpack(bgp, "{s:s}", "peer-ipv4-address", &s) == 0) { + if (!inet_pton(AF_INET, s, &bgp_config->ipv4_peer_address)) { + fprintf(stderr, "JSON config error: Invalid value for bgp->peer-ipv4-address\n"); return false; } } else { - fprintf(stderr, "JSON config error: Missing value for bgp->destination-ipv4-address\n"); + fprintf(stderr, "JSON config error: Missing value for bgp->peer-ipv4-address\n"); return false; } diff --git a/code/bngblaster/src/bbl_ctrl.c b/code/bngblaster/src/bbl_ctrl.c index d9d209bd..76b93223 100644 --- a/code/bngblaster/src/bbl_ctrl.c +++ b/code/bngblaster/src/bbl_ctrl.c @@ -1433,6 +1433,36 @@ bbl_ctrl_isis_lsp_update(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; +} + struct action { char *name; callback_function *fn; @@ -1481,6 +1511,7 @@ struct action actions[] = { {"isis-database", bbl_ctrl_isis_database}, {"isis-load-mrt", bbl_ctrl_isis_load_mrt}, {"isis-lsp-update", bbl_ctrl_isis_lsp_update}, + {"bgp-sessions", bbl_ctrl_bgp_sessions}, {NULL, NULL}, }; diff --git a/code/bngblaster/src/bgp/bgp.c b/code/bngblaster/src/bgp/bgp.c index 9227350a..5df50af5 100644 --- a/code/bngblaster/src/bgp/bgp.c +++ b/code/bngblaster/src/bgp/bgp.c @@ -82,12 +82,12 @@ bgp_init(bbl_ctx_s *ctx) { session->config = config; session->interface = network_if; - if(config->ipv4_src_address) { - session->ipv4_src_address = config->ipv4_src_address; + if(config->ipv4_local_address) { + session->ipv4_local_address = config->ipv4_local_address; } else { - session->ipv4_src_address = network_if->ip.address; + session->ipv4_local_address = network_if->ip.address; } - session->ipv4_dst_address = config->ipv4_dst_address; + session->ipv4_peer_address = config->ipv4_peer_address; /* Init read/write buffer */ session->read_buf.data = malloc(BGP_BUF_SIZE); @@ -114,8 +114,8 @@ bgp_init(bbl_ctx_s *ctx) { LOG(BGP, "BGP (%s %s - %s) init session\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); bgp_session_connect(session, 1); ctx->routing_sessions++; @@ -148,8 +148,8 @@ bgp_teardown(bbl_ctx_s *ctx) { if(!session->teardown) { LOG(BGP, "BGP (%s %s - %s) teardown session\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); session->teardown = true; if(!session->error_code) { diff --git a/code/bngblaster/src/bgp/bgp.h b/code/bngblaster/src/bgp/bgp.h index a605455b..b5cad53f 100644 --- a/code/bngblaster/src/bgp/bgp.h +++ b/code/bngblaster/src/bgp/bgp.h @@ -15,6 +15,7 @@ #include "bgp_message.h" #include "bgp_receive.h" #include "bgp_mrt.h" +#include "bgp_ctrl.h" bool bgp_init(bbl_ctx_s *ctx); diff --git a/code/bngblaster/src/bgp/bgp_ctrl.c b/code/bngblaster/src/bgp/bgp_ctrl.c new file mode 100644 index 00000000..eec5231f --- /dev/null +++ b/code/bngblaster/src/bgp/bgp_ctrl.c @@ -0,0 +1,32 @@ +/* + * BNG Blaster (BBL) - BGP CTRL (Control Commands) + * + * Christian Giese, March 2022 + * + * Copyright (C) 2020-2022, RtBrick, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "bgp.h" + +json_t * +bgp_ctrl_session(bgp_session_t *session) { + json_t *root = NULL; + + if(!session) { + return NULL; + } + + root = json_pack("{ss ss ss si si ss ss si si ss }", + "interface", session->interface->name, + "local-address", format_ipv4_address(&session->ipv4_local_address), + "local-id", format_ipv4_address(&session->config->id), + "local-as", session->config->local_as, + "local-holdtime", session->config->holdtime, + "peer-address", format_ipv4_address(&session->ipv4_peer_address), + "peer-id", format_ipv4_address(&session->peer.id), + "peer-as", session->peer.as, + "peer-holdtime", session->peer.holdtime, + "state", bgp_session_state_string(session->state)); + + return root; +} \ No newline at end of file diff --git a/code/bngblaster/src/bgp/bgp_ctrl.h b/code/bngblaster/src/bgp/bgp_ctrl.h new file mode 100644 index 00000000..350403d9 --- /dev/null +++ b/code/bngblaster/src/bgp/bgp_ctrl.h @@ -0,0 +1,15 @@ +/* + * BNG Blaster (BBL) - BGP CTRL (Control Commands) + * + * Christian Giese, March 2022 + * + * Copyright (C) 2020-2022, RtBrick, Inc. + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __BBL_BGP_CTRL_H__ +#define __BBL_BGP_CTRL_H__ + +json_t * +bgp_ctrl_session(bgp_session_t *session); + +#endif \ No newline at end of file diff --git a/code/bngblaster/src/bgp/bgp_def.h b/code/bngblaster/src/bgp/bgp_def.h index 738f9a90..39fdd8ec 100644 --- a/code/bngblaster/src/bgp/bgp_def.h +++ b/code/bngblaster/src/bgp/bgp_def.h @@ -52,8 +52,8 @@ typedef struct bgp_raw_update_ { * BGP Configuration */ typedef struct bgp_config_ { - uint32_t ipv4_src_address; - uint32_t ipv4_dst_address; + uint32_t ipv4_local_address; + uint32_t ipv4_peer_address; uint32_t id; uint32_t local_as; uint32_t peer_as; @@ -76,8 +76,8 @@ typedef struct bgp_config_ { typedef struct bgp_session_ { struct bbl_ctx_ *ctx; /* parent */ - uint32_t ipv4_src_address; - uint32_t ipv4_dst_address; + uint32_t ipv4_local_address; + uint32_t ipv4_peer_address; bgp_config_t *config; bbl_interface_s *interface; diff --git a/code/bngblaster/src/bgp/bgp_receive.c b/code/bngblaster/src/bgp/bgp_receive.c index 63a45c22..bc9a00d0 100644 --- a/code/bngblaster/src/bgp/bgp_receive.c +++ b/code/bngblaster/src/bgp/bgp_receive.c @@ -80,8 +80,8 @@ bgp_open(bgp_session_t *session, uint8_t *start, uint16_t length) { LOG(BGP, "BGP (%s %s - %s) open message received with peer AS: %u, holdtime: %us\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), session->peer.as, session->peer.holdtime); bgp_session_state_change(session, BGP_OPENCONFIRM); @@ -90,8 +90,8 @@ bgp_open(bgp_session_t *session, uint8_t *start, uint16_t length) { ERROR: LOG(BGP, "BGP (%s %s - %s) invalid open message received\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); if(!session->error_code) { session->error_code = 1; /* Message header error */ @@ -114,40 +114,40 @@ bgp_notification(bgp_session_t *session, uint8_t *start, uint16_t length) { case 1: /* Message Header Error */ LOG(BGP, "BGP (%s %s - %s) notification received with error: %s (%u), %s (%u)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_notification_error_values, error_code), error_code, keyval_get_key(bgp_notification_msg_hdr_error_values, error_subcode), error_subcode); break; case 2: /* OPEN Message Error */ LOG(BGP, "BGP (%s %s - %s) notification received with error: %s (%u), %s (%u)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_notification_error_values, error_code), error_code, keyval_get_key(bgp_notification_open_error_values, error_subcode), error_subcode); break; case 3: /* Update Message Error */ LOG(BGP, "BGP (%s %s - %s) notification received with error: %s (%u), %s (%u)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_notification_error_values, error_code), error_code, keyval_get_key(bgp_notification_update_error_values, error_subcode), error_subcode); break; case 6: /* Cease */ LOG(BGP, "BGP (%s %s - %s) notification received with error: %s (%u), %s (%u)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_notification_error_values, error_code), error_code, keyval_get_key(bgp_notification_cease_error_values, error_subcode), error_subcode); break; default: LOG(BGP, "BGP (%s %s - %s) notification received with error: %s (%u), subcode %u\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_notification_error_values, error_code), error_code, error_subcode); break; } @@ -158,8 +158,8 @@ bgp_notification(bgp_session_t *session, uint8_t *start, uint16_t length) { ERROR: LOG(BGP, "BGP (%s %s - %s) invalid notification message received\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); if(!session->error_code) { session->error_code = 1; /* Message header error */ @@ -215,8 +215,8 @@ bpg_read(bgp_session_t *session) { LOG(DEBUG, "BGP (%s %s - %s) read %s message\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), keyval_get_key(bgp_msg_names, type)); switch (type) { @@ -256,8 +256,8 @@ bgp_receive_cb(void *arg, uint8_t *buf, uint16_t len) { if(buffer->idx+len > buffer->size) { LOG(ERROR, "BGP (%s %s - %s) receive error (read buffer exhausted)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); if(!session->error_code) { session->error_code = 6; /* Cease */ diff --git a/code/bngblaster/src/bgp/bgp_session.c b/code/bngblaster/src/bgp/bgp_session.c index 3eb5b994..847875d7 100644 --- a/code/bngblaster/src/bgp/bgp_session.c +++ b/code/bngblaster/src/bgp/bgp_session.c @@ -10,18 +10,20 @@ extern bool g_init_phase; extern volatile bool g_teardown; -struct keyval_ bgp_fsm_state_names[] = { - { BGP_CLOSED, "closed" }, - { BGP_IDLE, "idle" }, - { BGP_CONNECT, "connect" }, - { BGP_ACTIVE, "active" }, - { BGP_OPENSENT, "opensent" }, - { BGP_OPENCONFIRM, "openconfirm" }, - { BGP_ESTABLISHED, "established" }, - { BGP_CLOSING, "closing" }, - { 0, NULL} -}; - +const char * +bgp_session_state_string(bgp_state_t state) { + switch(state) { + case BGP_CLOSED: return "closed"; + case BGP_IDLE: return "idle"; + case BGP_CONNECT: return "connect"; + case BGP_ACTIVE: return "active"; + case BGP_OPENSENT: return "opensent"; + case BGP_OPENCONFIRM: return "openconfirm"; + case BGP_ESTABLISHED: return "established"; + case BGP_CLOSING: return "closing"; + default: return "unknown"; + } +} /** * bgp_session_reset_read_buffer @@ -151,10 +153,10 @@ bgp_session_state_change(bgp_session_t *session, bgp_state_t new_state) { LOG(BGP, "BGP (%s %s - %s) state changed from %s -> %s\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), - keyval_get_key(bgp_fsm_state_names, session->state), - keyval_get_key(bgp_fsm_state_names, new_state)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), + bgp_session_state_string(session->state), + bgp_session_state_string(new_state)); session->state = new_state; @@ -185,8 +187,8 @@ bgp_error_cb(void *arg, err_t err) { LOG(BGP, "BGP (%s %s - %s) TCP error %d (%s)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), err, tcp_err_string(err)); session->error_code = 0; @@ -206,8 +208,8 @@ bgp_session_connect_job(timer_s *timer) { /* Connect TCP session */ session->tcpc = bbl_tcp_ipv4_connect( session->interface, - &session->ipv4_src_address, - &session->ipv4_dst_address, + &session->ipv4_local_address, + &session->ipv4_peer_address, BGP_PORT); if(session->tcpc) { @@ -221,8 +223,8 @@ bgp_session_connect_job(timer_s *timer) { } else { LOG(BGP, "BGP (%s %s - %s) TCP connect failed\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); } } else if(session->state == BGP_ESTABLISHED) { timer->periodic = false; @@ -230,8 +232,8 @@ bgp_session_connect_job(timer_s *timer) { } else { LOG(BGP, "BGP (%s %s - %s) connect timeout\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); bgp_session_close(session); timer->periodic = false; @@ -309,8 +311,8 @@ bgp_session_close(bgp_session_t *session) { /* Send notification messages */ LOG(BGP, "BGP (%s %s - %s) send notification message (error code %u sub-code %u)\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address), + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address), session->error_code, session->error_subcode); bgp_session_reset_write_buffer(session); bgp_push_notification_message(session); @@ -330,8 +332,8 @@ bgp_session_hold_timer_job(timer_s *timer) { LOG(BGP, "BGP (%s %s - %s) session timeout\n", session->interface->name, - format_ipv4_address(&session->ipv4_src_address), - format_ipv4_address(&session->ipv4_dst_address)); + format_ipv4_address(&session->ipv4_local_address), + format_ipv4_address(&session->ipv4_peer_address)); if(!session->error_code) { session->error_code = 4; /* hold timer expired */ diff --git a/code/bngblaster/src/bgp/bgp_session.h b/code/bngblaster/src/bgp/bgp_session.h index 18a980e4..999e4c00 100644 --- a/code/bngblaster/src/bgp/bgp_session.h +++ b/code/bngblaster/src/bgp/bgp_session.h @@ -9,6 +9,9 @@ #ifndef __BBL_BGP_SESSION_H__ #define __BBL_BGP_SESSION_H__ +const char * +bgp_session_state_string(bgp_state_t state); + void bgp_session_state_change(bgp_session_t *session, bgp_state_t new_state); diff --git a/code/bngblaster/src/isis/isis_ctrl.c b/code/bngblaster/src/isis/isis_ctrl.c index 43193d1b..11c37540 100644 --- a/code/bngblaster/src/isis/isis_ctrl.c +++ b/code/bngblaster/src/isis/isis_ctrl.c @@ -31,7 +31,6 @@ isis_ctrl_adjacency_p2p(isis_adjacency_p2p_t *adjacency) { if(!root) { if(peer) json_decref(peer); } - return root; } diff --git a/docs/bgp.md b/docs/bgp.md new file mode 100644 index 00000000..9dd95f64 --- /dev/null +++ b/docs/bgp.md @@ -0,0 +1,45 @@ +# BGP + +The Border Gateway Protocol (BGP) is a standardized exterior gateway protocol +designed to exchange routing and reachability information among autonomous systems +(AS) on the internet. BGP is classified as a path-vector routing protocol, and it +makes routing decisions based on paths, network policies, or rule-sets configured +by a network administrator. + +Following an example ISIS configuration with one instance +attached to two network interfaces. + +```json +{ + "interfaces": { + "network": [ + { + "interface": "eth1", + "address": "10.0.1.2/24", + "gateway": "10.0.1.1" + } + ] + }, + "bgp": [ + { + "local-ipv4-address": "10.0.1.2", + "peer-ipv4-address": "10.0.1.1", + "raw-update-file": "test.bgp", + "local-as": 65001, + "peer-as": 65001 + } + ] +} +``` + +## Limitations + +Currently only IPv4 sessions are supported. + +## RAW Update Files + +The BNG Blaster is able to inject BGP update messages +from a pre-compiled RAW update file into the defined +session. + + diff --git a/docs/config.md b/docs/config.md index e1c2f5dc..425e046e 100644 --- a/docs/config.md +++ b/docs/config.md @@ -915,3 +915,20 @@ Attribute | Description | Default ] } ``` + +## BGP + +This section describes all attributes of the `bgp` hierarchy. + +Attribute | Description | Default +--------- | ----------- | ------- +`network-interface` | BGP local interface (source-interface) | first network interface +`local-ipv4-address` | BGP local IPv4 address (source-address) | network interface address +`local-as` | BGP local AS | 65000 +`peer-ipv4-address` | BGP peer address | +`peer-as` | BGP peer AS | local AS +`holdtime` | BGP holdtime in seconds | 90 +`id` | BGP identifier | 1.2.3.4 +`reconnect` | BGP reconnect | true +`teardown-time` | BGP teardown time in seconds | 5 +`raw-update-file` | BGP RAW update file | diff --git a/docs/index.md b/docs/index.md index e9e664e8..6c804672 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,6 +14,7 @@ - [Legal Interception](li) - [A10NSP](a10nsp) - [ISIS](isis) +- [BGP](bgp) The BNG Blaster is an open source network test tool which is able to simulate more than hundred thousand PPPoE and IPoE subscribers including IPTV, L2TPv2, QoS, forwarding