diff --git a/include/Ntop.h b/include/Ntop.h
index 56ff1a3055..efe332385f 100644
--- a/include/Ntop.h
+++ b/include/Ntop.h
@@ -355,6 +355,7 @@ class Ntop {
inline NagiosManager* getNagios() { return(nagios_manager); };
#endif
#endif
+ void checkSNMPDeviceAlerts(ScriptPeriodicity p);
void lua_periodic_activities_stats(NetworkInterface *iface, lua_State* vm);
void getUsers(lua_State* vm);
bool isUserAdministrator(lua_State* vm);
diff --git a/scripts/callbacks/alert_defs/alert_port_load_threshold_exceeded.lua b/scripts/callbacks/alert_defs/alert_port_load_threshold_exceeded.lua
index bb61f228e6..a27d0b1b25 100644
--- a/scripts/callbacks/alert_defs/alert_port_load_threshold_exceeded.lua
+++ b/scripts/callbacks/alert_defs/alert_port_load_threshold_exceeded.lua
@@ -5,13 +5,17 @@
local function snmpPortLoadThresholdFormatter(ifid, alert, info)
if ntop.isPro() then require "snmp_utils" end
- return(i18n("alerts_dashboard.snmp_port_load_threshold_exceeded_message",
- {device = info.device,
+ local fmt = {
+ device = info.device,
port = info.interface_name or info.interface,
url = snmpDeviceUrl(info.device),
port_url = snmpIfaceUrl(info.device, info.interface),
- port_load = info.interface_load,
- direction = ternary(info.interface_load, "RX", "TX")}))
+ in_load = info.in_load,
+ out_load = info.out_load,
+ threshold = info.load_threshold,
+ }
+
+ return(i18n("alerts_dashboard.snmp_port_load_threshold_exceeded_message", fmt))
end
-- #######################################################
diff --git a/scripts/callbacks/system/snmp_device.lua b/scripts/callbacks/system/snmp_device.lua
new file mode 100644
index 0000000000..43f8956754
--- /dev/null
+++ b/scripts/callbacks/system/snmp_device.lua
@@ -0,0 +1,100 @@
+--
+-- (C) 2019 - ntop.org
+--
+
+local dirs = ntop.getDirs()
+package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
+require "lua_utils"
+require "alert_utils"
+require "snmp_utils"
+
+local alerts_api = require("alerts_api")
+local user_scripts = require("user_scripts")
+local alert_consts = require("alert_consts")
+
+local do_benchmark = true -- Compute benchmarks and store their results
+local do_print_benchmark = false -- Print benchmarks results to standard output
+local do_trace = false -- Trace lua calls
+
+local config_alerts = nil
+local available_modules = nil
+local ifid = nil
+local snmp_device_entity = alert_consts.alert_entities.snmp_device.entity_id
+
+-- The function below ia called once (#pragma once)
+function setup(str_granularity)
+ if do_trace then print("alert.lua:setup("..str_granularity..") called\n") end
+
+ interface.select(getSystemInterfaceId())
+ ifid = interface.getId()
+ local ifname = getInterfaceName(tostring(ifid))
+
+ -- Load the threshold checking functions
+ available_modules = user_scripts.load(user_scripts.script_types.snmp_device, ifid, "snmp_device", nil --[[ load all hooks --]], nil, do_benchmark)
+
+ -- config_alerts = getNetworksConfiguredAlertThresholds(ifname, str_granularity, available_modules.modules)
+end
+
+-- #################################################################
+
+-- The function below ia called once (#pragma once)
+function teardown(str_granularity)
+ if(do_trace) then print("alert.lua:teardown("..str_granularity..") called\n") end
+
+ user_scripts.teardown(available_modules, do_benchmark, do_print_benchmark)
+end
+
+-- #################################################################
+
+local cur_granularity
+
+local function snmp_device_interfaces_check_alerts(snmp_device, deadline)
+ local do_call = true
+ local granularity = cur_granularity
+
+ local device_ip = snmp_device.get_device_info()["host"]
+ local device_interfaces = snmp_device.get_device()["interfaces"] or {}
+ local device_if_status = snmp_device.get_device()["interfaces_status"] or {}
+ local device_counters = snmp_device.get_device()["counters"] or {}
+ local device_bridge = snmp_device.get_device()["bridge"] or {}
+
+ -- For each callback that needs to be called on the interfaces...
+ for mod_key, hook_fn in pairs(available_modules.hooks["snmpDeviceInterface"]) do
+ local check = available_modules.modules[mod_key]
+
+ -- For each interface of the current device...
+ for snmp_interface_index, snmp_interface in pairs(device_interfaces) do
+ local entity_info = alerts_api.snmpInterfaceEntity(device_ip, snmp_interface_index)
+ local info = {
+ snmp_device_ip = device_ip,
+ snmp_interface = snmp_interface,
+ if_status = device_if_status[snmp_interface_index],
+ if_counters = device_counters[snmp_interface_index],
+ if_bridge = device_bridge[snmp_interface_index]}
+
+ if(do_call) then
+ hook_fn({
+ granularity = granularity,
+ alert_entity = entity_info,
+ entity_info = info,
+ cur_alerts = cur_alerts,
+ alert_config = config,
+ user_script = check,
+ })
+ end
+ end
+ end
+
+ return true
+end
+
+-- #################################################################
+
+-- The function below is called once per local snmp_device
+function checkAlerts(granularity)
+ cur_granularity = granularity
+
+ if not table.empty(available_modules.hooks["snmpDeviceInterface"]) then
+ local in_time = foreachSNMPDevice(snmp_device_interfaces_check_alerts, nil --[[ snmp_rrds_enabled --]], nil --[[ deadline --]])
+ end
+end
diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua
index b3f5e69784..d6b2ecc81f 100644
--- a/scripts/locales/en.lua
+++ b/scripts/locales/en.lua
@@ -381,7 +381,7 @@ local lang = {
["snmp_port_errors"] = "Interface Errors",
["snmp_port_errors_increased"] = "Discard/error counters increased on interface %{port} on SNMP device %{device}",
["snmp_port_load_threshold_exceeded"] = "Interface Load Threshold Exceeded",
- ["snmp_port_load_threshold_exceeded_message"] = "%{direction} load is %{port_load}%% on interface %{port} on SNMP device %{device}",
+ ["snmp_port_load_threshold_exceeded_message"] = "Load threshold exceeded on interface %{port} on SNMP device %{device} [threshold: %{threshold}%%][IN load: %{in_load}%%][OUT load: %{out_load}%%]",
["snmp_port_status_change"] = "Interface Status Change",
["starting_on"] = "starting on",
["submit"] = "Update Dashboard",
diff --git a/scripts/lua/modules/alert_utils.lua b/scripts/lua/modules/alert_utils.lua
index 516fd4e090..18657835d0 100644
--- a/scripts/lua/modules/alert_utils.lua
+++ b/scripts/lua/modules/alert_utils.lua
@@ -2873,39 +2873,6 @@ local function notify_ntopng_status(started)
return(alerts_api.store(entity_info, type_info))
end
-function notify_snmp_device_interface_status_change(snmp_host, snmp_interface)
- local entity_info = alerts_api.snmpInterfaceEntity(snmp_host, snmp_interface["index"])
- local type_info = alerts_api.snmpInterfaceStatusChangeType(snmp_host, snmp_interface["index"], snmp_interface["name"], snmp_interface["status"])
-
- interface.select(getSystemInterfaceId())
- return(alerts_api.store(entity_info, type_info))
-end
-
-function notify_snmp_device_interface_duplexstatus_change(snmp_host, snmp_interface)
- local entity_info = alerts_api.snmpInterfaceEntity(snmp_host, snmp_interface["index"])
- local type_info = alerts_api.snmpInterfaceDuplexStatusChangeType(snmp_host, snmp_interface["index"], snmp_interface["name"], snmp_interface["duplexstatus"])
-
- interface.select(getSystemInterfaceId())
- return(alerts_api.store(entity_info, type_info))
-end
-
-function notify_snmp_device_interface_errors(snmp_host, snmp_interface)
- local entity_info = alerts_api.snmpInterfaceEntity(snmp_host, snmp_interface["index"])
- local type_info = alerts_api.snmpInterfaceErrorsType(snmp_host, snmp_interface["index"], snmp_interface["name"])
-
- interface.select(getSystemInterfaceId())
- return(alerts_api.store(entity_info, type_info))
-end
-
-function notify_snmp_device_interface_load_threshold_exceeded(snmp_host, snmp_interface, interface_load, in_direction)
- local entity_info = alerts_api.snmpInterfaceEntity(snmp_host, snmp_interface["index"])
- local type_info = alerts_api.snmpPortLoadThresholdExceededType(snmp_host, snmp_interface["index"], snmp_interface["name"],
- interface_load, in_direction)
-
- interface.select(getSystemInterfaceId())
- return(alerts_api.store(entity_info, type_info))
-end
-
function notify_ntopng_start()
return(notify_ntopng_status(true))
end
diff --git a/scripts/lua/modules/alerts_api.lua b/scripts/lua/modules/alerts_api.lua
index 6dde6dedbd..dc1716ca41 100644
--- a/scripts/lua/modules/alerts_api.lua
+++ b/scripts/lua/modules/alerts_api.lua
@@ -763,55 +763,92 @@ end
-- ##############################################
-function alerts_api.snmpInterfaceStatusChangeType(device, interface, interface_name, status)
- return({
- alert_type = alert_consts.alert_types.alert_port_status_change,
- alert_severity = alert_consts.alert_severities.info,
- alert_type_params = {
- device = device, interface = interface,
- interface_name = interface_name, status = status,
- },
- })
+function alerts_api.snmpInterfaceStatusChangeType(snmp_interface_info, device, interface, interface_name, status)
+ local snmp_interface_index = snmp_interface_info["snmp_interface"]["index"]
+ local snmp_interface_name = snmp_interface_info["snmp_interface"]["name"]
+ local snmp_interface_status = snmp_interface_info["if_status"]["status"]
+ local snmp_device_ip = snmp_interface_info["snmp_device_ip"]
+
+ local res = {
+ alert_type = alert_consts.alert_types.alert_port_status_change,
+ alert_severity = alert_consts.alert_severities.info,
+ alert_type_params = {
+ device = snmp_device_ip,
+ interface = snmp_interface_index,
+ interface_name = snmp_interface_name,
+ status = snmp_interface_status,
+ },
+ }
+
+ return res
end
-- ##############################################
-function alerts_api.snmpInterfaceDuplexStatusChangeType(device, interface, interface_name, status)
- return({
- alert_type = alert_consts.alert_types.alert_port_duplexstatus_change,
- alert_severity = alert_consts.alert_severities.warning,
- alert_type_params = {
- device = device, interface = interface,
- interface_name = interface_name, status = status,
- },
- })
+function alerts_api.snmpInterfaceDuplexStatusChangeType(snmp_interface_info)
+ local snmp_interface_index = snmp_interface_info["snmp_interface"]["index"]
+ local snmp_interface_name = snmp_interface_info["snmp_interface"]["name"]
+ local snmp_interface_duplexstatus = snmp_interface_info["if_status"]["duplexstatus"]
+ local snmp_device_ip = snmp_interface_info["snmp_device_ip"]
+
+ local res = {
+ alert_type = alert_consts.alert_types.alert_port_duplexstatus_change,
+ alert_severity = alert_consts.alert_severities.warning,
+ alert_type_params = {
+ device = snmp_device_ip,
+ interface = snmp_interface_index,
+ interface_name = snmp_interface_name,
+ status = snmp_interface_duplexstatus,
+ },
+ }
+
+ return res
end
-- ##############################################
-function alerts_api.snmpInterfaceErrorsType(device, interface, interface_name)
- return({
- alert_type = alert_consts.alert_types.alert_port_errors,
- alert_severity = alert_consts.alert_severities.info,
- alert_type_params = {
- device = device, interface = interface,
- interface_name = interface_name,
- },
- })
+function alerts_api.snmpInterfaceErrorsType(snmp_interface_info)
+ local snmp_interface_index = snmp_interface_info["snmp_interface"]["index"]
+ local snmp_interface_name = snmp_interface_info["snmp_interface"]["name"]
+ local snmp_device_ip = snmp_interface_info["snmp_device_ip"]
+
+ local res = {
+ alert_type = alert_consts.alert_types.alert_port_errors,
+ alert_severity = alert_consts.alert_severities.info,
+ alert_type_params = {
+ device = snmp_device_ip,
+ interface = snmp_interface_index,
+ interface_name = snmp_interface_name,
+ },
+ }
+
+ return res
end
-- ##############################################
-function alerts_api.snmpPortLoadThresholdExceededType(device, interface, interface_name, interface_load, in_direction)
- return({
- alert_type = alert_consts.alert_types.alert_port_load_threshold_exceeded,
- alert_severity = alert_consts.alert_severities.warning,
- alert_type_params = {
- device = device, interface = interface,
- interface_name = interface_name,
- interface_load = interface_load, in_direction = in_direction,
- },
- })
+function alerts_api.snmpPortLoadThresholdExceededType(snmp_interface_info)
+ local snmp_interface_index = snmp_interface_info["snmp_interface"]["index"]
+ local snmp_interface_name = snmp_interface_info["snmp_interface"]["name"]
+ local snmp_device_ip = snmp_interface_info["snmp_device_ip"]
+ local in_port_load = snmp_interface_info["in_port_load"]
+ local out_port_load = snmp_interface_info["out_port_load"]
+ local load_threshold = snmp_interface_info["load_threshold"]
+
+ local res = {
+ alert_type = alert_consts.alert_types.alert_port_load_threshold_exceeded,
+ alert_severity = alert_consts.alert_severities.warning,
+ alert_type_params = {
+ device = snmp_device_ip,
+ interface = snmp_interface_index,
+ interface_name = snmp_interface_name,
+ in_load = in_port_load,
+ out_load = out_port_load,
+ load_threshold = load_threshold,
+ },
+ }
+
+ return res
end
-- ##############################################
@@ -939,6 +976,21 @@ end
-- ##############################################
+-- TODO: comment
+function alerts_api.snmp_device_interface_check_function(params)
+ local check_res = params.user_script.snmp_device_interface_check(params.granularity, params.entity_info)
+
+ if check_res then
+ local type_builder = params.user_script.type_builder
+
+ local check_type = type_builder(params.entity_info)
+
+ return alerts_api.store(params.alert_entity, check_type)
+ end
+end
+
+-- ##############################################
+
-- An alert check function which performs threshold checks of a value
-- against a configured threshold and generates a threshold_cross alert
-- if the value is above the threshold.
diff --git a/scripts/lua/modules/user_scripts.lua b/scripts/lua/modules/user_scripts.lua
index 150225492e..a344033ca8 100644
--- a/scripts/lua/modules/user_scripts.lua
+++ b/scripts/lua/modules/user_scripts.lua
@@ -38,6 +38,9 @@ user_scripts.script_types = {
}, traffic_element = {
parent_dir = "interface",
hooks = {"min", "5mins", "hour", "day"},
+ }, snmp_device = {
+ parent_dir = "system",
+ hooks = {"snmpDeviceInterface"},
}, syslog = {
parent_dir = "syslog",
hooks = {"handleEvent"},
@@ -70,7 +73,7 @@ local benchmarks = {}
function user_scripts.getSubdirectoryPath(script_type, subdir, is_pro)
local prefix = ternary(is_pro, PRO_CALLBACKS_DIR, CALLBACKS_DIR)
local path
-
+
if not isEmptyString(subdir) and subdir ~= "." then
path = string.format("%s/%s/%s", prefix, script_type.parent_dir, subdir)
else
@@ -465,6 +468,7 @@ function user_scripts.load(script_type, ifid, subdir, hook_filter, ignore_disabl
elseif(rv.hooks[hook] == nil) then
traceError(TRACE_WARNING, TRACE_CONSOLE, string.format("Unknown hook '%s' in module '%s'", hook, user_script.key))
else
+
if do_benchmark then
rv.hooks[hook][user_script.key] = benchmark_init(subdir, user_script.key, hook, hook_fn)
else
diff --git a/scripts/lua/test_alerts.lua b/scripts/lua/test_alerts.lua
index 31d7994a12..190d4f4d2e 100644
--- a/scripts/lua/test_alerts.lua
+++ b/scripts/lua/test_alerts.lua
@@ -26,5 +26,10 @@ interface.checkNetworksAlertsMin()
-- checks the current interface alerts
interface.checkInterfaceAlertsMin()
+--require "snmp_utils"
+--run_5min_snmp_caching(600)
+--dofile(dirs.installdir .. "/pro/scripts/callbacks/system/5min.lua")
+--ntop.checkSNMPDeviceAlerts5Min()
+
dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")
diff --git a/src/AlertCheckLuaEngine.cpp b/src/AlertCheckLuaEngine.cpp
index 9655fa75d3..746d2b9148 100644
--- a/src/AlertCheckLuaEngine.cpp
+++ b/src/AlertCheckLuaEngine.cpp
@@ -44,6 +44,9 @@ AlertCheckLuaEngine::AlertCheckLuaEngine(AlertEntity alert_entity, ScriptPeriodi
case alert_entity_flow:
lua_file = "flow.lua";
break;
+ case alert_entity_snmp_device:
+ lua_file = "snmp_device.lua";
+ break;
default:
/* Example: lua_file = "generic.lua" to handle a generic entity */
break;
@@ -51,8 +54,9 @@ AlertCheckLuaEngine::AlertCheckLuaEngine(AlertEntity alert_entity, ScriptPeriodi
if(lua_file) {
snprintf(script_path, sizeof(script_path),
- "%s/callbacks/interface/%s",
+ "%s/callbacks/%s/%s",
ntop->getPrefs()->get_scripts_dir(),
+ iface ? "interface" : "system",
lua_file);
ntop->fixPath(script_path);
diff --git a/src/LuaEngine.cpp b/src/LuaEngine.cpp
index a0b1206013..027d663ba5 100644
--- a/src/LuaEngine.cpp
+++ b/src/LuaEngine.cpp
@@ -291,7 +291,7 @@ static int ntop_set_active_interface_id(lua_State* vm) {
ntop->getTrace()->traceEvent(TRACE_DEBUG, "%s() called", __FUNCTION__);
if(ntop_lua_check(vm, __FUNCTION__, 1, LUA_TNUMBER) != CONST_LUA_OK) return(CONST_LUA_ERROR);
- id = (u_int32_t)lua_tonumber(vm, 1);
+ id = lua_tonumber(vm, 1);
iface = ntop->getNetworkInterface(vm, id);
@@ -2569,6 +2569,17 @@ static int ntop_check_interface_alerts_day(lua_State* vm) { return(ntop_check_i
/* ****************************************** */
+static int ntop_check_snmp_device_alerts(lua_State* vm, ScriptPeriodicity p) {
+ ntop->checkSNMPDeviceAlerts(p);
+
+ lua_pushnil(vm);
+ return(CONST_LUA_OK);
+}
+
+static int ntop_check_snmp_device_alerts_5min(lua_State* vm) { return(ntop_check_snmp_device_alerts(vm, five_minute_script)); }
+
+/* ****************************************** */
+
static int ntop_temporary_disable_alerts(lua_State* vm) {
bool to_disable;
if(!ntop->isUserAdministrator(vm)) return(CONST_LUA_ERROR);
@@ -11321,6 +11332,9 @@ static const luaL_Reg ntop_reg[] = {
{ "refreshDeviceProtocolsPoliciesConf", ntop_refresh_device_protocols_policies_pref },
#endif
+ /* Alerts */
+ { "checkSNMPDeviceAlerts5Min", ntop_check_snmp_device_alerts_5min },
+
{ NULL, NULL}
};
diff --git a/src/Ntop.cpp b/src/Ntop.cpp
index 4acb850b6d..36a0206957 100644
--- a/src/Ntop.cpp
+++ b/src/Ntop.cpp
@@ -818,6 +818,17 @@ void Ntop::setCustomnDPIProtos(char *path) {
}
}
+/* *************************************** */
+
+void Ntop::checkSNMPDeviceAlerts(ScriptPeriodicity p) {
+ AlertCheckLuaEngine acle(alert_entity_snmp_device, p, NULL);
+ lua_State *L = acle.getState();
+
+ lua_getglobal(L, ALERT_ENTITY_CALLBACK_CHECK_ALERTS); /* Called function */
+ lua_pushstring(L, acle.getGranularity()); /* push 1st argument */
+ acle.pcall(1 /* num args */, 0);
+}
+
/* ******************************************* */
void Ntop::lua_periodic_activities_stats(NetworkInterface *iface, lua_State* vm) {