-- -- (C) 2013-18 - ntop.org -- local dirs = ntop.getDirs() package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path if((dirs.scriptdir ~= nil) and (dirs.scriptdir ~= "")) then package.path = dirs.scriptdir .. "/lua/modules/?.lua;" .. package.path end active_page = "if_stats" if ntop.isPro() then package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path package.path = dirs.installdir .. "/pro/scripts/callbacks/?.lua;" .. package.path require "snmp_utils" end local json = require "dkjson" local host_pools_utils = require "host_pools_utils" local template = require "template_utils" local os_utils = require "os_utils" local format_utils = require "format_utils" local page_utils = require("page_utils") require "lua_utils" require "prefs_utils" require "graph_utils" require "alert_utils" require "db_utils" local ts_utils = require "ts_utils" local recording_utils = require "recording_utils" local storage_utils = require "storage_utils" local have_nedge = ntop.isnEdge() if ntop.isPro() then shaper_utils = require("shaper_utils") end sendHTTPContentTypeHeader('text/html') page = _GET["page"] ifid = _GET["ifid"] ifname_clean = "iface_"..tostring(ifid) msg = "" function inline_input_form(name, placeholder, tooltip, value, can_edit, input_opts, input_class) if(can_edit) then print(']] else if(value ~= nil) then print(value) end end end if(_POST["switch_interface"] ~= nil) then -- First switch interfaces so the new cookie will have effect ifname = interface.setActiveInterfaceId(tonumber(ifid)) --print("@"..ifname.."="..id.."@") if((ifname ~= nil) and (_SESSION["session"] ~= nil)) then key = getRedisPrefix("ntopng.prefs") .. ".ifname" ntop.setCache(key, ifname) msg = "
" .. i18n("if_stats_overview.iface_switch_active_msg", {interface=getHumanReadableInterfaceName(ifname), ifid=ifid}) .. "
" ntop.setCache(getRedisPrefix("ntopng.prefs")..'.iface', ifid) else msg = "
" .. i18n("if_stats_overview.iface_switch_error_msg") .. "
" if(_SESSION["session"] == nil) then msg = msg .."
" .. i18n("if_stats_overview.iface_switch_empty_session_msg") .. "
" end end end -- parse interface names and possibly fall back to the selected interface: -- priority goes to the interface id if ifid ~= nil and ifid ~= "" then if_name = getInterfaceName(ifid) else -- fall-back to the default interface if_name = ifname ifid = interface.name2id(ifname) end interface.select(ifname) local is_packet_interface = interface.isPacketInterface() local ifstats = interface.getStats() -- this is a user-browseable page, so we must return counters from -- the latest reset as the user may have chosen to reset statistics at some point if ifstats.stats and ifstats.stats_since_reset then -- override stats with the values calculated from the latest user reset for k, v in pairs(ifstats.stats_since_reset) do ifstats.stats[k] = v end end local ext_interfaces = {} -- refresh traffic recording availability as one may have installed n2disk -- with a running instance of ntopng recording_utils.checkAvailable() if recording_utils.isAvailable() and recording_utils.isSupportedZMQInterface(ifid) then ext_interfaces = recording_utils.getExtInterfaces(ifid) end if (isAdministrator()) then if (page == "config") and (not table.empty(_POST)) then -- TODO move keys to new schema: replace ifstats.name with ifid ntop.setCache('ntopng.prefs.'..ifstats.name..'.name',_POST["custom_name"]) local ifspeed_cache = 'ntopng.prefs.'..ifstats.name..'.speed' if isEmptyString(_POST["ifSpeed"]) then ntop.delCache(ifspeed_cache) else ntop.setCache(ifspeed_cache, _POST["ifSpeed"]) end local hide_set = getHideFromTopSet(ifstats.id) ntop.delCache(hide_set) for _, net in pairs(split(_POST["hide_from_top"] or "", ",")) do net = trimSpace(net) if not isEmptyString(net) then local address, prefix = splitNetworkPrefix(net) if isIPv6(address) and prefix == "128" then net = address elseif isIPv4(address) and prefix == "32" then net = address end ntop.setMembersCache(hide_set, net) end end interface.reloadHideFromTop() setInterfaceRegreshRate(ifstats.id, tonumber(_POST["ifRate"])) local sf = tonumber(_POST["scaling_factor"]) if(sf == nil) then sf = 1 end ntop.setCache(getRedisIfacePrefix(ifid)..'.scaling_factor',tostring(sf)) interface.loadScalingFactorPrefs() end end page_utils.print_header(i18n("interface_ifname", { ifname=if_name })) print("") dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") print(msg) url = ntop.getHttpPrefix()..'/lua/if_stats.lua?ifid=' .. ifid -- Added global javascript variable, in order to disable the refresh of pie chart in case -- of historical interface print('\n\n') print [[ ]] if((page == "overview") or (page == nil)) then print("\n") print("\n") if interface.isPcapDumpInterface() == false and ifstats["type"] ~= "netfilter" then print("\n") end if(ifstats["remote.name"] ~= nil) then local remote_if_addr, remote_probe_ip, remote_probe_public_ip = '', '', '' local num_remote_flow_exports, num_remote_flow_exporters = '', '' if not isEmptyString(ifstats["remote.if_addr"]) then remote_if_addr = ""..i18n("if_stats_overview.interface_ip")..": "..ifstats["remote.if_addr"] end if not isEmptyString(ifstats["probe.ip"]) then remote_probe_ip = ""..i18n("if_stats_overview.probe_ip")..": "..ifstats["probe.ip"] end if not isEmptyString(ifstats["probe.public_ip"]) then remote_probe_public_ip = ""..i18n("if_stats_overview.public_probe_ip")..": "..ifstats["probe.public_ip"].."\n" end if not isEmptyString(ifstats["zmq.num_flow_exports"]) then num_remote_flow_exports = ""..i18n("if_stats_overview.probe_zmq_num_flow_exports")..": "..formatValue(ifstats["zmq.num_flow_exports"]).."" end if not isEmptyString(ifstats["zmq.num_exporters"]) then num_remote_flow_exporters = ""..i18n("if_stats_overview.probe_zmq_num_endpoints")..": "..formatValue(ifstats["zmq.num_exporters"]).."" end print("") print("") print("") print("\n") print("\n") print("") local colspan = 4 if ifstats["timeout.lifetime"] > 0 then print("") else colspan = colspan - 1 end if ifstats["timeout.idle"] > 0 then print("") else colspan = colspan - 1 end print("") print("") local has_drops_export_queue_full = (tonumber(ifstats["zmq.drops.export_queue_full"]) and tonumber(ifstats["zmq.drops.export_queue_full"]) > 0) local has_drops_flow_collection_drops = (tonumber(ifstats["zmq.drops.flow_collection_drops"]) and tonumber(ifstats["zmq.drops.flow_collection_drops"]) > 0) local has_remote_drops = (has_drops_export_queue_full or has_drops_flow_collection_drops) if not has_remote_drops then print('') else print("") local export_queue_full, flow_collection_drops local colspan = 5 if has_drops_export_queue_full then local num_full = tonumber(ifstats["zmq.drops.export_queue_full"]) local span_class = ' ' if num_full > 0 then span_class = 'class="label label-danger"' end export_queue_full = ""..i18n("if_stats_overview.probe_zmq_drops_export_queue_full").." : "..formatValue(ifstats["zmq.drops.export_queue_full"]).."" end if has_drops_flow_collection_drops then local num_full = tonumber(ifstats["zmq.drops.flow_collection_drops"]) local span_class = ' ' if num_full > 0 then span_class = 'class="label label-danger"' end flow_collection_drops = ""..i18n("if_stats_overview.probe_zmq_drops_flow_collection_drops").." : "..formatValue(ifstats["zmq.drops.flow_collection_drops"]).."" end if export_queue_full then print("") colspan = colspan - 1 end if flow_collection_drops then print("") colspan = colspan - 1 end if colspan then print("") end end print("") end local is_physical_iface = (interface.isPacketInterface()) and (interface.isPcapDumpInterface() == false) local label = getHumanReadableInterfaceName(ifstats.name) local s if ((not isEmptyString(label)) and (label ~= ifstats.name)) then s = label.." (" .. ifstats.name .. ")" else s = ifstats.name end if((isAdministrator()) and (interface.isPcapDumpInterface() == false)) then s = s .. " " end print('\n') print("") if is_physical_iface then print("") print("\n") local speed_key = 'ntopng.prefs.'..ifname..'.speed' local speed = ntop.getCache(speed_key) if (tonumber(speed) == nil) then speed = ifstats.speed end print("") print("") end label = i18n("pkts") print[[ ]] if(ifstats.type ~= "zmq") then print [[ ]] else print [[ ]] end print [[ \n") if(ifstats.zmqRecvStats ~= nil) then print("\n") print("") print("") print("") print("") -- empty placeholder, can be used for future items print("") end print("\n") print("") if ifstats.isDynamic == false then print("") print("") else print("") end print("") if(ifstats.has_traffic_directions) then print("") print("") end if(prefs.is_dump_flows_enabled and ifstats.isView == false) then local dump_to = "MySQL" if prefs.is_dump_flows_to_es_enabled == true then dump_to = "ElasticSearch" end if prefs.is_dump_flows_to_ls_enabled == true then dump_to = "Logstash" end if prefs.is_nindex_enabled == true then dump_to = "nIndex" end local export_count = ifstats.stats.flow_export_count local export_rate = ifstats.stats.flow_export_rate local export_drops = ifstats.stats.flow_export_drops local export_drops_pct = 0 if export_drops == nill then elseif export_drops > 0 and export_count > 0 then export_drops_pct = export_drops / export_count * 100 elseif export_drops > 0 then export_drops_pct = 100 end print("\n") print("") print("") print("") print("") local span_danger = "" if export_drops == nil then elseif(export_drops > 0) then span_danger = ' class="label label-danger"' end print("") print("") print("") end if isAdministrator() and ifstats.isView == false then local storage_info = storage_utils.interfaceStorageInfo(ifid) local storage_items = {} if storage_info.rrd ~= nil and storage_info.rrd > 0 then table.insert(storage_items, { title = i18n("prefs.timeseries"), value = storage_info.rrd, class = "primary", }) end if storage_info.flows ~= nil and storage_info.flows > 0 then table.insert(storage_items, { title = i18n("flows"), value = storage_info.flows, class = "info", }) end if storage_info.pcap ~= nil and storage_info.pcap > 0 then local link = nil if recording_utils.isAvailable(ifstats.id) then link = ntop.getHttpPrefix() .. "/lua/if_stats.lua?ifid=" .. ifid .. "&page=traffic_recording" end table.insert(storage_items, { title = i18n("traffic_recording.packet_dumps"), value = storage_info.pcap, class = "warning", link = link }) end if #storage_items > 0 then print("\n") end end if (isAdministrator() and ifstats.isView == false and ifstats.isDynamic == false and interface.isPacketInterface()) then print("\n") print("") print("") print("\n") end if have_nedge and ifstats.type == "netfilter" and ifstats.netfilter then local st = ifstats.netfilter print("") local span_class = '' if st.nfq.queue_pct > 80 then span_class = "class='label label-danger'" end print("") print("") print("") print("") print("") print("") print("") print("") end print [[ ]] print("
"..i18n("if_stats_overview.id").."" .. ifstats.id .. " ") if(ifstats.description ~= ifstats.name) then print(" ("..ifstats.description..")") end print("
"..i18n("if_stats_overview.state").."") state = toggleTableButton("", "", i18n("if_stats_overview.active"), "1","primary", i18n("if_stats_overview.paused"), "0","primary", "toggle_local", "ntopng.prefs."..if_name.."_not_idle") if(state == "0") then on_state = true else on_state = false end interface.setInterfaceIdleState(on_state) print("
"..i18n("if_stats_overview.remote_probe")..""..i18n("if_stats_overview.interface_name")..": "..ifstats["remote.name"].." [ ".. maxRateToString(ifstats.speed*1000) .." ]"..remote_if_addr..""..remote_probe_ip..""..remote_probe_public_ip.."
"..i18n("if_stats_overview.probe_timeout_lifetime")..": "..secondsToTime(ifstats["timeout.lifetime"])..""..i18n("if_stats_overview.probe_timeout_idle")..": "..secondsToTime(ifstats["timeout.idle"])..""..num_remote_flow_exporters.."
"..export_queue_full..""..flow_collection_drops.."
'..i18n("name")..'' .. s ..' "..i18n("if_stats_overview.family").."") print(ifstats.type) if(ifstats.inline) then print(" "..i18n("if_stats_overview.in_path_interface")) end if(ifstats.has_traffic_directions) then print(" ".. i18n("if_stats_overview.has_traffic_directions") .. " ") end print("
"..i18n("mtu")..""..ifstats.mtu.." "..i18n("bytes")..""..i18n("speed").."" .. maxRateToString(speed*1000) .. "
]] print(i18n("if_stats_overview.traffic_breakdown")) print[[
"..i18n("if_stats_overview.zmq_rx_statistics").."
"..i18n("if_stats_overview.collected_flows")..""..formatValue(ifstats.zmqRecvStats.flows)..""..i18n("if_stats_overview.interface_rx_updates")..""..formatValue(ifstats.zmqRecvStats.events)..""..i18n("if_stats_overview.sflow_counter_updates")..""..formatValue(ifstats.zmqRecvStats.counters).."
"..i18n("if_stats_overview.zmq_message_drops")..""..formatValue(ifstats.zmqRecvStats.zmq_msg_drops).."
"..i18n("if_stats_overview.traffic_statistics").."
"..i18n("report.total_traffic")..""..bytesToSize(ifstats.stats.bytes).." [".. formatValue(ifstats.stats.packets) .. " ".. label .."] ") print(" ") print(i18n("if_stats_overview.dropped_packets").."") if(ifstats.stats.drops > 0) then print('') end print(formatValue(ifstats.stats.drops).. " " .. label) if((ifstats.stats.packets+ifstats.stats.drops) > 0) then local pctg = round((ifstats.stats.drops*100)/(ifstats.stats.packets+ifstats.stats.drops), 2) if(pctg > 0) then print(" [ " .. pctg .. " % ] ") end end if(ifstats.stats.drops > 0) then print('') end print(" ") if(ifstats.zmqRecvStats ~= nil) then print("

"..i18n("if_stats_overview.note")..":
".. i18n("if_stats_overview.note_drops_sflow").."
") end print("

") print(""..i18n("if_stats_overview.note")..": "..i18n("if_stats_overview.note_drop_ifstats_dynamic").."") print("
"..i18n("http_page.traffic_sent")..""..bytesToSize(ifstats.eth.egress.bytes).." [".. formatValue(ifstats.eth.egress.packets) .. " ".. label .."] "..i18n("http_page.traffic_received")..""..bytesToSize(ifstats.eth.ingress.bytes).." [".. formatValue(ifstats.eth.ingress.packets) .. " ".. label .."]
"..dump_to.." "..i18n("if_stats_overview.flows_export_statistics").."
"..i18n("if_stats_overview.exported_flows")..""..formatValue(export_count).."") if export_rate == nil then export_rate = 0 end print(" ["..formatValue(round(export_rate, 2)).." Flows/s] ") print(i18n("if_stats_overview.dropped_flows")..""..formatValue(export_drops).." ") print("[" ..formatValue(round(export_drops_pct, 2)).."%] 
"..i18n("traffic_recording.storage_utilization").."") print(stackedProgressBars(storage_info.total, storage_items, nil, bytesToSize)) print("
"..i18n("download").." ") local live_traffic_utils = require("live_traffic_utils") live_traffic_utils.printLiveTrafficForm(ifId) print("
"..i18n("if_stats_overview.reset_counters").."") local tot = ifstats.stats.bytes + ifstats.stats.packets + ifstats.stats.drops if(ifstats.stats.flow_export_count ~= nil) then tot = tot + ifstats.stats.flow_export_count + ifstats.stats.flow_export_drops end print(' ') print('') print("
"..i18n("if_stats_overview.nf_queue_total")..""..string.format("%s [%s %%]", formatValue(st.nfq.queue_total), formatValue(st.nfq.queue_pct)).." "..i18n("if_stats_overview.nf_handle_packet_failed")..""..formatValue(st.failures.handle_packet).." "..i18n("if_stats_overview.nf_enobufs")..""..formatValue(st.failures.no_buffers).."
Conntrack Flow Entries") print(""..formatValue(st.nfq.num_conntrack_entries).."
]] print(i18n("if_stats_overview.note")..":

"..i18n("if_stats_overview.note_packets")) print[[

\n") elseif((page == "networks")) then print("") if(ifstats.ip_addresses ~= "") then local tokens = split(ifstats.ip_addresses, ",") if(tokens ~= nil) then print("") end end local has_ghost_networks = false local ghost_icon = '' if ifstats.bcast_domains and table.len(ifstats.bcast_domains) > 0 then print("") end print("
"..i18n("ip_address").."") local addresses = {} for _,s in pairs(tokens) do t = string.split(s, "/") host = interface.getHostInfo(t[1]) if(host ~= nil) then addresses[#addresses+1] = "".. t[1].."".."/"..t[2] else addresses[#addresses+1] = s end end print(table.concat(addresses, ", ")) print("
"..i18n("broadcast_domain").."") local num = 1 local bcast_domains = "" for bcast_domain, in_interface_range in pairs(ifstats.bcast_domains) do if num > 1 then bcast_domains = bcast_domains.."," end bcast_domain = string.format("%s", ntop.getHttpPrefix(), bcast_domain, bcast_domain) bcast_domains = bcast_domains..bcast_domain if in_interface_range == 0 and interface.isPacketInterface() and not interface.isPcapDumpInterface() and ntop.getPref(string.format("ntopng.prefs.ifid_%d.is_traffic_mirrored", ifId)) ~= "1" then has_ghost_networks = true bcast_domains = bcast_domains..' '..ghost_icon end num = num + 1 end print(bcast_domains) if has_ghost_networks then print("
"..i18n("if_stats_overview.note")..": "..i18n("if_stats_overview.ghost_bcast_domain_descr", {ghost_icon = ghost_icon}).."
") end print("
") print("

"..i18n("if_stats_overview.note")..":