#10 LI Flow Support

This commit is contained in:
Christian Giese
2021-02-23 12:47:32 +01:00
parent b4e0888f69
commit 5dd3e4c19a
10 changed files with 239 additions and 1 deletions
+4
View File
@@ -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;
}
+6
View File
@@ -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;
+41
View File
@@ -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},
};
+6
View File
@@ -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);
+85
View File
@@ -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;
}
}
}
+32
View File
@@ -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
View File
@@ -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;
}
+14
View File
@@ -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
*/
+2
View File
@@ -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);
}
+15
View File
@@ -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);
}
}