Added TCP Packets issues check (#6899)

This commit is contained in:
MatteoBiscosi 2022-11-16 11:28:16 +01:00
parent 45dcb77182
commit b6692f3fea
15 changed files with 726 additions and 2 deletions

View file

@ -0,0 +1,63 @@
--
-- (C) 2019-22 - ntop.org
--
-- ##############################################
local flow_alert_keys = require "flow_alert_keys"
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
local alert = require "alert"
-- ##############################################
local alert_tcp_packets_issues = classes.class(alert)
-- ##############################################
alert_tcp_packets_issues.meta = {
alert_key = flow_alert_keys.flow_alert_tcp_packets_issues,
i18n_title = "flow_checks_config.tcp_packets_issues",
icon = "fas fa-fw fa-exclamation",
}
-- ##############################################
-- @brief Prepare an alert table used to generate the alert
-- @param tcp_stats A lua table with TCP stats obtained with flow.getTCPStats
-- @param cli2srv_pkts Number of packets sent from the client to the server
-- @param srv2cli_pkts Number of packets sent from the server to the client
-- @param is_severe A boolean indicating whether connection issues are severe
-- @param client_issues A boolean indicating if the client has connection issues
-- @param server_issues A boolean indicating if the server has connection issues
-- @return A table with the alert built
function alert_tcp_packets_issues:init()
-- Call the parent constructor
self.super:init()
end
-- #######################################################
-- @brief Format an alert into a human-readable string
-- @param ifid The integer interface id of the generated alert
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_tcp_packets_issues.format(ifid, alert, alert_type_params)
local msg = ''
tprint(alert_type_params)
if alert_type_params.lost > alert_type_params.lost_threshold then
msg = i18n("flow_checks_config.tcp_packets_issues_alert", { type = 'loss', value = alert_type_params.lost, threshold = alert_type_params.lost_threshold })
elseif alert_type_params.retransmission > alert_type_params.retransmission_threshold then
msg = i18n("flow_checks_config.tcp_packets_issues_alert", { type = 'retransmission', value = alert_type_params.retransmission, threshold = alert_type_params.retransmission_threshold })
elseif alert_type_params.out_of_order > alert_type_params.out_of_order_threshold then
msg = i18n("flow_checks_config.tcp_packets_issues_alert", { type = 'out of order', value = alert_type_params.out_of_order, threshold = alert_type_params.out_of_order_threshold })
end
return msg
end
-- #######################################################
return alert_tcp_packets_issues

View file

@ -0,0 +1,57 @@
--
-- (C) 2019-22 - ntop.org
--
local checks = require ("checks")
local alerts_api = require "alerts_api"
local alert_consts = require("alert_consts")
local flow_alert_keys = require "flow_alert_keys"
-- #################################################################
-- NOTE: this module is always enabled
local script = {
-- Script category
category = checks.check_categories.network,
enabled = false,
-- This script is only for alerts generation
alert_id = flow_alert_keys.flow_alert_tcp_packets_issues,
default_value = {
retransmissions = {
default_value = 15, -- 15%,
field_min = 0, -- 0%
field_max = 99, -- 99%
field_operator = "gt";
i18n_fields_unit = checks.field_units.percentage,
title = i18n('retransmission')
},
out_of_orders = {
default_value = 15, -- 15%,
field_min = 0, -- 0%
field_max = 99, -- 99%
field_operator = "gt";
i18n_fields_unit = checks.field_units.percentage,
title = i18n('out_of_order')
},
packet_loss = {
default_value = 15, -- 15%,
field_min = 0, -- 0%
field_max = 99, -- 99%
field_operator = "gt";
i18n_fields_unit = checks.field_units.percentage,
title = i18n('packet_loss')
},
},
gui = {
i18n_title = "flow_checks_config.tcp_packets_issues",
i18n_description = "flow_checks_config.tcp_packets_issues_description",
input_builder = "multi_threshold_cross",
}
}
-- #################################################################
return script

View file

@ -0,0 +1,54 @@
--
-- (C) 2019-22 - ntop.org
--
-- ##############################################
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
package.path = dirs.installdir .. "/scripts/lua/modules/check_templates/?.lua;" .. package.path
-- Import the classes library.
local classes = require "classes"
-- Make sure to import the Superclass!
local check_template = require "check_template"
-- ##############################################
local multi_threshold_cross = classes.class(check_template)
-- ##############################################
multi_threshold_cross.meta = {
}
-- ##############################################
-- @brief Prepare an instance of the template
-- @return A table with the template built
function multi_threshold_cross:init(check)
-- Call the parent constructor
self.super:init(check)
end
-- #######################################################
function multi_threshold_cross:parseConfig(conf)
return true, conf
end
-- #######################################################
function multi_threshold_cross:describeConfig(hooks_conf)
local configured_threshold = hooks_conf.all.script_conf
local msg = ''
for field, value in pairs(configured_threshold) do
msg = msg .. i18n(field) .. ": " .. value.threshold .. "%, "
end
return msg
end
-- #######################################################
return multi_threshold_cross

View file

@ -0,0 +1,65 @@
{#
(C) 2020 - ntop.org
Template for the Checks using the 'Threshold Cross' GUI.
Defined fields:
* hook_name: contains the name for the current rendered hook
* hook_conf: contains the configuration for the current rendered hook
* user_script: contains data about the loaded user script
#}
{%
local field_unit = i18n(user_script.gui.i18n_field_unit)
local default_operator_not_defined = isEmptyString(user_script.default_value.operator)
%}
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">{{ i18n("enabled") }}</label>
<div class="col-2">
<div class="custom-control custom-switch">
<input id="enabled-{{ hook_name }}" name="enabled" class="custom-control-input" type="checkbox" {{ (hook_conf.enabled and 'checked' or '') }}>
<label class="custom-control-label" for="enabled-{{ hook_name }}"></label>
</div>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-2 col-form-label">{{ i18n("edit_user_script.hooks_name." .. hook_name) or hook_name }}</label>
<div class="col-2">
<div class="input-group">
<div class="input-group-prepend">
{% if default_operator_not_defined then %}
<select name="operator" required class="btn btn-outline-secondary" {{ (hook_conf.enabled and '' or 'disabled') }}>
<option value="gt" {{ (hook_conf.script_conf.operator == 'gt' and 'selected' or '') }} >&gt;</option>
<option value="lt" {{ (hook_conf.script_conf.operator == 'lt' and 'selected' or '') }} >&lt;</option>
</select>
{% else %}
<span class='input-group-text'>&{{ (user_script.default_value.operator) }}</span>
<input name="operator" hidden value="{{ user_script.default_value.operator }}">
{% end %}
</div>
<input type="number" class="form-control text-right" required {{ (hook_conf.enabled and '' or 'disabled') }} value="{{ hook_conf.script_conf.threshold }}" name="threshold">
<span class="mt-auto mb-auto ms-2 me-2">{{ field_unit }}</span>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
const $thresholdInput = $(`input[name='threshold']`);
const $operatorSelect = $(`select[name='operator']`);
// Notice: the registerResetCallback must be called inside the document ready!
registerResetCallback('{{ hook_name }}', function(hookName, hook, resetData) {
const scriptConf = hook.script_conf;
NtopUtils.fillFieldIfValid($thresholdInput, scriptConf.threshold);
NtopUtils.fillFieldIfValid($operatorSelect, scriptConf.operator);
});
});
</script>