LDP initial structure

This commit is contained in:
Christian Giese
2023-01-03 13:12:52 +01:00
committed by Christian Giese
parent 89a8ef44a0
commit 6f5979ee2e
44 changed files with 1219 additions and 98 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FILE(GLOB BBL_SOURCES src/*.c src/io/*.c src/isis/*.c src/bgp/*.c)
FILE(GLOB BBL_SOURCES src/*.c src/io/*.c src/isis/*.c src/ldp/*.c src/bgp/*.c)
list(SORT BBL_SOURCES)
# Deterministic randomness for symbol name creation
+12 -5
View File
@@ -23,16 +23,15 @@
bbl_ctx_s *g_ctx = NULL;
/* Global Variables */
bool g_interactive = false; /* interactive mode using ncurses */
uint8_t g_log_buf_cur = 0;
char *g_log_buf = NULL;
bool g_interactive = false; /* interactive mode using ncurses */
bool g_init_phase = true;
bool g_traffic = true;
bool g_banner = true;
bool g_monkey = true;
uint8_t g_log_buf_cur = 0;
char *g_log_buf = NULL;
extern char *g_log_file;
volatile bool g_teardown = false;
volatile bool g_teardown_request = false;
@@ -152,6 +151,7 @@ struct keyval_ log_names[] = {
{ L2TP, "l2tp" },
{ DHCP, "dhcp" },
{ ISIS, "isis" },
{ LDP, "ldp" },
{ BGP, "bgp" },
{ TCP, "tcp" },
{ LAG, "lag" },
@@ -293,6 +293,7 @@ bbl_ctrl_job(timer_s *timer)
}
/* Teardown routing protocols. */
isis_teardown();
ldp_teardown();
bgp_teardown();
g_teardown_request = false;
} else {
@@ -549,6 +550,12 @@ main(int argc, char *argv[])
goto CLEANUP;
}
/* Init LDP instances. */
if(!ldp_init()) {
fprintf(stderr, "Error: Failed to init LDP\n");
goto CLEANUP;
}
/* Init interfaces. */
if(!bbl_interface_init()) {
fprintf(stderr, "Error: Failed to init interfaces\n");
+2
View File
@@ -27,6 +27,7 @@
#include "io/io_def.h"
#include "bgp/bgp_def.h"
#include "isis/isis_def.h"
#include "ldp/ldp_def.h"
#include "bbl_ctrl.h"
#include "bbl_stats.h"
@@ -49,6 +50,7 @@
#include "io/io.h"
#include "bgp/bgp.h"
#include "isis/isis.h"
#include "ldp/ldp.h"
extern bbl_ctx_s *g_ctx;
extern WINDOW *log_win;
+112 -10
View File
@@ -635,6 +635,13 @@ json_parse_network_interface(json_t *network_interface, bbl_network_config_s *ne
network_config->isis_l2_metric = 10;
}
}
/* LDP interface configuration */
value = json_object_get(network_interface, "ldp-instance-id");
if(json_is_number(value)) {
network_config->ldp_instance_id = json_number_value(value);
}
return true;
}
@@ -1068,11 +1075,11 @@ json_parse_bgp_config(json_t *bgp, bgp_config_s *bgp_config)
bgp_config->peer_as = bgp_config->local_as;
}
value = json_object_get(bgp, "holdtime");
value = json_object_get(bgp, "hold-time");
if(value) {
bgp_config->holdtime = json_number_value(value);
bgp_config->hold_time = json_number_value(value);
} else {
bgp_config->holdtime = BGP_DEFAULT_HOLDTIME;
bgp_config->hold_time = BGP_DEFAULT_HOLD_TIME;
}
bgp_config->id = htobe32(0x01020304);
@@ -1191,11 +1198,11 @@ json_parse_isis_config(json_t *isis, isis_config_s *isis_config)
isis_config->hello_padding = json_boolean_value(value);
}
value = json_object_get(isis, "holding-time");
value = json_object_get(isis, "hold-time");
if(json_is_number(value)) {
isis_config->holding_time = json_number_value(value);
isis_config->hold_time = json_number_value(value);
} else {
isis_config->holding_time = ISIS_DEFAULT_HOLDING_TIME;
isis_config->hold_time = ISIS_DEFAULT_HOLD_TIME;
}
value = json_object_get(isis, "lsp-lifetime");
@@ -1358,6 +1365,72 @@ json_parse_isis_config(json_t *isis, isis_config_s *isis_config)
return true;
}
static bool
json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
{
json_t *value = NULL;
const char *s = NULL;
value = json_object_get(ldp, "instance-id");
if(value) {
ldp_config->id = json_number_value(value);
} else {
fprintf(stderr, "JSON config error: Missing value for ldp->instance-id\n");
return false;
}
value = json_object_get(ldp, "overload");
if(json_is_boolean(value)) {
ldp_config->overload = json_boolean_value(value);
}
value = json_object_get(ldp, "hello-interval");
if(json_is_number(value)) {
ldp_config->hello_interval = json_number_value(value);
} else {
ldp_config->hello_interval = LDP_DEFAULT_HELLO_INTERVAL;
}
value = json_object_get(ldp, "hold-time");
if(json_is_number(value)) {
ldp_config->hold_time = json_number_value(value);
} else {
ldp_config->hold_time = LDP_DEFAULT_HOLD_TIME;
}
value = json_object_get(ldp, "teardown-time");
if(json_is_number(value)) {
ldp_config->teardown_time = json_number_value(value);
} else {
ldp_config->teardown_time = LDP_DEFAULT_TEARDOWN_TIME;
}
if(json_unpack(ldp, "{s:s}", "hostname", &s) == 0) {
ldp_config->hostname = strdup(s);
} else {
ldp_config->hostname = g_default_hostname;
}
if(json_unpack(ldp, "{s:s}", "lsr-id", &s) == 0) {
ldp_config->lsr_id_str = strdup(s);
} else {
ldp_config->lsr_id_str = g_default_router_id;
}
if(!inet_pton(AF_INET, ldp_config->lsr_id_str, &ldp_config->lsr_id)) {
fprintf(stderr, "JSON config error: Invalid value for ldp->lsr-id\n");
return false;
}
if(json_unpack(ldp, "{s:s}", "ipv4-transport-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ldp_config->ipv4_transport_address)) {
fprintf(stderr, "JSON config error: Invalid value for ldp->ipv4-transport-address\n");
return false;
}
} else {
ldp_config->ipv4_transport_address = ldp_config->lsr_id;
}
return true;
}
static bool
json_parse_stream(json_t *stream, bbl_stream_config_s *stream_config)
{
@@ -1642,6 +1715,7 @@ json_parse_config(json_t *root)
bgp_config_s *bgp_config = NULL;
isis_config_s *isis_config = NULL;
ldp_config_s *ldp_config = NULL;
if(json_typeof(root) != JSON_OBJECT) {
fprintf(stderr, "JSON config error: Configuration root element must object\n");
@@ -2167,7 +2241,7 @@ json_parse_config(json_t *root)
/* BGP Configuration */
sub = json_object_get(root, "bgp");
if(json_is_array(sub)) {
/* Config is provided as array (multiple bgp sessions) */
/* Config is provided as array (multiple BGP sessions) */
size = json_array_size(sub);
for(i = 0; i < size; i++) {
if(!bgp_config) {
@@ -2182,7 +2256,7 @@ json_parse_config(json_t *root)
}
}
} else if(json_is_object(sub)) {
/* Config is provided as object (single bgp session) */
/* Config is provided as object (single BGP session) */
bgp_config = calloc(1, sizeof(bgp_config_s));
if(!g_ctx->config.bgp_config) {
g_ctx->config.bgp_config = bgp_config;
@@ -2209,7 +2283,7 @@ json_parse_config(json_t *root)
/* IS-IS Configuration */
sub = json_object_get(root, "isis");
if(json_is_array(sub)) {
/* Config is provided as array (multiple isis instances) */
/* Config is provided as array (multiple IS-IS instances) */
size = json_array_size(sub);
for(i = 0; i < size; i++) {
if(!isis_config) {
@@ -2224,7 +2298,7 @@ json_parse_config(json_t *root)
}
}
} else if(json_is_object(sub)) {
/* Config is provided as object (single isis instance) */
/* Config is provided as object (single IS-IS instance) */
isis_config = calloc(1, sizeof(isis_config_s));
if(!g_ctx->config.isis_config) {
g_ctx->config.isis_config = isis_config;
@@ -2234,6 +2308,34 @@ json_parse_config(json_t *root)
}
}
/* LDP Configuration */
sub = json_object_get(root, "ldp");
if(json_is_array(sub)) {
/* Config is provided as array (multiple LDP instances) */
size = json_array_size(sub);
for(i = 0; i < size; i++) {
if(!ldp_config) {
g_ctx->config.ldp_config = calloc(1, sizeof(ldp_config_s));
ldp_config = g_ctx->config.ldp_config;
} else {
ldp_config->next = calloc(1, sizeof(ldp_config_s));
ldp_config = ldp_config->next;
}
if(!json_parse_ldp_config(json_array_get(sub, i), ldp_config)) {
return false;
}
}
} else if(json_is_object(sub)) {
/* Config is provided as object (single LDP instance) */
ldp_config = calloc(1, sizeof(ldp_config_s));
if(!g_ctx->config.ldp_config) {
g_ctx->config.ldp_config = ldp_config;
}
if(!json_parse_ldp_config(sub, ldp_config)) {
return false;
}
}
/* Interface Configuration */
section = json_object_get(root, "interfaces");
if(json_is_object(section)) {
+2
View File
@@ -106,6 +106,8 @@ typedef struct bbl_network_config_
uint32_t isis_l1_metric;
uint32_t isis_l2_metric;
uint16_t ldp_instance_id;
void *next; /* pointer to next network config element */
bbl_network_interface_s *network_interface;
} bbl_network_config_s;
+4
View File
@@ -95,6 +95,7 @@ typedef struct bbl_ctx_
bgp_session_s *bgp_sessions;
bgp_raw_update_s *bgp_raw_updates;
isis_instance_s *isis_instances;
ldp_instance_s *ldp_instances;
/* Scratchpad memory */
uint8_t *sp;
@@ -191,6 +192,9 @@ typedef struct bbl_ctx_
/* ISIS Instances */
isis_config_s *isis_config;
/* LDP Instances */
ldp_config_s *ldp_config;
/* Global Session Settings */
uint32_t sessions;
uint32_t sessions_max_outstanding;
+1
View File
@@ -90,6 +90,7 @@
#define BBL_IF_SEND_ARP_REQUEST 0x00000001
#define BBL_IF_SEND_ICMPV6_NS 0x00000002
#define BBL_IF_SEND_ISIS_P2P_HELLO 0x00000004
#define BBL_IF_SEND_LDP_HELLO 0x00000008
#define DUID_LEN 10
+45 -11
View File
@@ -42,7 +42,8 @@ bbl_network_interfaces_add()
bbl_network_interface_s *network_interface;
bbl_interface_s *interface;
isis_instance_s *isis;
bool isis_result;
ldp_instance_s *ldp;
bool result;
char ifname[SUB_STR_LEN];
@@ -142,12 +143,12 @@ bbl_network_interfaces_add()
/* Init routing protocols */
if(network_config->isis_instance_id) {
isis_result = false;
result = false;
isis = g_ctx->isis_instances;
while (isis) {
while(isis) {
if(isis->config->id == network_config->isis_instance_id) {
isis_result = isis_adjacency_init(network_interface, network_config, isis);
if(!isis_result) {
result = isis_adjacency_init(network_interface, network_config, isis);
if(!result) {
LOG(ERROR, "Failed to enable IS-IS for network interface %s (adjacency init failed)\n", ifname);
return false;
}
@@ -155,11 +156,30 @@ bbl_network_interfaces_add()
}
isis = isis->next;
}
if(!isis_result) {
if(!result) {
LOG(ERROR, "Failed to enable IS-IS for network interface %s (instance not found)\n", ifname);
return false;
}
}
if(network_config->ldp_instance_id) {
result = false;
ldp = g_ctx->ldp_instances;
while(ldp) {
if(ldp->config->id == network_config->ldp_instance_id) {
result = ldp_interface_init(network_interface, network_config, ldp);
if(!result) {
LOG(ERROR, "Failed to enable LDP for network interface %s (adjacency init failed)\n", ifname);
return false;
}
break;
}
ldp = ldp->next;
}
if(!result) {
LOG(ERROR, "Failed to enable LDP for network interface %s (instance not found)\n", ifname);
return false;
}
}
/* TX list init */
CIRCLEQ_INIT(&network_interface->l2tp_tx_qhead);
@@ -386,25 +406,39 @@ bbl_network_rx_handler(bbl_network_interface_s *interface,
bbl_network_rx_arp(interface, eth);
return;
case ETH_TYPE_IPV4:
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
/* Drop wrong MAC */
return;
}
ipv4 = (bbl_ipv4_s*)eth->next;
if(ipv4->protocol == PROTOCOL_IPV4_UDP) {
udp = (bbl_udp_s*)ipv4->next;
/* LDP hello is send to all routers multicast address and therefore
* processed before check on local MAC address. */
if(udp->protocol == UDP_PROTOCOL_LDP) {
ldp_hello_rx(interface, eth, ipv4, (bbl_ldp_hello_s*)udp->next);
return;
}
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
/* Drop wrong MAC */
return;
}
if(udp->protocol == UDP_PROTOCOL_QMX_LI) {
bbl_qmx_li_handler_rx(interface, eth, (bbl_qmx_li_s*)udp->next);
return;
} else if(udp->protocol == UDP_PROTOCOL_L2TP) {
bbl_l2tp_handler_rx(interface, eth, (bbl_l2tp_s*)udp->next);
return;
}
}
} else if(ipv4->protocol == PROTOCOL_IPV4_ICMP) {
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
/* Drop wrong MAC */
return;
}
interface->stats.icmp_rx++;
bbl_network_rx_icmp(interface, eth, ipv4);
return;
} else if(ipv4->protocol == PROTOCOL_IPV4_TCP) {
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
/* Drop wrong MAC */
return;
}
interface->stats.tcp_rx++;
bbl_tcp_ipv4_rx(interface, eth, ipv4);
return;
+5
View File
@@ -56,6 +56,7 @@ typedef struct bbl_network_interface_
isis_adjacency_p2p_s *isis_adjacency_p2p;
isis_adjacency_s *isis_adjacency[ISIS_LEVELS];
ldp_adjacency_s *ldp_adjacency;
struct {
uint64_t packets_tx;
@@ -108,6 +109,10 @@ typedef struct bbl_network_interface_
uint32_t isis_tx;
uint32_t isis_rx_error;
uint32_t ldp_udp_rx;
uint32_t ldp_udp_tx;
uint32_t ldp_udp_rx_error;
/* Rate Stats */
bbl_rate_s rate_packets_tx;
+184 -18
View File
@@ -10,6 +10,7 @@
#include "bbl_protocols.h"
#include "bbl_access_line.h"
#include "isis/isis_def.h"
#include "ldp/ldp_def.h"
static protocol_error_t decode_l2tp(uint8_t *buf, uint16_t len, uint8_t *sp, uint16_t sp_len, bbl_ethernet_header_s *eth, bbl_l2tp_s **_l2tp);
static protocol_error_t encode_l2tp(uint8_t *buf, uint16_t *len, bbl_l2tp_s *l2tp);
@@ -551,6 +552,55 @@ encode_dhcp(uint8_t *buf, uint16_t *len,
return PROTOCOL_SUCCESS;
}
/*
* encode_ldp_hello
*/
static protocol_error_t
encode_ldp_hello(uint8_t *buf, uint16_t *len, bbl_ldp_hello_s *ldp)
{
/* PDU version and length */
*(uint16_t*)buf = htobe16(1);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(30);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
/* LDP identifier (LSR ID + label space) */
*(uint32_t*)buf = htobe32(ldp->lsr_id);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
*(uint16_t*)buf = htobe16(ldp->label_space_id);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
/* LDP message type and length */
*(uint16_t*)buf = htobe16(LDP_MESSAGE_TYPE_HELLO);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(20);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
/* LDP message ID */
*(uint32_t*)buf = htobe32(ldp->msg_id);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
/* Common hello parameters TLV */
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_COMMON_HELLO_PARAMETERS);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(4);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(ldp->hold_time);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = 0;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
/* IPv4 transport address TLV */
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(4);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint32_t*)buf = htobe32(ldp->ipv4_transport_address);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
return PROTOCOL_SUCCESS;
}
/*
* encode_bbl
*/
@@ -628,6 +678,9 @@ encode_udp(uint8_t *buf, uint16_t *len,
case UDP_PROTOCOL_DHCP:
result = encode_dhcp(buf, len, (bbl_dhcp_s*)udp->next);
break;
case UDP_PROTOCOL_LDP:
result = encode_ldp_hello(buf, len, (bbl_ldp_hello_s*)udp->next);
break;
default:
result = PROTOCOL_SUCCESS;
break;
@@ -2746,6 +2799,106 @@ decode_qmx_li(uint8_t *buf, uint16_t len,
return decode_ethernet(buf, len, sp, sp_len, (bbl_ethernet_header_s**)&qmx_li->next);
}
/*
* decode_ldp_hello
*/
static protocol_error_t
decode_ldp_hello(uint8_t *buf, uint16_t len,
uint8_t *sp, uint16_t sp_len,
bbl_ldp_hello_s **_ldp)
{
bbl_ldp_hello_s *ldp;
uint16_t pdu_version;
uint16_t pdu_len;
uint16_t msg_type;
uint16_t msg_len;
uint16_t tlv_type;
uint16_t tlv_len;
if(len < 10 || sp_len < sizeof(bbl_ldp_hello_s)) {
return DECODE_ERROR;
}
/* Init LDP structure */
ldp = (bbl_ldp_hello_s*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_ldp_hello_s));
memset(ldp, 0x0, sizeof(bbl_ldp_hello_s));
/* PDU version and length */
pdu_version = be16toh(*(uint16_t*)buf) & 0x7FFF;
BUMP_BUFFER(buf, len, sizeof(uint16_t));
pdu_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
if(pdu_version != 1) {
return UNKNOWN_PROTOCOL;
}
/* The PDU length is defined as two octet integer specifying
* the total length of the PDU in octets, excluding the version
* and PDU length fields. */
if(pdu_len > len) {
return UNKNOWN_PROTOCOL;
}
len = pdu_len;
/* LDP identifier (LSR ID + label space) */
ldp->lsr_id = be32toh(*(uint32_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
ldp->label_space_id = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
/* LDP message type and length */
if(len < 4) {
return DECODE_ERROR;
}
msg_type = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
msg_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
if(msg_len > len || msg_len < 4 ||
msg_type != LDP_MESSAGE_TYPE_HELLO) {
return DECODE_ERROR;
}
len = msg_len;
/* LDP message ID */
ldp->msg_id = be32toh(*(uint32_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint32_t));
/* LDP TLV's */
while(len >= LDP_TLV_LEN_MIN) {
tlv_type = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
tlv_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
if(tlv_len > len) {
return DECODE_ERROR;
}
switch(tlv_type) {
case LDP_TLV_TYPE_COMMON_HELLO_PARAMETERS:
if(tlv_len != 4) {
return DECODE_ERROR;
}
ldp->hold_time = be16toh(*(uint16_t*)buf);
break;
case LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS:
if(tlv_len != 4) {
return DECODE_ERROR;
}
ldp->ipv4_transport_address = be32toh(*(uint16_t*)buf);
break;
default:
break;
}
BUMP_BUFFER(buf, len, tlv_len);
}
*_ldp = ldp;
return PROTOCOL_SUCCESS;
}
/*
* decode_udp
*/
@@ -2755,7 +2908,7 @@ decode_udp(uint8_t *buf, uint16_t len,
bbl_ethernet_header_s *eth,
bbl_udp_s **_udp)
{
protocol_error_t ret_val = PROTOCOL_SUCCESS;
protocol_error_t ret_val = UNKNOWN_PROTOCOL;
bbl_udp_s *udp;
@@ -2791,8 +2944,10 @@ decode_udp(uint8_t *buf, uint16_t len,
eth->bbl = udp->next;
break;
case L2TP_UDP_PORT:
udp->protocol = UDP_PROTOCOL_L2TP;
ret_val = decode_l2tp(buf, len, sp, sp_len, eth, (bbl_l2tp_s**)&udp->next);
if(udp->src == L2TP_UDP_PORT) {
udp->protocol = UDP_PROTOCOL_L2TP;
ret_val = decode_l2tp(buf, len, sp, sp_len, eth, (bbl_l2tp_s**)&udp->next);
}
break;
case DHCP_UDP_CLIENT:
case DHCP_UDP_SERVER:
@@ -2803,23 +2958,34 @@ decode_udp(uint8_t *buf, uint16_t len,
udp->protocol = UDP_PROTOCOL_QMX_LI;
ret_val = decode_qmx_li(buf, len, sp, sp_len, (bbl_qmx_li_s**)&udp->next);
break;
default:
if(udp->src == QMX_LI_UDP_PORT) {
udp->protocol = UDP_PROTOCOL_QMX_LI;
ret_val = decode_qmx_li(buf, len, sp, sp_len, (bbl_qmx_li_s**)&udp->next);
} else {
/* Try if payload could be decoded as BBL!
* This fails fast if the 64 bit magic number
* is not found on the expected position. */
if(decode_bbl(buf, len, sp, sp_len, (bbl_bbl_s**)&udp->next) == PROTOCOL_SUCCESS) {
udp->protocol = UDP_PROTOCOL_BBL;
eth->bbl = udp->next;
} else {
udp->protocol = 0;
udp->next = NULL;
}
case LDP_PORT:
if(udp->src == LDP_PORT) {
udp->protocol = UDP_PROTOCOL_LDP;
ret_val = decode_ldp_hello(buf, len, sp, sp_len, (bbl_ldp_hello_s**)&udp->next);
}
break;
default:
break;
}
if(ret_val == UNKNOWN_PROTOCOL) {
if(udp->src == QMX_LI_UDP_PORT) {
udp->protocol = UDP_PROTOCOL_QMX_LI;
ret_val = decode_qmx_li(buf, len, sp, sp_len, (bbl_qmx_li_s**)&udp->next);
} else {
/* Try if payload could be decoded as BBL!
* This fails fast if the 64 bit magic number
* is not found on the expected position. */
ret_val = decode_bbl(buf, len, sp, sp_len, (bbl_bbl_s**)&udp->next);
if(ret_val == PROTOCOL_SUCCESS) {
udp->protocol = UDP_PROTOCOL_BBL;
eth->bbl = udp->next;
} else {
ret_val = PROTOCOL_SUCCESS;
udp->protocol = 0;
udp->next = NULL;
}
}
}
*_udp = udp;
+12 -1
View File
@@ -202,6 +202,7 @@
#define UDP_PROTOCOL_L2TP 3
#define UDP_PROTOCOL_QMX_LI 4
#define UDP_PROTOCOL_DHCP 5
#define UDP_PROTOCOL_LDP 6
#define IPV6_NEXT_HEADER_TCP 6
#define IPV6_NEXT_HEADER_UDP 17
@@ -285,6 +286,8 @@ static const ipv6addr_t ipv6_solicited_node_multicast = {0xFF, 0x02, 0x00, 0x00,
/* MAC Addresses */
static const uint8_t broadcast_mac[ETH_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const uint8_t slow_mac[ETH_ADDR_LEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02};
static const uint8_t all_hosts_mac[ETH_ADDR_LEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01};
static const uint8_t all_routers_mac[ETH_ADDR_LEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x02};
typedef enum protocol_error_ {
PROTOCOL_SUCCESS = 0,
@@ -530,12 +533,20 @@ typedef struct bbl_mpls_ {
/*
* ISIS PDU
*/
typedef struct bbl_isis_s {
typedef struct bbl_isis_ {
uint8_t type;
uint8_t *pdu;
uint16_t pdu_len;
} bbl_isis_s;
typedef struct bbl_ldp_hello_ {
uint32_t lsr_id;
uint16_t label_space_id;
uint32_t msg_id;
uint32_t ipv4_transport_address;
uint16_t hold_time;
} bbl_ldp_hello_s;
typedef struct bbl_bbl_ {
uint16_t padding;
uint8_t type;
+3
View File
@@ -1421,6 +1421,9 @@ bbl_tx_encode_network_packet(bbl_network_interface_s *interface, uint8_t *buf, u
} else if(interface->send_requests & BBL_IF_SEND_ISIS_P2P_HELLO) {
interface->send_requests &= ~BBL_IF_SEND_ISIS_P2P_HELLO;
result = isis_p2p_hello_encode(interface, buf, len, &eth);
} else if(interface->send_requests & BBL_IF_SEND_LDP_HELLO) {
interface->send_requests &= ~BBL_IF_SEND_LDP_HELLO;
result = ldp_hello_encode(interface, buf, len, &eth);
} else {
interface->send_requests = 0;
}
+2 -2
View File
@@ -60,11 +60,11 @@ bgp_ctrl_session_json(bgp_session_s *session)
"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,
"local-hold-time", session->config->hold_time,
"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,
"peer-hold-time", session->peer.hold_time,
"state", bgp_session_state_string(session->state),
"raw-update-state", raw_update_state(session),
"raw-update-file", raw_update_file,
+3 -3
View File
@@ -16,7 +16,7 @@
#define BGP_MAX_MESSAGE_SIZE 4096U
#define BGP_BUF_SIZE 256*1024
#define BGP_DEFAULT_AS 65000
#define BGP_DEFAULT_HOLDTIME 90
#define BGP_DEFAULT_HOLD_TIME 90
#define BGP_DEFAULT_TEARDOWN_TIME 5
#define BGP_MSG_OPEN 1
@@ -58,7 +58,7 @@ typedef struct bgp_config_ {
uint32_t id;
uint32_t local_as;
uint32_t peer_as;
uint16_t holdtime;
uint16_t hold_time;
uint16_t teardown_time;
bool reconnect;
@@ -101,7 +101,7 @@ typedef struct bgp_session_ {
struct {
uint32_t as;
uint32_t id;
uint16_t holdtime;
uint16_t hold_time;
} peer;
struct {
+1 -1
View File
@@ -69,7 +69,7 @@ bgp_push_open_message(bgp_session_s *session)
} else {
push_be_uint(buffer, 2, session->config->local_as);
}
push_be_uint(buffer, 2, session->config->holdtime); /* holdtime */
push_be_uint(buffer, 2, session->config->hold_time); /* hold-time */
push_data(buffer, (uint8_t*)&session->config->id, 4); /* BGP ID */
/* Optional parameters */
+7 -7
View File
@@ -92,14 +92,14 @@ bgp_open(bgp_session_s *session, uint8_t *start, uint16_t length)
return;
}
session->peer.as = read_be_uint(start+20, 2);
session->peer.holdtime = read_be_uint(start+22, 2);
session->peer.hold_time = read_be_uint(start+22, 2);
session->peer.id = read_be_uint(start+24, 4);
LOG(BGP, "BGP (%s %s - %s) open message received with peer AS: %u, holdtime: %us\n",
LOG(BGP, "BGP (%s %s - %s) open message received with peer AS: %u, hold-time: %us\n",
session->interface->name,
format_ipv4_address(&session->ipv4_local_address),
format_ipv4_address(&session->ipv4_peer_address),
session->peer.as, session->peer.holdtime);
session->peer.as, session->peer.hold_time);
bgp_session_state_change(session, BGP_OPENCONFIRM);
return;
@@ -185,7 +185,7 @@ bgp_rebase_read_buffer(bgp_session_s *session)
}
static void
bpg_read(bgp_session_s *session)
bgp_read(bgp_session_s *session)
{
uint32_t size;
uint16_t length;
@@ -223,7 +223,7 @@ bpg_read(bgp_session_s *session)
format_ipv4_address(&session->ipv4_peer_address),
keyval_get_key(bgp_msg_names, type));
switch (type) {
switch(type) {
case BGP_MSG_OPEN:
bgp_open(session, start, length);
break;
@@ -244,7 +244,7 @@ bpg_read(bgp_session_s *session)
}
/* Reset hold timer */
bgp_restart_hold_timer(session, session->config->holdtime);
bgp_restart_hold_timer(session, session->config->hold_time);
/* Progress pointer to next BGP message */
buffer->start_idx += length;
@@ -274,6 +274,6 @@ bgp_receive_cb(void *arg, uint8_t *buf, uint16_t len)
memcpy(buffer->data+buffer->idx, buf, len);
buffer->idx+=len;
} else {
bpg_read(session);
bgp_read(session);
}
}
+4 -4
View File
@@ -176,10 +176,10 @@ bgp_session_state_established(bgp_session_s *session)
clock_gettime(CLOCK_MONOTONIC, &session->established_timestamp);
/* Start BGP keepalive */
if(session->peer.holdtime < session->config->holdtime) {
keepalive_interval = session->peer.holdtime/2U;
if(session->peer.hold_time < session->config->hold_time) {
keepalive_interval = session->peer.hold_time/2U;
} else {
keepalive_interval = session->config->holdtime/2U;
keepalive_interval = session->config->hold_time/2U;
}
if(!keepalive_interval) {
keepalive_interval = 1;
@@ -320,7 +320,7 @@ bgp_session_connect(bgp_session_s *session, time_t delay)
session->peer.as = 0;
session->peer.id = 0;
session->peer.holdtime = 0;
session->peer.hold_time = 0;
session->stats.message_rx = 0;
session->stats.message_tx = 0;
+3 -3
View File
@@ -111,20 +111,20 @@ isis_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth)
result = isis_pdu_load(&pdu, isis->pdu, isis->pdu_len);
if(result != PROTOCOL_SUCCESS) {
LOG(ISIS, "ISIS RX %s PDU decode error on interface %s\n",
isis_pdu_sype_string(pdu.pdu_type), interface->name);
isis_pdu_type_string(pdu.pdu_type), interface->name);
interface->stats.isis_rx_error++;
return;
}
if(!isis_pdu_validate_checksum(&pdu)) {
LOG(ISIS, "ISIS RX %s PDU checksum error on interface %s\n",
isis_pdu_sype_string(pdu.pdu_type), interface->name);
isis_pdu_type_string(pdu.pdu_type), interface->name);
interface->stats.isis_rx_error++;
return;
}
LOG(DEBUG, "ISIS RX %s on interface %s\n",
isis_pdu_sype_string(pdu.pdu_type), interface->name);
isis_pdu_type_string(pdu.pdu_type), interface->name);
switch (pdu.pdu_type) {
case ISIS_PDU_P2P_HELLO:
+1 -1
View File
@@ -140,7 +140,7 @@ isis_adjacency_down(isis_adjacency_s *adjacency)
timer_del(adjacency->timer_retry);
timer_del(adjacency->timer_csnp);
timer_del(adjacency->timer_csnp_next);
timer_del(adjacency->timer_holding);
timer_del(adjacency->timer_hold);
if(g_ctx->routing_sessions) g_ctx->routing_sessions--;
}
+2 -1
View File
@@ -147,8 +147,9 @@ isis_csnp_job(timer_s *timer)
isis.pdu_len = pdu.pdu_len;
if(bbl_txq_to_buffer(adjacency->interface->txq, &eth) == BBL_TXQ_OK) {
LOG(DEBUG, "ISIS TX %s on interface %s\n",
isis_pdu_sype_string(isis.type), adjacency->interface->name);
isis_pdu_type_string(isis.type), adjacency->interface->name);
adjacency->stats.csnp_tx++;
adjacency->interface->stats.isis_tx++;
/* Clear PSNP tree after CSNP was send */
hb_tree_clear(adjacency->psnp_tree, isis_psnp_free);
timer_del(adjacency->timer_psnp_next);
+2 -2
View File
@@ -21,7 +21,7 @@ isis_ctrl_adjacency(isis_adjacency_s *adjacency)
peer = json_pack("{ss si}",
"system-id", isis_system_id_to_str(adjacency->peer->system_id),
"holding-timer", adjacency->peer->holding_time);
"hold-timer", adjacency->peer->hold_time);
root = json_pack("{ss ss ss si ss so}",
"interface", adjacency->interface->name,
@@ -50,7 +50,7 @@ isis_ctrl_adjacency_p2p(isis_adjacency_p2p_s *adjacency)
peer = json_pack("{ss si}",
"system-id", isis_system_id_to_str(adjacency->peer->system_id),
"holding-timer", adjacency->peer->holding_time);
"hold-timer", adjacency->peer->hold_time);
root = json_pack("{ss ss, ss si ss so}",
"interface", adjacency->interface->name,
+6 -6
View File
@@ -62,7 +62,7 @@
#define ISIS_DEFAULT_HELLO_INTERVAL 10
#define ISIS_DEFAULT_CSNP_INTERVAL 30
#define ISIS_DEFAULT_HOLDING_TIME 30
#define ISIS_DEFAULT_HOLD_TIME 30
#define ISIS_DEFAULT_LSP_LIFETIME 65535
#define ISIS_DEFAULT_LSP_RETRY_IVL 5
#define ISIS_DEFAULT_LSP_REFRESH_IVL 300
@@ -130,7 +130,7 @@ typedef enum isis_pdu_type_ {
/* IS-IS TLV Codepoints
* https://www.iana.org/assignments/isis-tlv-codepoints/isis-tlv-codepoints.xhtml
*/
typedef enum isis_tlv_sype_ {
typedef enum isis_tlv_type_ {
ISIS_TLV_AREA_ADDRESSES = 1,
ISIS_TLV_PADDING = 8,
ISIS_TLV_LSP_ENTRIES = 9,
@@ -145,7 +145,7 @@ typedef enum isis_tlv_sype_ {
ISIS_TLV_IPV6_REACHABILITY = 236,
ISIS_TLV_P2P_ADJACENCY_STATE = 240,
ISIS_TLV_ROUTER_CAPABILITY = 242
} isis_tlv_sype;
} isis_tlv_type;
/* STRUCTURES ... */
@@ -203,7 +203,7 @@ typedef struct isis_config_ {
uint16_t lsp_refresh_interval;
uint16_t lsp_lifetime;
uint16_t hello_interval;
uint16_t holding_time;
uint16_t hold_time;
uint16_t teardown_time;
const char *hostname;
@@ -238,7 +238,7 @@ typedef struct isis_config_ {
typedef struct isis_peer_ {
uint8_t level;
uint8_t system_id[ISIS_SYSTEM_ID_LEN];
uint16_t holding_time;
uint16_t hold_time;
char *hostname;
} isis_peer_s;
@@ -260,7 +260,7 @@ typedef struct isis_adjacency_ {
struct timer_ *timer_csnp;
struct timer_ *timer_csnp_next;
struct timer_ *timer_psnp_next;
struct timer_ *timer_holding;
struct timer_ *timer_hold;
bool timer_psnp_started;
+1
View File
@@ -291,6 +291,7 @@ isis_lsp_sx_job(timer_s *timer)
entry->tx_timestamp.tv_sec = now.tv_sec;
entry->tx_timestamp.tv_nsec = now.tv_nsec;
adjacency->stats.lsp_tx++;
adjacency->interface->stats.isis_tx++;
if(window) window--;
if(window == 0) break;
}
+12 -11
View File
@@ -16,7 +16,7 @@ isis_p2p_hello_timeout(timer_s *timer)
}
void
isis_p2p_holding_timeout(timer_s *timer)
isis_p2p_hold_timeout(timer_s *timer)
{
isis_adjacency_s *adjacency = timer->data;
@@ -24,7 +24,7 @@ isis_p2p_holding_timeout(timer_s *timer)
return;
}
LOG(ISIS, "ISIS %s holding timeout to %s on interface %s\n",
LOG(ISIS, "ISIS %s hold timeout to %s on interface %s\n",
isis_level_string(adjacency->level),
isis_system_id_to_str(adjacency->peer->system_id),
adjacency->interface->name);
@@ -36,16 +36,16 @@ isis_p2p_holding_timeout(timer_s *timer)
}
static void
isis_p2p_restart_holding_timers(bbl_network_interface_s *interface)
isis_p2p_restart_hold_timers(bbl_network_interface_s *interface)
{
isis_adjacency_s *adjacency;
for(int i=0; i<ISIS_LEVELS; i++) {
adjacency = interface->isis_adjacency[i];
if(adjacency) {
timer_add(&g_ctx->timer_root, &adjacency->timer_holding,
"ISIS holding", adjacency->peer->holding_time, 0, adjacency,
&isis_p2p_holding_timeout);
timer_add(&g_ctx->timer_root, &adjacency->timer_hold,
"ISIS Hold", adjacency->peer->hold_time, 0, adjacency,
&isis_p2p_hold_timeout);
}
}
}
@@ -77,7 +77,7 @@ isis_p2p_hello_encode(bbl_network_interface_s *interface,
/* Start next timer ... */
timer_add(&g_ctx->timer_root, &interface->timer_isis_hello,
"ISIS hello", config->hello_interval, 0, interface,
"ISIS Hello", config->hello_interval, 0, interface,
&isis_p2p_hello_timeout);
if(config->level1_auth && config->level1_key) {
@@ -93,7 +93,7 @@ isis_p2p_hello_encode(bbl_network_interface_s *interface,
/* PDU header */
isis_pdu_add_u8(&pdu, adjacency->level);
isis_pdu_add_bytes(&pdu, config->system_id, ISIS_SYSTEM_ID_LEN);
isis_pdu_add_u16(&pdu, config->holding_time);
isis_pdu_add_u16(&pdu, config->hold_time);
isis_pdu_add_u16(&pdu, 0);
isis_pdu_add_u8(&pdu, 0x1);
/* TLV section */
@@ -118,8 +118,9 @@ isis_p2p_hello_encode(bbl_network_interface_s *interface,
result = encode_ethernet(buf, len, eth);
if(result == PROTOCOL_SUCCESS) {
LOG(DEBUG, "ISIS TX %s on interface %s\n",
isis_pdu_sype_string(isis.type), interface->name);
isis_pdu_type_string(isis.type), interface->name);
adjacency->stats.hello_tx++;
adjacency->interface->stats.isis_tx++;
}
return result;
}
@@ -170,9 +171,9 @@ isis_p2p_hello_handler_rx(bbl_network_interface_s *interface, isis_pdu_s *pdu)
peer = adjacency->peer;
peer->level = *PDU_OFFSET(pdu, ISIS_OFFSET_P2P_HELLO_LEVEL) & 0x03;
memcpy(peer->system_id, PDU_OFFSET(pdu, ISIS_OFFSET_P2P_HELLO_SYSTEM_ID), ISIS_SYSTEM_ID_LEN);
peer->holding_time = be16toh(*(uint16_t*)PDU_OFFSET(pdu, ISIS_OFFSET_P2P_HELLO_HOLD_TIME));
peer->hold_time = be16toh(*(uint16_t*)PDU_OFFSET(pdu, ISIS_OFFSET_P2P_HELLO_HOLD_TIME));
isis_p2p_restart_holding_timers(interface);
isis_p2p_restart_hold_timers(interface);
tlv = isis_pdu_first_tlv(pdu);
while(tlv) {
+2 -1
View File
@@ -129,8 +129,9 @@ isis_psnp_job (timer_s *timer)
isis.pdu_len = pdu.pdu_len;
if(bbl_txq_to_buffer(adjacency->interface->txq, &eth) == BBL_TXQ_OK) {
LOG(DEBUG, "ISIS TX %s on interface %s\n",
isis_pdu_sype_string(isis.type), adjacency->interface->name);
isis_pdu_type_string(isis.type), adjacency->interface->name);
adjacency->stats.psnp_tx++;
adjacency->interface->stats.isis_tx++;
}
return;
}
+1 -1
View File
@@ -52,7 +52,7 @@ isis_adjacency_state_string(uint8_t state)
}
const char *
isis_pdu_sype_string(uint8_t type)
isis_pdu_type_string(uint8_t type)
{
switch(type) {
case ISIS_PDU_L1_HELLO: return "L1-Hello";
+1 -1
View File
@@ -22,7 +22,7 @@ const char *
isis_adjacency_state_string(uint8_t state);
const char *
isis_pdu_sype_string(uint8_t type);
isis_pdu_type_string(uint8_t type);
bool
isis_str_to_area(const char *str, isis_area_s *area);
+63
View File
@@ -0,0 +1,63 @@
/*
* BNG Blaster (BBL) - LDP Functions
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
/**
* ldp_init
*
* This function inits all LDP sessions.
*/
bool
ldp_init()
{
ldp_config_s *config = g_ctx->config.ldp_config;
ldp_instance_s *instance = NULL;
while(config) {
LOG(LDP, "Init LDP instance %u\n", config->id);
if(instance) {
instance->next = calloc(1, sizeof(ldp_instance_s));
instance = instance->next;
} else {
instance = calloc(1, sizeof(ldp_instance_s));
g_ctx->ldp_instances = instance;
}
instance->config = config;
config = config->next;
}
return true;
}
void
ldp_teardown_job(timer_s *timer) {
ldp_instance_s *instance = timer->data;
UNUSED(instance);
}
/**
* ldp_teardown
*
* This function stops all LDP sessions.
*/
void
ldp_teardown()
{
ldp_instance_s *instance = g_ctx->ldp_instances;
while(instance) {
if(!instance->teardown) {
LOG(LDP, "Teardown LDP instance %u\n", instance->config->id);
instance->teardown = true;
timer_add(&g_ctx->timer_root, &instance->teardown_timer,
"LDP TEARDOWN", instance->config->teardown_time, 0, instance,
&ldp_teardown_job);
}
instance = instance->next;
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* BNG Blaster (BBL) - LDP Main
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_H__
#define __BBL_LDP_H__
#include "../bbl.h"
#include "ldp_def.h"
#include "ldp_pdu.h"
#include "ldp_hello.h"
#include "ldp_interface.h"
bool
ldp_init();
void
ldp_teardown();
#endif
+201
View File
@@ -0,0 +1,201 @@
/*
* BNG Blaster (BBL) - LDP Definitions
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_DEF_H__
#define __BBL_LDP_DEF_H__
/* DEFINITIONS ... */
#define LDP_PORT 646
#define LDP_IDENTIFIER_LEN 6U
#define LDP_MAX_PDU_LEN_INIT 4096U
#define LDP_MESSAGE_TYPE_NOTIFICATION 0x0001
#define LDP_MESSAGE_TYPE_HELLO 0x0100
#define LDP_MESSAGE_TYPE_INITIALIZATION 0x0200
#define LDP_MESSAGE_TYPE_KEEPALIVE 0x0201
#define LDP_MESSAGE_TYPE_ADDRESS 0x0300
#define LDP_MESSAGE_TYPE_ADDRESS_WITHDRAW 0x0301
#define LDP_MESSAGE_TYPE_LABEL_MAPPING 0x0400
#define LDP_MESSAGE_TYPE_LABEL_REQUEST 0x0401
#define LDP_MESSAGE_TYPE_LABEL_WITHDRAW 0x0402
#define LDP_MESSAGE_TYPE_LABEL_RELEASE 0x0403
#define LDP_MESSAGE_TYPE_ABORT_REQUEST 0x0404
#define LDP_TLV_TYPE_FEC 0x0100
#define LDP_TLV_TYPE_ADDRESS_LIST 0x0101
#define LDP_TLV_TYPE_HOP_COUNT 0x0103
#define LDP_TLV_TYPE_PATH_VECTOR 0x0104
#define LDP_TLV_TYPE_GENERIC_LABEL 0x0200
#define LDP_TLV_TYPE_STATUS 0x0300
#define LDP_TLV_TYPE_EXTENDED_STATUS 0x0301
#define LDP_TLV_TYPE_RETURNED_PDU 0x0302
#define LDP_TLV_TYPE_RETURNED_MESSAGE 0x0303
#define LDP_TLV_TYPE_COMMON_HELLO_PARAMETERS 0x0400
#define LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS 0x0401
#define LDP_TLV_TYPE_CONFIG_SEQ_NUMBER 0x0402
#define LDP_TLV_TYPE_IPV6_TRANSPORT_ADDRESS 0x0403
#define LDP_TLV_TYPE_COMMON_SESSION_PARAMETERS 0x0500
#define LDP_TLV_TYPE_LABEL_REQUEST_ID 0x0600
#define LDP_TLV_LEN_MIN 4
#define LDP_DEFAULT_HELLO_INTERVAL 10
#define LDP_DEFAULT_HOLD_TIME 30
#define LDP_DEFAULT_TEARDOWN_TIME 5
typedef enum ldp_state_ {
LDP_NON_EXISTENT,
LDP_INITIALIZED,
LDP_OPENREC,
LDP_OPENSENT,
LDP_OPERATIONAL,
} ldp_state_t;
typedef struct ldp_instance_ ldp_instance_s;
typedef struct ldp_session_ ldp_session_s;
typedef struct ldp_adjacency_ ldp_adjacency_s;
/*
* LDP Type-Length-Value (TLV).
*/
typedef struct ldp_tlv_ {
bool u_bit; /* Unknown TLV bit. */
bool f_bit; /* Forward unknown TLV bit. */
uint16_t type;
uint16_t len;
uint8_t *value;
struct ldp_tlv_ *next;
} ldp_tlv_s;
/*
* LDP Message which contains
* one or more LDP TLV.
*/
typedef struct ldp_message_ {
bool u_bit; /* Unknown message bit. */
uint16_t type;
uint32_t msg_id;
ldp_tlv_s *tlv;
struct ldp_message_ *next;
} ldp_message_s;
/*
* LDP Protocol Data Unit (PDU) which contains
* one or more LDP messages.
*/
typedef struct ldp_pdu_ {
uint16_t version;
uint16_t len;
uint32_t lsr_id;
uint16_t label_space_id;
ldp_message_s *message;
} ldp_pdu_s;
/*
* LDP Instance Configuration.
*/
typedef struct ldp_config_ {
uint16_t id; /* LDP instance identifier */
uint32_t lsr_id;
uint32_t ipv4_transport_address;
const char *lsr_id_str;
const char *hostname;
bool overload;
uint16_t hello_interval;
uint16_t hold_time;
uint16_t teardown_time;
/* Pointer to next instance. */
struct ldp_config_ *next;
} ldp_config_s;
/*
* LDP Session.
*/
typedef struct ldp_session_ {
struct {
uint32_t ipv4_address;
uint32_t lsr_id;
uint16_t label_space_id;
uint16_t hold_time;
} local;
struct {
uint32_t ipv4_address;
uint32_t lsr_id;
uint16_t label_space_id;
uint16_t hold_time;
} peer;
struct {
uint32_t message_rx;
uint32_t message_tx;
uint32_t keepalive_rx;
uint32_t keepalive_tx;
} stats;
struct {
bool e_bit; /* Fatal error bit. */
bool f_bit; /* Forward bit. */
uint32_t code;
uint16_t msg_type;
} status;
uint16_t max_pdu_len;
ldp_instance_s *instance;
ldp_state_t state;
io_buffer_t read_buf;
io_buffer_t write_buf;
/* Pointer to next peer of
* corresponding instance. */
struct ldp_session_ *next;
} ldp_session_s;
/*
* LDP Adjacency.
*/
typedef struct ldp_adjacency_ {
bbl_network_interface_s *interface;
ldp_instance_s *instance;
ldp_session_s *session;
struct timer_ *hello_timer;
/* Pointer to next adjacency of
* corresponding instance with. */
struct ldp_adjacency_ *next;
} ldp_adjacency_s;
/*
* LDP Instance
*/
typedef struct ldp_instance_ {
ldp_config_s *config;
bool overload;
bool teardown;
struct timer_ *teardown_timer;
ldp_adjacency_s *adjacencies;
ldp_session_s *sessions;
hb_tree *ldb; /* Label database. */
/* Pointer to next instance. */
struct ldp_instance_ *next;
} ldp_instance_s;
#endif
+106
View File
@@ -0,0 +1,106 @@
/*
* BNG Blaster (BBL) - LDP Hello
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
void
ldp_hello_job(timer_s *timer)
{
ldp_adjacency_s *adjacency = timer->data;
bbl_network_interface_s *interface = adjacency->interface;
interface->send_requests |= BBL_IF_SEND_LDP_HELLO;
}
/**
* ldp_hello_start
*
* @param config LDP configuration
* @param adjacency LDP adjacency
*/
void
ldp_hello_start(ldp_config_s *config, ldp_adjacency_s *adjacency)
{
timer_add_periodic(&g_ctx->timer_root, &adjacency->hello_timer,
"LDP Hello", config->hello_interval, 0, adjacency,
&ldp_hello_job);
}
/**
* ldp_hello_encode
*
* @param interface send interface
* @param buf send buffer
* @param len send buffer length
* @param eth send ethernet parent structure
* @return PROTOCOL_SUCCESS on success
*/
protocol_error_t
ldp_hello_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth)
{
protocol_error_t result;
bbl_ipv4_s ipv4 = {0};
bbl_udp_s udp = {0};
bbl_ldp_hello_s ldp = {0};
ldp_adjacency_s *adjacency = interface->ldp_adjacency;
ldp_instance_s *instance = adjacency->instance;
ldp_config_s *config = instance->config;
/* Build packet ... */
eth->type = ETH_TYPE_IPV4;
eth->next = &ipv4;
eth->dst = (uint8_t*)all_routers_mac;
ipv4.dst = IPV4_MC_ALL_ROUTERS;
ipv4.src = interface->ip.address;
ipv4.ttl = 1;
ipv4.protocol = PROTOCOL_IPV4_UDP;
ipv4.router_alert_option = true;
ipv4.next = &udp;
udp.src = LDP_PORT;
udp.dst = LDP_PORT;
udp.protocol = UDP_PROTOCOL_LDP;
udp.next = &ldp;
ldp.lsr_id = config->lsr_id;
ldp.hold_time = config->hold_time;
ldp.ipv4_transport_address = config->ipv4_transport_address;
result = encode_ethernet(buf, len, eth);
if(result == PROTOCOL_SUCCESS) {
LOG(DEBUG, "LDP TX hello on interface %s\n", interface->name);
adjacency->interface->stats.ldp_udp_tx++;
}
return result;
}
/**
* ldp_hello_rx
*
* This function handles all received LDP hello packets.
*
* @param interface receiving interface
* @param eth received ethernet header
* @param ipv4 received ipv4 header
* @param ldp LDP header of received packet
*/
void
ldp_hello_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv4_s *ipv4,
bbl_ldp_hello_s *ldp)
{
ldp_adjacency_s *adjacency = interface->ldp_adjacency;
UNUSED(adjacency);
UNUSED(eth);
UNUSED(ipv4);
UNUSED(ldp);
}
+26
View File
@@ -0,0 +1,26 @@
/*
* BNG Blaster (BBL) - LDP Hello
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_HELLO_H__
#define __BBL_LDP_HELLO_H__
void
ldp_hello_start(ldp_config_s *config, ldp_adjacency_s *adjacency);
protocol_error_t
ldp_hello_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth);
void
ldp_hello_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv4_s *ipv4,
bbl_ldp_hello_s *ldp);
#endif
+49
View File
@@ -0,0 +1,49 @@
/*
* BNG Blaster (BBL) - LDP Interface
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
void
ldp_interface_hello_job(timer_s *timer)
{
ldp_adjacency_s *adjacency = timer->data;
bbl_network_interface_s *interface = adjacency->interface;
interface->send_requests |= BBL_IF_SEND_LDP_HELLO;
}
/**
* ldp_interface_init
*
* This function inits the LDP interface.
*
* @param interface network interface
* @param config network interface configuration
* @param instance LDP instance
*/
bool
ldp_interface_init(bbl_network_interface_s *interface,
bbl_network_config_s *interface_config,
ldp_instance_s *instance)
{
ldp_config_s *config = instance->config;
ldp_adjacency_s *adjacency;
LOG(LDP, "Add network interface %s to LDP instance %u\n",
interface->name, interface_config->ldp_instance_id);
adjacency = calloc(1, sizeof(ldp_adjacency_s));
adjacency->next = instance->adjacencies;
instance->adjacencies = adjacency;
adjacency->instance = instance;
adjacency->interface = interface;
interface->ldp_adjacency = adjacency;
ldp_hello_start(config, adjacency);
return true;
}
+17
View File
@@ -0,0 +1,17 @@
/*
* BNG Blaster (BBL) - LDP Interface
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_INTERFACE_H__
#define __BBL_LDP_INTERFACE_H__
bool
ldp_interface_init(bbl_network_interface_s *interface,
bbl_network_config_s *interface_config,
ldp_instance_s *instance);
#endif
+9
View File
@@ -0,0 +1,9 @@
/*
* BNG Blaster (BBL) - LDP PDU
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
+12
View File
@@ -0,0 +1,12 @@
/*
* BNG Blaster (BBL) - LDP PDU
*
* Christian Giese, November 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_LDP_PDU_H__
#define __BBL_LDP_PDU_H__
#endif
+176
View File
@@ -0,0 +1,176 @@
/*
* BNG Blaster (BBL) - LDP Message Receive Functions
*
* Christian Giese, March 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "ldp.h"
struct keyval_ ldp_msg_names[] = {
{ LDP_MESSAGE_TYPE_NOTIFICATION, "notification" },
{ LDP_MESSAGE_TYPE_HELLO, "hello" },
{ LDP_MESSAGE_TYPE_INITIALIZATION, "initialization" },
{ LDP_MESSAGE_TYPE_KEEPALIVE, "keepalive" },
{ LDP_MESSAGE_TYPE_ADDRESS, "address" },
{ LDP_MESSAGE_TYPE_ADDRESS_WITHDRAW, "address-withdraw" },
{ LDP_MESSAGE_TYPE_LABEL_MAPPING, "label-mapping" },
{ LDP_MESSAGE_TYPE_LABEL_REQUEST, "label-request" },
{ LDP_MESSAGE_TYPE_LABEL_WITHDRAW, "label-withdraw" },
{ LDP_MESSAGE_TYPE_LABEL_RELEASE, "label-release" },
{ LDP_MESSAGE_TYPE_ABORT_REQUEST, "abort-request" },
{ 0, NULL}
};
/*
* When there is only little data left and
* the buffer start is close to buffer end,
* then 'rebase' the buffer by copying
* the tail data to the buffer head.
*/
static void
ldp_rebase_buffer(io_buffer_t *buffer)
{
uint32_t size;
size = buffer->idx - buffer->start_idx;
if(size) {
/* Copy what is left to the buffer start. */
memcpy(buffer->data, buffer->data+buffer->start_idx, size);
}
buffer->start_idx = 0;
buffer->idx = size;
}
static void
ldp_read(ldp_session_s *session)
{
uint32_t size;
uint16_t length;
io_buffer_t *buffer = &session->read_buf;
uint32_t lsr_id;
uint16_t label_space_id;
uint8_t *pdu_start;
uint16_t pdu_version;
uint16_t pdu_length;
uint8_t *msg_start;
uint16_t msg_type;
uint16_t msg_length;
while(true) {
pdu_start = buffer->data+buffer->start_idx;
size = buffer->idx - buffer->start_idx;
/* Minimum PDU size */
if(size < 4) {
break;
}
pdu_version = read_be_uint(pdu_start, 2);
pdu_length = read_be_uint(pdu_start+2, 2);
/* The PDU length is defined as two octet integer specifying
* the total length of the PDU in octets, excluding the version
* and PDU length fields. */
if(pdu_version != 1 ||
pdu_length < LDP_IDENTIFIER_LEN ||
pdu_length > session->max_pdu_len) {
//ldp_decode_error(session);
break;
}
length = pdu_length+4;
/* Full message on the wire to consume? */
if(length > size) {
break;
}
/* Read LDP Identifier. */
lsr_id = read_be_uint(pdu_start+4, 4);
label_space_id = read_be_uint(pdu_start+8, 2);
if(lsr_id != session->peer.lsr_id ||
label_space_id != session->peer.label_space_id) {
/* TODO: INVALID MESSAGE!!!! */
break;
}
pdu_length -= LDP_IDENTIFIER_LEN;
msg_start = pdu_start+10;
while(pdu_length >= 4) {
msg_type = read_be_uint(msg_start, 2);
msg_length = read_be_uint(msg_start+2, 2);
UNUSED(msg_length);
LOG(DEBUG, "LDP (%s - %s) read %s message\n",
format_ipv4_address(&session->local.ipv4_address),
format_ipv4_address(&session->peer.ipv4_address),
keyval_get_key(ldp_msg_names, msg_type));
session->stats.message_rx++;
switch(msg_type) {
case LDP_MESSAGE_TYPE_NOTIFICATION:
break;
case LDP_MESSAGE_TYPE_INITIALIZATION:
break;
case LDP_MESSAGE_TYPE_KEEPALIVE:
session->stats.keepalive_rx++;
break;
case LDP_MESSAGE_TYPE_ADDRESS:
case LDP_MESSAGE_TYPE_ADDRESS_WITHDRAW:
case LDP_MESSAGE_TYPE_LABEL_MAPPING:
case LDP_MESSAGE_TYPE_LABEL_REQUEST:
case LDP_MESSAGE_TYPE_LABEL_WITHDRAW:
case LDP_MESSAGE_TYPE_LABEL_RELEASE:
case LDP_MESSAGE_TYPE_ABORT_REQUEST:
break;
default:
break;
}
}
/* Reset hold timer */
//ldp_restart_hold_timer(session, session->instance->config->hold_time);
/* Progress pointer to next LDP PDU. */
buffer->start_idx += length;
}
ldp_rebase_buffer(buffer);
}
void
ldp_receive_cb(void *arg, uint8_t *buf, uint16_t len)
{
ldp_session_s *session = (ldp_session_s*)arg;
io_buffer_t *buffer = &session->read_buf;
if(buf) {
if(buffer->idx+len > buffer->size) {
LOG(ERROR, "LDP (%s - %s) receive error (read buffer exhausted)\n",
format_ipv4_address(&session->local.ipv4_address),
format_ipv4_address(&session->peer.ipv4_address));
#if 0
if(!session->status_code) {
peer->status_code = 0x00000019; /* Cease */
session->error_subcode = 8; /* Out of resources */
}
#endif
//ldp_session_close(session);
return;
}
memcpy(buffer->data+buffer->idx, buf, len);
buffer->idx+=len;
} else {
ldp_read(session);
}
}
+1
View File
@@ -36,6 +36,7 @@ enum {
L2TP,
DHCP,
ISIS,
LDP,
BGP,
TCP,
LSDB,
+2 -2
View File
@@ -25,8 +25,8 @@
* - `peer-as`
- BGP peer AS
- local AS
* - `holdtime`
- BGP holdtime in seconds
* - `hold-time`
- BGP hold-time in seconds
- 90
* - `id`
- BGP identifier
+2 -2
View File
@@ -43,8 +43,8 @@
* - `hello-padding`
- ISIS hello padding
- false
* - `holding-time`
- ISIS holding time in seconds
* - `hold-time`
- ISIS hold time in seconds
- 30
* - `lsp-lifetime`
- ISIS LSP lifetime in seconds
+33
View File
@@ -0,0 +1,33 @@
.. code-block:: json
{ "ldp": {} }
.. list-table::
:widths: 25 50 25
:header-rows: 1
* - Attribute
- Description
- Default
* - `instance-id`
- LDP instance identifier
-
* - `overload`
- LDP overload
- false
* - `hello-interval`
- LDP hello interval in seconds
- 10
* - `hold-time`
- LDP hold time in seconds
- 30
* - `hostname`
- LDP hostname
- bngblaster
* - `router-id`
- LDP router identifier
- 10.10.10.10
* - `teardown-time`
- LDP teardown time in seconds
- 5
+3 -3
View File
@@ -519,7 +519,7 @@ Finally, start the BNG Blaster in another terminal window.
Apr 08 14:53:52.904389 All network interfaces resolved
Apr 08 14:53:53.904448 BGP (veth1.2 192.168.92.2 - 192.168.92.1) state changed from idle -> connect
Apr 08 14:53:53.905659 BGP (veth1.2 192.168.92.2 - 192.168.92.1) state changed from connect -> opensent
Apr 08 14:53:53.907888 BGP (veth1.2 192.168.92.2 - 192.168.92.1) open message received with peer AS: 65001, holdtime: 90s
Apr 08 14:53:53.907888 BGP (veth1.2 192.168.92.2 - 192.168.92.1) open message received with peer AS: 65001, hold-time: 90s
Apr 08 14:53:53.907903 BGP (veth1.2 192.168.92.2 - 192.168.92.1) state changed from opensent -> openconfirm
Apr 08 14:53:53.907917 BGP (veth1.2 192.168.92.2 - 192.168.92.1) state changed from openconfirm -> established
Apr 08 14:53:54.907989 BGP (veth1.2 192.168.92.2 - 192.168.92.1) raw update start
@@ -544,11 +544,11 @@ from where you started the BNG Blaster and enter the following command.
"local-address": "192.168.92.2",
"local-id": "1.2.3.4",
"local-as": 65001,
"local-holdtime": 90,
"local-hold-time": 90,
"peer-address": "192.168.92.1",
"peer-id": "1.92.168.192",
"peer-as": 65001,
"peer-holdtime": 90,
"peer-hold-time": 90,
"state": "established",
"raw-update-state": "done",
"raw-update-file": "out.bgp",
+2 -1
View File
@@ -9,5 +9,6 @@ router testing.
:maxdepth: 1
isis.rst
bgp.rst
ldp.rst
mpls.rst
bgp.rst
+62
View File
@@ -0,0 +1,62 @@
.. _ldp:
LDP
---
The Label Distribution Protocol (LDP) is a protocol defined for
distributing labels.
Configuration
~~~~~~~~~~~~~
Following an example LDP configuration with one instance
attached to two network interfaces.
.. code-block:: json
{
"interfaces": {
"network": [
{
"interface": "eth1",
"address": "10.0.1.2/24",
"gateway": "10.0.1.1",
"address-ipv6": "fc66:1337:7331:1::2/64",
"gateway-ipv6": "fc66:1337:7331:1::1",
"ldp-instance-id": 1,
},
{
"interface": "eth2",
"address": "10.0.2.2/24",
"gateway": "10.0.2.1",
"address-ipv6": "fc66:1337:7331:2::2/64",
"gateway-ipv6": "fc66:1337:7331:2::1",
"ldp-instance-id": 1
}
]
},
"ldp": [
{
"instance-id": 1,
"lsr-id": "10.10.10.10",
"hostname": "R1",
}
]
}
.. include:: ../configuration/ldp.rst
The support for multiple instances allows different use cases. One example might
be to create two instances connected to the device or network under test. Now
inject an LSP on one instance and check if learned over the tested network on
the other instance.
Peers
~~~~~
Database
~~~~~~~~
Limitations
~~~~~~~~~~~