mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
LDP initial structure
This commit is contained in:
committed by
Christian Giese
parent
89a8ef44a0
commit
6f5979ee2e
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, ð);
|
||||
} 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, ð);
|
||||
} else {
|
||||
interface->send_requests = 0;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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--;
|
||||
}
|
||||
@@ -147,8 +147,9 @@ isis_csnp_job(timer_s *timer)
|
||||
isis.pdu_len = pdu.pdu_len;
|
||||
if(bbl_txq_to_buffer(adjacency->interface->txq, ð) == 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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -129,8 +129,9 @@ isis_psnp_job (timer_s *timer)
|
||||
isis.pdu_len = pdu.pdu_len;
|
||||
if(bbl_txq_to_buffer(adjacency->interface->txq, ð) == 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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ enum {
|
||||
L2TP,
|
||||
DHCP,
|
||||
ISIS,
|
||||
LDP,
|
||||
BGP,
|
||||
TCP,
|
||||
LSDB,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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",
|
||||
|
||||
@@ -9,5 +9,6 @@ router testing.
|
||||
:maxdepth: 1
|
||||
|
||||
isis.rst
|
||||
bgp.rst
|
||||
ldp.rst
|
||||
mpls.rst
|
||||
bgp.rst
|
||||
|
||||
@@ -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
|
||||
~~~~~~~~~~~
|
||||
|
||||
Reference in New Issue
Block a user