diff --git a/include/Flow.h b/include/Flow.h
index 4897ad8894..8e9f4ae69f 100644
--- a/include/Flow.h
+++ b/include/Flow.h
@@ -80,6 +80,8 @@ class Flow : public GenericHashEntry {
u_int8_t routing_table_id;
#ifndef HAVE_OLD_NEDGE
FlowProfile *trafficProfile;
+#else
+ u_int16_t cli2srv_in, cli2srv_out, srv2cli_in, srv2cli_out;
#endif
CounterTrend throughputTrend, goodputTrend, thptRatioTrend;
#endif
@@ -257,7 +259,7 @@ class Flow : public GenericHashEntry {
bool checkPassVerdict(const struct tm *now);
bool isPassVerdict();
#endif
- inline void setDropVerdict() { passVerdict = false; };
+ void setDropVerdict();
void incFlowDroppedCounters();
u_int32_t getPid(bool client);
diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua
index e0509f25d0..37cf0b6249 100644
--- a/scripts/locales/en.lua
+++ b/scripts/locales/en.lua
@@ -2438,6 +2438,10 @@ local en = {
safe_search_description = "Use the Safe Search DNS to block inappropriate content.",
enforce_global_dns = "Enforce Global DNS",
enforce_global_dns_description = "Enable DNS forging to force the devices to use the specified global DNS.",
+ shapers = "Shapers",
+ adaptive_rate = "Adaptive Rate",
+ adaptive_rate_description = "When the adaptive rate is enabled, the available bandwidth will be shared across the active devices to maximize bandwidth utilization. You can disabled adaptive rate to shape a-priori regardless of the available bandwidth.",
+ you_can_assign_shapers_to_users_protocols = "You can assign shapers to Users specific protocols or set them globally as a Fallback Policy.",
},
}
diff --git a/scripts/lua/modules/http_lint.lua b/scripts/lua/modules/http_lint.lua
index 1f0fa377e1..bc7a8e283c 100644
--- a/scripts/lua/modules/http_lint.lua
+++ b/scripts/lua/modules/http_lint.lua
@@ -1074,6 +1074,7 @@ local known_parameters = {
["hostname"] = validateSingleWord,
["delete"] = validateEmpty,
["reset_quotas"] = validateEmpty,
+ ["adaptive_rate"] = validateBool,
-- json POST DATA
["payload"] = validateJSON
diff --git a/src/Flow.cpp b/src/Flow.cpp
index 073908b256..eab5c2aba2 100644
--- a/src/Flow.cpp
+++ b/src/Flow.cpp
@@ -105,6 +105,8 @@ Flow::Flow(NetworkInterface *_iface,
#ifdef NTOPNG_PRO
#ifndef HAVE_OLD_NEDGE
trafficProfile = NULL;
+#else
+ cli2srv_in = cli2srv_out = srv2cli_in = srv2cli_out = DEFAULT_SHAPER_ID;
#endif
memset(&flowShaperIds, 0, sizeof(flowShaperIds));
#endif
@@ -776,6 +778,17 @@ bool Flow::dumpFlow(bool idle_flow) {
/* *************************************** */
+void Flow::setDropVerdict() {
+#ifdef HAVE_NEDGE
+ if((iface->getIfType() == interface_type_NETFILTER) && (passVerdict == true))
+ ((NetfilterInterface *) iface)->setPolicyChanged();
+#endif
+
+ passVerdict = false;
+}
+
+/* *************************************** */
+
void Flow::incFlowDroppedCounters() {
if(!flow_dropped_counts_increased) {
if(cli_host) {
@@ -2717,9 +2730,19 @@ bool Flow::updateDirectionShapers(bool src2dst_direction, TrafficShaper **ingres
*ingress_shaper = srv_host->get_ingress_shaper(ndpiDetectedProtocol),
*egress_shaper = cli_host->get_egress_shaper(ndpiDetectedProtocol);
+#ifdef HAVE_NEDGE
+ if(*ingress_shaper) srv2cli_in = (*ingress_shaper)->get_shaper_id();
+ if(*egress_shaper) cli2srv_out = (*egress_shaper)->get_shaper_id();
+#endif
+
} else {
*ingress_shaper = cli_host->get_ingress_shaper(ndpiDetectedProtocol),
*egress_shaper = srv_host->get_egress_shaper(ndpiDetectedProtocol);
+
+#ifdef HAVE_NEDGE
+ if(*ingress_shaper) cli2srv_in = (*ingress_shaper)->get_shaper_id();
+ if(*egress_shaper) srv2cli_out = (*egress_shaper)->get_shaper_id();
+#endif
}
if((*ingress_shaper && (*ingress_shaper)->shaping_enabled() && (*ingress_shaper)->get_max_rate_kbit_sec() == 0)
@@ -2739,6 +2762,11 @@ void Flow::updateFlowShapers(bool first_update) {
bool cli2srv_verdict, srv2cli_verdict;
#ifdef HAVE_NEDGE
bool old_verdict = passVerdict;
+
+ u_int16_t old_cli2srv_in = cli2srv_in,
+ old_cli2srv_out = cli2srv_out,
+ old_srv2cli_in = srv2cli_in,
+ old_srv2cli_out = srv2cli_out;
#endif
/* Check if this application protocol is allowd for the specified device type */
@@ -2764,7 +2792,12 @@ void Flow::updateFlowShapers(bool first_update) {
passVerdict = (cli2srv_verdict && srv2cli_verdict);
#if defined(HAVE_NEDGE) && defined(HAVE_NETFILTER)
- if((!first_update) && (iface->getIfType() == interface_type_NETFILTER) && (old_verdict == true) && (passVerdict == false))
+ if((!first_update) && (iface->getIfType() == interface_type_NETFILTER) &&
+ (((old_verdict != passVerdict)) ||
+ (old_cli2srv_in != cli2srv_in) ||
+ (old_cli2srv_out != cli2srv_out) ||
+ (old_srv2cli_in != srv2cli_in) ||
+ (old_srv2cli_out != srv2cli_out)))
((NetfilterInterface *) iface)->setPolicyChanged();
#endif
diff --git a/src/Lua.cpp b/src/Lua.cpp
index ed5259fca5..7ba6e218a8 100644
--- a/src/Lua.cpp
+++ b/src/Lua.cpp
@@ -3399,6 +3399,16 @@ static int ntop_get_policy_change_marker(lua_State* vm) {
return(CONST_LUA_OK);
}
+static int ntop_update_flows_shapers(lua_State* vm) {
+ NetworkInterface *ntop_interface = getCurrentInterface(vm);
+
+ if(ntop_interface)
+ ntop_interface->updateFlowsL7Policy();
+
+ lua_pushnil(vm);
+ return(CONST_LUA_OK);
+}
+
#endif
/* ****************************************** */
@@ -6833,7 +6843,7 @@ static const luaL_Reg ntop_interface_reg[] = {
{ "setLanIpAddress", ntop_set_lan_ip_address },
{ "getPolicyChangeMarker", ntop_get_policy_change_marker },
-
+ { "updateFlowsShapers", ntop_update_flows_shapers },
#endif
/* Network Discovery */
diff --git a/src/NetworkInterface.cpp b/src/NetworkInterface.cpp
index 64d0133bdd..e817b456db 100644
--- a/src/NetworkInterface.cpp
+++ b/src/NetworkInterface.cpp
@@ -6398,7 +6398,7 @@ bool NetworkInterface::updateFlowStats(u_int8_t protocol,
bool old_verdict = f->isPassVerdict();
bool new_verdict = f->checkPassVerdict(&now);
- if((old_verdict == true) && (new_verdict == false))
+ if(old_verdict != new_verdict)
return true;
#endif
#ifdef DEBUG