BGP Initial (WIP)

This commit is contained in:
Christian Giese
2022-03-09 13:45:10 +01:00
parent 2e3fe1fa1d
commit 15e17ecc70
21 changed files with 754 additions and 108 deletions
+9
View File
@@ -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);
+2
View File
@@ -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;
+104
View File
@@ -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)) {
+2 -1
View File
@@ -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;
+3 -6
View File
@@ -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;
}
+18
View File
@@ -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);
+1
View File
@@ -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
+1
View File
@@ -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];
+36
View File
@@ -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;
+10
View File
@@ -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
*/
-14
View File
@@ -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);
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+20
View File
@@ -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
+80
View File
@@ -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
+102
View File
@@ -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);
}
+15
View File
@@ -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
+12
View File
@@ -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
View File
@@ -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