mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
BGP Initial (WIP)
This commit is contained in:
@@ -564,6 +564,15 @@ main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Init TCP. */
|
||||
bbl_tcp_init(ctx);
|
||||
|
||||
/* Init BGP sessions. */
|
||||
if(!bgp_init(ctx)) {
|
||||
fprintf(stderr, "Error: Failed to init BGP\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Start curses. */
|
||||
if (interactive) {
|
||||
bbl_init_curses(ctx);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "bbl_def.h"
|
||||
|
||||
#include "bbl_protocols.h"
|
||||
#include "bgp/bgp_def.h"
|
||||
#include "isis/isis_def.h"
|
||||
|
||||
#include "bbl_stats.h"
|
||||
@@ -43,6 +44,7 @@
|
||||
#include "bbl_a10nsp.h"
|
||||
#include "bbl_li.h"
|
||||
#include "bbl_tcp.h"
|
||||
#include "bgp/bgp.h"
|
||||
#include "isis/isis.h"
|
||||
|
||||
WINDOW *log_win;
|
||||
|
||||
@@ -282,6 +282,18 @@ json_parse_network_interface(bbl_ctx_s *ctx, json_t *network_interface, bbl_netw
|
||||
network_config->vlan &= 4095;
|
||||
}
|
||||
|
||||
value = json_object_get(network_interface, "mtu");
|
||||
if (json_is_number(value)) {
|
||||
network_config->mtu = json_number_value(value);
|
||||
} else {
|
||||
network_config->mtu = 1500;
|
||||
}
|
||||
|
||||
if(network_config->mtu < 64 || network_config->mtu > 9000) {
|
||||
fprintf(stderr, "JSON config error: Invalid value for network->mtu\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
value = json_object_get(network_interface, "gateway-resolve-wait");
|
||||
if (json_is_boolean(value)) {
|
||||
network_config->gateway_resolve_wait = json_boolean_value(value);
|
||||
@@ -679,6 +691,69 @@ json_parse_a10nsp_interface(bbl_ctx_s *ctx, json_t *a10nsp_interface, bbl_a10nsp
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
json_parse_bgp_config(bbl_ctx_s *ctx, json_t *bgp, bgp_config_t *bgp_config) {
|
||||
json_t *value = NULL;
|
||||
const char *s = NULL;
|
||||
|
||||
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}", "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");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "JSON config error: Missing value for bgp->destination-ipv4-address\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
value = json_object_get(bgp, "local-as");
|
||||
if (value) {
|
||||
bgp_config->local_as = json_number_value(value);
|
||||
} else {
|
||||
bgp_config->local_as = BGP_DEFAULT_AS;
|
||||
}
|
||||
|
||||
value = json_object_get(bgp, "peer-as");
|
||||
if (value) {
|
||||
bgp_config->peer_as = json_number_value(value);
|
||||
} else {
|
||||
bgp_config->peer_as = bgp_config->local_as;
|
||||
}
|
||||
|
||||
value = json_object_get(bgp, "holdtime");
|
||||
if (value) {
|
||||
bgp_config->holdtime = json_number_value(value);
|
||||
} else {
|
||||
bgp_config->holdtime = BGP_DEFAULT_HOLDTIME;
|
||||
}
|
||||
|
||||
bgp_config->id = htobe32(0x01020304);
|
||||
if (json_unpack(bgp, "{s:s}", "id", &s) == 0) {
|
||||
if (!inet_pton(AF_INET, s, &bgp_config->id)) {
|
||||
fprintf(stderr, "JSON config error: Invalid value for bgp->id\n");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (json_unpack(bgp, "{s:s}", "mrt-file", &s) == 0) {
|
||||
bgp_config->mrt_file = strdup(s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
json_parse_isis_config(bbl_ctx_s *ctx, json_t *isis, isis_config_t *isis_config) {
|
||||
json_t *sub, *con, *c, *value = NULL;
|
||||
@@ -1181,6 +1256,7 @@ json_parse_config(json_t *root, bbl_ctx_s *ctx) {
|
||||
bbl_access_config_s *access_config = NULL;
|
||||
bbl_a10nsp_config_s *a10nsp_config = NULL;
|
||||
|
||||
bgp_config_t *bgp_config = NULL;
|
||||
isis_config_t *isis_config = NULL;
|
||||
|
||||
if (json_typeof(root) != JSON_OBJECT) {
|
||||
@@ -1581,6 +1657,34 @@ json_parse_config(json_t *root, bbl_ctx_s *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
/* BGP Configuration */
|
||||
sub = json_object_get(root, "bgp");
|
||||
if (json_is_array(sub)) {
|
||||
/* Config is provided as array (multiple bgp sessions) */
|
||||
size = json_array_size(sub);
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!bgp_config) {
|
||||
ctx->config.bgp_config = calloc(1, sizeof(bgp_config_t));
|
||||
bgp_config = ctx->config.bgp_config;
|
||||
} else {
|
||||
bgp_config->next = calloc(1, sizeof(bgp_config_t));
|
||||
bgp_config = bgp_config->next;
|
||||
}
|
||||
if (!json_parse_bgp_config(ctx, json_array_get(sub, i), bgp_config)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (json_is_object(sub)) {
|
||||
/* Config is provided as object (single bgp session) */
|
||||
bgp_config = calloc(1, sizeof(bgp_config_t));
|
||||
if (!ctx->config.bgp_config) {
|
||||
ctx->config.bgp_config = bgp_config;
|
||||
}
|
||||
if (!json_parse_bgp_config(ctx, sub, bgp_config)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* IS-IS Configuration */
|
||||
sub = json_object_get(root, "isis");
|
||||
if (json_is_array(sub)) {
|
||||
|
||||
@@ -87,7 +87,8 @@ typedef struct bbl_network_config_
|
||||
uint8_t gateway_mac[ETH_ADDR_LEN];
|
||||
bool gateway_resolve_wait;
|
||||
uint16_t vlan;
|
||||
|
||||
uint16_t mtu;
|
||||
|
||||
ipv4_prefix ip;
|
||||
ipv4addr_t gateway;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ bbl_compare_key32 (void *key1, void *key2)
|
||||
}
|
||||
|
||||
uint32_t
|
||||
bbl_key32_hash (const void* k)
|
||||
bbl_key32_hash(const void* k)
|
||||
{
|
||||
uint32_t hash = 2166136261U;
|
||||
hash ^= *(uint32_t *)k;
|
||||
@@ -29,7 +29,7 @@ bbl_key32_hash (const void* k)
|
||||
}
|
||||
|
||||
int
|
||||
bbl_compare_key64 (void *key1, void *key2)
|
||||
bbl_compare_key64(void *key1, void *key2)
|
||||
{
|
||||
const uint64_t a = *(const uint64_t*)key1;
|
||||
const uint64_t b = *(const uint64_t*)key2;
|
||||
@@ -37,7 +37,7 @@ bbl_compare_key64 (void *key1, void *key2)
|
||||
}
|
||||
|
||||
uint32_t
|
||||
bbl_key64_hash (const void* k)
|
||||
bbl_key64_hash(const void* k)
|
||||
{
|
||||
uint32_t hash = 2166136261U;
|
||||
|
||||
@@ -85,9 +85,6 @@ bbl_ctx_add (void)
|
||||
ctx->li_flow_dict = hashtable_dict_new((dict_compare_func)bbl_compare_key32, bbl_key32_hash, BBL_LI_HASHTABLE_SIZE);
|
||||
ctx->stream_flow_dict = hashtable_dict_new((dict_compare_func)bbl_compare_key64, bbl_key64_hash, BBL_STREAM_FLOW_HASHTABLE_SIZE);
|
||||
|
||||
/* Initialize TCP. */
|
||||
bbl_tcp_init(ctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ typedef struct bbl_ctx_
|
||||
|
||||
void *stream_thread; /* single linked list of threads */
|
||||
|
||||
bool tcp;
|
||||
|
||||
/* Interfaces */
|
||||
struct {
|
||||
uint8_t count;
|
||||
@@ -99,6 +101,7 @@ typedef struct bbl_ctx_
|
||||
struct bbl_interface_ *a10nsp_if[BBL_MAX_INTERFACES];
|
||||
} interfaces;
|
||||
|
||||
bgp_session_t *bgp_sessions;
|
||||
isis_instance_t *isis_instances;
|
||||
|
||||
/* Scratchpad memory */
|
||||
@@ -171,6 +174,9 @@ typedef struct bbl_ctx_
|
||||
/* Traffic Streams */
|
||||
void *stream_config;
|
||||
|
||||
/* BGP Instances */
|
||||
bgp_config_t *bgp_config;
|
||||
|
||||
/* ISIS Instances */
|
||||
isis_config_t *isis_config;
|
||||
|
||||
@@ -301,6 +307,18 @@ typedef struct bbl_ctx_
|
||||
} config;
|
||||
} bbl_ctx_s;
|
||||
|
||||
int
|
||||
bbl_compare_key32 (void *key1, void *key2);
|
||||
|
||||
uint
|
||||
bbl_key32_hash(const void* k);
|
||||
|
||||
int
|
||||
bbl_compare_key64(void *key1, void *key2);
|
||||
|
||||
uint
|
||||
bbl_key64_hash(const void* k);
|
||||
|
||||
bbl_ctx_s *
|
||||
bbl_ctx_add(void);
|
||||
|
||||
|
||||
@@ -173,5 +173,6 @@ typedef struct bbl_a10nsp_session_ bbl_a10nsp_session_t;
|
||||
typedef struct bbl_stream_thread_ bbl_stream_thread;
|
||||
typedef struct bbl_stream_config_ bbl_stream_config;
|
||||
typedef struct bbl_stream_ bbl_stream;
|
||||
typedef struct bbl_tcp_ctx_ bbl_tcp_ctx_t;
|
||||
|
||||
#endif
|
||||
@@ -86,6 +86,7 @@ typedef struct bbl_interface_
|
||||
uint16_t mc_packet_cursor;
|
||||
|
||||
struct netif netif; /* LwIP network interface */
|
||||
dict *tcp_connections; /* hashtable for tcp_connections */
|
||||
|
||||
isis_adjacency_p2p_t *isis_adjacency_p2p;
|
||||
isis_adjacency_t *isis_adjacency[ISIS_LEVELS];
|
||||
|
||||
@@ -2555,6 +2555,35 @@ decode_udp(uint8_t *buf, uint16_t len,
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_tcp
|
||||
*/
|
||||
protocol_error_t
|
||||
decode_tcp(uint8_t *buf, uint16_t len,
|
||||
uint8_t *sp, uint16_t sp_len,
|
||||
bbl_tcp_t **_tcp) {
|
||||
|
||||
protocol_error_t ret_val = PROTOCOL_SUCCESS;
|
||||
|
||||
bbl_tcp_t *tcp;
|
||||
|
||||
if(len < 20 || sp_len < sizeof(bbl_tcp_t)) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
|
||||
/* Init UDP header */
|
||||
tcp = (bbl_tcp_t*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_tcp_t));
|
||||
|
||||
tcp->src = be16toh(*(uint16_t*)buf);
|
||||
BUMP_BUFFER(buf, len, sizeof(uint16_t));
|
||||
tcp->dst = be16toh(*(uint16_t*)buf);
|
||||
BUMP_BUFFER(buf, len, sizeof(uint16_t));
|
||||
|
||||
*_tcp = tcp;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* decode_ipv6
|
||||
*/
|
||||
@@ -2607,6 +2636,9 @@ decode_ipv6(uint8_t *buf, uint16_t len,
|
||||
case IPV6_NEXT_HEADER_UDP:
|
||||
ret_val = decode_udp(buf, len, sp, sp_len, (bbl_udp_t**)&ipv6->next);
|
||||
break;
|
||||
case IPV6_NEXT_HEADER_TCP:
|
||||
ret_val = decode_tcp(buf, len, sp, sp_len, (bbl_tcp_t**)&ipv6->next);
|
||||
break;
|
||||
default:
|
||||
ipv6->next = NULL;
|
||||
break;
|
||||
@@ -2703,6 +2735,10 @@ decode_ipv4(uint8_t *buf, uint16_t len,
|
||||
case PROTOCOL_IPV4_UDP:
|
||||
ret_val = decode_udp(buf, len, sp, sp_len, (bbl_udp_t**)&ipv4->next);
|
||||
break;
|
||||
case PROTOCOL_IPV4_TCP:
|
||||
ret_val = decode_tcp(buf, len, sp, sp_len, (bbl_tcp_t**)&ipv4->next);
|
||||
break;
|
||||
|
||||
default:
|
||||
ipv4->next = NULL;
|
||||
break;
|
||||
|
||||
@@ -675,6 +675,16 @@ typedef struct bbl_udp_ {
|
||||
uint16_t payload_len; /* UDP payload length */
|
||||
} bbl_udp_t;
|
||||
|
||||
/*
|
||||
* TCP Structure
|
||||
*/
|
||||
typedef struct bbl_tcp_ {
|
||||
uint16_t src;
|
||||
uint16_t dst;
|
||||
uint16_t len; /* TCP total length */
|
||||
uint8_t *hdr; /* TCP header start */
|
||||
} bbl_tcp_t;
|
||||
|
||||
/*
|
||||
* IGMP Structure
|
||||
*/
|
||||
|
||||
@@ -1781,27 +1781,13 @@ bbl_rx_handler_access(bbl_ethernet_header_t *eth, bbl_interface_s *interface) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_rx_test_tcp(bbl_interface_s *interface) {
|
||||
static uint8_t test_packet[1024] = {0};
|
||||
LOG(TCP, "START TCP SESSION on interface %s\n", interface->name);
|
||||
bbl_tcp_t *tcp = bbl_tcp_ipv4_connect(interface, &interface->ip.address, &interface->gateway, 179);
|
||||
if(tcp) {
|
||||
bbl_tcp_send(tcp, test_packet, sizeof(test_packet));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_rx_network_arp(bbl_ethernet_header_t *eth, bbl_interface_s *interface) {
|
||||
bbl_secondary_ip_s *secondary_ip;
|
||||
|
||||
bbl_arp_t *arp = (bbl_arp_t*)eth->next;
|
||||
if(arp->sender_ip == interface->gateway) {
|
||||
if(!interface->arp_resolved) {
|
||||
bbl_rx_test_tcp(interface);
|
||||
}
|
||||
interface->arp_resolved = true;
|
||||
|
||||
if(*(uint32_t*)interface->gateway_mac == 0) {
|
||||
memcpy(interface->gateway_mac, arp->sender, ETH_ADDR_LEN);
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ typedef struct isis_external_connection_ {
|
||||
} isis_external_connection_t;
|
||||
|
||||
/*
|
||||
* IS-IS Instance
|
||||
* IS-IS Instance Configuration
|
||||
*/
|
||||
typedef struct isis_config_ {
|
||||
|
||||
|
||||
+174
-67
@@ -10,8 +10,8 @@
|
||||
#include "bbl.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
|
||||
void
|
||||
bbl_tcp_ctx_free(bbl_tcp_t *tcp) {
|
||||
static void
|
||||
bbl_tcp_ctx_free(bbl_tcp_ctx_t *tcp) {
|
||||
if(tcp) {
|
||||
if(tcp->pcb) {
|
||||
tcp_close(tcp->pcb);
|
||||
@@ -20,13 +20,13 @@ bbl_tcp_ctx_free(bbl_tcp_t *tcp) {
|
||||
}
|
||||
}
|
||||
|
||||
static bbl_tcp_t *
|
||||
bbl_tcp_new(bbl_interface_s *interface) {
|
||||
static bbl_tcp_ctx_t *
|
||||
bbl_tcp_ctx_new(bbl_interface_s *interface) {
|
||||
|
||||
bbl_tcp_t *tcp;
|
||||
bbl_tcp_ctx_t *tcp;
|
||||
|
||||
/* Init TCP context */
|
||||
tcp = calloc(1, sizeof(bbl_tcp_t));
|
||||
tcp = calloc(1, sizeof(bbl_tcp_ctx_t));
|
||||
if(!tcp) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -50,18 +50,24 @@ bbl_tcp_new(bbl_interface_s *interface) {
|
||||
|
||||
err_t
|
||||
bbl_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) {
|
||||
bbl_tcp_t *tcp = arg;
|
||||
bbl_tcp_ctx_t *tcpc = arg;
|
||||
size_t tx = tpcb->snd_buf;
|
||||
|
||||
UNUSED(len);
|
||||
|
||||
if(tcp->tx.offset < tcp->tx.len) {
|
||||
tcp->state = BBL_TCP_STATE_SEND;
|
||||
if((tcp->tx.offset + tx) > tcp->tx.len) {
|
||||
tx = tcp->tx.len - tcp->tx.offset;
|
||||
if(tcpc->tx.offset < tcpc->tx.len) {
|
||||
tcpc->state = BBL_TCP_STATE_SEND;
|
||||
if((tcpc->tx.offset + tx) > tcpc->tx.len) {
|
||||
tx = tcpc->tx.len - tcpc->tx.offset;
|
||||
}
|
||||
if(tcp_write(tpcb, tcp->tx.buf + tcp->tx.offset, tx, 0) == ERR_OK) {
|
||||
tcp->tx.offset += tx;
|
||||
if(tcp_write(tpcb, tcpc->tx.buf + tcpc->tx.offset, tx, 0) == ERR_OK) {
|
||||
tcpc->tx.offset += tx;
|
||||
if(tcpc->af == AF_INET) {
|
||||
LOG(TCP_DETAIL, "TCP %lu bytes send (%s %s:%u - %s:%u)\n",
|
||||
tx, tcpc->interface->name,
|
||||
format_ipv4_address(&tcpc->local_ipv4), tcpc->key.local_port,
|
||||
format_ipv4_address(&tcpc->remote_ipv4), tcpc->key.remote_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
@@ -69,42 +75,100 @@ bbl_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) {
|
||||
|
||||
err_t
|
||||
bbl_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
|
||||
bbl_tcp_t *tcp = arg;
|
||||
bbl_tcp_ctx_t *tcpc = arg;
|
||||
struct pbuf *_p;
|
||||
|
||||
UNUSED(err); /* TODO!!! */
|
||||
LOG(TCP, "TCP RX CB\n");
|
||||
|
||||
if(p) {
|
||||
_p = p;
|
||||
while(_p) {
|
||||
if(tcp->receive_cb) {
|
||||
(tcp->receive_cb)(tcp->arg, p->payload, p->len);
|
||||
if(tcpc->receive_cb) {
|
||||
(tcpc->receive_cb)(tcpc->arg, p->payload, p->len);
|
||||
}
|
||||
_p = _p->next;
|
||||
}
|
||||
tcp->bytes_rx += p->tot_len;
|
||||
tcpc->bytes_rx += p->tot_len;
|
||||
tcp_recved(tpcb, p->tot_len);
|
||||
pbuf_free(p);
|
||||
|
||||
if(tcpc->af == AF_INET) {
|
||||
LOG(TCP_DETAIL, "TCP %u bytes received (%s %s:%u - %s:%u)\n",
|
||||
p->tot_len, tcpc->interface->name,
|
||||
format_ipv4_address(&tcpc->local_ipv4), tcpc->key.local_port,
|
||||
format_ipv4_address(&tcpc->remote_ipv4), tcpc->key.remote_port);
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the pcb receives a RST or is unexpectedly closed for any other reason.
|
||||
*
|
||||
* @note The corresponding pcb is already freed when this callback is called!
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param err Error code to indicate why the pcb has been closed
|
||||
* ERR_ABRT: aborted through tcp_abort or by a TCP timer
|
||||
* ERR_RST: the connection was reset by the remote host
|
||||
*/
|
||||
void
|
||||
bbl_tcp_error_cb(void *arg, err_t err) {
|
||||
bbl_tcp_ctx_t *tcpc = arg;
|
||||
|
||||
if(tcpc->af == AF_INET) {
|
||||
LOG(TCP, "TCP error %u (%s %s:%u - %s:%u)\n",
|
||||
err, tcpc->interface->name,
|
||||
format_ipv4_address(&tcpc->local_ipv4), tcpc->key.local_port,
|
||||
format_ipv4_address(&tcpc->remote_ipv4), tcpc->key.remote_port);
|
||||
}
|
||||
|
||||
if(tcpc->error_cb) {
|
||||
(tcpc->error_cb)(tcpc->arg, err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called periodically.
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param tpcb tcp pcb
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*/
|
||||
err_t
|
||||
bbl_tcp_poll_cb(void *arg, struct tcp_pcb *tpcb) {
|
||||
bbl_tcp_ctx_t *tcpc = arg;
|
||||
if(tcpc->poll_cb) {
|
||||
return (tcpc->poll_cb)(tcpc->arg, tpcb);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t
|
||||
bbl_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
||||
bbl_tcp_t *tcp = arg;
|
||||
bbl_tcp_ctx_t *tcpc = arg;
|
||||
|
||||
UNUSED(err); /* TODO!!! */
|
||||
|
||||
/* Add send/receive callback functions. */
|
||||
tcp_sent(tpcb, bbl_tcp_sent_cb);
|
||||
tcp_recv(tpcb, bbl_tcp_recv_cb);
|
||||
//tcp_err(tpcb, bbl_tcp_error_cb);
|
||||
//tcp_poll(tpcb, bbl_tcp_poll_cb, 0);
|
||||
tcp_err(tpcb, bbl_tcp_error_cb);
|
||||
if(tcpc->poll_cb && tcpc->poll_interval) {
|
||||
tcp_poll(tpcb, bbl_tcp_poll_cb, tcpc->poll_interval);
|
||||
}
|
||||
|
||||
LOG(TCP, "TCP session connected\n");
|
||||
if(tcpc->af == AF_INET) {
|
||||
LOG(TCP_DETAIL, "TCP session connected (%s %s:%u - %s:%u)\n",
|
||||
tcpc->interface->name,
|
||||
format_ipv4_address(&tcpc->local_ipv4), tcpc->key.local_port,
|
||||
format_ipv4_address(&tcpc->remote_ipv4), tcpc->key.remote_port);
|
||||
}
|
||||
|
||||
tcp->state = BBL_TCP_STATE_IDLE;
|
||||
bbl_tcp_sent_cb(tcp, tpcb, 0);
|
||||
tcpc->state = BBL_TCP_STATE_IDLE;
|
||||
bbl_tcp_sent_cb(tcpc, tpcb, 0);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -115,44 +179,54 @@ bbl_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
||||
* @param src source address
|
||||
* @param dst destination address
|
||||
* @param port destination port
|
||||
* @return bbl_tcp_t*
|
||||
* @return bbl_tcp_ctx_t *
|
||||
*/
|
||||
bbl_tcp_t *
|
||||
bbl_tcp_ctx_t *
|
||||
bbl_tcp_ipv4_connect(bbl_interface_s *interface, ipv4addr_t *src, ipv4addr_t *dst, uint16_t port) {
|
||||
|
||||
bbl_tcp_t *tcp;
|
||||
bbl_tcp_ctx_t *tcpc;
|
||||
dict_insert_result result;
|
||||
|
||||
tcp = bbl_tcp_new(interface);
|
||||
if(!tcp) {
|
||||
if(!interface->ctx->tcp) return NULL;
|
||||
|
||||
tcpc = bbl_tcp_ctx_new(interface);
|
||||
if(!tcpc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Bind local IP address and port */
|
||||
tcp_bind(tcp->pcb, (const ip_addr_t*)src, 0);
|
||||
tcp_bind(tcpc->pcb, (const ip_addr_t*)src, 0);
|
||||
|
||||
/* Connect session */
|
||||
if(tcp_connect(tcp->pcb, (const ip_addr_t*)dst, port, bbl_tcp_connected) != ERR_OK) {
|
||||
bbl_tcp_ctx_free(tcp);
|
||||
if(tcp_connect(tcpc->pcb, (const ip_addr_t*)dst, port, bbl_tcp_connected) != ERR_OK) {
|
||||
bbl_tcp_ctx_free(tcpc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcpc->af = AF_INET;
|
||||
tcpc->key.local_port = tcpc->pcb->local_port;
|
||||
tcpc->key.remote_port = port;
|
||||
tcpc->local_ipv4 = *src;
|
||||
tcpc->remote_ipv4 = *dst;
|
||||
|
||||
/* Add BBL TCP context to interface */
|
||||
result = dict_insert(interface->tcp_connections, &tcpc->key);
|
||||
if (!result.inserted) {
|
||||
bbl_tcp_ctx_free(tcpc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcp->af = AF_INET;
|
||||
tcp->local.ipv4 = *src;
|
||||
tcp->local.port = tcp->pcb->local_port;
|
||||
tcp->remote.ipv4 = *dst;
|
||||
tcp->remote.port = port;
|
||||
|
||||
/* TODO: This looks wrong but is required.
|
||||
* Further investigations needed! */
|
||||
tcp->pcb->remote_ip.type = IPADDR_TYPE_V4;
|
||||
tcpc->pcb->local_ip.type = IPADDR_TYPE_V4;
|
||||
tcpc->pcb->remote_ip.type = IPADDR_TYPE_V4;
|
||||
|
||||
LOG(TCP, "TCP connect from %s (%u) %s:%u to %s:%u\n",
|
||||
LOG(TCP, "TCP connect (%s %s:%u - %s:%u)\n",
|
||||
interface->name,
|
||||
tcp->pcb->netif_idx,
|
||||
format_ipv4_address(&tcp->local.ipv4), tcp->local.port,
|
||||
format_ipv4_address(&tcp->remote.ipv4), tcp->remote.port);
|
||||
format_ipv4_address(&tcpc->local_ipv4), tcpc->key.local_port,
|
||||
format_ipv4_address(&tcpc->remote_ipv4), tcpc->key.remote_port);
|
||||
|
||||
return tcp;
|
||||
return tcpc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,20 +239,16 @@ bbl_tcp_ipv4_connect(bbl_interface_s *interface, ipv4addr_t *src, ipv4addr_t *ds
|
||||
void
|
||||
bbl_tcp_ipv4_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv4_t *ipv4) {
|
||||
struct pbuf *pbuf;
|
||||
bbl_tcp_t *tcp = (bbl_tcp_t*)ipv4->next;
|
||||
|
||||
UNUSED(eth);
|
||||
|
||||
LOG(TCP, "TCP RX from %s %s to %s\n",
|
||||
interface->name,
|
||||
format_ipv4_address(&ipv4->src),
|
||||
format_ipv4_address(&ipv4->dst));
|
||||
if(!interface->ctx->tcp) return;
|
||||
|
||||
/* Alternative code...
|
||||
struct ip_hdr *iphdr = (struct ip_hdr*)ipv4->hdr;
|
||||
ip_addr_copy_from_ip4(*ip_current_dest_addr(), iphdr->dest);
|
||||
ip_addr_copy_from_ip4(*ip_current_src_addr(), iphdr->src);
|
||||
ip_current_netif() = &interface->netif;
|
||||
ip_current_input_netif() = &interface->netif;
|
||||
*/
|
||||
LOG(TCP_DETAIL, "TCP packet received (%s %s:%u - %s:%u)\n",
|
||||
interface->name,
|
||||
format_ipv4_address(&ipv4->dst), tcp->dst,
|
||||
format_ipv4_address(&ipv4->src), tcp->src);
|
||||
|
||||
ip_data.current_netif = &interface->netif;
|
||||
ip_data.current_input_netif = &interface->netif;
|
||||
@@ -191,6 +261,26 @@ bbl_tcp_ipv4_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv4
|
||||
tcp_input(pbuf, &interface->netif);
|
||||
}
|
||||
|
||||
/**
|
||||
* bbl_tcp_ipv6_connect
|
||||
*
|
||||
* @param interface interface
|
||||
* @param src source address
|
||||
* @param dst destination address
|
||||
* @param port destination port
|
||||
* @return bbl_tcp_ctx_t *
|
||||
*/
|
||||
bbl_tcp_ctx_t *
|
||||
bbl_tcp_ipv6_connect(bbl_interface_s *interface, ipv6addr_t *src, ipv6addr_t *dst, uint16_t port) {
|
||||
|
||||
if(!interface->ctx->tcp) return NULL;
|
||||
|
||||
UNUSED(src);
|
||||
UNUSED(dst);
|
||||
UNUSED(port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* bbl_tcp_ipv6_rx
|
||||
*
|
||||
@@ -201,7 +291,17 @@ bbl_tcp_ipv4_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv4
|
||||
void
|
||||
bbl_tcp_ipv6_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv6_t *ipv6) {
|
||||
struct pbuf *pbuf;
|
||||
bbl_tcp_t *tcp = (bbl_tcp_t*)ipv6->next;
|
||||
|
||||
UNUSED(eth);
|
||||
|
||||
if(!interface->ctx->tcp) return;
|
||||
|
||||
LOG(TCP_DETAIL, "TCP packet received (%s %s:%u - %s:%u)\n",
|
||||
interface->name,
|
||||
format_ipv6_address((ipv6addr_t*)ipv6->dst), tcp->dst,
|
||||
format_ipv6_address((ipv6addr_t*)ipv6->src), tcp->src);
|
||||
|
||||
pbuf = pbuf_alloc_reference(ipv6->hdr, ipv6->len, PBUF_ROM);
|
||||
interface->netif.input(pbuf, &interface->netif);
|
||||
}
|
||||
@@ -215,19 +315,19 @@ bbl_tcp_ipv6_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv6
|
||||
* @return ERR_OK if successfull
|
||||
*/
|
||||
err_t
|
||||
bbl_tcp_send(bbl_tcp_t *tcp, uint8_t *buf, uint16_t len) {
|
||||
bbl_tcp_send(bbl_tcp_ctx_t *tcpc, uint8_t *buf, uint16_t len) {
|
||||
|
||||
if(tcp->tx.offset < tcp->tx.len) {
|
||||
if(tcpc->tx.offset < tcpc->tx.len) {
|
||||
/* There is still data to send */
|
||||
return ERR_INPROGRESS;
|
||||
}
|
||||
|
||||
tcp->tx.buf = buf;
|
||||
tcp->tx.len = len;
|
||||
tcp->tx.offset = 0;
|
||||
tcpc->tx.buf = buf;
|
||||
tcpc->tx.len = len;
|
||||
tcpc->tx.offset = 0;
|
||||
|
||||
if(tcp->state == BBL_TCP_STATE_IDLE) {
|
||||
bbl_tcp_sent_cb(tcp, tcp->pcb, 0);
|
||||
if(tcpc->state == BBL_TCP_STATE_IDLE) {
|
||||
bbl_tcp_sent_cb(tcpc, tcpc->pcb, 0);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -263,8 +363,8 @@ bbl_tcp_netif_output_ipv4(struct netif *netif, struct pbuf *p, const ip4_addr_t
|
||||
*/
|
||||
err_t
|
||||
bbl_tcp_netif_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) {
|
||||
bbl_tcp_t *tcp = netif->state;
|
||||
bbl_interface_s *interface = tcp->interface;
|
||||
bbl_tcp_ctx_t *tcpc = netif->state;
|
||||
bbl_interface_s *interface = tcpc->interface;
|
||||
bbl_ethernet_header_t eth = {0};
|
||||
|
||||
UNUSED(ipaddr);
|
||||
@@ -306,12 +406,17 @@ bbl_tcp_netif_init(struct netif *netif) {
|
||||
bool
|
||||
bbl_tcp_interface_init(bbl_interface_s *interface, bbl_network_config_s *network_config) {
|
||||
UNUSED(network_config);
|
||||
|
||||
if(!interface->ctx->tcp) return true;
|
||||
|
||||
if(!netif_add(&interface->netif, NULL, NULL, NULL, interface, bbl_tcp_netif_init, ip_input)) {
|
||||
return false;
|
||||
}
|
||||
interface->netif.state = interface;
|
||||
interface->netif.mtu = 1492;
|
||||
interface->netif.mtu6 = 1492;
|
||||
interface->netif.mtu = network_config->mtu;
|
||||
interface->netif.mtu6 = network_config->mtu;
|
||||
interface->tcp_connections = hashtable_dict_new((dict_compare_func)bbl_compare_key32, bbl_key32_hash, BBL_TCP_HASHTABLE_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -333,9 +438,11 @@ bbl_tcp_timer(timer_s *timer) {
|
||||
void
|
||||
bbl_tcp_init(bbl_ctx_s *ctx) {
|
||||
|
||||
if(!ctx->tcp) return;
|
||||
|
||||
lwip_init();
|
||||
|
||||
/* Start TCP timer */
|
||||
timer_add_periodic(&ctx->timer_root, &ctx->tcp_timer, "TCP",
|
||||
0, BBL_TCP_INTERVAL, ctx, &bbl_tcp_timer);
|
||||
0, BBL_TCP_INTERVAL, ctx, &bbl_tcp_timer);
|
||||
}
|
||||
+31
-18
@@ -12,6 +12,7 @@
|
||||
|
||||
#define BBL_TCP_BUF_SIZE 65000
|
||||
#define BBL_TCP_INTERVAL 250*MSEC
|
||||
#define BBL_TCP_HASHTABLE_SIZE 32771
|
||||
|
||||
typedef enum bbl_tcp_state_ {
|
||||
BBL_TCP_STATE_CONNECT,
|
||||
@@ -22,29 +23,36 @@ typedef enum bbl_tcp_state_ {
|
||||
BBL_TCP_STATE_CLOSED,
|
||||
} bbl_tcp_state_t;
|
||||
|
||||
typedef void (*bbl_tcp_receive_cb)(void *arg, uint8_t *buf, uint16_t len);
|
||||
typedef void (*bbl_tcp_receive_fn)(void *arg, uint8_t *buf, uint16_t len);
|
||||
typedef void (*bbl_tcp_error_fn)(void *arg, err_t err);
|
||||
typedef err_t (*bbl_tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
|
||||
|
||||
typedef struct bbl_tcp_
|
||||
typedef struct bbl_tcp_key_ {
|
||||
uint16_t local_port;
|
||||
uint16_t remote_port;
|
||||
} __attribute__ ((__packed__)) bbl_tcp_key_t;
|
||||
|
||||
typedef struct bbl_tcp_ctx_
|
||||
{
|
||||
bbl_interface_s *interface;
|
||||
|
||||
|
||||
uint8_t af; /* AF_INET or AF_INET6 */
|
||||
|
||||
bbl_tcp_key_t key;
|
||||
|
||||
struct {
|
||||
ipv4addr_t ipv4;
|
||||
ipv6addr_t ipv6;
|
||||
uint16_t port;
|
||||
} local;
|
||||
|
||||
struct {
|
||||
ipv4addr_t ipv4;
|
||||
ipv6addr_t ipv6;
|
||||
uint16_t port;
|
||||
} remote;
|
||||
ipv4addr_t local_ipv4;
|
||||
ipv6addr_t local_ipv6;
|
||||
ipv4addr_t remote_ipv4;
|
||||
ipv6addr_t remote_ipv6;
|
||||
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
bbl_tcp_receive_cb receive_cb; /* application receive callback */
|
||||
bbl_tcp_receive_fn receive_cb; /* application receive callback */
|
||||
bbl_tcp_error_fn error_cb; /* application receive callback */
|
||||
|
||||
bbl_tcp_poll_fn poll_cb; /* application poll callback */
|
||||
uint8_t poll_interval;
|
||||
|
||||
void *arg; /* application callback argument */
|
||||
|
||||
bbl_tcp_state_t state;
|
||||
@@ -55,22 +63,27 @@ typedef struct bbl_tcp_
|
||||
size_t offset;
|
||||
} tx;
|
||||
|
||||
uint64_t packets_rx;
|
||||
uint64_t bytes_rx;
|
||||
uint64_t packets_tx;
|
||||
uint64_t bytes_tx;
|
||||
|
||||
} bbl_tcp_t;
|
||||
} bbl_tcp_ctx_t;
|
||||
|
||||
bbl_tcp_t *
|
||||
bbl_tcp_ctx_t *
|
||||
bbl_tcp_ipv4_connect(bbl_interface_s *interface, ipv4addr_t *src, ipv4addr_t *dst, uint16_t port);
|
||||
|
||||
void
|
||||
bbl_tcp_ipv4_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv4_t *ipv4);
|
||||
|
||||
bbl_tcp_ctx_t *
|
||||
bbl_tcp_ipv6_connect(bbl_interface_s *interface, ipv6addr_t *src, ipv6addr_t *dst, uint16_t port);
|
||||
|
||||
void
|
||||
bbl_tcp_ipv6_rx(bbl_interface_s *interface, bbl_ethernet_header_t *eth, bbl_ipv6_t *ipv6);
|
||||
|
||||
err_t
|
||||
bbl_tcp_send(bbl_tcp_t *tcp, uint8_t *buf, uint16_t len);
|
||||
bbl_tcp_send(bbl_tcp_ctx_t *tcpc, uint8_t *buf, uint16_t len);
|
||||
|
||||
bool
|
||||
bbl_tcp_interface_init(bbl_interface_s *interface, bbl_network_config_s *network_config);
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - BGP Functions
|
||||
*
|
||||
* Christian Giese, March 2022
|
||||
*
|
||||
* Copyright (C) 2020-2022, RtBrick, Inc.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "bgp.h"
|
||||
|
||||
static const char *
|
||||
bgp_state_string(uint32_t state) {
|
||||
switch(state) {
|
||||
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";
|
||||
default: return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bgp_state_change(bgp_session_t *session, bgp_state_t new_state)
|
||||
{
|
||||
if (session->state == new_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(BGP, "BGP %s:%s state change from %s -> %s\n",
|
||||
format_ipv4_address(&session->ipv4_src_address),
|
||||
format_ipv4_address(&session->ipv4_dst_address),
|
||||
bgp_state_string(session->state),
|
||||
bgp_state_string(new_state));
|
||||
|
||||
session->state = new_state;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_receive_cb(void *arg, uint8_t *buf, uint16_t len) {
|
||||
bgp_session_t *session = (bgp_session_t*)arg;
|
||||
|
||||
UNUSED(buf);
|
||||
UNUSED(len);
|
||||
|
||||
if(session->state == BGP_CONNECT) {
|
||||
bgp_message_open(session);
|
||||
bbl_tcp_send(session->tcpc, session->write_buf, session->write_idx);
|
||||
bgp_state_change(session, BGP_OPENSENT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bgp_connect_job(timer_s *timer) {
|
||||
bgp_session_t *session = timer->data;
|
||||
if(!session->interface->arp_resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
session->tcpc = bbl_tcp_ipv4_connect(
|
||||
session->interface,
|
||||
&session->ipv4_src_address,
|
||||
&session->ipv4_dst_address,
|
||||
BGP_PORT);
|
||||
|
||||
if(!session->tcpc) {
|
||||
/* Try again... */
|
||||
return;
|
||||
}
|
||||
|
||||
session->tcpc->arg = session;
|
||||
session->tcpc->receive_cb = bgp_receive_cb;
|
||||
|
||||
bgp_state_change(session, BGP_CONNECT);
|
||||
|
||||
/* Stop timer... */
|
||||
timer->periodic = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* bgp_init
|
||||
*
|
||||
* This function inits all BGP sessions.
|
||||
*
|
||||
* @param ctx global context
|
||||
*/
|
||||
bool
|
||||
bgp_init(bbl_ctx_s *ctx) {
|
||||
|
||||
bgp_config_t *config = ctx->config.bgp_config;
|
||||
bgp_session_t *session = NULL;
|
||||
bbl_interface_s *network_if;
|
||||
|
||||
while(config) {
|
||||
if(session) {
|
||||
session->next = calloc(1, sizeof(bgp_session_t));
|
||||
session = session->next;
|
||||
} else {
|
||||
session = calloc(1, sizeof(bgp_session_t));
|
||||
ctx->bgp_sessions = session;
|
||||
}
|
||||
if(!session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
network_if = bbl_get_network_interface(ctx, config->network_interface);
|
||||
if(!network_if) {
|
||||
free(session);
|
||||
return false;
|
||||
}
|
||||
|
||||
session->ctx = ctx;
|
||||
session->config = config;
|
||||
session->interface = network_if;
|
||||
|
||||
if(config->ipv4_src_address) {
|
||||
session->ipv4_src_address = config->ipv4_src_address;
|
||||
} else {
|
||||
session->ipv4_src_address = network_if->ip.address;
|
||||
}
|
||||
session->ipv4_dst_address = config->ipv4_dst_address;
|
||||
session->write_buf = malloc(BGP_WRITEBUFSIZE);
|
||||
session->write_idx = 0;
|
||||
|
||||
timer_add(&ctx->timer_root, &session->connect_timer,
|
||||
"BGP CONNECT", 1, 0, session, &bgp_connect_job);
|
||||
|
||||
config = config->next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - BGP Main
|
||||
*
|
||||
* Christian Giese, Mach 2022
|
||||
*
|
||||
* Copyright (C) 2020-2022, RtBrick, Inc.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef __BBL_BGP_H__
|
||||
#define __BBL_BGP_H__
|
||||
|
||||
#include "../bbl.h"
|
||||
#include "bgp_def.h"
|
||||
#include "bgp_message.h"
|
||||
#include "bgp_mrt.h"
|
||||
|
||||
bool
|
||||
bgp_init(bbl_ctx_s *ctx);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - BGP Definitions
|
||||
*
|
||||
* Christian Giese, MARCH 2022
|
||||
*
|
||||
* Copyright (C) 2020-2022, RtBrick, Inc.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef __BBL_BGP_DEF_H__
|
||||
#define __BBL_BGP_DEF_H__
|
||||
|
||||
/* DEFINITIONS ... */
|
||||
|
||||
#define BGP_PORT 179
|
||||
#define BGP_MAX_MESSAGE_SIZE 4096
|
||||
#define BGP_WRITEBUFSIZE 4096
|
||||
#define BGP_DEFAULT_AS 65000
|
||||
#define BGP_DEFAULT_HOLDTIME 90
|
||||
|
||||
#define BGP_MSG_OPEN 1
|
||||
#define BGP_MSG_UPDATE 2
|
||||
#define BGP_MSG_NOTIFICATION 3
|
||||
#define BGP_MSG_KEEPALIVE 4
|
||||
|
||||
typedef enum bgp_state_ {
|
||||
BGP_IDLE,
|
||||
BGP_CONNECT,
|
||||
BGP_ACTIVE,
|
||||
BGP_OPENSENT,
|
||||
BGP_OPENCONFIRM,
|
||||
BGP_ESTABLISHED
|
||||
} bgp_state_t;
|
||||
|
||||
/*
|
||||
* BGP Configuration
|
||||
*/
|
||||
typedef struct bgp_config_ {
|
||||
uint32_t ipv4_src_address;
|
||||
uint32_t ipv4_dst_address;
|
||||
uint32_t id;
|
||||
uint32_t local_as;
|
||||
uint32_t peer_as;
|
||||
uint16_t holdtime;
|
||||
|
||||
char *network_interface;
|
||||
char *mrt_file;
|
||||
|
||||
/* Pointer to next instance */
|
||||
struct bgp_config_ *next;
|
||||
} bgp_config_t;
|
||||
|
||||
/*
|
||||
* BGP Session
|
||||
*/
|
||||
typedef struct bgp_session_ {
|
||||
struct bbl_ctx_ *ctx; /* parent */
|
||||
|
||||
uint32_t ipv4_src_address;
|
||||
uint32_t ipv4_dst_address;
|
||||
|
||||
bgp_config_t *config;
|
||||
bbl_interface_s *interface;
|
||||
bbl_tcp_ctx_t *tcpc;
|
||||
|
||||
struct timer_ *connect_timer;
|
||||
struct timer_ *send_open_timer;
|
||||
struct timer_ *open_sent_timer;
|
||||
struct timer_ *keepalive_timer;
|
||||
struct timer_ *hold_timer;
|
||||
struct timer_ *close_timer;
|
||||
|
||||
uint8_t *write_buf;
|
||||
uint16_t write_idx;
|
||||
|
||||
bgp_state_t state;
|
||||
|
||||
struct bgp_session_ *next; /* pointer to next instance */
|
||||
} bgp_session_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - BGP Functions
|
||||
*
|
||||
* Christian Giese, March 2022
|
||||
*
|
||||
* Copyright (C) 2020-2022, RtBrick, Inc.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "bgp.h"
|
||||
|
||||
static uint16_t
|
||||
as4_capability(uint8_t *buf, uint32_t as) {
|
||||
uint16_t len;
|
||||
|
||||
*buf = 2; /* cap code */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 6; /* cap length */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 65; /* AS4 capability */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 4; /* length to encode my AS4 */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*(uint32_t*)buf = htobe32(as);
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint32_t));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
mp_capability(uint8_t *buf, uint16_t afi, uint8_t safi) {
|
||||
uint16_t len;
|
||||
|
||||
*buf = 2; /* cap code */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 6; /* cap length */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 1; /* MP extension capability */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = 4; /* length */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*(uint16_t*)buf = htobe16(afi);
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint16_t));
|
||||
*buf = 0; /* Reserved */
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
*buf = safi;
|
||||
BUMP_WRITE_BUFFER(buf, &len, sizeof(uint8_t));
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
bgp_message_open(bgp_session_t *session) {
|
||||
uint16_t opt_parms_idx, opt_parms_length;
|
||||
|
||||
uint8_t *buf = session->write_buf;
|
||||
uint16_t cap_len;
|
||||
|
||||
memset(buf, 16, 0xff); /* marker */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, 16);
|
||||
*(uint16_t*)buf = 0; /* length */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint16_t));
|
||||
*buf = BGP_MSG_OPEN; /* message type */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint8_t));
|
||||
*buf = BGP_MSG_OPEN; /* version 4 */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint8_t));
|
||||
|
||||
/* local AS */
|
||||
if(session->config->local_as > 65535) {
|
||||
*(uint16_t*)buf = htobe16(23456);
|
||||
} else {
|
||||
*(uint16_t*)buf = htobe16(session->config->local_as);
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint16_t));
|
||||
|
||||
*(uint16_t*)buf = htobe16(session->config->holdtime); /* holdtime */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint16_t));
|
||||
*(uint32_t*)buf = session->config->id; /* BGP ID */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint32_t));
|
||||
|
||||
/* Optional parameters */
|
||||
*buf = 0; /* optional parameter length */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, sizeof(uint8_t));
|
||||
opt_parms_idx = session->write_idx;
|
||||
|
||||
cap_len = as4_capability(buf, session->config->local_as);
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, cap_len);
|
||||
|
||||
cap_len = mp_capability(buf, 1, 1); /* ipv4 unicast */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, cap_len);
|
||||
cap_len = mp_capability(buf, 2, 1); /* ipv6 unicast */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, cap_len);
|
||||
cap_len = mp_capability(buf, 1, 4); /* ipv4 labeled unicast */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, cap_len);
|
||||
cap_len = mp_capability(buf, 2, 4); /* ipv6 labeled unicast */
|
||||
BUMP_WRITE_BUFFER(buf, &session->write_idx, cap_len);
|
||||
|
||||
/* Update optional parameters length field */
|
||||
opt_parms_length = session->write_idx - opt_parms_idx;
|
||||
*(session->write_buf+opt_parms_idx-1) = opt_parms_length;
|
||||
|
||||
/* Update message length field */
|
||||
*(uint16_t*)(session->write_buf+16) = htobe16(session->write_idx);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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_MESSAGE_H__
|
||||
#define __BBL_BGP_MESSAGE_H__
|
||||
|
||||
void
|
||||
bgp_message_open(bgp_session_t *session);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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
|
||||
+1
-1
@@ -153,7 +153,7 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
#define TCP_MAXRTX 12
|
||||
|
||||
/* Maximum number of retransmissions of SYN segments. */
|
||||
#define TCP_SYNMAXRTX 4
|
||||
#define TCP_SYNMAXRTX 12
|
||||
|
||||
#define TCP_LISTEN_BACKLOG 1
|
||||
#define LWIP_CALLBACK_API 1
|
||||
|
||||
Reference in New Issue
Block a user