LAG fixes, enhancements, commands...

This commit is contained in:
Christian Giese
2022-10-10 13:36:01 +00:00
parent e56d801026
commit bd30f127a5
12 changed files with 439 additions and 225 deletions
+38 -17
View File
@@ -284,6 +284,18 @@ json_parse_lag(json_t *lag, bbl_lag_config_s *lag_config)
lag_config->lacp_system_id[3] = 0xff;
lag_config->lacp_system_id[4] = 0xff;
}
value = json_object_get(lag, "lacp-min-active-links");
if(value) {
lag_config->lacp_min_active_links = json_number_value(value);
} else {
lag_config->lacp_min_active_links = 0;
}
value = json_object_get(lag, "lacp-max-active-links");
if(value) {
lag_config->lacp_min_active_links = json_number_value(value);
} else {
lag_config->lacp_max_active_links = UINT8_MAX;
}
if(json_unpack(lag, "{s:s}", "mac", &s) == 0) {
if(sscanf(s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
@@ -1304,6 +1316,22 @@ json_parse_stream(json_t *stream, bbl_stream_config_s *stream_config)
double bps;
double number;
if(json_unpack(stream, "{s:s}", "name", &s) == 0) {
stream_config->name = strdup(s);
} else {
fprintf(stderr, "JSON config error: Missing value for stream->name\n");
return false;
}
value = json_object_get(stream, "stream-group-id");
if(value) {
number = json_number_value(value);
if(number >= UINT16_MAX) {
fprintf(stderr, "JSON config error: Invalid value for stream->stream-group-id\n");
}
stream_config->stream_group_id = number;
}
if(json_unpack(stream, "{s:s}", "type", &s) == 0) {
if(strcmp(s, "ipv4") == 0) {
stream_config->type = BBL_SUB_TYPE_IPV4;
@@ -1332,24 +1360,17 @@ json_parse_stream(json_t *stream, bbl_stream_config_s *stream_config)
return false;
}
} else {
stream_config->direction = BBL_DIRECTION_BOTH;
return false;
}
if(json_unpack(stream, "{s:s}", "name", &s) == 0) {
stream_config->name = strdup(s);
} else {
fprintf(stderr, "JSON config error: Missing value for stream->name\n");
return false;
}
value = json_object_get(stream, "stream-group-id");
if(value) {
number = json_number_value(value);
if(number >= UINT16_MAX) {
fprintf(stderr, "JSON config error: Invalid value for stream->stream-group-id\n");
if(stream_config->stream_group_id) {
stream_config->direction = BBL_DIRECTION_BOTH;
} else {
stream_config->direction = BBL_DIRECTION_DOWN;
}
stream_config->stream_group_id = number;
}
if(stream_config->stream_group_id == 0 &&
stream_config->direction != BBL_DIRECTION_DOWN) {
fprintf(stderr, "JSON config error: Invalid value for stream->direction (must be downstream for RAW streams)\n");
return false;
}
if(json_unpack(stream, "{s:s}", "network-interface", &s) == 0) {
+2 -1
View File
@@ -153,10 +153,11 @@ typedef struct bbl_lag_config_
char *interface;
bool lacp_enable;
bool lacp_timeout_short;
uint8_t lacp_min_active_links;
uint8_t lacp_max_active_links;
uint16_t lacp_system_priority;
uint8_t lacp_system_id[ETH_ADDR_LEN];
uint8_t mac[ETH_ADDR_LEN];
void *next; /* pointer to next lag config element */
} bbl_lag_config_s;
+5 -4
View File
@@ -1592,7 +1592,7 @@ bbl_ctrl_traffic_stop(int fd, uint32_t session_id __attribute__((unused)), json_
}
int
bgp_ctrl_monkey_start(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
bbl_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");
@@ -1602,7 +1602,7 @@ bgp_ctrl_monkey_start(int fd, uint32_t session_id __attribute__((unused)), json_
}
int
bgp_ctrl_monkey_stop(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
bbl_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");
@@ -1674,8 +1674,9 @@ struct action actions[] = {
{"bgp-teardown", bgp_ctrl_teardown, true},
{"bgp-raw-update-list", bgp_ctrl_raw_update_list, true},
{"bgp-raw-update", bgp_ctrl_raw_update, false},
{"monkey-start", bgp_ctrl_monkey_start, false},
{"monkey-stop", bgp_ctrl_monkey_stop, false},
{"monkey-start", bbl_ctrl_monkey_start, false},
{"monkey-stop", bbl_ctrl_monkey_stop, false},
{"lag-info", bbl_lag_ctrl_info, true},
{NULL, NULL, false},
};
+3 -3
View File
@@ -616,7 +616,7 @@ bbl_interactive_window_job(timer_s *timer)
if(i >= stats_win_postion && i < 16+stats_win_postion) {
wprintw(stats_win, " %-16.16s | %-9.9s | %7lu | %10lu | %7lu | %10lu | %8lu\n", stream->config->name,
stream->direction == BBL_DIRECTION_UP ? "up" : "down",
stream->rate_packets_tx.avg, tx_kbps, stream->rate_packets_rx.avg, rx_kbps, stream->loss);
stream->rate_packets_tx.avg, tx_kbps, stream->rate_packets_rx.avg, rx_kbps, stream->rx_loss);
} else if (i == 16+stats_win_postion) {
wprintw(stats_win, " ...\n");
}
@@ -627,13 +627,13 @@ bbl_interactive_window_job(timer_s *timer)
stream_sum_up_tx_kbps += tx_kbps;
stream_sum_up_rx_pps += stream->rate_packets_rx.avg;
stream_sum_up_rx_kbps += rx_kbps;
stream_sum_up_loss += stream->loss;
stream_sum_up_loss += stream->rx_loss;
} else {
stream_sum_down_tx_pps += stream->rate_packets_tx.avg;
stream_sum_down_tx_kbps += tx_kbps;
stream_sum_down_rx_pps += stream->rate_packets_rx.avg;
stream_sum_down_rx_kbps += rx_kbps;
stream_sum_down_loss += stream->loss;
stream_sum_down_loss += stream->rx_loss;
}
stream = stream->session_next;
}
+1
View File
@@ -15,6 +15,7 @@ typedef struct bbl_interface_
char *name; /* interface name */
interface_type_t type; /* interface type */
interface_state_t state; /* interface state */
uint32_t state_transitions; /* interface state transitions */
uint32_t ifindex; /* interface index */
uint32_t pcap_index; /* interface index for packet captures */
+191 -17
View File
@@ -7,9 +7,21 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bbl.h"
#include "../bbl_ctrl.h"
uint16_t g_lag_port_id = 1;
const char *
lacp_state_string(lacp_state_t type)
{
switch(type) {
case LACP_EXPIRED: return "Expired";
case LACP_DEFAULTED: return "Defaulted";
case LACP_CURRENT: return "Current";
default: return "Disabled";
}
}
bbl_lag_s *
bbl_lag_get_by_name(char *interface)
{
@@ -76,18 +88,37 @@ bbl_lag_lacp_job(timer_s *timer)
if(member->timeout > 3) {
interface->state = INTERFACE_DOWN;
if(!(member->actor_state & LACP_STATE_FLAG_EXPIRED)) {
member->lacp_state = LACP_EXPIRED;
member->actor_state |= LACP_STATE_FLAG_EXPIRED;
LOG(LAG, "LAG (%s) LACP expired on interface %s\n",
member->lag->interface->name, interface->name);
}
if(member->timeout > 6) {
if(!(member->actor_state & LACP_STATE_FLAG_DEFAULTED)) {
member->lacp_state = LACP_DEFAULTED;
member->actor_state |= LACP_STATE_FLAG_DEFAULTED;
LOG(LAG, "LAG (%s) LACP defaulted on interface %s\n",
member->lag->interface->name, interface->name);
}
}
}
}
static void
bbl_lag_member_insert(bbl_lag_s *lag, bbl_lag_member_s *member)
{
/* Insert LAG member links by port priority
* (lower value is higher priority). */
bbl_lag_member_s *member_iter;
CIRCLEQ_FOREACH(member_iter, &lag->lag_member_qhead, lag_member_qnode) {
if(member_iter->actor_port_priority > member->actor_port_priority) {
CIRCLEQ_INSERT_BEFORE(&lag->lag_member_qhead, member_iter, member, lag_member_qnode);
return;
}
}
CIRCLEQ_INSERT_TAIL(&lag->lag_member_qhead, member, lag_member_qnode);
}
bool
bbl_lag_interface_add(bbl_interface_s *interface, bbl_link_config_s *link_config)
{
@@ -135,41 +166,92 @@ bbl_lag_interface_add(bbl_interface_s *interface, bbl_link_config_s *link_config
} else {
member->lacp_state = LACP_DISABLED;
}
CIRCLEQ_INSERT_TAIL(&lag->lag_member_qhead, member, lag_member_qnode);
bbl_lag_member_insert(lag, member);
LOG(LAG, "LAG (%s) Interface %s added\n", lag->interface->name, interface->name);
}
return true;
}
static void
bbl_lag_member_update_state(bbl_lag_member_s *member, interface_state_t state)
{
bbl_interface_s *interface = member->interface;
if(interface->state == state) {
return;
}
LOG(LAG, "LAG (%s) Member interface %s state changed from %s to %s\n",
member->lag->interface->name,
interface->name,
interface_state_string(interface->state),
interface_state_string(state));
interface->state_transitions++;
interface->state = state;
switch(state) {
case INTERFACE_UP:
member->actor_state |= (LACP_STATE_FLAG_COLLECTING|LACP_STATE_FLAG_DISTRIBUTING);
break;
case INTERFACE_STANDBY:
member->actor_state &= ~LACP_STATE_FLAG_DISTRIBUTING;
member->actor_state |= LACP_STATE_FLAG_COLLECTING;
break;
default:
member->actor_state &= ~(LACP_STATE_FLAG_COLLECTING|LACP_STATE_FLAG_DISTRIBUTING);
break;
}
}
static void
bbl_lag_update_state(bbl_lag_s *lag, interface_state_t state)
{
bbl_interface_s *interface = lag->interface;
if(interface->state == state) {
return;
}
LOG(LAG, "LAG (%s) Interface state changed from %s to %s\n",
interface->name,
interface_state_string(interface->state),
interface_state_string(state));
interface->state_transitions++;
interface->state = state;
}
static void
bbl_lag_select(bbl_lag_s *lag)
{
bbl_lag_member_s *member;
lag->active_count = 0;
uint8_t active_count = 0;
CIRCLEQ_FOREACH(member, &lag->lag_member_qhead, lag_member_qnode) {
member->primary = false;
if(member->partner_state & (LACP_STATE_FLAG_COLLECTING|LACP_STATE_FLAG_DISTRIBUTING)) {
member->actor_state |= (LACP_STATE_FLAG_COLLECTING|LACP_STATE_FLAG_DISTRIBUTING);
member->interface->state = INTERFACE_UP;
lag->active_list[lag->active_count++] = member;
if(lag->active_count == 1) {
member->primary = true;
LOG(LAG, "LAG (%s) Interface %s set to UP (primary)\n", member->lag->interface->name, member->interface->name);
if(active_count >= LAG_MEMBER_ACTIVE_MAX ||
active_count >= lag->config->lacp_max_active_links) {
bbl_lag_member_update_state(member, INTERFACE_STANDBY);
} else {
LOG(LAG, "LAG (%s) Interface %s set to UP\n", member->lag->interface->name, member->interface->name);
lag->active_list[active_count++] = member;
if(active_count == 1) {
member->primary = true;
}
bbl_lag_member_update_state(member, INTERFACE_UP);
}
} else {
member->interface->state = INTERFACE_DOWN;
bbl_lag_member_update_state(member, INTERFACE_DOWN);
}
}
if(lag->active_count) {
lag->interface->state = INTERFACE_UP;
/* Update LAG state */
if(active_count &&
active_count >= lag->config->lacp_min_active_links) {
bbl_lag_update_state(lag, INTERFACE_UP);
} else {
lag->interface->state = INTERFACE_DOWN;
bbl_lag_update_state(lag, INTERFACE_DOWN);
}
lag->active_count = active_count;
}
void
@@ -179,12 +261,14 @@ bbl_lag_rx_lacp(bbl_interface_s *interface,
bbl_lag_member_s *member = interface->lag_member;
bbl_lacp_s *lacp = (bbl_lacp_s*)eth->next;
if(member) {
if(member && member->lacp_state) {
member->timeout = 0;
member->lacp_state = LACP_CURRENT;
member->actor_state &= ~(LACP_STATE_FLAG_DEFAULTED|LACP_STATE_FLAG_EXPIRED);
member->stats.lacp_rx++;
if(member->partner_state != lacp->actor_state ||
member->partner_system_priority != lacp->actor_system_priority) {
member->partner_system_priority != lacp->actor_system_priority ||
member->partner_port_priority != lacp->actor_port_priority) {
memcpy(member->partner_system_id, lacp->actor_system_id, ETH_ADDR_LEN);
member->partner_system_priority = lacp->actor_system_priority;
member->partner_key = lacp->actor_key;
@@ -194,4 +278,94 @@ bbl_lag_rx_lacp(bbl_interface_s *interface,
bbl_lag_select(member->lag);
}
}
}
static json_t *
bbl_lag_json(bbl_lag_s *lag)
{
bbl_lag_member_s *member;
json_t *jobj_lag, *jobj_member, *jobj_lacp, *jobj_array;
jobj_array = json_array();
CIRCLEQ_FOREACH(member, &lag->lag_member_qhead, lag_member_qnode) {
if(member->lacp_state) {
jobj_lacp = json_pack("{si si si ss* si si si si si ss* si si si si si}",
"bpdu-rx", member->stats.lacp_rx,
"bpdu-tx", member->stats.lacp_tx,
"bpdu-dropped", member->stats.lacp_dropped,
"actor-system-id", format_mac_address(member->actor_system_id),
"actor-system-priority", member->actor_system_priority,
"actor-key", member->actor_key,
"actor-port-priority", member->actor_port_priority,
"actor-port-id", member->actor_port_id,
"actor-state", member->actor_state,
"partner-system-id", format_mac_address(member->partner_system_id),
"partner-system-priority", member->partner_system_priority,
"partner-key", member->partner_key,
"partner-port-priority", member->partner_port_priority,
"partner-port-id", member->partner_port_id,
"partner-state", member->partner_state);
} else {
jobj_lacp = NULL;
}
jobj_member = json_pack("{ss* ss* si ss* so*}",
"interface", member->interface->name,
"state", interface_state_string(member->interface->state),
"state-transitions", member->interface->state_transitions,
"lacp-state", lacp_state_string(member->lacp_state),
"lacp", jobj_lacp);
if(jobj_member) {
json_array_append(jobj_array, jobj_member);
}
}
jobj_lag = json_pack("{si ss* ss* si so*}",
"id", lag->id,
"interface", lag->interface->name,
"state", interface_state_string(lag->interface->state),
"state-transitions", lag->interface->state_transitions,
"members", jobj_array);
return jobj_lag;
}
int
bbl_lag_ctrl_info(int fd, uint32_t session_id __attribute__((unused)), json_t* arguments __attribute__((unused)))
{
int result = 0;
bbl_lag_s *lag;
json_t *root, *jobj, *jobj_array;
const char *interface = NULL;
jobj_array = json_array();
/* Unpack further arguments */
json_unpack(arguments, "{s:s}", "interface", &interface);
CIRCLEQ_FOREACH(lag, &g_ctx->lag_qhead, lag_qnode) {
if(interface) {
if(strcmp(lag->interface->name, interface) != 0) {
continue;
}
}
jobj = bbl_lag_json(lag);
if(jobj) {
json_array_append(jobj_array, jobj);
}
}
root = json_pack("{ss si so*}",
"status", "ok",
"code", 200,
"lag-info", 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;
}
+7 -3
View File
@@ -10,7 +10,7 @@
#ifndef __BBL_LAG_H__
#define __BBL_LAG_H__
#define LAG_MEMBER_ACTIVE_MAX 16
#define LAG_MEMBER_ACTIVE_MAX 64
typedef struct bbl_lag_
{
@@ -18,7 +18,6 @@ typedef struct bbl_lag_
bbl_interface_s *interface;
bbl_lag_config_s *config;
uint8_t active_max;
uint8_t active_count;
bbl_lag_member_s *active_list[LAG_MEMBER_ACTIVE_MAX];
@@ -32,7 +31,10 @@ typedef struct bbl_lag_member_
bbl_interface_s *interface;
lacp_state_t lacp_state;
/* The "primary" link is used for
* all control traffic. */
bool primary;
bool periodic_fast;
struct timer_ *lacp_timer;
@@ -57,7 +59,6 @@ typedef struct bbl_lag_member_
uint32_t lacp_rx;
uint32_t lacp_tx;
uint32_t lacp_dropped;
uint32_t lacp_transitions;
} stats;
} bbl_lag_member_s;
@@ -74,4 +75,7 @@ void
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);
#endif
+6 -6
View File
@@ -19,8 +19,8 @@ bbl_rx_stream_network(bbl_network_interface_s *interface,
}
stream = bbl_stream_rx(eth, NULL);
if(stream) {
if(stream->network_interface == NULL) {
stream->network_interface = interface;
if(stream->rx_network_interface == NULL) {
stream->rx_network_interface = interface;
}
return true;
}
@@ -49,8 +49,8 @@ bbl_rx_stream_access(bbl_access_interface_s *interface,
session->session_state != BBL_IDLE) {
stream = bbl_stream_rx(eth, session);
if(stream) {
if(stream->access_interface == NULL) {
stream->access_interface = interface;
if(stream->rx_access_interface == NULL) {
stream->rx_access_interface = interface;
}
return true;
}
@@ -69,8 +69,8 @@ bbl_rx_stream_a10nsp(bbl_a10nsp_interface_s *interface,
}
stream = bbl_stream_rx(eth, NULL);
if(stream) {
if(stream->a10nsp_interface == NULL) {
stream->a10nsp_interface = interface;
if(stream->rx_a10nsp_interface == NULL) {
stream->rx_a10nsp_interface = interface;
}
return true;
}
+24 -24
View File
@@ -994,56 +994,56 @@ bbl_session_json(bbl_session_s *session)
if(session->session_traffic.ipv4_down) {
stream = session->session_traffic.ipv4_down;
json_object_set(session_traffic, "downstream-ipv4-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "downstream-ipv4-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv4-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv4-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv4-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv4-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "downstream-ipv4-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv4-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "downstream-ipv4-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv4-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
if(session->session_traffic.ipv4_up) {
stream = session->session_traffic.ipv4_up;
json_object_set(session_traffic, "upstream-ipv4-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "upstream-ipv4-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv4-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv4-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv4-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv4-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "upstream-ipv4-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv4-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "upstream-ipv4-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv4-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
if(session->session_traffic.ipv6_down) {
stream = session->session_traffic.ipv6_down;
json_object_set(session_traffic, "downstream-ipv6-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "downstream-ipv6-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv6-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv6-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv6-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv6-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "downstream-ipv6-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv6-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "downstream-ipv6-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv6-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
if(session->session_traffic.ipv6_up) {
stream = session->session_traffic.ipv6_up;
json_object_set(session_traffic, "upstream-ipv6-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "upstream-ipv6-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv6-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv6-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv6-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv6-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "upstream-ipv6-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv6-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "upstream-ipv6-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv6-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
if(session->session_traffic.ipv6pd_down) {
stream = session->session_traffic.ipv6pd_down;
json_object_set(session_traffic, "downstream-ipv6pd-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "downstream-ipv6pd-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv6pd-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv6pd-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "downstream-ipv6pd-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "downstream-ipv6pd-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "downstream-ipv6pd-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv6pd-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "downstream-ipv6pd-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "downstream-ipv6pd-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
if(session->session_traffic.ipv6pd_up) {
stream = session->session_traffic.ipv6pd_up;
json_object_set(session_traffic, "upstream-ipv6pd-flow-id", json_integer(stream->flow_id));
json_object_set(session_traffic, "upstream-ipv6pd-tx-packets", json_integer(stream->packets_tx - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv6pd-rx-packets", json_integer(stream->packets_rx - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv6pd-tx-packets", json_integer(stream->tx_packets - stream->reset_packets_tx));
json_object_set(session_traffic, "upstream-ipv6pd-rx-packets", json_integer(stream->rx_packets - stream->reset_packets_rx));
json_object_set(session_traffic, "upstream-ipv6pd-rx-first-seq", json_integer(stream->rx_first_seq));
json_object_set(session_traffic, "upstream-ipv6pd-loss", json_integer(stream->loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv6pd-wrong-session", json_integer(stream->wrong_session - stream->reset_wrong_session));
json_object_set(session_traffic, "upstream-ipv6pd-loss", json_integer(stream->rx_loss - stream->reset_loss));
json_object_set(session_traffic, "upstream-ipv6pd-wrong-session", json_integer(stream->rx_wrong_session - stream->reset_wrong_session));
}
}
if(session->a10nsp_session) {
+27 -19
View File
@@ -351,11 +351,11 @@ bbl_stats_generate(bbl_stats_s * stats)
stream = (bbl_stream_s*)*dict_itor_datum(itor);
if(stream) {
if(stats->min_stream_loss) {
if(stream->loss < stats->min_stream_loss) stats->min_stream_loss = stream->loss;
if(stream->rx_loss < stats->min_stream_loss) stats->min_stream_loss = stream->rx_loss;
} else {
stats->min_stream_loss = stream->loss;
stats->min_stream_loss = stream->rx_loss;
}
if(stream->loss > stats->max_stream_loss) stats->max_stream_loss = stream->loss;
if(stream->rx_loss > stats->max_stream_loss) stats->max_stream_loss = stream->rx_loss;
if(stream->rx_first_seq) {
if(stats->min_stream_rx_first_seq) {
@@ -366,11 +366,11 @@ bbl_stats_generate(bbl_stats_s * stats)
if(stream->rx_first_seq > stats->max_stream_rx_first_seq) stats->max_stream_rx_first_seq = stream->rx_first_seq;
if(stats->min_stream_delay_ns) {
if(stream->min_delay_ns < stats->min_stream_delay_ns) stats->min_stream_delay_ns = stream->min_delay_ns;
if(stream->rx_min_delay_ns < stats->min_stream_delay_ns) stats->min_stream_delay_ns = stream->rx_min_delay_ns;
} else {
stats->min_stream_delay_ns = stream->min_delay_ns;
stats->min_stream_delay_ns = stream->rx_min_delay_ns;
}
if(stream->max_delay_ns > stats->max_stream_delay_ns) stats->max_stream_delay_ns = stream->max_delay_ns;
if(stream->rx_max_delay_ns > stats->max_stream_delay_ns) stats->max_stream_delay_ns = stream->rx_max_delay_ns;
}
}
}
@@ -425,21 +425,29 @@ bbl_stats_stdout(bbl_stats_s *stats) {
access_interface = interface->access;
a10nsp_interface = interface->a10nsp;
bbl_stats_generate_interface(interface->io.tx, &interface_stats_tx);
bbl_stats_generate_interface(interface->io.rx, &interface_stats_rx);
printf("\nInterface: %s", interface->name);
if(interface->type == LAG_INTERFACE) {
printf(" (LAG)");
} else if(interface->type == LAG_MEMBER_INTERFACE) {
printf(" (%s)", interface->lag->interface->name);
}
printf("\n--------------------------------------------------------------\n");
printf(" TX: %10lu packets %16lu bytes\n",
interface_stats_tx.packets, interface_stats_tx.bytes);
printf(" TX Polled: %10lu\n", interface_stats_tx.polled);
printf(" TX IO Error: %10lu\n", interface_stats_tx.io_errors);
printf(" RX: %10lu packets %16lu bytes\n",
interface_stats_rx.packets, interface_stats_rx.bytes);
printf(" RX Protocol Error: %10lu packets\n", interface_stats_rx.protocol_errors);
printf(" RX Unknown: %10lu packets\n", interface_stats_rx.unknown);
printf(" RX Polled: %10lu\n", interface_stats_rx.polled);
printf(" RX IO Error: %10lu\n", interface_stats_rx.io_errors);
if(interface->type != LAG_INTERFACE) {
bbl_stats_generate_interface(interface->io.tx, &interface_stats_tx);
bbl_stats_generate_interface(interface->io.rx, &interface_stats_rx);
printf(" TX: %10lu packets %16lu bytes\n",
interface_stats_tx.packets, interface_stats_tx.bytes);
printf(" TX Polled: %10lu\n", interface_stats_tx.polled);
printf(" TX IO Error: %10lu\n", interface_stats_tx.io_errors);
printf(" RX: %10lu packets %16lu bytes\n",
interface_stats_rx.packets, interface_stats_rx.bytes);
printf(" RX Protocol Error: %10lu packets\n", interface_stats_rx.protocol_errors);
printf(" RX Unknown: %10lu packets\n", interface_stats_rx.unknown);
printf(" RX Polled: %10lu\n", interface_stats_rx.polled);
printf(" RX IO Error: %10lu\n", interface_stats_rx.io_errors);
}
while(network_interface) {
printf("\nNetwork Interface: %s\n", network_interface->name);
+124 -125
View File
@@ -28,15 +28,15 @@ bbl_stream_delay(bbl_stream_s *stream, struct timespec *rx_timestamp, struct tim
uint64_t delay_nsec;
timespec_sub(&delay, rx_timestamp, bbl_timestamp);
delay_nsec = delay.tv_sec * 1000000000 + delay.tv_nsec;
if(delay_nsec > stream->max_delay_ns) {
stream->max_delay_ns = delay_nsec;
if(delay_nsec > stream->rx_max_delay_ns) {
stream->rx_max_delay_ns = delay_nsec;
}
if(stream->min_delay_ns) {
if(delay_nsec < stream->min_delay_ns) {
stream->min_delay_ns = delay_nsec;
if(stream->rx_min_delay_ns) {
if(delay_nsec < stream->rx_min_delay_ns) {
stream->rx_min_delay_ns = delay_nsec;
}
} else {
stream->min_delay_ns = delay_nsec;
stream->rx_min_delay_ns = delay_nsec;
}
}
@@ -925,101 +925,97 @@ bbl_stream_rx_stats(bbl_stream_s *stream, uint64_t packets, uint64_t bytes, uint
bbl_network_interface_s *network_interface;
bbl_a10nsp_interface_s *a10nsp_interface;
if(stream->direction == BBL_DIRECTION_DOWN) {
access_interface = stream->access_interface;
if(stream->rx_access_interface) {
access_interface = stream->rx_access_interface;
access_interface->stats.packets_rx += packets;
access_interface->stats.bytes_rx += bytes;
access_interface->stats.stream_rx += packets;
access_interface->stats.stream_loss += loss;
session = stream->session;
if(access_interface) {
access_interface->stats.packets_rx += packets;
access_interface->stats.bytes_rx += bytes;
access_interface->stats.stream_rx += packets;
access_interface->stats.stream_loss += loss;
if(session) {
session->stats.packets_rx += packets;
session->stats.bytes_rx += bytes;
session->stats.accounting_packets_rx += packets;
session->stats.accounting_bytes_rx += bytes;
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
access_interface->stats.session_ipv4_rx += packets;
access_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
access_interface->stats.session_ipv6_rx += packets;
access_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
access_interface->stats.session_ipv6pd_rx += packets;
access_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
if(session) {
session->stats.packets_rx += packets;
session->stats.bytes_rx += bytes;
session->stats.accounting_packets_rx += packets;
session->stats.accounting_bytes_rx += bytes;
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
access_interface->stats.session_ipv4_rx += packets;
access_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
access_interface->stats.session_ipv6_rx += packets;
access_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
access_interface->stats.session_ipv6pd_rx += packets;
access_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
}
}
} else {
if(stream->network_interface) {
network_interface = stream->network_interface;
network_interface->stats.packets_rx += packets;
network_interface->stats.bytes_rx += bytes;
network_interface->stats.stream_rx += packets;
network_interface->stats.stream_loss += loss;
if(session) {
if(session->l2tp_session) {
network_interface->stats.l2tp_data_rx += packets;
session->l2tp_session->tunnel->stats.data_rx += packets;
session->l2tp_session->stats.data_rx += packets;
if(stream->type == BBL_SUB_TYPE_IPV4) {
session->l2tp_session->stats.data_ipv4_rx += packets;
}
}
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
network_interface->stats.session_ipv4_rx += packets;
network_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
network_interface->stats.session_ipv6_rx += packets;
network_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
network_interface->stats.session_ipv6pd_rx += packets;
network_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
} else if(stream->rx_network_interface) {
network_interface = stream->rx_network_interface;
network_interface->stats.packets_rx += packets;
network_interface->stats.bytes_rx += bytes;
network_interface->stats.stream_rx += packets;
network_interface->stats.stream_loss += loss;
if(session) {
if(session->l2tp_session) {
network_interface->stats.l2tp_data_rx += packets;
session->l2tp_session->tunnel->stats.data_rx += packets;
session->l2tp_session->stats.data_rx += packets;
if(stream->type == BBL_SUB_TYPE_IPV4) {
session->l2tp_session->stats.data_ipv4_rx += packets;
}
}
} else if(stream->a10nsp_interface) {
a10nsp_interface = stream->a10nsp_interface;
a10nsp_interface->stats.packets_rx += packets;
a10nsp_interface->stats.bytes_rx += bytes;
a10nsp_interface->stats.stream_rx += packets;
a10nsp_interface->stats.stream_loss += loss;
if(session) {
if(session->a10nsp_session) {
session->a10nsp_session->stats.packets_rx += packets;
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
network_interface->stats.session_ipv4_rx += packets;
network_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
network_interface->stats.session_ipv6_rx += packets;
network_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
network_interface->stats.session_ipv6pd_rx += packets;
network_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
a10nsp_interface->stats.session_ipv4_rx += packets;
a10nsp_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
a10nsp_interface->stats.session_ipv6_rx += packets;
a10nsp_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
a10nsp_interface->stats.session_ipv6pd_rx += packets;
a10nsp_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
}
}
} else if(stream->rx_a10nsp_interface) {
a10nsp_interface = stream->rx_a10nsp_interface;
a10nsp_interface->stats.packets_rx += packets;
a10nsp_interface->stats.bytes_rx += bytes;
a10nsp_interface->stats.stream_rx += packets;
a10nsp_interface->stats.stream_loss += loss;
if(session) {
if(session->a10nsp_session) {
session->a10nsp_session->stats.packets_rx += packets;
}
if(stream->session_traffic) {
switch(stream->sub_type) {
case BBL_SUB_TYPE_IPV4:
a10nsp_interface->stats.session_ipv4_rx += packets;
a10nsp_interface->stats.session_ipv4_loss += loss;
break;
case BBL_SUB_TYPE_IPV6:
a10nsp_interface->stats.session_ipv6_rx += packets;
a10nsp_interface->stats.session_ipv6_loss += loss;
break;
case BBL_SUB_TYPE_IPV6PD:
a10nsp_interface->stats.session_ipv6pd_rx += packets;
a10nsp_interface->stats.session_ipv6pd_loss += loss;
break;
default:
break;
}
}
}
@@ -1032,7 +1028,7 @@ bbl_stream_rx_wrong_session(bbl_stream_s *stream)
uint64_t packets;
uint64_t packets_delta;
packets = stream->wrong_session;
packets = stream->rx_wrong_session;
packets_delta = packets - stream->last_sync_wrong_session;
stream->last_sync_wrong_session = packets;
@@ -1064,18 +1060,18 @@ bbl_stream_ctrl(bbl_stream_s *stream)
uint64_t loss_delta;
/* Calculate TX packets/bytes since last sync. */
packets = stream->packets_tx;
packets = stream->tx_packets;
packets_delta = packets - stream->last_sync_packets_tx;
bytes_delta = packets_delta * stream->tx_len;
stream->last_sync_packets_tx = packets;
bbl_stream_tx_stats(stream, packets_delta, bytes_delta);
if(g_ctx->config.stream_rate_calc) {
bbl_compute_avg_rate(&stream->rate_packets_tx, stream->packets_tx);
bbl_compute_avg_rate(&stream->rate_packets_tx, stream->tx_packets);
}
if(stream->type == BBL_TYPE_MULTICAST) {
return;
}
if(unlikely(stream->wrong_session)) {
if(unlikely(stream->rx_wrong_session)) {
bbl_stream_rx_wrong_session(stream);
}
if(unlikely(!stream->verified)) {
@@ -1107,17 +1103,17 @@ bbl_stream_ctrl(bbl_stream_s *stream)
}
/* Calculate RX packets/bytes since last sync. */
packets = stream->packets_rx;
packets = stream->rx_packets;
packets_delta = packets - stream->last_sync_packets_rx;
bytes_delta = packets_delta * stream->rx_len;
stream->last_sync_packets_rx = packets;
/* Calculate RX loss since last sync. */
packets = stream->loss;
packets = stream->rx_loss;
loss_delta = packets - stream->last_sync_loss;
stream->last_sync_loss = packets;
bbl_stream_rx_stats(stream, packets_delta, bytes_delta, loss_delta);
if(g_ctx->config.stream_rate_calc) {
bbl_compute_avg_rate(&stream->rate_packets_rx, stream->packets_rx);
bbl_compute_avg_rate(&stream->rate_packets_rx, stream->rx_packets);
}
}
@@ -1179,7 +1175,7 @@ bbl_stream_send_window(bbl_stream_s *stream, struct timespec *now) {
struct timespec time_elapsed = {0};
/** Enforce optional stream traffic start delay ... */
if(stream->config->start_delay && stream->packets_tx == 0) {
if(stream->config->start_delay && stream->tx_packets == 0) {
if(stream->wait) {
timespec_sub(&time_elapsed, now, &stream->wait_start);
if(time_elapsed.tv_sec < stream->config->start_delay) {
@@ -1216,9 +1212,9 @@ bbl_stream_send_window(bbl_stream_s *stream, struct timespec *now) {
/** Enforce optional stream packet limit ... */
if(stream->config->max_packets &&
stream->packets_tx + packets > stream->config->max_packets) {
if(stream->packets_tx < stream->config->max_packets) {
packets = stream->config->max_packets - stream->packets_tx;
stream->tx_packets + packets > stream->config->max_packets) {
if(stream->tx_packets < stream->config->max_packets) {
packets = stream->config->max_packets - stream->tx_packets;
} else {
packets = 0;
}
@@ -1278,8 +1274,8 @@ bbl_stream_tx(bbl_stream_s *stream)
return false;
}
stream->send_window_packets++;
stream->packets_tx++;
stream->flow_seq++;
stream->tx_packets++;
packets--;
send++;
}
@@ -1297,9 +1293,12 @@ bbl_stream_lag_tx_job(timer_s *timer)
{
bbl_stream_s *stream = timer->data;
bbl_lag_s *lag = stream->tx_interface->lag;
uint8_t key = stream->flow_id % lag->active_count;
stream->io = lag->active_list[key]->interface->io.tx;
bbl_stream_tx(stream);
uint8_t key = 0;
if(lag->active_count) {
key = stream->flow_id % lag->active_count;
stream->io = lag->active_list[key]->interface->io.tx;
bbl_stream_tx(stream);
}
}
void
@@ -1829,13 +1828,13 @@ bbl_stream_reset(bbl_stream_s *stream)
stream->reset = true;
stream->reset_packets_tx = stream->packets_tx;
stream->reset_packets_rx = stream->packets_rx;
stream->reset_loss = stream->loss;
stream->reset_wrong_session = stream->wrong_session;
stream->reset_packets_tx = stream->tx_packets;
stream->reset_packets_rx = stream->rx_packets;
stream->reset_loss = stream->rx_loss;
stream->reset_wrong_session = stream->rx_wrong_session;
stream->min_delay_ns = 0;
stream->max_delay_ns = 0;
stream->rx_min_delay_ns = 0;
stream->rx_max_delay_ns = 0;
stream->rx_len = 0;
stream->rx_first_seq = 0;
stream->rx_last_seq = 0;
@@ -1894,7 +1893,7 @@ bbl_stream_rx(bbl_ethernet_header_s *eth, bbl_session_s *session)
/* Stream already verified */
if((stream->rx_last_seq +1) < bbl->flow_seq) {
loss = bbl->flow_seq - (stream->rx_last_seq +1);
stream->loss += loss;
stream->rx_loss += loss;
if(session) {
LOG(LOSS, "LOSS (ID: %u) Unicast flow: %lu seq: %lu last: %lu\n",
session->session_id, bbl->flow_id, bbl->flow_seq, stream->rx_last_seq);
@@ -1946,13 +1945,13 @@ bbl_stream_rx(bbl_ethernet_header_s *eth, bbl_session_s *session)
if(bbl->outer_vlan_id != session->vlan_key.outer_vlan_id ||
bbl->inner_vlan_id != session->vlan_key.inner_vlan_id ||
bbl->session_id != session->session_id) {
stream->wrong_session++;
stream->rx_wrong_session++;
return NULL;
}
}
stream->rx_first_seq = bbl->flow_seq;
}
stream->packets_rx++;
stream->rx_packets++;
stream->rx_last_seq = bbl->flow_seq;
bbl_stream_delay(stream, &eth->timestamp, &bbl->timestamp);
return stream;
@@ -2001,12 +2000,12 @@ bbl_stream_json(bbl_stream_s *stream)
"rx-inner-vlan-pbit", stream->rx_inner_vlan_pbit,
"rx-len", stream->rx_len,
"tx-len", stream->tx_len,
"tx-packets", stream->packets_tx - stream->reset_packets_tx,
"rx-packets", stream->packets_rx - stream->reset_packets_rx,
"rx-loss", stream->loss - stream->reset_loss,
"rx-wrong-session", stream->wrong_session - stream->reset_wrong_session,
"rx-delay-nsec-min", stream->min_delay_ns,
"rx-delay-nsec-max", stream->max_delay_ns,
"tx-packets", stream->tx_packets - stream->reset_packets_tx,
"rx-packets", stream->rx_packets - stream->reset_packets_rx,
"rx-loss", stream->rx_loss - stream->reset_loss,
"rx-wrong-session", stream->rx_wrong_session - stream->reset_wrong_session,
"rx-delay-nsec-min", stream->rx_min_delay_ns,
"rx-delay-nsec-max", stream->rx_max_delay_ns,
"rx-pps", stream->rate_packets_rx.avg,
"tx-pps", stream->rate_packets_tx.avg,
"tx-bps-l2", stream->rate_packets_tx.avg * stream->tx_len * 8,
@@ -2045,7 +2044,7 @@ bbl_stream_json(bbl_stream_s *stream)
"network-interface", network_interface_name,
"flow-id", stream->flow_id,
"tx-len", stream->tx_len,
"tx-packets", stream->packets_tx - stream->reset_packets_tx,
"tx-packets", stream->tx_packets - stream->reset_packets_tx,
"tx-pps", stream->rate_packets_tx.avg,
"tx-bps-l2", stream->rate_packets_tx.avg * stream->tx_len * 8,
"tx-mbps-l2", (double)(stream->rate_packets_tx.avg * stream->tx_len * 8) / 1000000.0);
+11 -6
View File
@@ -107,16 +107,17 @@ typedef struct bbl_stream_
struct timespec wait_start;
struct timespec send_window_start;
uint64_t send_window_packets;
uint64_t packets_tx;
uint64_t tx_packets;
char _pad0 __attribute__((__aligned__(CACHE_LINE_SIZE))); /* empty cache line */
uint64_t packets_rx;
uint64_t loss;
uint64_t wrong_session;
uint64_t rx_packets;
uint64_t rx_loss;
uint64_t rx_wrong_session;
uint64_t min_delay_ns;
uint64_t max_delay_ns;
uint64_t rx_min_delay_ns;
uint64_t rx_max_delay_ns;
uint16_t rx_len;
uint64_t rx_first_seq;
@@ -136,6 +137,10 @@ typedef struct bbl_stream_
uint8_t rx_mpls2_ttl;
uint32_t rx_mpls2_label;
bbl_access_interface_s *rx_access_interface;
bbl_network_interface_s *rx_network_interface;
bbl_a10nsp_interface_s *rx_a10nsp_interface;
char _pad1 __attribute__((__aligned__(CACHE_LINE_SIZE))); /* empty cache line */
uint64_t last_sync_packets_tx;