mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
#10 LI Flow Support
This commit is contained in:
@@ -653,6 +653,10 @@ bbl_add_ctx (void)
|
||||
bbl_l2tp_session_hash,
|
||||
BBL_SESSION_HASHTABLE_SIZE);
|
||||
|
||||
ctx->li_flow_dict = hashtable2_dict_new((dict_compare_func)bbl_compare_l2tp_session,
|
||||
bbl_l2tp_session_hash,
|
||||
BBL_SESSION_HASHTABLE_SIZE);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "bbl_tx.h"
|
||||
#include "bbl_l2tp.h"
|
||||
#include "bbl_l2tp_avp.h"
|
||||
#include "bbl_li.h"
|
||||
|
||||
#define WRITE_BUF_LEN 1514
|
||||
#define SCRATCHPAD_LEN 1514
|
||||
@@ -271,6 +272,9 @@ typedef struct bbl_interface_
|
||||
uint64_t l2tp_data_tx;
|
||||
bbl_rate_s rate_l2tp_data_rx;
|
||||
bbl_rate_s rate_l2tp_data_tx;
|
||||
|
||||
uint64_t li_rx;
|
||||
bbl_rate_s rate_li_rx;
|
||||
} stats;
|
||||
|
||||
struct timer_ *tx_job;
|
||||
@@ -373,6 +377,8 @@ typedef struct bbl_ctx_
|
||||
|
||||
dict *session_dict; /* hashtable for sessions */
|
||||
dict *l2tp_session_dict; /* hashtable for L2TP sessions */
|
||||
dict *li_flow_dict; /* hashtable for LI flows */
|
||||
|
||||
uint16_t next_tunnel_id;
|
||||
|
||||
uint64_t flow_id;
|
||||
|
||||
@@ -650,6 +650,46 @@ bbl_ctrl_session_ip6cp_close(int fd, bbl_ctx_s *ctx, session_key_t *key, json_t*
|
||||
return bbl_ctrl_session_ncp_open_close(fd, ctx, key, false, false);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
bbl_ctrl_li_flows(int fd, bbl_ctx_s *ctx, session_key_t *key __attribute__((unused)), json_t* arguments __attribute__((unused))) {
|
||||
ssize_t result = 0;
|
||||
json_t *root, *flows, *flow;
|
||||
bbl_li_flow_t *li_flow;
|
||||
struct dict_itor *itor;
|
||||
|
||||
flows = json_array();
|
||||
itor = dict_itor_new(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("{si si si si si si si si si si}",
|
||||
"direction", li_flow->direction,
|
||||
"packet-type", li_flow->packet_type,
|
||||
"sub-packet-type", 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);
|
||||
json_array_append(flows, flow);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
bbl_ctrl_status(fd, "error", 500, "internal error");
|
||||
json_decref(flows);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
struct action {
|
||||
char *name;
|
||||
callback_function *fn;
|
||||
@@ -673,6 +713,7 @@ struct action actions[] = {
|
||||
{"igmp-join", bbl_ctrl_igmp_join},
|
||||
{"igmp-leave", bbl_ctrl_igmp_leave},
|
||||
{"igmp-info", bbl_ctrl_igmp_info},
|
||||
{"li-flows", bbl_ctrl_li_flows},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -178,6 +178,12 @@ bbl_stats_job (timer_s *timer)
|
||||
}
|
||||
|
||||
if (ctx->op.network_if) {
|
||||
if(dict_count(ctx->li_flow_dict)) {
|
||||
wprintw(stats_win, "\nLI Statistics\n");
|
||||
wprintw(stats_win, " Flows %10lu\n", dict_count(ctx->li_flow_dict));
|
||||
wprintw(stats_win, " Rx Packets %10lu (%7lu PPS)\n",
|
||||
ctx->op.network_if->stats.li_rx, ctx->op.network_if->stats.rate_li_rx.avg);
|
||||
}
|
||||
if(ctx->config.l2tp_server) {
|
||||
wprintw(stats_win, "\nL2TP LNS Statistics\n");
|
||||
wprintw(stats_win, " Tunnels %10lu\n", ctx->l2tp_tunnels);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - LI Functions
|
||||
*
|
||||
* Christian Giese, February 2021
|
||||
*
|
||||
* Copyright (C) 2020-2021, RtBrick, Inc.
|
||||
*/
|
||||
|
||||
#include "bbl.h"
|
||||
#include "bbl_logging.h"
|
||||
|
||||
/**
|
||||
* bbl_l2tp_handler_rx
|
||||
*
|
||||
* This function handles all received L2TPv2 traffic.
|
||||
*
|
||||
* @param eth Received ethernet packet.
|
||||
* @param l2tp L2TP header of received ethernet packet.
|
||||
* @param interface Receiving interface.
|
||||
*/
|
||||
void
|
||||
bbl_qmx_li_handler_rx(bbl_ethernet_header_t *eth, bbl_qmx_li_t *qmx_li, bbl_interface_s *interface) {
|
||||
bbl_ctx_s *ctx = interface->ctx;
|
||||
bbl_ipv4_t *ipv4 = (bbl_ipv4_t*)eth->next;
|
||||
bbl_li_flow_t *li_flow;
|
||||
|
||||
bbl_ethernet_header_t *inner_eth;
|
||||
bbl_pppoe_session_t *inner_pppoe;
|
||||
bbl_ipv4_t *inner_ipv4 = NULL;
|
||||
|
||||
dict_insert_result result;
|
||||
void **search = NULL;
|
||||
|
||||
UNUSED(eth);
|
||||
|
||||
search = dict_search(ctx->li_flow_dict, &qmx_li->header);
|
||||
if(search) {
|
||||
li_flow = *search;
|
||||
} else {
|
||||
/* New flow ... */
|
||||
li_flow = calloc(1, sizeof(bbl_li_flow_t));
|
||||
li_flow->direction = qmx_li->direction;
|
||||
li_flow->packet_type = qmx_li->packet_type;
|
||||
li_flow->sub_packet_type = qmx_li->sub_packet_type;
|
||||
li_flow->liid = qmx_li->liid;
|
||||
result = dict_insert(ctx->li_flow_dict, &qmx_li->header);
|
||||
if (!result.inserted) {
|
||||
free(li_flow);
|
||||
return;
|
||||
}
|
||||
*result.datum_ptr = li_flow;
|
||||
}
|
||||
|
||||
interface->stats.li_rx++;
|
||||
li_flow->packets_rx++;
|
||||
li_flow->bytes_rx += qmx_li->payload_len;
|
||||
|
||||
inner_eth = (bbl_ethernet_header_t*)qmx_li->next;
|
||||
if(inner_eth->type == ETH_TYPE_PPPOE_SESSION) {
|
||||
inner_pppoe = (bbl_pppoe_session_t*)inner_eth->next;
|
||||
if(inner_pppoe->protocol == PROTOCOL_IPV4) {
|
||||
inner_ipv4 = (bbl_ipv4_t*)inner_pppoe->next;
|
||||
|
||||
}
|
||||
} else if(inner_eth->type == ETH_TYPE_IPV4) {
|
||||
inner_ipv4 = (bbl_ipv4_t*)eth->next;
|
||||
}
|
||||
|
||||
if(inner_ipv4) {
|
||||
li_flow->packets_rx_ipv4++;
|
||||
switch(ipv4->protocol) {
|
||||
case PROTOCOL_IPV4_TCP:
|
||||
li_flow->packets_rx_ipv4_tcp++;
|
||||
break;
|
||||
case PROTOCOL_IPV4_UDP:
|
||||
li_flow->packets_rx_ipv4_udp++;
|
||||
break;
|
||||
case PROTOCOL_IPV4_INTERNAL:
|
||||
li_flow->packets_rx_ipv4_internal++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* BNG Blaster (BBL) - LI Functions
|
||||
*
|
||||
* Christian Giese, February 2021
|
||||
*
|
||||
* Copyright (C) 2020-2021, RtBrick, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __BBL_LI_H__
|
||||
#define __BBL_LI_H__
|
||||
|
||||
typedef struct bbl_interface_ bbl_interface_s;
|
||||
|
||||
typedef struct bbl_li_flow_
|
||||
{
|
||||
uint8_t direction;
|
||||
uint8_t packet_type;
|
||||
uint8_t sub_packet_type;
|
||||
uint32_t liid;
|
||||
|
||||
uint64_t packets_rx;
|
||||
uint64_t bytes_rx;
|
||||
uint64_t packets_rx_ipv4;
|
||||
uint64_t packets_rx_ipv4_tcp;
|
||||
uint64_t packets_rx_ipv4_udp;
|
||||
uint64_t packets_rx_ipv4_internal;
|
||||
} bbl_li_flow_t;
|
||||
|
||||
|
||||
void bbl_qmx_li_handler_rx(bbl_ethernet_header_t *eth, bbl_qmx_li_t *qmx_li, bbl_interface_s *interface);
|
||||
|
||||
#endif
|
||||
+34
-1
@@ -1422,6 +1422,30 @@ decode_bbl(uint8_t *buf, uint len,
|
||||
return PROTOCOL_SUCCESS;
|
||||
}
|
||||
|
||||
protocol_error_t
|
||||
decode_qmx_li(uint8_t *buf, uint len,
|
||||
uint8_t *sp, uint sp_len,
|
||||
bbl_qmx_li_t **_qmx_li) {
|
||||
|
||||
bbl_qmx_li_t *qmx_li;
|
||||
|
||||
if(len < 4 || sp_len < sizeof(bbl_qmx_li_t)) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
/* Init QMX LI header */
|
||||
qmx_li = (bbl_qmx_li_t*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_qmx_li_t));
|
||||
qmx_li->header = *(uint32_t*)buf;
|
||||
qmx_li->direction = (*buf >> 5) & 0x7;
|
||||
qmx_li->packet_type = (*buf >> 1) & 0xf;
|
||||
qmx_li->sub_packet_type =(*(uint16_t*)buf >> 6) & 0x0f;
|
||||
qmx_li->liid =*(uint32_t*)buf & 0x3FFFFF;
|
||||
BUMP_BUFFER(buf, len, sizeof(uint32_t));
|
||||
qmx_li->payload = buf;
|
||||
qmx_li->payload_len = len;
|
||||
*_qmx_li = qmx_li;
|
||||
return decode_ethernet(buf, len, sp, sp_len, (bbl_ethernet_header_t**)&qmx_li->next);
|
||||
}
|
||||
|
||||
protocol_error_t
|
||||
decode_udp(uint8_t *buf, uint len,
|
||||
uint8_t *sp, uint sp_len,
|
||||
@@ -1467,8 +1491,17 @@ decode_udp(uint8_t *buf, uint len,
|
||||
udp->protocol = UDP_PROTOCOL_L2TP;
|
||||
ret_val = decode_l2tp(buf, len, sp, sp_len, (bbl_l2tp_t**)&udp->next);
|
||||
break;
|
||||
case QMX_LI_UDP_PORT:
|
||||
udp->protocol = UDP_PROTOCOL_QMX_LI;
|
||||
ret_val = decode_qmx_li(buf, len, sp, sp_len, (bbl_qmx_li_t**)&udp->next);
|
||||
break;
|
||||
default:
|
||||
udp->next = NULL;
|
||||
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_t**)&udp->next);
|
||||
} else {
|
||||
udp->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#define PROTOCOL_IPV4_IGMP 0x02
|
||||
#define PROTOCOL_IPV4_TCP 0x06
|
||||
#define PROTOCOL_IPV4_UDP 0x11
|
||||
#define PROTOCOL_IPV4_INTERNAL 0x3D
|
||||
|
||||
#define ICMP_TYPE_ECHO_REPLY 0x00
|
||||
#define ICMP_TYPE_ECHO_REQUEST 0x08
|
||||
@@ -134,6 +135,7 @@
|
||||
#define UDP_PROTOCOL_DHCPV6 1
|
||||
#define UDP_PROTOCOL_BBL 2
|
||||
#define UDP_PROTOCOL_L2TP 3
|
||||
#define UDP_PROTOCOL_QMX_LI 4
|
||||
|
||||
#define IPV6_NEXT_HEADER_UDP 17
|
||||
#define IPV6_NEXT_HEADER_ICMPV6 58
|
||||
@@ -175,6 +177,7 @@
|
||||
|
||||
#define L2TP_NH_TYPE_VALUE 18
|
||||
|
||||
#define QMX_LI_UDP_PORT 49152
|
||||
|
||||
#define MAX_VLANS 3
|
||||
|
||||
@@ -580,6 +583,17 @@ typedef struct bbl_bbl_ {
|
||||
uint64_t timestamp;
|
||||
} bbl_bbl_t;
|
||||
|
||||
typedef struct bbl_qmx_li_ {
|
||||
uint32_t header;
|
||||
uint8_t direction;
|
||||
uint8_t packet_type;
|
||||
uint8_t sub_packet_type;
|
||||
uint32_t liid;
|
||||
void *next; // next header
|
||||
void *payload; // LI payload
|
||||
uint16_t payload_len; // LI payload length
|
||||
} bbl_qmx_li_t;
|
||||
|
||||
/*
|
||||
* decode_ethernet
|
||||
*/
|
||||
|
||||
@@ -1793,6 +1793,8 @@ bbl_rx_handler_network(bbl_ethernet_header_t *eth, bbl_interface_s *interface) {
|
||||
udp = (bbl_udp_t*)ipv4->next;
|
||||
if(udp->protocol == UDP_PROTOCOL_BBL) {
|
||||
bbl = (bbl_bbl_t*)udp->next;
|
||||
} else if(udp->protocol == UDP_PROTOCOL_QMX_LI) {
|
||||
return bbl_qmx_li_handler_rx(eth, (bbl_qmx_li_t*)udp->next, interface);
|
||||
} else if(udp->protocol == UDP_PROTOCOL_L2TP) {
|
||||
return bbl_l2tp_handler_rx(eth, (bbl_l2tp_t*)udp->next, interface);
|
||||
}
|
||||
|
||||
@@ -165,6 +165,11 @@ bbl_stats_stdout (bbl_ctx_s *ctx, bbl_stats_t * stats) {
|
||||
printf("Flapped: %u\n", ctx->sessions_flapped);
|
||||
|
||||
if(ctx->op.network_if) {
|
||||
if(dict_count(ctx->li_flow_dict)) {
|
||||
printf("\nLI Statistics:\n");
|
||||
printf(" Flows: %10lu\n", dict_count(ctx->li_flow_dict));
|
||||
printf(" RX Packets: %10lu\n", ctx->op.network_if->stats.li_rx);
|
||||
}
|
||||
if(ctx->config.l2tp_server) {
|
||||
printf("\nL2TP LNS Statistics:\n");
|
||||
printf(" Tunnels: %10u\n", ctx->l2tp_tunnels_max);
|
||||
@@ -312,6 +317,7 @@ bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) {
|
||||
json_t *jobj_access_if = NULL;
|
||||
json_t *jobj_network_if = NULL;
|
||||
json_t *jobj_l2tp = NULL;
|
||||
json_t *jobj_li = NULL;
|
||||
json_t *jobj_straffic = NULL;
|
||||
json_t *jobj_multicast = NULL;
|
||||
json_t *jobj_protocols = NULL;
|
||||
@@ -335,6 +341,12 @@ bbl_stats_json (bbl_ctx_s *ctx, bbl_stats_t * stats) {
|
||||
|
||||
jobj_array = json_array();
|
||||
if (ctx->op.network_if) {
|
||||
if(dict_count(ctx->li_flow_dict)) {
|
||||
jobj_li = json_object();
|
||||
json_object_set(jobj_li, "flows", json_integer(dict_count(ctx->li_flow_dict)));
|
||||
json_object_set(jobj_li, "rx-packets", json_integer(ctx->op.network_if->stats.li_rx));
|
||||
json_object_set(jobj, "li-statistics", jobj_li);
|
||||
}
|
||||
if(ctx->config.l2tp_server) {
|
||||
jobj_l2tp = json_object();
|
||||
json_object_set(jobj_l2tp, "tunnels", json_integer(ctx->l2tp_tunnels_max));
|
||||
@@ -505,6 +517,8 @@ bbl_compute_avg_rate (bbl_rate_s *rate, uint64_t current_value)
|
||||
uint idx, div;
|
||||
uint64_t sum;
|
||||
|
||||
if(current_value == 0) return;
|
||||
|
||||
rate->diff_value[rate->cursor] = current_value - rate->last_value;
|
||||
|
||||
sum = 0;
|
||||
@@ -547,5 +561,6 @@ bbl_compute_interface_rate_job (timer_s *timer)
|
||||
bbl_compute_avg_rate(&interface->stats.rate_mc_tx, interface->stats.mc_tx);
|
||||
bbl_compute_avg_rate(&interface->stats.rate_l2tp_data_rx, interface->stats.l2tp_data_rx);
|
||||
bbl_compute_avg_rate(&interface->stats.rate_l2tp_data_tx, interface->stats.l2tp_data_tx);
|
||||
bbl_compute_avg_rate(&interface->stats.rate_li_rx, interface->stats.li_rx);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user