EVOLUTION-MANAGER
Edit File: top_talkers_utils.lua
-- -- (C) 2014-20 - ntop.org -- local callback_utils = require "callback_utils" require "lua_utils" -- TODO: remove local json = require "dkjson" local top_talkers_utils = {} top_talkers_utils.MAX_NUM_ENTRIES = 10 top_talkers_utils.THRESHOLD_LOW = .05 top_talkers_utils.TOP_ENABLED_KEY = "ntopng.prefs.ifid_%i.interface_top_talkers_creation" local vlan_totals = {} local asname_cache = {} local hostname_cache = {} local localhost_cache = {} local ipaddr_cache = {} -- ######################################################## local function getTopEnabledKey(ifid) return string.format(top_talkers_utils.TOP_ENABLED_KEY, ifid) end -- ######################################################## local function updateCache(cache, key, val) if cache[key] == nil then cache[key] = val end end -- ######################################################## local function getCache(cache, key) return cache[key] end -- ######################################################## local function updateRes(res, vlan, what_key, what_value, direction, delta) if res == nil then res = {} end if res[vlan] == nil then res[vlan] = {} end if res[vlan][what_key] == nil then res[vlan][what_key] = {} end if res[vlan][what_key][direction] == nil then res[vlan][what_key][direction] = {} end if res[vlan][what_key][direction][what_value] == nil then res[vlan][what_key][direction][what_value] = 0 end res[vlan][what_key][direction][what_value] = res[vlan][what_key][direction][what_value] + delta end -- ######################################################## local function sortRes(res) for vlan_k, vlan_val in pairs(res) do for what_key_k, what_key_val in pairs(vlan_val) do for direction_key, direction_val in pairs(what_key_val) do local total, count, other = 0, 0, 0 for what_val_k, delta in pairsByValues(direction_val, rev) do count = count + 1 total = total + delta if delta <= 0 or count > top_talkers_utils.MAX_NUM_ENTRIES then if delta > 0 then other = other + delta end direction_val[what_val_k] = nil end end count = 0 for what_val_k, delta in pairs(direction_val) do count = count + 1 -- at least 5 if (count > top_talkers_utils.MAX_NUM_ENTRIES / 2 and delta / total < top_talkers_utils.THRESHOLD_LOW) then if delta > 0 then other = other + delta end direction_val[what_val_k] = nil end end if other > 0 then direction_val["Other"] = other end end end end end -- ######################################################## local function finalizeRes(res) for vlan_k, vlan_val in pairs(res) do for what_key_k, what_key_val in pairs(vlan_val) do for direction_key, direction_val in pairs(what_key_val) do for what_val_k, delta in pairs(direction_val) do local label = what_val_k if (what_val_k ~= "Other") and (what_val_k ~= "Hidden Hosts") then if what_key_k == "hosts" then label = getCache(hostname_cache, what_val_k) elseif what_key_k == "asn" then label = getCache(asname_cache, what_val_k) end end if label == what_val_k then -- Skip this label, as it is the same as the address label = nil end direction_val[what_val_k] = {address = what_val_k..'', value = delta, label = label} if what_key_k == "hosts" then local ip_addr = getCache(ipaddr_cache, what_val_k) direction_val[what_val_k]["local"] = tostring(getCache(localhost_cache, what_val_k) or "false") if ip_addr ~= what_val_k then -- storing the IP address is necessary for MAC based keys to create the -- correct URL direction_val[what_val_k]["ipaddr"] = ip_addr end end end end end end -- Convert to the previous format local p = {} for vlan_k, vlan_val in pairs(res) do p[#p + 1] = vlan_val for what_key_k, what_key_val in pairs(vlan_val) do local s = {} for _, sender in pairs(what_key_val["sent"]) do s[#s + 1] = sender end local r = {} for _, receiver in pairs(what_key_val["rcvd"]) do r[#r + 1] = receiver end vlan_val[what_key_k] = {{senders = s, receivers = r}} end vlan_val["value"] = vlan_totals[vlan_k] vlan_val["address"] = vlan_k.."" end return {vlan = p} end -- ######################################################## function top_talkers_utils.areTopEnabled(ifid) local k = getTopEnabledKey(ifid) return not (ntop.getPref(k) == "false") end -- ######################################################## function top_talkers_utils.disableTop(ifid) local k = getTopEnabledKey(ifid) ntop.setPref(k, "false") end -- ######################################################## function top_talkers_utils.enableTop(ifid) local k = getTopEnabledKey(ifid) ntop.delCache(k) end -- ######################################################## function top_talkers_utils.makeTopJson(_ifname) local ifid = getInterfaceId(_ifname) local res = {} if not top_talkers_utils.areTopEnabled(ifid) then return nil end local in_time = callback_utils.foreachHost(_ifname, function (hostname, hoststats) local checkpoint = interface.checkpointHostTalker(ifid, hostname) local tskey = hoststats["tskey"] local vlan = hoststats["vlan"] updateCache(hostname_cache, tskey, hoststats["name"]) updateCache(localhost_cache, tskey, hoststats["localhost"]) updateCache(ipaddr_cache, tskey, hostname) updateCache(asname_cache, hoststats["asn"], hoststats["asname"]) if((checkpoint == nil) or (checkpoint["delta"] == nil)) then goto continue end for _, direction in pairs({"sent", "rcvd"}) do local delta = checkpoint["delta"][direction] vlan_totals[vlan] = (vlan_totals[vlan] or 0) + delta local os_key = "non-local os" if hoststats["localhost"] then os_key = "local os" end local country = interface.getHostCountry(hostname) for what_key, what_value in pairs({ ["hosts"] = tskey, ["asn"] = hoststats["asn"], [os_key] = hoststats["os"], ["countries"] = ternary(not isEmptyString(country), country, nil), ["networks"] = hoststats["local_network_id"], }) do if hoststats.hiddenFromTop then what_value = "Hidden Hosts" end updateRes(res, vlan, what_key, what_value, direction, delta) end end ::continue:: end) if not in_time then print("[".. _ifname .."] ERROR: Cannot complete top talkers generation in 1 minute. Is there a huge number of hosts in the system?") end sortRes(res) return json.encode(finalizeRes(res)) end -- ######################################################## -- Computes label and url during visualization function top_talkers_utils.enrichRecordInformation(class_key, rec, show_vlan) local url = "" local label = rec.label or rec.address local url_target = rec.address if (rec.address ~= "Other") and (rec.address ~= "Hidden Hosts") then if class_key == "hosts" then local address = rec.address if ends(address, "_v4") or ends(address, "_v6") then rec.visual_addr = visualTsKey(address) address = string.sub(address, 1, string.len(address)-3) if(rec.ipaddr ~= nil) then url_target = rec.ipaddr end end url_target = url_target .. "&tskey=" .. rec.address url = ntop.getHttpPrefix()..'/lua/host_details.lua?always_show_hist=true&host=' -- Use the host alias as label, if set local alt_name = getHostAltName(address) if not isEmptyString(alt_name) and (alt_name ~= address) then label = alt_name else local hinfo = hostkey2hostinfo(address) if not show_vlan then hinfo.vlan = 0 end alt_name = host2name(hinfo.host, hinfo.vlan) if not isEmptyString(alt_name) and (alt_name ~= address) then label = alt_name else label = address end end elseif class_key == "asn" then url = ntop.getHttpPrefix()..'/lua/hosts_stats.lua?asn=' elseif class_key == "networks" then url = ntop.getHttpPrefix()..'/lua/hosts_stats.lua?network=' local network_name = nil if rec.address == "-1" then network_name = i18n("remote_networks") else network_name = getFullLocalNetworkName(ntop.getNetworkNameById(tonumber(rec.address))) end if not isEmptyString(network_name) then label = network_name end elseif class_key:contains("os") then url = ntop.getHttpPrefix()..'/lua/hosts_stats.lua?os=' end if not isEmptyString(url) then url = url .. url_target end end -- Update record information rec.url = url rec.label = label end -- ######################################################## function top_talkers_utils.enrichVlanInformation(vlan_tbl) local vlan_id = ternary(vlan_tbl.address, tostring(vlan_tbl.address), "0") vlan_tbl["label"] = vlan_id vlan_tbl["name"] = vlan_id vlan_tbl["url"] = ntop.getHttpPrefix()..'/lua/hosts_stats.lua?vlan='..vlan_id end -- ######################################################## return top_talkers_utils