diff --git a/include/Flow.h b/include/Flow.h index 78c8c5ed02..4fed7eb06c 100644 --- a/include/Flow.h +++ b/include/Flow.h @@ -83,6 +83,10 @@ class Flow : public GenericHashEntry { good_low_flow_detected, good_ssl_hs; u_int16_t diff_num_http_requests; #ifdef NTOPNG_PRO + struct { + struct { int cli, srv; } src2dst; + struct { int cli, srv; } dst2src; + } flow_shapers; FlowProfile *trafficProfile; CounterTrend throughputTrend, goodputTrend, thptRatioTrend; #endif @@ -191,7 +195,7 @@ class Flow : public GenericHashEntry { } FlowStatus getFlowStatus(); char* printTCPflags(u_int8_t flags, char *buf, u_int buf_len); - + void updateFlowShapers(); inline bool isProtoSSL(u_int16_t p ) { return((ndpi_get_lower_proto(ndpiDetectedProtocol) == p) ? true : false); } inline bool isSSL() { return(isProtoSSL(NDPI_PROTOCOL_SSL)); } inline bool isDNS() { return(isProtoSSL(NDPI_PROTOCOL_DNS)); } @@ -349,8 +353,8 @@ class Flow : public GenericHashEntry { FlowSSLEncryptionStatus getSSLEncryptionStatus(); void setDumpFlowTraffic(bool what) { dump_flow_traffic = what; } bool getDumpFlowTraffic(void) { return dump_flow_traffic; } - void getFlowShapers(bool src2dst_direction, int *a_shaper_id, int *b_shaper_id, u_int16_t *ndpiProtocol); #ifdef NTOPNG_PRO + void getFlowShapers(bool src2dst_direction, int *a_shaper_id, int *b_shaper_id, int *c_shaper_id, int *d_shaper_id); inline void updateProfile() { trafficProfile = iface->getFlowProfile(this); } inline char* get_profile_name() { return(trafficProfile ? trafficProfile->getName() : (char*)"");} #endif diff --git a/include/NetworkInterface.h b/include/NetworkInterface.h index 0e22804235..3706e329c2 100644 --- a/include/NetworkInterface.h +++ b/include/NetworkInterface.h @@ -246,7 +246,7 @@ class NetworkInterface { u_int8_t dst_mac[6], IpAddress *_dst_ip, Host **dst); Flow* findFlowByKey(u_int32_t key, patricia_tree_t *allowed_hosts); bool findHostsByName(lua_State* vm, patricia_tree_t *allowed_hosts, char *key); - bool dissectPacket(const struct pcap_pkthdr *h, const u_char *packet, bool *shaped, u_int16_t *ndpiProtocol); + bool dissectPacket(const struct pcap_pkthdr *h, const u_char *packet, u_int16_t *ndpiProtocol); bool processPacket(const struct bpf_timeval *when, const u_int64_t time, struct ndpi_ethhdr *eth, @@ -256,7 +256,6 @@ class NetworkInterface { u_int16_t ipsize, u_int32_t rawsize, const struct pcap_pkthdr *h, const u_char *packet, - bool *shaped, u_int16_t *ndpiProtocol); void processFlow(ZMQ_Flow *zflow); void processInterfaceStats(sFlowInterfaceStats *stats); diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index 2f2e0a667d..b8be883b42 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -48,7 +48,7 @@ local en = { network_group = "Network Group", network_groups = "Network Groups", protocols = "Protocols", - manage_shapers = "Manage Shapers", + manage_shapers = "Traffic Shapers", shaper0_message = "Shaper 0 is the default shaper used for local hosts that have no shaper defined", set_max_rate_to = "Set max rate to", for_no_shaping = "for no shaping", diff --git a/scripts/lua/if_stats.lua b/scripts/lua/if_stats.lua index 06106c0121..c4925e9166 100644 --- a/scripts/lua/if_stats.lua +++ b/scripts/lua/if_stats.lua @@ -490,10 +490,9 @@ print("\n") if((ifstats["bridge.device_a"] ~= nil) and (ifstats["bridge.device_b"] ~= nil)) then print("Bridged Traffic\n") - print("Interface DirectionIngress PacketsEgress PacketsShaped PacketsFiltered PacketsSend ErrorBuffer Full\n") + print("Interface DirectionIngress PacketsEgress PacketsShaped/Filtered PacketsSend ErrorBuffer Full\n") print("".. ifstats["bridge.device_a"] .. " ".. ifstats["bridge.device_b"] .."".. formatPackets(ifstats["bridge.a_to_b.in_pkts"]) .." ") print("".. formatPackets(ifstats["bridge.a_to_b.out_pkts"]) .." ") - print("".. formatPackets(ifstats["bridge.a_to_b.shaped_pkts"]) .."") print("".. formatPackets(ifstats["bridge.a_to_b.filtered_pkts"]) .."") print("".. formatPackets(ifstats["bridge.a_to_b.num_pkts_send_error"]) .."") @@ -503,7 +502,6 @@ print("\n") print("".. ifstats["bridge.device_b"] .. " ".. ifstats["bridge.device_a"] .."".. formatPackets(ifstats["bridge.b_to_a.in_pkts"]) .." ") print(""..formatPackets( ifstats["bridge.b_to_a.out_pkts"]) .." ") - print("".. formatPackets(ifstats["bridge.b_to_a.shaped_pkts"]) .."") print("".. formatPackets(ifstats["bridge.b_to_a.filtered_pkts"]) .."") print("".. formatPackets(ifstats["bridge.b_to_a.num_pkts_send_error"]) .."") @@ -1895,7 +1893,6 @@ if(ifstats["bridge.device_a"] ~= nil) then print("var a_to_b_last_in_bytes = " .. ifstats["bridge.a_to_b.in_bytes"] .. ";\n") print("var a_to_b_last_out_bytes = " .. ifstats["bridge.a_to_b.out_bytes"] .. ";\n") print("var a_to_b_last_filtered_pkts = " .. ifstats["bridge.a_to_b.filtered_pkts"] .. ";\n") - print("var a_to_b_last_shaped_pkts = " .. ifstats["bridge.a_to_b.shaped_pkts"] .. ";\n") print("var a_to_b_last_num_pkts_send_buffer_full = " .. ifstats["bridge.a_to_b.num_pkts_send_buffer_full"] .. ";\n") print("var a_to_b_last_num_pkts_send_error = " .. ifstats["bridge.a_to_b.num_pkts_send_error"] .. ";\n") @@ -1904,7 +1901,6 @@ if(ifstats["bridge.device_a"] ~= nil) then print("var b_to_a_last_in_bytes = " .. ifstats["bridge.b_to_a.in_bytes"] .. ";\n") print("var b_to_a_last_out_bytes = " .. ifstats["bridge.b_to_a.out_bytes"] .. ";\n") print("var b_to_a_last_filtered_pkts = " .. ifstats["bridge.b_to_a.filtered_pkts"] .. ";\n") - print("var b_to_a_last_shaped_pkts = " .. ifstats["bridge.b_to_a.shaped_pkts"] .. ";\n") print("var b_to_a_last_num_pkts_send_buffer_full = " .. ifstats["bridge.b_to_a.num_pkts_send_buffer_full"] .. ";\n") print("var b_to_a_last_num_pkts_send_error = " .. ifstats["bridge.b_to_a.num_pkts_send_error"] .. ";\n") end @@ -2035,7 +2031,6 @@ print [[ } $('#a_to_b_filtered_pkts').html(addCommas(rsp["a_to_b_filtered_pkts"])+" Pkts "+get_trend(a_to_b_last_filtered_pkts, rsp["a_to_b_filtered_pkts"])); - $('#a_to_b_shaped_pkts').html(addCommas(rsp["a_to_b_shaped_pkts"])+" Pkts "+get_trend(a_to_b_last_shaped_pkts, rsp["a_to_b_shaped_pkts"])); $('#a_to_b_num_pkts_send_error').html(addCommas(rsp["a_to_b_num_pkts_send_error"])+" Pkts "+get_trend(a_to_b_last_num_pkts_send_error, rsp["a_to_b_num_pkts_send_error"])); $('#a_to_b_num_pkts_send_buffer_full').html(addCommas(rsp["a_to_b_num_pkts_send_buffer_full"])+" Pkts "+get_trend(a_to_b_last_num_pkts_send_buffer_full, rsp["a_to_b_num_pkts_send_buffer_full"])); @@ -2052,7 +2047,6 @@ print [[ $('#b_to_a_out_pps').html(" ["+fbits(bps)+"]"); } $('#b_to_a_filtered_pkts').html(addCommas(rsp["b_to_a_filtered_pkts"])+" Pkts "+get_trend(b_to_a_last_filtered_pkts, rsp["b_to_a_filtered_pkts"])); - $('#b_to_a_shaped_pkts').html(addCommas(rsp["b_to_a_shaped_pkts"])+" Pkts "+get_trend(b_to_a_last_shaped_pkts, rsp["b_to_a_shaped_pkts"])); $('#b_to_a_num_pkts_send_error').html(addCommas(rsp["b_to_a_num_pkts_send_error"])+" Pkts "+get_trend(b_to_a_last_num_pkts_send_error, rsp["b_to_a_num_pkts_send_error"])); $('#b_to_a_num_pkts_send_buffer_full').html(addCommas(rsp["b_to_a_num_pkts_send_buffer_full"])+" Pkts "+get_trend(b_to_a_last_num_pkts_send_buffer_full, rsp["b_to_a_num_pkts_send_buffer_full"])); @@ -2061,7 +2055,6 @@ print [[ a_to_b_last_in_bytes = rsp["a_to_b_in_bytes"]; a_to_b_last_out_bytes = rsp["a_to_b_out_bytes"]; a_to_b_last_filtered_pkts = rsp["a_to_b_filtered_pkts"]; - a_to_b_last_shaped_pkts = rsp["a_to_b_shaped_pkts"]; a_to_b_last_num_pkts_send_buffer_full = rsp["a_to_b_num_pkts_send_buffer_full"]; a_to_b_last_num_pkts_send_error = rsp["a_to_b_num_pkts_send_error"]; @@ -2070,7 +2063,6 @@ print [[ b_to_a_last_in_bytes = rsp["b_to_a_in_bytes"]; b_to_a_last_out_bytes = rsp["b_to_a_out_bytes"]; b_to_a_last_filtered_pkts = rsp["b_to_a_filtered_pkts"]; - b_to_a_last_shaped_pkts = rsp["b_to_a_shaped_pkts"]; b_to_a_last_num_pkts_send_buffer_full = rsp["b_to_a_num_pkts_send_buffer_full"]; b_to_a_last_num_pkts_send_error = rsp["b_to_a_num_pkts_send_error"]; last_epoch = rsp["epoch"]; diff --git a/src/DivertInterface.cpp b/src/DivertInterface.cpp index 08e9294983..93c2fa0466 100644 --- a/src/DivertInterface.cpp +++ b/src/DivertInterface.cpp @@ -59,7 +59,7 @@ static void* divertPacketPollLoop(void* ptr) { } h.len = h.caplen = len, gettimeofday(&h.ts, NULL); - iface->dissectPacket(&h, packet, &shaped, &c); + iface->dissectPacket(&h, packet, &c); /* Enable the row below to specify the firewall rule corresponding to the protocol */ #if 0 diff --git a/src/Flow.cpp b/src/Flow.cpp index 49d7f1e572..9efb15bb0f 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -109,6 +109,7 @@ Flow::Flow(NetworkInterface *_iface, last_update_time.tv_sec = (long)first_seen; #ifdef NTOPNG_PRO + flow_shapers.src2dst.cli = flow_shapers.src2dst.srv = flow_shapers.dst2src.cli = flow_shapers.dst2src.srv = -1; trafficProfile = NULL; #endif @@ -554,8 +555,12 @@ void Flow::setDetectedProtocol(ndpi_protocol proto_id, bool forceDetection) { detection_completed = true; } - if (detection_completed) + if(detection_completed) { +#ifdef NTOPNG_PRO + updateFlowShapers(); +#endif iface->luaEvalFlow(this, callback_flow_proto_callback); + } #ifdef NTOPNG_PRO // Update the profile even if the detection is not yet completed. @@ -860,6 +865,22 @@ bool Flow::dumpFlow(bool partial_dump) { /* *************************************** */ +#ifdef NTOPNG_PRO +void Flow::updateFlowShapers() { + L7Policer *policer = iface->getL7Policer(); + + if(cli_host && srv_host && policer) { + flow_shapers.src2dst.cli = policer->getShaperIdForProtocol(cli_host->getL7NetworkIndex(), ndpiDetectedProtocol.protocol, L7_POLICY_DIRECTION_INGRESS); + flow_shapers.src2dst.srv = policer->getShaperIdForProtocol(srv_host->getL7NetworkIndex(), ndpiDetectedProtocol.protocol, L7_POLICY_DIRECTION_EGRESS); + flow_shapers.dst2src.cli = policer->getShaperIdForProtocol(cli_host->getL7NetworkIndex(), ndpiDetectedProtocol.protocol, L7_POLICY_DIRECTION_EGRESS); + flow_shapers.dst2src.srv = policer->getShaperIdForProtocol(srv_host->getL7NetworkIndex(), ndpiDetectedProtocol.protocol, L7_POLICY_DIRECTION_INGRESS); + } else + flow_shapers.src2dst.cli = flow_shapers.src2dst.srv = flow_shapers.dst2src.cli = flow_shapers.dst2src.srv = -1; +} +#endif + +/* *************************************** */ + void Flow::update_hosts_stats(struct timeval *tv, bool inDeleteMethod) { u_int64_t sent_packets, sent_bytes, sent_goodput_bytes, rcvd_packets, rcvd_bytes, rcvd_goodput_bytes; u_int64_t diff_sent_packets, diff_sent_bytes, diff_sent_goodput_bytes, @@ -1393,20 +1414,25 @@ void Flow::lua(lua_State* vm, patricia_tree_t * ptree, lua_push_int_table_entry(vm, "protos.http.last_return_code", protos.http.last_return_code); } +#ifdef NTOPNG_PRO /* Shapers */ if(cli_host && srv_host) { - int a, b; - u_int16_t p; + int a, b, c, d; - getFlowShapers(true, &a, &b, &p); + getFlowShapers(true, &a, &b, &c, &d); lua_push_int_table_entry(vm, "shaper.cli2srv_a", a); lua_push_int_table_entry(vm, "shaper.cli2srv_b", b); + lua_push_int_table_entry(vm, "shaper.cli2srv_c", c); + lua_push_int_table_entry(vm, "shaper.cli2srv_d", d); - getFlowShapers(false, &a, &b, &p); + getFlowShapers(false, &a, &b, &c, &d); lua_push_int_table_entry(vm, "shaper.srv2cli_a", a); lua_push_int_table_entry(vm, "shaper.srv2cli_b", b); + lua_push_int_table_entry(vm, "shaper.srv2cli_c", c); + lua_push_int_table_entry(vm, "shaper.srv2cli_d", d); } - +#endif + if(isHTTP() && protos.http.last_method && protos.http.last_url) lua_push_str_table_entry(vm, "protos.http.last_url", protos.http.last_url); @@ -1918,7 +1944,7 @@ void Flow::incStats(bool cli2srv_direction, u_int pkt_len, u_int8_t *payload, u_int payload_len, u_int8_t l4_proto, const struct timeval *when) { payload_len *= iface->getScalingFactor(); - + updateSeen(); updatePacketStats(cli2srv_direction ? &cli2srvStats.pktTime : &srv2cliStats.pktTime, when); @@ -2084,7 +2110,7 @@ void Flow::incTcpBadStats(bool src2dst_direction, TCPPacketStats * stats; /*Host * host;*/ - if (src2dst_direction) { + if(src2dst_direction) { stats = &tcp_stats_s2d; /*host = cli_host;*/ } else { @@ -2383,8 +2409,8 @@ bool Flow::isPassVerdict() { /* TODO: isAboveQuota() must be checked periodically */ if(cli_host && srv_host) - return(!(cli_host->isAboveQuota() || srv_host->isAboveQuota()) && - !(cli_host->dropAllTraffic() || srv_host->dropAllTraffic())); + return((!(cli_host->isAboveQuota() || srv_host->isAboveQuota())) + && (!(cli_host->dropAllTraffic() || srv_host->dropAllTraffic()))); else return(true); } @@ -2433,19 +2459,22 @@ void Flow::checkFlowCategory() { /* *************************************** */ +#ifdef NTOPNG_PRO void Flow::getFlowShapers(bool src2dst_direction, int *a_shaper_id, int *b_shaper_id, - u_int16_t *ndpiProtocol) { + int *c_shaper_id, int *d_shaper_id) { if(cli_host && srv_host) { - if(src2dst_direction) - *a_shaper_id = cli_host->get_egress_shaper_id(), *b_shaper_id = srv_host->get_ingress_shaper_id(); - else - *a_shaper_id = cli_host->get_ingress_shaper_id(), *b_shaper_id = srv_host->get_egress_shaper_id(); + if(src2dst_direction) { + *a_shaper_id = cli_host->get_egress_shaper_id(), *b_shaper_id = srv_host->get_ingress_shaper_id(), + *c_shaper_id = flow_shapers.src2dst.cli, *d_shaper_id = flow_shapers.src2dst.srv; + } else { + *a_shaper_id = cli_host->get_ingress_shaper_id(), *b_shaper_id = srv_host->get_egress_shaper_id(), + *c_shaper_id = flow_shapers.dst2src.cli, *d_shaper_id = flow_shapers.dst2src.srv; + } } else - *a_shaper_id = *b_shaper_id = -1; - - *ndpiProtocol = ndpiDetectedProtocol.protocol; + *a_shaper_id = *b_shaper_id = *c_shaper_id = *d_shaper_id = -1; } +#endif /* *************************************** */ diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp index 47251cd9b6..2dda548b11 100644 --- a/src/NetworkInterface.cpp +++ b/src/NetworkInterface.cpp @@ -880,7 +880,6 @@ bool NetworkInterface::processPacket(const struct bpf_timeval *when, u_int32_t rawsize, const struct pcap_pkthdr *h, const u_char *packet, - bool *shaped, u_int16_t *ndpiProtocol) { bool src2dst_direction; u_int8_t l4_proto; @@ -895,7 +894,6 @@ bool NetworkInterface::processPacket(const struct bpf_timeval *when, u_int8_t *ip; bool is_fragment = false, new_flow; bool pass_verdict = true; - int a_shaper_id = -1, b_shaper_id = -1; if(vlanInterfaces && (vlan_id > 0)) { if((vlanInterfaces[vlan_id] == NULL) @@ -915,7 +913,7 @@ bool NetworkInterface::processPacket(const struct bpf_timeval *when, if(vlanInterfaces[vlan_id]) return(vlanInterfaces[vlan_id]->processPacket(when, time, eth, vlan_id, iph, ip6, ipsize, rawsize, - h, packet, shaped, ndpiProtocol)); + h, packet, ndpiProtocol)); } decode_ip: @@ -1213,31 +1211,14 @@ bool NetworkInterface::processPacket(const struct bpf_timeval *when, flow->dissectSSL(payload, payload_len, when, src2dst_direction); } - flow->processDetectedProtocol(), *shaped = false; - pass_verdict = flow->isPassVerdict(); - flow->getFlowShapers(src2dst_direction, &a_shaper_id, &b_shaper_id, ndpiProtocol); + flow->processDetectedProtocol(), pass_verdict = flow->isPassVerdict(); #ifdef NTOPNG_PRO if(is_bridge_interface() && pass_verdict) { - int ingress_proto_shaper = -1, egress_proto_shaper = -1; - - /* Get the per-network protocol shapers */ - if(policer && flow->get_cli_host() && flow->get_srv_host()) { - l7_policy_direction cli_dir, srv_dir; - - if(src2dst_direction) - cli_dir = L7_POLICY_DIRECTION_INGRESS, srv_dir = L7_POLICY_DIRECTION_EGRESS; - else - cli_dir = L7_POLICY_DIRECTION_EGRESS, srv_dir = L7_POLICY_DIRECTION_INGRESS; - - ingress_proto_shaper = policer->getShaperIdForProtocol(flow->get_cli_host()->getL7NetworkIndex(), *ndpiProtocol, cli_dir); - egress_proto_shaper = policer->getShaperIdForProtocol(flow->get_srv_host()->getL7NetworkIndex(), *ndpiProtocol, srv_dir); - } else { - ingress_proto_shaper = egress_proto_shaper = -1; - } - - pass_verdict = passShaperPacket(a_shaper_id, b_shaper_id, ingress_proto_shaper, egress_proto_shaper, (struct pcap_pkthdr*)h); - if(!pass_verdict) *shaped = true; + int a_shaper_id, b_shaper_id, c_shaper_id, d_shaper_id; + + flow->getFlowShapers(src2dst_direction, &a_shaper_id, &b_shaper_id, &c_shaper_id, &d_shaper_id); + pass_verdict = passShaperPacket(a_shaper_id, b_shaper_id, c_shaper_id, d_shaper_id, (struct pcap_pkthdr*)h); } #endif @@ -1319,7 +1300,7 @@ void NetworkInterface::purgeIdle(time_t when) { /* **************************************************** */ bool NetworkInterface::dissectPacket(const struct pcap_pkthdr *h, - const u_char *packet, bool *shaped, + const u_char *packet, u_int16_t *ndpiProtocol) { struct ndpi_ethhdr *ethernet, dummy_ethernet; u_int64_t time; @@ -1558,7 +1539,7 @@ bool NetworkInterface::dissectPacket(const struct pcap_pkthdr *h, try { pass_verdict = processPacket(&h->ts, time, ethernet, vlan_id, iph, ip6, h->caplen - ip_offset, rawsize, - h, packet, shaped, ndpiProtocol); + h, packet, ndpiProtocol); } catch(std::bad_alloc& ba) { static bool oom_warning_sent = false; @@ -1644,7 +1625,7 @@ bool NetworkInterface::dissectPacket(const struct pcap_pkthdr *h, try { pass_verdict = processPacket(&h->ts, time, ethernet, vlan_id, iph, ip6, h->len - ip_offset, rawsize, - h, packet, shaped, ndpiProtocol); + h, packet, ndpiProtocol); } catch(std::bad_alloc& ba) { static bool oom_warning_sent = false; diff --git a/src/PF_RINGInterface.cpp b/src/PF_RINGInterface.cpp index 9a513f9ca4..e36314589d 100644 --- a/src/PF_RINGInterface.cpp +++ b/src/PF_RINGInterface.cpp @@ -101,12 +101,10 @@ static void* packetPollLoop(void* ptr) { if(pfring_recv(pd, &buffer, 0, &hdr, 0 /* wait_for_packet */) > 0) { try { - bool shaped; u_int16_t p; if(hdr.ts.tv_sec == 0) gettimeofday(&hdr.ts, NULL); - iface->dissectPacket((const struct pcap_pkthdr *) &hdr, buffer, - &shaped, &p); + iface->dissectPacket((const struct pcap_pkthdr *) &hdr, buffer, &p); } catch(std::bad_alloc& ba) { static bool oom_warning_sent = false; diff --git a/src/PcapInterface.cpp b/src/PcapInterface.cpp index 20b49a8f38..c7d1111a00 100644 --- a/src/PcapInterface.cpp +++ b/src/PcapInterface.cpp @@ -165,7 +165,6 @@ static void* packetPollLoop(void* ptr) { if((rc = pcap_next_ex(pd, &hdr, &pkt)) > 0) { if((rc > 0) && (pkt != NULL) && (hdr->caplen > 0)) { u_int16_t p; - bool shaped; #ifdef WIN32 /* @@ -182,10 +181,10 @@ static void* packetPollLoop(void* ptr) { hdr_copy.len = min(hdr->len, sizeof(pkt_copy) - 1); hdr_copy.caplen = min(hdr_copy.len, hdr_copy.caplen); memcpy(pkt_copy, pkt, hdr_copy.len); - iface->dissectPacket(&hdr_copy, (const u_char*)pkt_copy, &shaped, &p); + iface->dissectPacket(&hdr_copy, (const u_char*)pkt_copy, &p); #else hdr->caplen = min_val(hdr->caplen, iface->getMTU()); - iface->dissectPacket(hdr, pkt, &shaped, &p); + iface->dissectPacket(hdr, pkt, &p); #endif } } else if(rc < 0) {