restructure control commands

This commit is contained in:
Christian Giese
2022-10-10 13:36:01 +00:00
parent bd30f127a5
commit d55e76ec1f
32 changed files with 1986 additions and 1709 deletions
+3
View File
@@ -26,6 +26,7 @@
#include "bgp/bgp_def.h"
#include "isis/isis_def.h"
#include "bbl_ctrl.h"
#include "bbl_stats.h"
#include "bbl_access_line.h"
#include "bbl_config.h"
@@ -39,6 +40,8 @@
#include "bbl_network.h"
#include "bbl_a10nsp.h"
#include "bbl_li.h"
#include "bbl_igmp.h"
#include "bbl_cfm.h"
#include "bbl_tcp.h"
#include "io/io.h"
+67
View File
@@ -547,4 +547,71 @@ bbl_a10nsp_rx_handler(bbl_a10nsp_interface_s *interface,
if(session) {
bbl_a10nsp_rx(interface, session, eth);
}
}
static json_t *
bbl_a10nsp_interface_json(bbl_a10nsp_interface_s *interface)
{
return json_pack("{ss si ss si si si si si si si si si si si si si si si si si si si si si si si si si si si si}",
"name", interface->name,
"ifindex", interface->ifindex,
"type", "a10nsp",
"tx-packets", interface->stats.packets_tx,
"tx-bytes", interface->stats.bytes_tx,
"tx-pps", interface->stats.rate_packets_tx.avg,
"tx-kbps", interface->stats.rate_bytes_tx.avg * 8 / 1000,
"rx-packets", interface->stats.packets_rx,
"rx-bytes", interface->stats.bytes_rx,
"rx-pps", interface->stats.rate_packets_rx.avg,
"rx-kbps", interface->stats.rate_bytes_rx.avg * 8 / 1000,
"tx-packets-session-ipv4", interface->stats.session_ipv4_tx,
"tx-pps-session-ipv4", interface->stats.rate_session_ipv4_tx.avg,
"rx-packets-session-ipv4", interface->stats.session_ipv4_rx,
"rx-pps-session-ipv4", interface->stats.rate_session_ipv4_rx.avg,
"rx-loss-packets-session-ipv4", interface->stats.session_ipv4_loss,
"tx-packets-session-ipv6", interface->stats.session_ipv6_tx,
"tx-pps-session-ipv6", interface->stats.rate_session_ipv6_tx.avg,
"rx-packets-session-ipv6", interface->stats.session_ipv6_rx,
"rx-pps-session-ipv6", interface->stats.rate_session_ipv6_rx.avg,
"rx-loss-packets-session-ipv6", interface->stats.session_ipv6_loss,
"tx-packets-session-ipv6pd", interface->stats.session_ipv6pd_tx,
"tx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_tx.avg,
"rx-packets-session-ipv6pd", interface->stats.session_ipv6pd_rx,
"rx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_rx.avg,
"rx-loss-packets-session-ipv6pd", interface->stats.session_ipv6pd_loss,
"tx-packets-streams", interface->stats.stream_tx,
"tx-pps-streams", interface->stats.rate_stream_tx.avg,
"rx-packets-streams", interface->stats.stream_rx,
"rx-pps-streams", interface->stats.rate_stream_rx.avg,
"rx-loss-packets-streams", interface->stats.stream_loss
);
}
/* Control Socket Commands */
int
bbl_a10nsp_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *interfaces;
bbl_interface_s *interface;
interfaces = json_array();
CIRCLEQ_FOREACH(interface, &g_ctx->interface_qhead, interface_qnode) {
if(interface->a10nsp) {
json_array_append(interfaces, bbl_a10nsp_interface_json(interface->a10nsp));
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"a10nsp-interfaces", interfaces);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(interfaces);
}
return result;
}
+4 -1
View File
@@ -111,4 +111,7 @@ void
bbl_a10nsp_rx_handler(bbl_a10nsp_interface_s *interface,
bbl_ethernet_header_s *eth);
#endif
int
bbl_a10nsp_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+70
View File
@@ -1846,4 +1846,74 @@ bbl_access_rx_handler(bbl_access_interface_s *interface,
}
}
}
}
static json_t *
bbl_access_interface_json(bbl_access_interface_s *interface)
{
return json_pack("{ss si ss si si si si si si si si si si si si si si si si si si si si si si si si si si si si si si si}",
"name", interface->name,
"ifindex", interface->ifindex,
"type", "access",
"tx-packets", interface->stats.packets_tx,
"tx-bytes", interface->stats.bytes_tx,
"tx-pps", interface->stats.rate_packets_tx.avg,
"tx-kbps", interface->stats.rate_bytes_tx.avg * 8 / 1000,
"rx-packets", interface->stats.packets_rx,
"rx-bytes", interface->stats.bytes_rx,
"rx-pps", interface->stats.rate_packets_rx.avg,
"rx-kbps", interface->stats.rate_bytes_rx.avg * 8 / 1000,
"rx-packets-multicast", interface->stats.mc_rx,
"rx-pps-multicast", interface->stats.rate_mc_rx.avg,
"rx-loss-packets-multicast", interface->stats.mc_loss,
"tx-packets-session-ipv4", interface->stats.session_ipv4_tx,
"tx-pps-session-ipv4", interface->stats.rate_session_ipv4_tx.avg,
"rx-packets-session-ipv4", interface->stats.session_ipv4_rx,
"rx-pps-session-ipv4", interface->stats.rate_session_ipv4_rx.avg,
"rx-loss-packets-session-ipv4", interface->stats.session_ipv4_loss,
"tx-packets-session-ipv6", interface->stats.session_ipv6_tx,
"tx-pps-session-ipv6", interface->stats.rate_session_ipv6_tx.avg,
"rx-packets-session-ipv6", interface->stats.session_ipv6_rx,
"rx-pps-session-ipv6", interface->stats.rate_session_ipv6_rx.avg,
"rx-loss-packets-session-ipv6", interface->stats.session_ipv6_loss,
"tx-packets-session-ipv6pd", interface->stats.session_ipv6pd_tx,
"tx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_tx.avg,
"rx-packets-session-ipv6pd", interface->stats.session_ipv6pd_rx,
"rx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_rx.avg,
"rx-loss-packets-session-ipv6pd", interface->stats.session_ipv6pd_loss,
"tx-packets-streams", interface->stats.stream_tx,
"tx-pps-streams", interface->stats.rate_stream_tx.avg,
"rx-packets-streams", interface->stats.stream_rx,
"rx-pps-streams", interface->stats.rate_stream_rx.avg,
"rx-loss-packets-streams", interface->stats.stream_loss
);
}
/* Control Socket Commands */
int
bbl_access_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *interfaces;
bbl_interface_s *interface;
interfaces = json_array();
CIRCLEQ_FOREACH(interface, &g_ctx->interface_qhead, interface_qnode) {
if(interface->access) {
json_array_append(interfaces, bbl_access_interface_json(interface->access));
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"access-interfaces", interfaces);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(interfaces);
}
return result;
}
+3
View File
@@ -140,4 +140,7 @@ void
bbl_access_rx_handler(bbl_access_interface_s *interface,
bbl_ethernet_header_s *eth);
int
bbl_access_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+83
View File
@@ -0,0 +1,83 @@
/*
* BNG Blaster (BBL) - CFM Functions
*
* Christian Giese, October 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bbl.h"
static int
bbl_cfm_ctrl_cc_start_stop(int fd, uint32_t session_id, bool status)
{
bbl_session_s *session;
uint32_t i;
if(session_id) {
session = bbl_session_get(session_id);
if(session) {
session->cfm_cc = status;
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
session->cfm_cc = status;
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
}
int
bbl_cfm_ctrl_cc_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_cfm_ctrl_cc_start_stop(fd, session_id, true);
}
int
bbl_cfm_ctrl_cc_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_cfm_ctrl_cc_start_stop(fd, session_id, false);
}
static int
bbl_cfm_ctrl_cc_rdi(int fd, uint32_t session_id, bool status)
{
bbl_session_s *session;
uint32_t i;
if(session_id) {
session = bbl_session_get(session_id);
if(session) {
session->cfm_rdi = status;
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
session->cfm_rdi = status;
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
}
int
bbl_cfm_ctrl_cc_rdi_on(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_cfm_ctrl_cc_rdi(fd, session_id, true);
}
int
bbl_cfm_ctrl_cc_rdi_off(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_cfm_ctrl_cc_rdi(fd, session_id, false);
}
+25
View File
@@ -0,0 +1,25 @@
/*
* BNG Blaster (BBL) - CFM Functions
*
* Christian Giese, October 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_CFM_H__
#define __BBL_CFM_H__
int
bbl_cfm_ctrl_cc_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_cfm_ctrl_cc_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_cfm_ctrl_cc_rdi_on(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_cfm_ctrl_cc_rdi_off(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
#endif
File diff suppressed because it is too large Load Diff
+430
View File
@@ -0,0 +1,430 @@
/*
* BNG Blaster (BBL) - IGMP Functions
*
* Christian Giese, October 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bbl.h"
int
bbl_igmp_ctrl_join(int fd, uint32_t session_id, json_t *arguments)
{
bbl_session_s *session;
const char *s;
uint32_t group_address = 0;
uint32_t source1 = 0;
uint32_t source2 = 0;
uint32_t source3 = 0;
bbl_igmp_group_s *group = NULL;
int i;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
/* Unpack further arguments */
if (json_unpack(arguments, "{s:s}", "group", &s) == 0) {
if(!inet_pton(AF_INET, s, &group_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid group address");
}
} else {
return bbl_ctrl_status(fd, "error", 400, "missing group address");
}
if (json_unpack(arguments, "{s:s}", "source1", &s) == 0) {
if(!inet_pton(AF_INET, s, &source1)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source1 address");
}
}
if (json_unpack(arguments, "{s:s}", "source2", &s) == 0) {
if(!inet_pton(AF_INET, s, &source2)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source2 address");
}
}
if (json_unpack(arguments, "{s:s}", "source3", &s) == 0) {
if(!inet_pton(AF_INET, s, &source3)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source3 address");
}
}
/* Search session */
session = bbl_session_get(session_id);
if(session) {
/* Search for free slot ... */
for(i=0; i < IGMP_MAX_GROUPS; i++) {
if(!session->igmp_groups[i].zapping) {
if (session->igmp_groups[i].group == group_address) {
group = &session->igmp_groups[i];
if(group->state == IGMP_GROUP_IDLE) {
break;
} else {
return bbl_ctrl_status(fd, "error", 409, "group already exists");
}
} else if(session->igmp_groups[i].state == IGMP_GROUP_IDLE) {
group = &session->igmp_groups[i];
}
}
}
if(!group) {
return bbl_ctrl_status(fd, "error", 409, "no igmp group slot available");
}
/* Join group... */
memset(group, 0x0, sizeof(bbl_igmp_group_s));
group->group = group_address;
if(source1) group->source[0] = source1;
if(source2) group->source[1] = source2;
if(source3) group->source[2] = source3;
group->state = IGMP_GROUP_JOINING;
group->robustness_count = session->igmp_robustness;
group->send = true;
session->send_requests |= BBL_SEND_IGMP;
bbl_session_tx_qnode_insert(session);
LOG(IGMP, "IGMP (ID: %u) join %s\n",
session->session_id, format_ipv4_address(&group->group));
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_igmp_ctrl_join_iter(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
bbl_session_s *session;
const char *s;
uint32_t group_address = 0;
uint32_t group_iter = 1;
int group_count = 0;
bbl_igmp_group_s *group = NULL;
uint32_t source1 = 0;
uint32_t source2 = 0;
uint32_t source3 = 0;
uint32_t i, i2;
uint32_t join_count;
/* Unpack group arguments */
if (json_unpack(arguments, "{s:s}", "group", &s) == 0) {
if(!inet_pton(AF_INET, s, &group_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid group address");
}
} else {
return bbl_ctrl_status(fd, "error", 400, "missing group address");
}
if (json_unpack(arguments, "{s:d}", "group-iter", &s) == 0) {
if(!inet_pton(AF_INET, s, &group_iter)) {
return bbl_ctrl_status(fd, "error", 400, "invalid group-iter");
}
group_iter = be32toh(group_iter);
}
json_unpack(arguments, "{s:i}", "group-count", &group_count);
if(group_count < 1) group_count = 1;
/* Unpack source address arguments */
if (json_unpack(arguments, "{s:s}", "source1", &s) == 0) {
if(!inet_pton(AF_INET, s, &source1)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source1 address");
}
}
if (json_unpack(arguments, "{s:s}", "source2", &s) == 0) {
if(!inet_pton(AF_INET, s, &source2)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source2 address");
}
}
if (json_unpack(arguments, "{s:s}", "source3", &s) == 0) {
if(!inet_pton(AF_INET, s, &source3)) {
return bbl_ctrl_status(fd, "error", 400, "invalid source3 address");
}
}
while(group_count) {
/* Iterate over all sessions */
join_count = 0;
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
/* Search for free slot ... */
for(i2=0; i2 < IGMP_MAX_GROUPS; i2++) {
group = &session->igmp_groups[i2];
if(group->zapping) {
continue;
}
if(group->group == group_address &&
group->state != IGMP_GROUP_IDLE) {
/* Group already exists. */
group_address = htobe32(be32toh(group_address) + group_iter);
break;
}
if(group->state != IGMP_GROUP_IDLE) {
continue;
}
/* Join group. */
memset(group, 0x0, sizeof(bbl_igmp_group_s));
group->group = group_address;
if(source1) group->source[0] = source1;
if(source2) group->source[1] = source2;
if(source3) group->source[2] = source3;
group->state = IGMP_GROUP_JOINING;
group->robustness_count = session->igmp_robustness;
group->send = true;
LOG(IGMP, "IGMP (ID: %u) join %s\n",
session->session_id, format_ipv4_address(&group->group));
session->send_requests |= BBL_SEND_IGMP;
join_count++;
if(--group_count == 0) {
return bbl_ctrl_status(fd, "ok", 200, NULL);
};
/* Get next group address. */
group_address = htobe32(be32toh(group_address) + group_iter);
break;
}
}
}
/* Prevent infinity loops! */
if(!join_count) break;
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bbl_igmp_ctrl_leave(int fd, uint32_t session_id, json_t *arguments)
{
bbl_session_s *session;
const char *s;
uint32_t group_address = 0;
bbl_igmp_group_s *group = NULL;
int i;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
/* Unpack further arguments */
if (json_unpack(arguments, "{s:s}", "group", &s) == 0) {
if(!inet_pton(AF_INET, s, &group_address)) {
return bbl_ctrl_status(fd, "error", 400, "invalid group address");
}
} else {
return bbl_ctrl_status(fd, "error", 400, "missing group address");
}
session = bbl_session_get(session_id);
if(session) {
/* Search for group ... */
for(i=0; i < IGMP_MAX_GROUPS; i++) {
if (session->igmp_groups[i].group == group_address) {
group = &session->igmp_groups[i];
break;
}
}
if(!group) {
return bbl_ctrl_status(fd, "warning", 404, "group not found");
}
if(group->zapping) {
return bbl_ctrl_status(fd, "error", 408, "group used by zapping test");
}
if(group->state <= IGMP_GROUP_LEAVING) {
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
group->state = IGMP_GROUP_LEAVING;
group->robustness_count = session->igmp_robustness;
group->send = true;
group->leave_tx_time.tv_sec = 0;
group->leave_tx_time.tv_nsec = 0;
group->last_mc_rx_time.tv_sec = 0;
group->last_mc_rx_time.tv_nsec = 0;
session->send_requests |= BBL_SEND_IGMP;
bbl_session_tx_qnode_insert(session);
LOG(IGMP, "IGMP (ID: %u) leave %s\n",
session->session_id, format_ipv4_address(&group->group));
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_igmp_ctrl_leave_all(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
bbl_session_s *session;
bbl_igmp_group_s *group = NULL;
uint32_t i, i2;
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
/* Search for group ... */
for(i2=0; i2 < IGMP_MAX_GROUPS; i2++) {
group = &session->igmp_groups[i2];
if(group->zapping || group->state <= IGMP_GROUP_LEAVING) {
continue;
}
group->state = IGMP_GROUP_LEAVING;
group->robustness_count = session->igmp_robustness;
group->send = true;
group->leave_tx_time.tv_sec = 0;
group->leave_tx_time.tv_nsec = 0;
group->last_mc_rx_time.tv_sec = 0;
group->last_mc_rx_time.tv_nsec = 0;
LOG(IGMP, "IGMP (ID: %u) leave %s\n",
session->session_id, format_ipv4_address(&group->group));
session->send_requests |= BBL_SEND_IGMP;
bbl_session_tx_qnode_insert(session);
}
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bbl_igmp_ctrl_info(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *groups, *record, *sources;
bbl_session_s *session = NULL;
bbl_igmp_group_s *group = NULL;
uint32_t delay = 0;
uint32_t ms;
struct timespec time_diff;
int i, i2;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
session = bbl_session_get(session_id);
if(session) {
groups = json_array();
/* Add group informations */
for(i=0; i < IGMP_MAX_GROUPS; i++) {
group = &session->igmp_groups[i];
if(group->group) {
sources = json_array();
for(i2=0; i2 < IGMP_MAX_SOURCES; i2++) {
if(group->source[i2]) {
json_array_append(sources, json_string(format_ipv4_address(&group->source[i2])));
}
}
record = json_pack("{ss so si si}",
"group", format_ipv4_address(&group->group),
"sources", sources,
"packets", group->packets,
"loss", group->loss);
switch (group->state) {
case IGMP_GROUP_IDLE:
json_object_set(record, "state", json_string("idle"));
if(group->last_mc_rx_time.tv_sec && group->leave_tx_time.tv_sec) {
timespec_sub(&time_diff, &group->last_mc_rx_time, &group->leave_tx_time);
ms = time_diff.tv_nsec / 1000000; /* convert nanoseconds to milliseconds */
if(time_diff.tv_nsec % 1000000) ms++; /* simple roundup function */
delay = (time_diff.tv_sec * 1000) + ms;
json_object_set(record, "leave-delay-ms", json_integer(delay));
}
break;
case IGMP_GROUP_LEAVING:
json_object_set(record, "state", json_string("leaving"));
break;
case IGMP_GROUP_ACTIVE:
json_object_set(record, "state", json_string("active"));
if(group->first_mc_rx_time.tv_sec) {
timespec_sub(&time_diff, &group->first_mc_rx_time, &group->join_tx_time);
ms = time_diff.tv_nsec / 1000000; /* convert nanoseconds to milliseconds */
if(time_diff.tv_nsec % 1000000) ms++; /* simple roundup function */
delay = (time_diff.tv_sec * 1000) + ms;
json_object_set(record, "join-delay-ms", json_integer(delay));
}
break;
case IGMP_GROUP_JOINING:
json_object_set(record, "state", json_string("joining"));
if(group->first_mc_rx_time.tv_sec) {
timespec_sub(&time_diff, &group->first_mc_rx_time, &group->join_tx_time);
ms = time_diff.tv_nsec / 1000000; /* convert nanoseconds to milliseconds */
if(time_diff.tv_nsec % 1000000) ms++; /* simple roundup function */
delay = (time_diff.tv_sec * 1000) + ms;
json_object_set(record, "join-delay-ms", json_integer(delay));
}
break;
default:
break;
}
json_array_append(groups, record);
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"igmp-groups", groups);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(groups);
}
return result;
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_igmp_ctrl_zapping_start(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
g_ctx->zapping = true;
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bbl_igmp_ctrl_zapping_stop(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
g_ctx->zapping = false;
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bbl_igmp_ctrl_zapping_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root;
bbl_stats_s stats = {0};
int reset = 0;
json_unpack(arguments, "{s:b}", "reset", &reset);
bbl_stats_generate_multicast(&stats, reset);
root = json_pack("{ss si s{si si si si si si si si si si si si si si si si si}}",
"status", "ok",
"code", 200,
"zapping-stats",
"join-delay-ms-min", stats.min_join_delay,
"join-delay-ms-avg", stats.avg_join_delay,
"join-delay-ms-max", stats.max_join_delay,
"join-delay-violations", stats.join_delay_violations,
"join-delay-violations-threshold", g_ctx->config.igmp_max_join_delay,
"join-delay-violations-125ms", stats.join_delay_violations_125ms,
"join-delay-violations-250ms", stats.join_delay_violations_250ms,
"join-delay-violations-500ms", stats.join_delay_violations_500ms,
"join-delay-violations-1s", stats.join_delay_violations_1s,
"join-delay-violations-2s", stats.join_delay_violations_2s,
"join-count", stats.zapping_join_count,
"leave-delay-ms-min", stats.min_leave_delay,
"leave-delay-ms-avg", stats.avg_leave_delay,
"leave-delay-ms-max", stats.max_leave_delay,
"leave-count", stats.zapping_leave_count,
"multicast-packets-overlap", stats.mc_old_rx_after_first_new,
"multicast-not-received", stats.mc_not_received);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
}
return result;
}
+37
View File
@@ -0,0 +1,37 @@
/*
* BNG Blaster (BBL) - IGMP Functions
*
* Christian Giese, October 2022
*
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __BBL_IGMP_H__
#define __BBL_IGMP_H__
int
bbl_igmp_ctrl_join(int fd, uint32_t session_id, json_t *arguments);
int
bbl_igmp_ctrl_join_iter(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bbl_igmp_ctrl_leave(int fd, uint32_t session_id, json_t *arguments);
int
bbl_igmp_ctrl_leave_all(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_igmp_ctrl_info(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_igmp_ctrl_zapping_start(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_igmp_ctrl_zapping_stop(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_igmp_ctrl_zapping_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+36
View File
@@ -214,3 +214,39 @@ bbl_interface_get(char *interface_name)
}
return NULL;
}
int
bbl_interface_ctrl(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
bbl_interface_s *interface;
json_t *root, *jobj, *jobj_array;
jobj_array = json_array();
CIRCLEQ_FOREACH(interface, &g_ctx->interface_qhead, interface_qnode) {
jobj = json_pack("{ss si ss* ss* si }",
"name", interface->name,
"ifindex", interface->ifindex,
"type", interface_type_string(interface->type),
"state", interface_state_string(interface->state),
"state-transitions", interface->state_transitions);
if(jobj) {
json_array_append(jobj_array, jobj);
}
}
root = json_pack("{ss si so*}",
"status", "ok",
"code", 200,
"interfaces", jobj_array);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
}
return result;
}
+3
View File
@@ -55,4 +55,7 @@ bbl_interface_init();
bbl_interface_s *
bbl_interface_get(char *interface_name);
int
bbl_interface_ctrl(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+367 -46
View File
@@ -14,7 +14,7 @@
#include <openssl/rand.h>
void
bbl_l2tp_send(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type);
bbl_l2tp_send(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type);
const char*
l2tp_message_string(l2tp_message_t type)
@@ -71,7 +71,7 @@ l2tp_session_state_string(l2tp_session_state_t state)
* bbl_l2tp_force_stop
*/
static void
bbl_l2tp_force_stop(bbl_l2tp_sunnel_s *l2tp_tunnel)
bbl_l2tp_force_stop(bbl_l2tp_tunnel_s *l2tp_tunnel)
{
bbl_l2tp_queue_s *q = NULL;
bbl_l2tp_queue_s *q_del = NULL;
@@ -149,7 +149,7 @@ bbl_l2tp_session_delete(bbl_l2tp_session_s *l2tp_session)
}
/**
* bbl_l2tp_sunnel_delete
* bbl_l2tp_tunnel_delete
*
* This function will free all dynamic memory for the given
* l2tp tunnel instance including corresponding send queues.
@@ -157,7 +157,7 @@ bbl_l2tp_session_delete(bbl_l2tp_session_s *l2tp_session)
* @param l2tp_tunnel L2TP tunnel structure to be deleted.
*/
void
bbl_l2tp_sunnel_delete(bbl_l2tp_sunnel_s *l2tp_tunnel)
bbl_l2tp_tunnel_delete(bbl_l2tp_tunnel_s *l2tp_tunnel)
{
bbl_l2tp_queue_s *q;
if(l2tp_tunnel) {
@@ -205,13 +205,13 @@ bbl_l2tp_sunnel_delete(bbl_l2tp_sunnel_s *l2tp_tunnel)
}
/**
* bbl_l2tp_sunnel_update_state
* bbl_l2tp_tunnel_update_state
*
* @param l2tp_tunnel L2TP tunnel structure.
* @param state New L2TP tunnel state.
*/
void
bbl_l2tp_sunnel_update_state(bbl_l2tp_sunnel_s *l2tp_tunnel, l2tp_tunnel_state_t state) {
bbl_l2tp_tunnel_update_state(bbl_l2tp_tunnel_s *l2tp_tunnel, l2tp_tunnel_state_t state) {
if(l2tp_tunnel->state != state) {
/* State has changed */
LOG(DEBUG, "L2TP Debug (%s) Tunnel %u state changed from %s to %s\n",
@@ -241,12 +241,12 @@ bbl_l2tp_sunnel_update_state(bbl_l2tp_sunnel_s *l2tp_tunnel, l2tp_tunnel_state_t
}
/**
* bbl_l2tp_sunnel_tx_job
* bbl_l2tp_tunnel_tx_job
*/
void
bbl_l2tp_sunnel_tx_job(timer_s *timer)
bbl_l2tp_tunnel_tx_job(timer_s *timer)
{
bbl_l2tp_sunnel_s *l2tp_tunnel = timer->data;
bbl_l2tp_tunnel_s *l2tp_tunnel = timer->data;
bbl_network_interface_s *interface = l2tp_tunnel->interface;
bbl_l2tp_queue_s *q = NULL;
bbl_l2tp_queue_s *q_del = NULL;
@@ -260,7 +260,7 @@ bbl_l2tp_sunnel_tx_job(timer_s *timer)
l2tp_tunnel->timer_tx_active = false;
if(l2tp_tunnel->state == BBL_L2TP_TUNNEL_SEND_STOPCCN) {
if(CIRCLEQ_EMPTY(&l2tp_tunnel->txq_qhead)) {
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
}
}
@@ -303,7 +303,7 @@ bbl_l2tp_sunnel_tx_job(timer_s *timer)
l2tp_tunnel->result_code = 2;
l2tp_tunnel->error_code = 6;
l2tp_tunnel->error_message = "max retry";
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_force_stop(l2tp_tunnel);
}
/* When congestion occurs (indicated by the triggering of a
@@ -336,12 +336,12 @@ bbl_l2tp_sunnel_tx_job(timer_s *timer)
}
/**
* bbl_l2tp_sunnel_control_job
* bbl_l2tp_tunnel_control_job
*/
void
bbl_l2tp_sunnel_control_job(timer_s *timer)
bbl_l2tp_tunnel_control_job(timer_s *timer)
{
bbl_l2tp_sunnel_s *l2tp_tunnel = timer->data;
bbl_l2tp_tunnel_s *l2tp_tunnel = timer->data;
l2tp_tunnel->state_seconds++;
switch(l2tp_tunnel->state) {
case BBL_L2TP_TUNNEL_WAIT_CTR_CONN:
@@ -349,7 +349,7 @@ bbl_l2tp_sunnel_control_job(timer_s *timer)
l2tp_tunnel->result_code = 2;
l2tp_tunnel->error_code = 6;
l2tp_tunnel->error_message = "timeout";
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_force_stop(l2tp_tunnel);
}
break;
@@ -362,23 +362,23 @@ bbl_l2tp_sunnel_control_job(timer_s *timer)
break;
case BBL_L2TP_TUNNEL_RCVD_STOPCCN:
if(l2tp_tunnel->state_seconds > 5) {
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
}
break;
case BBL_L2TP_TUNNEL_SEND_STOPCCN:
if(l2tp_tunnel->state_seconds > 30) {
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_TERMINATED);
}
break;
case BBL_L2TP_TUNNEL_TERMINATED:
timer->periodic = false;
bbl_l2tp_sunnel_delete(l2tp_tunnel);
bbl_l2tp_tunnel_delete(l2tp_tunnel);
return;
default:
break;
}
if(!l2tp_tunnel->timer_tx_active) {
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX", 0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_sunnel_tx_job);
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX", 0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_tunnel_tx_job);
l2tp_tunnel->timer_tx_active = true;
}
}
@@ -394,7 +394,7 @@ bbl_l2tp_sunnel_control_job(timer_s *timer)
* @param l2tp_type L2TP message type (SCCRP, ICRP, ...).
*/
void
bbl_l2tp_send(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type) {
bbl_l2tp_send(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type) {
bbl_network_interface_s *interface = l2tp_tunnel->interface;
bbl_l2tp_queue_s *q = calloc(1, sizeof(bbl_l2tp_queue_s));
@@ -459,7 +459,7 @@ bbl_l2tp_send(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
} else {
CIRCLEQ_INSERT_TAIL(&l2tp_tunnel->txq_qhead, q, txq_qnode);
if(!l2tp_tunnel->timer_tx_active) {
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX", 0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_sunnel_tx_job);
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX", 0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_tunnel_tx_job);
l2tp_tunnel->timer_tx_active = true;
}
}
@@ -483,7 +483,7 @@ bbl_l2tp_send(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
static void
bbl_l2tp_send_data(bbl_l2tp_session_s *l2tp_session, uint16_t protocol, void *next) {
bbl_l2tp_sunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_l2tp_server_s *l2tp_server = l2tp_tunnel->server;
bbl_network_interface_s *interface = l2tp_tunnel->interface;
bbl_l2tp_queue_s *q = calloc(1, sizeof(bbl_l2tp_queue_s));
@@ -542,8 +542,8 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
bbl_ipv4_s *ipv4 = (bbl_ipv4_s*)eth->next;
bbl_l2tp_server_s *l2tp_server = g_ctx->config.l2tp_server;
bbl_l2tp_sunnel_s *l2tp_tunnel;
bbl_l2tp_sunnel_s *l2tp_tunnel2;
bbl_l2tp_tunnel_s *l2tp_tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel2;
bbl_l2tp_session_s *l2tp_session;
dict_insert_result result;
@@ -557,7 +557,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
l2tp_server->host_name,
format_ipv4_address(&ipv4->src));
/* Init tunnel ... */
l2tp_tunnel = calloc(1, sizeof(bbl_l2tp_sunnel_s));
l2tp_tunnel = calloc(1, sizeof(bbl_l2tp_tunnel_s));
g_ctx->l2tp_tunnels++;
CIRCLEQ_INIT(&l2tp_tunnel->txq_qhead);
CIRCLEQ_INIT(&l2tp_tunnel->session_qhead);
@@ -574,7 +574,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
interface->stats.l2tp_control_rx++;
/* Decode received attributes and store in tunnel */
if(!bbl_l2tp_avp_decode_tunnel(l2tp, l2tp_tunnel)) {
bbl_l2tp_sunnel_delete(l2tp_tunnel);
bbl_l2tp_tunnel_delete(l2tp_tunnel);
return;
}
if(!l2tp_tunnel->peer_tunnel_id ||
@@ -582,7 +582,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
LOG(ERROR, "L2TP Error (%s) Invalid SCCRQ received from %s\n",
l2tp_server->host_name,
format_ipv4_address(&ipv4->src));
bbl_l2tp_sunnel_delete(l2tp_tunnel);
bbl_l2tp_tunnel_delete(l2tp_tunnel);
return;
}
@@ -591,7 +591,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
if(l2tp_tunnel2->peer_ip == l2tp_tunnel->peer_ip &&
l2tp_tunnel2->peer_tunnel_id == l2tp_tunnel->peer_tunnel_id) {
/* Seems to be an SCCRQ retry ... */
bbl_l2tp_sunnel_delete(l2tp_tunnel);
bbl_l2tp_tunnel_delete(l2tp_tunnel);
return;
}
}
@@ -620,7 +620,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
LOG(ERROR, "L2TP Error (%s) Failed to add tunnel session\n",
l2tp_tunnel->server->host_name);
free(l2tp_session);
bbl_l2tp_sunnel_delete(l2tp_tunnel);
bbl_l2tp_tunnel_delete(l2tp_tunnel);
return;
}
*result.datum_ptr = l2tp_session;
@@ -668,7 +668,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
CIRCLEQ_INSERT_TAIL(&l2tp_server->tunnel_qhead, l2tp_tunnel, tunnel_qnode);
/* Start control job
* WARNING: Do not change the interval! */
timer_add_periodic(&g_ctx->timer_root, &l2tp_tunnel->timer_ctrl, "L2TP Control", 1, 0, l2tp_tunnel, &bbl_l2tp_sunnel_control_job);
timer_add_periodic(&g_ctx->timer_root, &l2tp_tunnel->timer_ctrl, "L2TP Control", 1, 0, l2tp_tunnel, &bbl_l2tp_tunnel_control_job);
/* Prepare ZLB */
bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_ZLB);
/* Send response */
@@ -685,7 +685,7 @@ bbl_l2tp_sccrq_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth
static void
bbl_l2tp_scccn_rx(bbl_network_interface_s *interface,
bbl_l2tp_sunnel_s *l2tp_tunnel,
bbl_l2tp_tunnel_s *l2tp_tunnel,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
uint8_t digest[L2TP_MD5_DIGEST_LEN];
@@ -700,7 +700,7 @@ bbl_l2tp_scccn_rx(bbl_network_interface_s *interface,
LOG(ERROR, "L2TP Error (%s) Invalid SCCCN received from %s\n",
l2tp_tunnel->server->host_name,
format_ipv4_address(&l2tp_tunnel->peer_ip));
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
l2tp_tunnel->result_code = 2;
l2tp_tunnel->error_code = 6;
l2tp_tunnel->error_message = "decode error";
@@ -719,7 +719,7 @@ bbl_l2tp_scccn_rx(bbl_network_interface_s *interface,
LOG(ERROR, "L2TP Error (%s) Wrong challenge response in SCCCN from %s\n",
l2tp_tunnel->server->host_name,
format_ipv4_address(&l2tp_tunnel->peer_ip));
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
l2tp_tunnel->result_code = 2;
l2tp_tunnel->error_code = 6;
l2tp_tunnel->error_message = "challenge authentication failed";
@@ -730,7 +730,7 @@ bbl_l2tp_scccn_rx(bbl_network_interface_s *interface,
LOG(ERROR, "L2TP Error (%s) Missing challenge response in SCCCN from %s\n",
l2tp_tunnel->server->host_name,
format_ipv4_address(&l2tp_tunnel->peer_ip));
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
l2tp_tunnel->result_code = 2;
l2tp_tunnel->error_code = 6;
l2tp_tunnel->error_message = "missing challenge response";
@@ -738,25 +738,25 @@ bbl_l2tp_scccn_rx(bbl_network_interface_s *interface,
return;
}
}
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_ESTABLISHED);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_ESTABLISHED);
}
}
static void
bbl_l2tp_stopccn_rx(bbl_network_interface_s *interface,
bbl_l2tp_sunnel_s *l2tp_tunnel,
bbl_l2tp_tunnel_s *l2tp_tunnel,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
UNUSED(interface);
UNUSED(eth);
UNUSED(l2tp);
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_RCVD_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_RCVD_STOPCCN);
}
static void
bbl_l2tp_csun_rx(bbl_network_interface_s *interface,
bbl_l2tp_sunnel_s *l2tp_tunnel,
bbl_l2tp_tunnel_s *l2tp_tunnel,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
UNUSED(interface);
@@ -767,7 +767,7 @@ bbl_l2tp_csun_rx(bbl_network_interface_s *interface,
static void
bbl_l2tp_icrq_rx(bbl_network_interface_s *interface,
bbl_l2tp_sunnel_s *l2tp_tunnel,
bbl_l2tp_tunnel_s *l2tp_tunnel,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
dict_insert_result result;
@@ -824,7 +824,7 @@ bbl_l2tp_iccn_rx(bbl_network_interface_s *interface,
bbl_l2tp_session_s *l2tp_session,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
bbl_l2tp_sunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel = l2tp_session->tunnel;
UNUSED(interface);
UNUSED(eth);
@@ -857,7 +857,7 @@ bbl_l2tp_cdn_rx(bbl_network_interface_s *interface,
bbl_l2tp_session_s *l2tp_session,
bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp)
{
bbl_l2tp_sunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel = l2tp_session->tunnel;
UNUSED(interface);
UNUSED(eth);
@@ -1034,7 +1034,7 @@ bbl_l2tp_handler_rx(bbl_network_interface_s *interface,
{
bbl_ipv4_s *ipv4 = (bbl_ipv4_s*)eth->next;
bbl_l2tp_session_s *l2tp_session;
bbl_l2tp_sunnel_s *l2tp_tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel;
l2tp_key_t key = {0};
void **search = NULL;
@@ -1085,7 +1085,7 @@ bbl_l2tp_handler_rx(bbl_network_interface_s *interface,
/* Start tx timer */
if(!l2tp_tunnel->timer_tx_active) {
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX",
0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_sunnel_tx_job);
0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_tunnel_tx_job);
l2tp_tunnel->timer_tx_active = true;
}
}
@@ -1174,7 +1174,7 @@ bbl_l2tp_handler_rx(bbl_network_interface_s *interface,
interface->stats.l2tp_control_rx_dup++;
if(!l2tp_tunnel->timer_tx_active) {
timer_add(&g_ctx->timer_root, &l2tp_tunnel->timer_tx, "L2TP TX",
0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_sunnel_tx_job);
0, L2TP_TX_WAIT_MS * MSEC, l2tp_tunnel, &bbl_l2tp_tunnel_tx_job);
l2tp_tunnel->timer_tx_active = true;
}
} else {
@@ -1204,11 +1204,11 @@ void
bbl_l2tp_stop_all_tunnel()
{
bbl_l2tp_server_s *l2tp_server = g_ctx->config.l2tp_server;
bbl_l2tp_sunnel_s *l2tp_tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel;
while(l2tp_server) {
CIRCLEQ_FOREACH(l2tp_tunnel, &l2tp_server->tunnel_qhead, tunnel_qnode) {
if(l2tp_tunnel->state < BBL_L2TP_TUNNEL_SEND_STOPCCN) {
bbl_l2tp_sunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
l2tp_tunnel->result_code = 6;
bbl_l2tp_force_stop(l2tp_tunnel);
}
@@ -1216,3 +1216,324 @@ bbl_l2tp_stop_all_tunnel()
l2tp_server = l2tp_server->next;
}
}
static json_t *
l2tp_session_json(bbl_l2tp_session_s *l2tp_session)
{
char *proxy_auth_response = NULL;
if(l2tp_session->proxy_auth_response) {
if(l2tp_session->proxy_auth_type == L2TP_PROXY_AUTH_TYPE_PAP) {
proxy_auth_response = (char*)l2tp_session->proxy_auth_response;
} else {
proxy_auth_response = "0x...";
}
}
return json_pack("{ss si si si si si ss ss ss ss ss si si ss ss si si si si}",
"state", l2tp_session_state_string(l2tp_session->state),
"tunnel-id", l2tp_session->key.tunnel_id,
"session-id", l2tp_session->key.session_id,
"peer-tunnel-id", l2tp_session->tunnel->peer_tunnel_id,
"peer-session-id", l2tp_session->peer_session_id,
"peer-proxy-auth-type", l2tp_session->proxy_auth_type,
"peer-proxy-auth-name", string_or_na(l2tp_session->proxy_auth_name),
"peer-proxy-auth-response", string_or_na(proxy_auth_response),
"peer-called-number", string_or_na(l2tp_session->peer_called_number),
"peer-calling-number", string_or_na(l2tp_session->peer_calling_number),
"peer-sub-address", string_or_na(l2tp_session->peer_sub_address),
"peer-tx-bps", l2tp_session->peer_tx_bps,
"peer-rx-bps", l2tp_session->peer_rx_bps,
"peer-ari", string_or_na(l2tp_session->peer_ari),
"peer-aci", string_or_na(l2tp_session->peer_aci),
"data-packets-rx", l2tp_session->stats.data_rx,
"data-packets-tx", l2tp_session->stats.data_tx,
"data-ipv4-packets-rx", l2tp_session->stats.data_ipv4_rx,
"data-ipv4-packets-tx", l2tp_session->stats.data_ipv4_tx);
}
/* Control Socket Commands */
int
bbl_l2tp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root, *sessions;
bbl_l2tp_server_s *l2tp_server = g_ctx->config.l2tp_server;
bbl_l2tp_tunnel_s *l2tp_tunnel;
bbl_l2tp_session_s *l2tp_session;
l2tp_key_t l2tp_key = {0};
void **search = NULL;
int l2tp_tunnel_id = 0;
int l2tp_session_id = 0;
json_unpack(arguments, "{s:i}", "tunnel-id", &l2tp_tunnel_id);
json_unpack(arguments, "{s:i}", "session-id", &l2tp_session_id);
sessions = json_array();
if(l2tp_tunnel_id && l2tp_session_id) {
l2tp_key.tunnel_id = l2tp_tunnel_id;
l2tp_key.session_id = l2tp_session_id;
search = dict_search(g_ctx->l2tp_session_dict, &l2tp_key);
if(search) {
l2tp_session = *search;
json_array_append(sessions, l2tp_session_json(l2tp_session));
} else {
result = bbl_ctrl_status(fd, "warning", 404, "session not found");
json_decref(sessions);
return result;
}
} else if (l2tp_tunnel_id) {
l2tp_key.tunnel_id = l2tp_tunnel_id;
search = dict_search(g_ctx->l2tp_session_dict, &l2tp_key);
if(search) {
l2tp_session = *search;
l2tp_tunnel = l2tp_session->tunnel;
CIRCLEQ_FOREACH(l2tp_session, &l2tp_tunnel->session_qhead, session_qnode) {
if(!l2tp_session->key.session_id) continue; /* skip tunnel session */
json_array_append(sessions, l2tp_session_json(l2tp_session));
}
} else {
result = bbl_ctrl_status(fd, "warning", 404, "tunnel not found");
json_decref(sessions);
return result;
}
} else {
while(l2tp_server) {
CIRCLEQ_FOREACH(l2tp_tunnel, &l2tp_server->tunnel_qhead, tunnel_qnode) {
CIRCLEQ_FOREACH(l2tp_session, &l2tp_tunnel->session_qhead, session_qnode) {
if(!l2tp_session->key.session_id) continue; /* skip tunnel session */
json_array_append(sessions, l2tp_session_json(l2tp_session));
}
}
l2tp_server = l2tp_server->next;
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"l2tp-sessions", sessions);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(sessions);
}
return result;
}
int
bbl_l2tp_ctrl_csurq(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
json_t *sessions, *number;
bbl_l2tp_tunnel_s *l2tp_tunnel;
bbl_l2tp_session_s *l2tp_session;
l2tp_key_t l2tp_key = {0};
void **search = NULL;
uint16_t l2tp_session_id = 0;
int l2tp_tunnel_id = 0;
int size, i;
/* Unpack further arguments */
if (json_unpack(arguments, "{s:i}", "tunnel-id", &l2tp_tunnel_id) != 0) {
return bbl_ctrl_status(fd, "error", 400, "missing tunnel-id");
}
l2tp_key.tunnel_id = l2tp_tunnel_id;
search = dict_search(g_ctx->l2tp_session_dict, &l2tp_key);
if(search) {
l2tp_session = *search;
l2tp_tunnel = l2tp_session->tunnel;
if(l2tp_tunnel->state != BBL_L2TP_TUNNEL_ESTABLISHED) {
return bbl_ctrl_status(fd, "warning", 400, "tunnel not established");
}
sessions = json_object_get(arguments, "sessions");
if (json_is_array(sessions)) {
size = json_array_size(sessions);
l2tp_tunnel->csurq_requests_len = size;
l2tp_tunnel->csurq_requests = malloc(size * sizeof(uint16_t));
for (i = 0; i < size; i++) {
number = json_array_get(sessions, i);
if(json_is_number(number)) {
l2tp_session_id = json_number_value(number);
l2tp_tunnel->csurq_requests[i] = l2tp_session_id;
}
}
bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_CSURQ);
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "error", 400, "invalid request");
}
} else {
return bbl_ctrl_status(fd, "warning", 404, "tunnel not found");
}
}
int
bbl_l2tp_ctrl_tunnel_terminate(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
bbl_l2tp_tunnel_s *l2tp_tunnel;
bbl_l2tp_session_s *l2tp_session;
l2tp_key_t l2tp_key = {0};
void **search = NULL;
int l2tp_tunnel_id = 0;
int result_code;
int error_code;
char *error_message;
/* Unpack further arguments */
if (json_unpack(arguments, "{s:i}", "tunnel-id", &l2tp_tunnel_id) != 0) {
return bbl_ctrl_status(fd, "error", 400, "missing tunnel-id");
}
l2tp_key.tunnel_id = l2tp_tunnel_id;
search = dict_search(g_ctx->l2tp_session_dict, &l2tp_key);
if(search) {
l2tp_session = *search;
l2tp_tunnel = l2tp_session->tunnel;
if(l2tp_tunnel->state != BBL_L2TP_TUNNEL_ESTABLISHED) {
return bbl_ctrl_status(fd, "warning", 400, "tunnel not established");
}
bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN);
if (json_unpack(arguments, "{s:i}", "result-code", &result_code) != 0) {
result_code = 1;
}
l2tp_tunnel->result_code = result_code;
if (json_unpack(arguments, "{s:i}", "error-code", &error_code) != 0) {
error_code = 0;
}
l2tp_tunnel->error_code = error_code;
if (json_unpack(arguments, "{s:s}", "error-message", &error_message) != 0) {
error_message = NULL;
}
l2tp_tunnel->error_message = error_message;
bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN);
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "tunnel not found");
}
}
int
bbl_l2tp_ctrl_session_terminate(int fd, uint32_t session_id, json_t *arguments)
{
bbl_session_s *session;
bbl_l2tp_tunnel_s *l2tp_tunnel;
bbl_l2tp_session_s *l2tp_session;
int result_code;
int error_code;
char *error_message;
int disconnect_code;
int disconnect_protocol;
int disconnect_direction;
char* disconnect_message;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
session = bbl_session_get(session_id);
if(session) {
l2tp_session = session->l2tp_session;
if(!l2tp_session) {
return bbl_ctrl_status(fd, "error", 400, "no L2TP session");
}
l2tp_tunnel = l2tp_session->tunnel;
if(l2tp_tunnel->state != BBL_L2TP_TUNNEL_ESTABLISHED) {
return bbl_ctrl_status(fd, "warning", 400, "tunnel not established");
}
if(l2tp_session->state != BBL_L2TP_SESSION_ESTABLISHED) {
return bbl_ctrl_status(fd, "warning", 400, "session not established");
}
if (json_unpack(arguments, "{s:i}", "result-code", &result_code) != 0) {
result_code = 2;
}
l2tp_session->result_code = result_code;
if (json_unpack(arguments, "{s:i}", "error-code", &error_code) != 0) {
error_code = 0;
}
l2tp_session->error_code = error_code;
if (json_unpack(arguments, "{s:s}", "error-message", &error_message) != 0) {
error_message = NULL;
}
l2tp_session->error_message = error_message;
if (json_unpack(arguments, "{s:i}", "disconnect-code", &disconnect_code) != 0) {
disconnect_code = 0;
}
l2tp_session->disconnect_code = disconnect_code;
if (json_unpack(arguments, "{s:i}", "disconnect-protocol", &disconnect_protocol) != 0) {
disconnect_protocol = 0;
}
l2tp_session->disconnect_protocol = disconnect_protocol;
if (json_unpack(arguments, "{s:i}", "disconnect-direction", &disconnect_direction) != 0) {
disconnect_direction = 0;
}
l2tp_session->disconnect_direction = disconnect_direction;
if (json_unpack(arguments, "{s:s}", "disconnect-message", &disconnect_message) != 0) {
disconnect_message = NULL;
}
l2tp_session->disconnect_message = disconnect_message;
bbl_l2tp_send(l2tp_tunnel, l2tp_session, L2TP_MESSAGE_CDN);
bbl_l2tp_session_delete(l2tp_session);
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_l2tp_ctrl_tunnels(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *tunnels, *tunnel;
bbl_l2tp_server_s *l2tp_server = g_ctx->config.l2tp_server;
bbl_l2tp_tunnel_s *l2tp_tunnel;
tunnels = json_array();
while(l2tp_server) {
CIRCLEQ_FOREACH(l2tp_tunnel, &l2tp_server->tunnel_qhead, tunnel_qnode) {
tunnel = json_pack("{ss ss ss si si ss ss ss ss si si si si si si si}",
"state", l2tp_tunnel_state_string(l2tp_tunnel->state),
"server-name", l2tp_server->host_name,
"server-address", format_ipv4_address(&l2tp_server->ip),
"tunnel-id", l2tp_tunnel->tunnel_id,
"peer-tunnel-id", l2tp_tunnel->peer_tunnel_id,
"peer-name", string_or_na(l2tp_tunnel->peer_name),
"peer-address", format_ipv4_address(&l2tp_tunnel->peer_ip),
"peer-vendor", string_or_na(l2tp_tunnel->peer_vendor),
"secret", string_or_na(l2tp_server->secret),
"control-packets-rx", l2tp_tunnel->stats.control_rx,
"control-packets-rx-dup", l2tp_tunnel->stats.control_rx_dup,
"control-packets-rx-out-of-order", l2tp_tunnel->stats.control_rx_ooo,
"control-packets-tx", l2tp_tunnel->stats.control_tx,
"control-packets-tx-retry", l2tp_tunnel->stats.control_retry,
"data-packets-rx", l2tp_tunnel->stats.data_rx,
"data-packets-tx", l2tp_tunnel->stats.data_tx);
json_array_append(tunnels, tunnel);
}
l2tp_server = l2tp_server->next;
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"l2tp-tunnels", tunnels);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(tunnels);
}
return result;
}
+31 -11
View File
@@ -87,7 +87,7 @@ typedef struct bbl_l2tp_server_
/* List of L2TP tunnel instances
* for the corresponding server. */
CIRCLEQ_HEAD(tunnel_, bbl_l2tp_sunnel_) tunnel_qhead;
CIRCLEQ_HEAD(tunnel_, bbl_l2tp_tunnel_) tunnel_qhead;
} bbl_l2tp_server_s;
/* L2TP Session Key */
@@ -107,15 +107,15 @@ typedef struct bbl_l2tp_queue_
uint8_t packet[L2TP_MAX_PACKET_SIZE];
uint16_t packet_len;
struct timespec last_tx_time;
struct bbl_l2tp_sunnel_ *tunnel;
struct bbl_l2tp_tunnel_ *tunnel;
CIRCLEQ_ENTRY(bbl_l2tp_queue_) txq_qnode; /* TX queue */
CIRCLEQ_ENTRY(bbl_l2tp_queue_) tx_qnode; /* TX request */
} bbl_l2tp_queue_s;
/* L2TP Tunnel Instance */
typedef struct bbl_l2tp_sunnel_
typedef struct bbl_l2tp_tunnel_
{
CIRCLEQ_ENTRY(bbl_l2tp_sunnel_) tunnel_qnode;
CIRCLEQ_ENTRY(bbl_l2tp_tunnel_) tunnel_qnode;
CIRCLEQ_HEAD(session_, bbl_l2tp_session_) session_qhead;
CIRCLEQ_HEAD(txq_, bbl_l2tp_queue_) txq_qhead;
@@ -193,14 +193,14 @@ typedef struct bbl_l2tp_sunnel_
char *peer_name;
char *peer_vendor;
} bbl_l2tp_sunnel_s;
} bbl_l2tp_tunnel_s;
/* L2TP Session Instance */
typedef struct bbl_l2tp_session_
{
CIRCLEQ_ENTRY(bbl_l2tp_session_) session_qnode;
bbl_l2tp_sunnel_s *tunnel;
bbl_l2tp_tunnel_s *tunnel;
l2tp_session_state_t state;
bbl_session_s *pppoe_session;
@@ -261,18 +261,23 @@ typedef struct bbl_l2tp_session_
char *peer_aci;
} bbl_l2tp_session_s;
const char* l2tp_message_string(l2tp_message_t type);
const char* l2tp_tunnel_state_string(l2tp_tunnel_state_t state);
const char* l2tp_session_state_string(l2tp_session_state_t state);
const char*
l2tp_message_string(l2tp_message_t type);
const char*
l2tp_tunnel_state_string(l2tp_tunnel_state_t state);
const char*
l2tp_session_state_string(l2tp_session_state_t state);
void
bbl_l2tp_session_delete(bbl_l2tp_session_s *l2tp_session);
void
bbl_l2tp_sunnel_update_state(bbl_l2tp_sunnel_s *l2tp_tunnel, l2tp_tunnel_state_t state);
bbl_l2tp_tunnel_update_state(bbl_l2tp_tunnel_s *l2tp_tunnel, l2tp_tunnel_state_t state);
void
bbl_l2tp_send(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type);
bbl_l2tp_send(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session, l2tp_message_t l2tp_type);
void
bbl_l2tp_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_l2tp_s *l2tp);
@@ -280,4 +285,19 @@ bbl_l2tp_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *e
void
bbl_l2tp_stop_all_tunnel();
int
bbl_l2tp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bbl_l2tp_ctrl_csurq(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bbl_l2tp_ctrl_tunnel_terminate(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bbl_l2tp_ctrl_session_terminate(int fd, uint32_t session_id, json_t *arguments);
int
bbl_l2tp_ctrl_tunnels(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+5 -5
View File
@@ -172,7 +172,7 @@ bbl_l2tp_avp_encode_disconnect_code(uint8_t **_buf, uint16_t *len,
/* bbl_l2tp_avp_unhide */
static bool
bbl_l2tp_avp_unhide(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_avp_t *avp, uint8_t
bbl_l2tp_avp_unhide(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_avp_t *avp, uint8_t
*random_vector, uint16_t random_vector_len)
{
MD5_CTX ctx;
@@ -236,7 +236,7 @@ bbl_l2tp_avp_unhide(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_avp_t *avp, uint8_t
}
bool
bbl_l2tp_avp_decode_session(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session)
bbl_l2tp_avp_decode_session(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session)
{
uint8_t *buf = l2tp->payload;
uint16_t len = l2tp->payload_len;
@@ -483,7 +483,7 @@ bbl_l2tp_avp_decode_session(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel, bb
}
bool
bbl_l2tp_avp_decode_tunnel(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel)
bbl_l2tp_avp_decode_tunnel(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel)
{
uint8_t *buf = l2tp->payload;
uint16_t len = l2tp->payload_len;
@@ -639,7 +639,7 @@ bbl_l2tp_avp_decode_tunnel(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel)
}
bool
bbl_l2tp_avp_decode_csun(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel)
bbl_l2tp_avp_decode_csun(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel)
{
uint8_t *buf = l2tp->payload;
uint16_t len = l2tp->payload_len;
@@ -708,7 +708,7 @@ bbl_l2tp_avp_decode_csun(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel)
}
void
bbl_l2tp_avp_encode_attributes(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
bbl_l2tp_avp_encode_attributes(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
l2tp_message_t l2tp_type, uint8_t *buf, uint16_t *len)
{
bbl_l2tp_avp_t avp = {0};
+4 -4
View File
@@ -74,16 +74,16 @@ typedef struct bbl_l2tp_avp_
} bbl_l2tp_avp_t;
bool
bbl_l2tp_avp_decode_session(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session);
bbl_l2tp_avp_decode_session(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session);
bool
bbl_l2tp_avp_decode_tunnel(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel);
bbl_l2tp_avp_decode_tunnel(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel);
bool
bbl_l2tp_avp_decode_csun(bbl_l2tp_s *l2tp, bbl_l2tp_sunnel_s *l2tp_tunnel);
bbl_l2tp_avp_decode_csun(bbl_l2tp_s *l2tp, bbl_l2tp_tunnel_s *l2tp_tunnel);
void
bbl_l2tp_avp_encode_attributes(bbl_l2tp_sunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
bbl_l2tp_avp_encode_attributes(bbl_l2tp_tunnel_s *l2tp_tunnel, bbl_l2tp_session_s *l2tp_session,
l2tp_message_t l2tp_type, uint8_t *buf, uint16_t *len);
#endif
+1 -2
View File
@@ -7,7 +7,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bbl.h"
#include "../bbl_ctrl.h"
uint16_t g_lag_port_id = 1;
@@ -331,7 +330,7 @@ bbl_lag_json(bbl_lag_s *lag)
}
int
bbl_lag_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
bbl_lag_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
+1 -1
View File
@@ -76,6 +76,6 @@ bbl_lag_rx_lacp(bbl_interface_s *interface,
bbl_ethernet_header_s *eth);
int
bbl_lag_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
bbl_lag_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
#endif
+54
View File
@@ -136,4 +136,58 @@ bbl_qmx_li_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s
break;
}
}
}
/* Control Socket Commands */
int
bbl_li_ctrl_flows(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *flows, *flow;
bbl_li_flow_t *li_flow;
struct dict_itor *itor;
flows = json_array();
itor = dict_itor_new(g_ctx->li_flow_dict);
dict_itor_first(itor);
for (; dict_itor_valid(itor); dict_itor_next(itor)) {
li_flow = (bbl_li_flow_t*)*dict_itor_datum(itor);
if(li_flow) {
flow = json_pack("{ss si ss si ss ss ss si si si si si si si si si si si si}",
"source-address", format_ipv4_address(&li_flow->src_ipv4),
"source-port", li_flow->src_port,
"destination-address", format_ipv4_address(&li_flow->dst_ipv4),
"destination-port", li_flow->dst_port,
"direction", bbl_li_direction_string(li_flow->direction),
"packet-type", bbl_li_packet_type_string(li_flow->packet_type),
"sub-packet-type", bbl_li_sub_packet_type_string(li_flow->sub_packet_type),
"liid", li_flow->liid,
"bytes-rx", li_flow->bytes_rx,
"packets-rx", li_flow->packets_rx,
"packets-rx-ipv4", li_flow->packets_rx_ipv4,
"packets-rx-ipv4-tcp", li_flow->packets_rx_ipv4_tcp,
"packets-rx-ipv4-udp", li_flow->packets_rx_ipv4_udp,
"packets-rx-ipv4-host-internal", li_flow->packets_rx_ipv4_internal,
"packets-rx-ipv6", li_flow->packets_rx_ipv6,
"packets-rx-ipv6-tcp", li_flow->packets_rx_ipv6_tcp,
"packets-rx-ipv6-udp", li_flow->packets_rx_ipv6_udp,
"packets-rx-ipv6-host-internal", li_flow->packets_rx_ipv6_internal,
"packets-rx-ipv6-no-next-header", li_flow->packets_rx_ipv6_no_next_header);
json_array_append(flows, flow);
}
}
dict_itor_free(itor);
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"li-flows", flows);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(flows);
}
return result;
}
+4 -4
View File
@@ -37,10 +37,10 @@ typedef struct bbl_li_flow_
uint64_t packets_rx_ipv6_no_next_header;
} bbl_li_flow_t;
const char* bbl_li_direction_string(uint8_t direction);
const char* bbl_li_packet_type_string(uint8_t packet_type);
const char* bbl_li_sub_packet_type_string(uint8_t sub_packet_type);
void
bbl_qmx_li_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_qmx_li_s *qmx_li);
void bbl_qmx_li_handler_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_qmx_li_s *qmx_li);
int
bbl_li_ctrl_flows(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+72
View File
@@ -414,4 +414,76 @@ bbl_network_rx_handler(bbl_network_interface_s *interface,
break;
}
interface->stats.unknown++;
}
static json_t *
bbl_network_interface_json(bbl_network_interface_s *interface)
{
return json_pack("{ss si ss si si si si si si si si si si si si si si si si si si si si si si si si si si si si si si}",
"name", interface->name,
"ifindex", interface->ifindex,
"type", "network",
"tx-packets", interface->stats.packets_tx,
"tx-bytes", interface->stats.bytes_tx,
"tx-pps", interface->stats.rate_packets_tx.avg,
"tx-kbps", interface->stats.rate_bytes_tx.avg * 8 / 1000,
"rx-packets", interface->stats.packets_rx,
"rx-bytes", interface->stats.bytes_rx,
"rx-pps", interface->stats.rate_packets_rx.avg,
"rx-kbps", interface->stats.rate_bytes_rx.avg * 8 / 1000,
"tx-packets-multicast", interface->stats.mc_tx,
"tx-pps-multicast", interface->stats.rate_mc_tx.avg,
"tx-packets-session-ipv4", interface->stats.session_ipv4_tx,
"tx-pps-session-ipv4", interface->stats.rate_session_ipv4_tx.avg,
"rx-packets-session-ipv4", interface->stats.session_ipv4_rx,
"rx-pps-session-ipv4", interface->stats.rate_session_ipv4_rx.avg,
"rx-loss-packets-session-ipv4", interface->stats.session_ipv4_loss,
"tx-packets-session-ipv6", interface->stats.session_ipv6_tx,
"tx-pps-session-ipv6", interface->stats.rate_session_ipv6_tx.avg,
"rx-packets-session-ipv6", interface->stats.session_ipv6_rx,
"rx-pps-session-ipv6", interface->stats.rate_session_ipv6_rx.avg,
"rx-loss-packets-session-ipv6", interface->stats.session_ipv6_loss,
"tx-packets-session-ipv6pd", interface->stats.session_ipv6pd_tx,
"tx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_tx.avg,
"rx-packets-session-ipv6pd", interface->stats.session_ipv6pd_rx,
"rx-pps-session-ipv6pd", interface->stats.rate_session_ipv6pd_rx.avg,
"rx-loss-packets-session-ipv6pd", interface->stats.session_ipv6pd_loss,
"tx-packets-streams", interface->stats.stream_tx,
"tx-pps-streams", interface->stats.rate_stream_tx.avg,
"rx-packets-streams", interface->stats.stream_rx,
"rx-pps-streams", interface->stats.rate_stream_rx.avg,
"rx-loss-packets-streams", interface->stats.stream_loss
);
}
/* Control Socket Commands */
int
bbl_network_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *interfaces;
bbl_interface_s *interface;
bbl_network_interface_s *network_interface;
interfaces = json_array();
CIRCLEQ_FOREACH(interface, &g_ctx->interface_qhead, interface_qnode) {
network_interface = interface->network;
while(network_interface) {
json_array_append(interfaces, bbl_network_interface_json(network_interface));
network_interface = network_interface->next;
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"network-interfaces", interfaces);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(interfaces);
}
return result;
}
+3
View File
@@ -145,4 +145,7 @@ void
bbl_network_rx_handler(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth);
int
bbl_network_ctrl_interfaces(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+326 -1
View File
@@ -13,6 +13,7 @@
#include "bbl_dhcpv6.h"
extern volatile bool g_teardown;
extern volatile bool g_teardown_request;
extern volatile bool g_monkey;
const char *
@@ -1170,4 +1171,328 @@ bbl_session_json(bbl_session_s *session)
if(session_traffic) json_decref(session_traffic);
}
return root;
}
}
/* Control Socket Commands */
int
bbl_session_ctrl_pending(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root, *json_session, *json_sessions;
bbl_session_s *session;
uint32_t i;
json_sessions = json_array();
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(!session) continue;
if(session->session_state != BBL_ESTABLISHED ||
session->session_traffic.flows != session->session_traffic.flows_verified) {
json_session = json_pack("{si ss si si}",
"session-id", session->session_id,
"session-state", session_state_string(session->session_state),
"session-traffic-flows", session->session_traffic.flows,
"session-traffic-flows-verified", session->session_traffic.flows_verified);
json_array_append(json_sessions, json_session);
}
}
root = json_pack("{ss si so}",
"status", "ok",
"code", 200,
"sessions-pending", json_sessions);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(json_sessions);
}
return result;
}
int
bbl_session_ctrl_counters(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root = json_pack("{ss si s{si si si si si si si si si si si si si si sf sf sf sf si si si si}}",
"status", "ok",
"code", 200,
"session-counters",
"sessions", g_ctx->config.sessions,
"sessions-pppoe", g_ctx->sessions_pppoe,
"sessions-ipoe", g_ctx->sessions_ipoe,
"sessions-established", g_ctx->sessions_established,
"sessions-established-max", g_ctx->sessions_established_max,
"sessions-terminated", g_ctx->sessions_terminated,
"sessions-flapped", g_ctx->sessions_flapped,
"dhcp-sessions", g_ctx->dhcp_requested,
"dhcp-sessions-established", g_ctx->dhcp_established,
"dhcp-sessions-established-max", g_ctx->dhcp_established_max,
"dhcpv6-sessions", g_ctx->dhcpv6_requested,
"dhcpv6-sessions-established", g_ctx->dhcpv6_established,
"dhcpv6-sessions-established-max", g_ctx->dhcpv6_established_max,
"setup-time", g_ctx->stats.setup_time,
"setup-rate", g_ctx->stats.cps,
"setup-rate-min", g_ctx->stats.cps_min,
"setup-rate-avg", g_ctx->stats.cps_avg,
"setup-rate-max", g_ctx->stats.cps_max,
"session-traffic-flows", g_ctx->stats.session_traffic_flows,
"session-traffic-flows-verified", g_ctx->stats.session_traffic_flows_verified,
"stream-traffic-flows", g_ctx->stats.stream_traffic_flows,
"stream-traffic-flows-verified", g_ctx->stats.stream_traffic_flows_verified
);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
}
return result;
}
int
bbl_session_ctrl_info(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root;
json_t *session_json;
bbl_session_s *session;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
session = bbl_session_get(session_id);
if(session) {
session_json = bbl_session_json(session);
if(!session_json) {
return bbl_ctrl_status(fd, "error", 500, "internal error");
}
root = json_pack("{ss si so*}",
"status", "ok",
"code", 200,
"session-info", session_json);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(session_json);
}
return result;
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_session_ctrl_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
bbl_session_s *session;
if(g_teardown) {
return bbl_ctrl_status(fd, "error", 405, "teardown");
}
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
session = bbl_session_get(session_id);
if(session) {
if(session->session_state == BBL_TERMINATED &&
session->reconnect_delay == 0) {
g_ctx->sessions_flapped++;
session->stats.flapped++;
session->session_state = BBL_IDLE;
bbl_session_reset(session);
if(g_ctx->sessions_terminated) {
g_ctx->sessions_terminated--;
}
} else if(session->session_state != BBL_IDLE ||
CIRCLEQ_NEXT(session, session_idle_qnode) ||
CIRCLEQ_PREV(session, session_idle_qnode)) {
return bbl_ctrl_status(fd, "error", 405, "wrong session state");
}
CIRCLEQ_INSERT_TAIL(&g_ctx->sessions_idle_qhead, session, session_idle_qnode);
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
int
bbl_session_ctrl_terminate(int fd, uint32_t session_id, json_t *arguments)
{
bbl_session_s *session;
int reconnect_delay = 0;
if(session_id) {
/* Terminate single matching session ... */
session = bbl_session_get(session_id);
if(session) {
json_unpack(arguments, "{s:i}", "reconnect-delay", &session->reconnect_delay);
if(reconnect_delay > 0) {
session->reconnect_delay = reconnect_delay;
}
bbl_session_clear(session);
return bbl_ctrl_status(fd, "ok", 200, "terminate session");
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Terminate all sessions ... */
g_teardown = true;
g_teardown_request = true;
LOG_NOARG(INFO, "Teardown request\n");
return bbl_ctrl_status(fd, "ok", 200, "terminate all sessions");
}
}
static int
bbl_session_ctrl_ncp_open_close(int fd, uint32_t session_id, bool open, bool ipcp)
{
bbl_session_s *session;
uint32_t i;
if(session_id) {
session = bbl_session_get(session_id);
if(session) {
if(session->access_type == ACCESS_TYPE_PPPOE) {
if(open) {
bbl_session_ncp_open(session, ipcp);
} else {
bbl_session_ncp_close(session, ipcp);
}
} else {
return bbl_ctrl_status(fd, "warning", 400, "matching session is not of type pppoe");
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
if(session->access_type == ACCESS_TYPE_PPPOE) {
if(open) {
bbl_session_ncp_open(session, ipcp);
} else {
bbl_session_ncp_close(session, ipcp);
}
}
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
}
int
bbl_session_ctrl_ipcp_open(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_ncp_open_close(fd, session_id, true, true);
}
int
bbl_session_ctrl_ipcp_close(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_ncp_open_close(fd, session_id, false, true);
}
int
bbl_session_ctrl_ip6cp_open(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_ncp_open_close(fd, session_id, true, false);
}
int
bbl_session_ctrl_ip6cp_close(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_ncp_open_close(fd, session_id, false, false);
}
static int
bbl_session_ctrl_traffic(int fd, uint32_t session_id, bool status)
{
bbl_session_s *session;
uint32_t i;
if(session_id) {
session = bbl_session_get(session_id);
if(session) {
session->session_traffic.active = status;
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
session->session_traffic.active = status;
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
}
int
bbl_session_ctrl_traffic_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_traffic(fd, session_id, true);
}
int
bbl_session_ctrl_traffic_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_session_ctrl_traffic(fd, session_id, false);
}
int
bbl_session_ctrl_traffic_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root = json_pack("{ss si s{si si}}",
"status", "ok",
"code", 200,
"session-traffic",
"total-flows", g_ctx->stats.session_traffic_flows,
"verified-flows", g_ctx->stats.session_traffic_flows_verified);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
}
return result;
}
int
bbl_session_ctrl_monkey_start(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
if(!g_monkey) {
LOG_NOARG(INFO, "Start monkey\n");
}
g_monkey = true;
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bbl_session_ctrl_monkey_stop(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
if(g_monkey) {
LOG_NOARG(INFO, "Stop monkey\n");
}
g_monkey = false;
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
+42
View File
@@ -401,4 +401,46 @@ bbl_session_id_from_broadcast(bbl_interface_s *interface, bbl_ethernet_header_s
json_t *
bbl_session_json(bbl_session_s *session);
int
bbl_session_ctrl_pending(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_counters(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_info(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_terminate(int fd, uint32_t session_id, json_t *arguments);
int
bbl_session_ctrl_ipcp_open(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_ipcp_close(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_ip6cp_open(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_ip6cp_close(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_traffic_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_traffic_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_traffic_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_monkey_start(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_session_ctrl_monkey_stop(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+212 -21
View File
@@ -697,7 +697,7 @@ bbl_stream_build_l2tp_packet(bbl_stream_s *stream)
bbl_stream_config_s *config = stream->config;
bbl_l2tp_session_s *l2tp_session = stream->session->l2tp_session;
bbl_l2tp_sunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_l2tp_tunnel_s *l2tp_tunnel = l2tp_session->tunnel;
bbl_network_interface_s *network_interface = l2tp_tunnel->interface;
@@ -1960,6 +1960,40 @@ bbl_stream_rx(bbl_ethernet_header_s *eth, bbl_session_s *session)
}
}
static json_t *
bbl_stream_summary_json()
{
struct dict_itor *itor;
bbl_stream_s *stream;
json_t *jobj, *jobj_array;
jobj_array = json_array();
itor = dict_itor_new(g_ctx->stream_flow_dict);
dict_itor_first(itor);
for (; dict_itor_valid(itor); dict_itor_next(itor)) {
stream = (bbl_stream_s*)*dict_itor_datum(itor);
if(stream) {
jobj = json_pack("{si ss* ss ss ss}",
"flow-id", stream->flow_id,
"name", stream->config->name,
"type", stream_type_string(stream),
"sub-type", stream_sub_type_string(stream),
"direction", stream->direction == BBL_DIRECTION_UP ? "upstream" : "downstream");
if(jobj) {
if(stream->session) {
json_object_set(jobj, "session-id", json_integer(stream->session->session_id));
json_object_set(jobj, "session-traffic", json_boolean(stream->session_traffic));
}
json_array_append(jobj_array, jobj);
}
}
}
dict_itor_free(itor);
return jobj_array;
}
json_t *
bbl_stream_json(bbl_stream_s *stream)
{
@@ -2052,36 +2086,193 @@ bbl_stream_json(bbl_stream_s *stream)
return root;
}
json_t *
bbl_stream_summary_json()
/* Control Socket Commands */
int
bbl_stream_ctrl_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
struct dict_itor *itor;
int result = 0;
json_t *root = json_pack("{ss si s{si si}}",
"status", "ok",
"code", 200,
"stream-stats",
"total-flows", g_ctx->stats.stream_traffic_flows,
"verified-flows", g_ctx->stats.stream_traffic_flows_verified);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
}
return result;
}
int
bbl_stream_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root;
json_t *json_stream = NULL;
bbl_stream_s *stream;
void **search = NULL;
int number = 0;
uint64_t flow_id;
/* Unpack further arguments */
if (json_unpack(arguments, "{s:i}", "flow-id", &number) != 0) {
return bbl_ctrl_status(fd, "error", 400, "missing flow-id");
}
flow_id = number;
search = dict_search(g_ctx->stream_flow_dict, &flow_id);
if(search) {
stream = *search;
json_stream = bbl_stream_json(stream);
root = json_pack("{ss si so*}",
"status", "ok",
"code", 200,
"stream-info", json_stream);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(json_stream);
}
return result;
} else {
return bbl_ctrl_status(fd, "warning", 404, "stream not found");
}
}
int
bbl_stream_ctrl_summary(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root = json_pack("{ss si so*}",
"status", "ok",
"code", 200,
"stream-summary", bbl_stream_summary_json());
result = json_dumpfd(root, fd, 0);
json_decref(root);
return result;
}
int
bbl_stream_ctrl_session(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
int result = 0;
json_t *root;
json_t *json_streams = NULL;
json_t *json_stream = NULL;
bbl_session_s *session;
bbl_stream_s *stream;
json_t *jobj, *jobj_array;
if(session_id == 0) {
/* session-id is mandatory */
return bbl_ctrl_status(fd, "error", 400, "missing session-id");
}
jobj_array = json_array();
session = bbl_session_get(session_id);
if(session) {
stream = session->streams.head;
json_streams = json_array();
while(stream) {
json_stream = bbl_stream_json(stream);
json_array_append(json_streams, json_stream);
stream = stream->session_next;
}
root = json_pack("{ss si s{si si si si si si si si si sf sf so*}}",
"status", "ok",
"code", 200,
"session-streams",
"session-id", session->session_id,
"rx-packets", session->stats.packets_rx,
"tx-packets", session->stats.packets_tx,
"rx-accounting-packets", session->stats.accounting_packets_rx,
"tx-accounting-packets", session->stats.accounting_packets_tx,
"rx-pps", session->stats.rate_packets_rx.avg,
"tx-pps", session->stats.rate_packets_tx.avg,
"rx-bps-l2", session->stats.rate_bytes_rx.avg * 8,
"tx-bps-l2", session->stats.rate_bytes_tx.avg * 8,
"rx-mbps-l2", (double)(session->stats.rate_bytes_rx.avg * 8) / 1000000.0,
"tx-mbps-l2", (double)(session->stats.rate_bytes_tx.avg * 8) / 1000000.0,
"streams", json_streams);
if(root) {
result = json_dumpfd(root, fd, 0);
json_decref(root);
} else {
result = bbl_ctrl_status(fd, "error", 500, "internal error");
json_decref(json_streams);
}
return result;
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
}
static int
bbl_stream_ctrl_traffic_start_stop(int fd, uint32_t session_id, bool status)
{
bbl_session_s *session;
uint32_t i;
if(session_id) {
session = bbl_session_get(session_id);
if(session) {
session->streams.active = status;
return bbl_ctrl_status(fd, "ok", 200, NULL);
} else {
return bbl_ctrl_status(fd, "warning", 404, "session not found");
}
} else {
/* Iterate over all sessions */
for(i = 0; i < g_ctx->sessions; i++) {
session = &g_ctx->session_list[i];
if(session) {
session->streams.active = status;
}
}
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
}
int
bbl_stream_ctrl_traffic_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_stream_ctrl_traffic_start_stop(fd, session_id, true);
}
int
bbl_stream_ctrl_traffic_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)))
{
return bbl_stream_ctrl_traffic_start_stop(fd, session_id, false);
}
int
bbl_stream_ctrl_reset(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
bbl_stream_s *stream;
struct dict_itor *itor;
g_ctx->stats.stream_traffic_flows_verified = 0;
/* Iterate over all traffic streams */
itor = dict_itor_new(g_ctx->stream_flow_dict);
dict_itor_first(itor);
for (; dict_itor_valid(itor); dict_itor_next(itor)) {
stream = (bbl_stream_s*)*dict_itor_datum(itor);
if(stream) {
jobj = json_pack("{si ss* ss ss ss}",
"flow-id", stream->flow_id,
"name", stream->config->name,
"type", stream_type_string(stream),
"sub-type", stream_sub_type_string(stream),
"direction", stream->direction == BBL_DIRECTION_UP ? "upstream" : "downstream");
if(jobj) {
if(stream->session) {
json_object_set(jobj, "session-id", json_integer(stream->session->session_id));
json_object_set(jobj, "session-traffic", json_boolean(stream->session_traffic));
}
json_array_append(jobj_array, jobj);
}
if(!stream) {
continue;
}
bbl_stream_reset(stream);
}
dict_itor_free(itor);
return jobj_array;
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
+20 -2
View File
@@ -176,7 +176,25 @@ bbl_stream_reset(bbl_stream_s *stream);
json_t *
bbl_stream_json(bbl_stream_s *stream);
json_t *
bbl_stream_summary_json();
int
bbl_stream_ctrl_stats(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_stream_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bbl_stream_ctrl_summary(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bbl_stream_ctrl_session(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_stream_ctrl_traffic_start(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_stream_ctrl_traffic_stop(int fd, uint32_t session_id, json_t *arguments __attribute__((unused)));
int
bbl_stream_ctrl_reset(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+5 -5
View File
@@ -77,7 +77,7 @@ bgp_ctrl_session_json(bgp_session_s *session)
}
int
bgp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
bgp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root, *sessions, *session;
@@ -133,14 +133,14 @@ bgp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t* a
}
int
bgp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
bgp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
bgp_teardown();
return bbl_ctrl_status(fd, "ok", 200, NULL);
}
int
bgp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
bgp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root;
@@ -223,7 +223,7 @@ bgp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t*
}
int
bgp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
bgp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
bgp_raw_update_s *raw_update = g_ctx->bgp_raw_updates;
@@ -256,7 +256,7 @@ bgp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), js
}
int
bgp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
bgp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root;
+5 -5
View File
@@ -10,18 +10,18 @@
#define __BBL_BGP_CTRL_H__
int
bgp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
bgp_ctrl_sessions(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bgp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
bgp_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bgp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
bgp_ctrl_raw_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
bgp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
bgp_ctrl_raw_update_list(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
bgp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
bgp_ctrl_disconnect(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
#endif
+5 -5
View File
@@ -67,7 +67,7 @@ isis_ctrl_adjacency_p2p(isis_adjacency_p2p_s *adjacency)
}
int
isis_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
isis_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
int result = 0;
int level;
@@ -167,7 +167,7 @@ isis_ctrl_database_entries(hb_tree *lsdb)
}
int
isis_ctrl_database(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
isis_ctrl_database(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
int result = 0;
json_t *root = NULL;
@@ -225,7 +225,7 @@ isis_ctrl_database(int fd, uint32_t session_id __attribute__((unused)), json_t*
}
int
isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
char *file_path;
int instance_id = 0;
@@ -260,7 +260,7 @@ isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t*
}
int
isis_ctrl_lsp_update(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments)
isis_ctrl_lsp_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments)
{
protocol_error_t result;
@@ -327,7 +327,7 @@ isis_ctrl_lsp_update(int fd, uint32_t session_id __attribute__((unused)), json_t
}
int
isis_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
isis_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)))
{
isis_teardown();
return bbl_ctrl_status(fd, "ok", 200, NULL);
+5 -5
View File
@@ -10,18 +10,18 @@
#define __BBL_ISIS_CTRL_H__
int
isis_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
isis_ctrl_adjacencies(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
int
isis_ctrl_database(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
isis_ctrl_database(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
isis_ctrl_load_mrt(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
isis_ctrl_lsp_update(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments);
isis_ctrl_lsp_update(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments);
int
isis_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)));
isis_ctrl_teardown(int fd, uint32_t session_id __attribute__((unused)), json_t *arguments __attribute__((unused)));
#endif
+10
View File
@@ -632,4 +632,14 @@ replace_substring(const char* source,
}
*result_pos = '\0';
return result;
}
char *
string_or_na(char *string)
{
if(string) {
return string;
} else {
return "N/A";
}
}
+1
View File
@@ -45,5 +45,6 @@ bool ipv6_addr_not_zero(ipv6addr_t *addr);
bool ipv6_prefix_not_zero(ipv6_prefix *prefix);
char *replace_substring(const char* s, const char* old, const char* new);
char *string_or_na(char *string);
#endif