Re: [PATCH 3/5] net: add udp limit to net cgroup

2016-08-15 Thread Mahesh Bandewar
On Fri, Aug 12, 2016 at 9:35 PM, Alexei Starovoitov
 wrote:
[...]
>> * 'net.udp_usage': Reading this file gives the number of udp ports used by
>> processes in this cgroup and all its descendants.
>> * 'net.udp_limit': Writing this file sets the total number of udp ports
>> that can be used by processes in this cgroup and all
>> its descendants. This file can also be read.
>> * 'net.udp_maxusage': Reading this file gives the highest value of
>> net.udp_usage that has been seen for this cgroup.
>> * 'net.udp_failcnt': Reading this file gives the number of times a
>> process in this cgroup or one of its descendants has attempted to acquire
>> a udp port but failed because the limit of this cgroup was reached.
>> * 'net.udp_underflowcnt': Reading this file gives the number of times a
>> process in this cgroup or one of its descendants released a udp port when
>> the usage value of this cgroup was 0.
>
> I have similar concern here. I don't think we should bloat the kernel by
> trying implement every possible port restriction combination and count.
> For the same reasons we don't do all possible tcp stats that research
> community finds useful. This additional code is a maintenance headache.
>
At this moment if a rampant process decides to just open a datagram
socket and just binds (does not listen) and does this for all
available ports, you are guaranteed to have machine becoming useless
for some (totally unrelated) legitimate process trying to do useful
things.

>From kernel we can't control such user-space behavior, but at least
restrict the damage to "a specific set of processes". This code
provides that feature to restrict the damage.

Additional code is always a maintenance headache but that doesn't stop
us from adding new code, isn't it? :)


Re: [PATCH 3/5] net: add udp limit to net cgroup

2016-08-12 Thread Alexei Starovoitov
On Wed, Aug 10, 2016 at 05:53:16PM -0700, Anoop Naravaram wrote:
> udp port limit
> --
> This property controls the limit of udp ports that can be used by the
> processes in a cgroup. The controller manages udp statistics (usage,
> limit, etc) for each cgroup. Every cgroup also keeps track of the udp
> ports acquired by its descendants. If a process tries to acquire a port
> when its cgroup has already reached its limit, it will fail with error
> EACCES. It will also fail if one of the cgroup's ancestors has reached its
> limit. There are 5 files exposed to userspace to configure this property:
> 
> * 'net.udp_usage': Reading this file gives the number of udp ports used by
> processes in this cgroup and all its descendants.
> * 'net.udp_limit': Writing this file sets the total number of udp ports
> that can be used by processes in this cgroup and all
> its descendants. This file can also be read.
> * 'net.udp_maxusage': Reading this file gives the highest value of
> net.udp_usage that has been seen for this cgroup.
> * 'net.udp_failcnt': Reading this file gives the number of times a
> process in this cgroup or one of its descendants has attempted to acquire
> a udp port but failed because the limit of this cgroup was reached.
> * 'net.udp_underflowcnt': Reading this file gives the number of times a
> process in this cgroup or one of its descendants released a udp port when
> the usage value of this cgroup was 0.

I have similar concern here. I don't think we should bloat the kernel by
trying implement every possible port restriction combination and count.
For the same reasons we don't do all possible tcp stats that research
community finds useful. This additional code is a maintenance headache.



[PATCH 3/5] net: add udp limit to net cgroup

2016-08-10 Thread Anoop Naravaram
udp port limit
--
This property controls the limit of udp ports that can be used by the
processes in a cgroup. The controller manages udp statistics (usage,
limit, etc) for each cgroup. Every cgroup also keeps track of the udp
ports acquired by its descendants. If a process tries to acquire a port
when its cgroup has already reached its limit, it will fail with error
EACCES. It will also fail if one of the cgroup's ancestors has reached its
limit. There are 5 files exposed to userspace to configure this property:

* 'net.udp_usage': Reading this file gives the number of udp ports used by
processes in this cgroup and all its descendants.
* 'net.udp_limit': Writing this file sets the total number of udp ports
that can be used by processes in this cgroup and all
its descendants. This file can also be read.
* 'net.udp_maxusage': Reading this file gives the highest value of
net.udp_usage that has been seen for this cgroup.
* 'net.udp_failcnt': Reading this file gives the number of times a
process in this cgroup or one of its descendants has attempted to acquire
a udp port but failed because the limit of this cgroup was reached.
* 'net.udp_underflowcnt': Reading this file gives the number of times a
process in this cgroup or one of its descendants released a udp port when
the usage value of this cgroup was 0.

When a new cgroup is created, its udp limit is copied from its parent.

Tested: Set the udp limit, then used python to use several udp ports,
ensuring that it is successful up until the limit, after which there
should be an error. Also tried different limits at different levels of the
hierarchy.

Signed-off-by: Anoop Naravaram 
---
 Documentation/cgroup-v1/net.txt |  26 
 include/net/net_cgroup.h|  29 +
 net/core/net_cgroup.c   | 273 
 net/ipv4/udp.c  |   8 ++
 4 files changed, 336 insertions(+)

diff --git a/Documentation/cgroup-v1/net.txt b/Documentation/cgroup-v1/net.txt
index 8c50c61..a14fd1c 100644
--- a/Documentation/cgroup-v1/net.txt
+++ b/Documentation/cgroup-v1/net.txt
@@ -30,6 +30,32 @@ This property is exposed to userspace through the 
'net.listen_port_ranges' file,
 as ranges of ports that the processes can listen on (as described in the HOW TO
 INTERACT WITH RANGES FILES section).
 
+udp port usage and limit
+
+This property controls the limit of udp ports that can be used by the
+processes in a cgroup. The controller manages udp statistics (usage, limit, 
etc)
+for each cgroup. Every cgroup also keeps track of the udp ports acquired by its
+descendants. If a process tries to acquire a port when its cgroup has
+already reached its limit, it will fail with error EACCES. It will also fail if
+one of the cgroup's ancestors has reached its limit. There are 5 files
+exposed to userspace to configure this property:
+
+* 'net.udp_usage': Reading this file gives the number of udp ports used by
+processes in this cgroup and all its descendants.
+* 'net.udp_limit': Writing this file sets the total number of udp ports
+that can be used by processes in this cgroup and all
+its descendants. This file can also be read.
+* 'net.udp_maxusage': Reading this file gives the highest value of
+net.udp_usage that has been seen for this cgroup.
+* 'net.udp_failcnt': Reading this file gives the number of times a
+process in this cgroup or one of its descendants has attempted to acquire a
+udp port but failed because the limit of this cgroup was reached.
+* 'net.udp_underflowcnt': Reading this file gives the number of times a
+process in this cgroup or one of its descendants released a udp port when the
+usage value of this cgroup was 0.
+
+When a new cgroup is created, its udp limit is copied from its parent.
+
 HOW TO INTERACT WITH RANGES FILES
 -
 Some cgroup properties can be expressed as ranges of allowed integers. From
diff --git a/include/net/net_cgroup.h b/include/net/net_cgroup.h
index 6ee79d5..25a9def 100644
--- a/include/net/net_cgroup.h
+++ b/include/net/net_cgroup.h
@@ -26,6 +26,16 @@ enum {
NETCG_NUM_RANGE_TYPES
 };
 
+/* udp statistic type */
+enum {
+   NETCG_LIMIT_UDP,
+   NETCG_USAGE_UDP,
+   NETCG_MAXUSAGE_UDP,
+   NETCG_FAILCNT_UDP,
+   NETCG_UNDERFLOWCNT_UDP,
+   NETCG_NUM_UDP_STATS
+};
+
 struct net_range {
u16 min_value;
u16 max_value;
@@ -43,9 +53,19 @@ struct net_range_types {
u16 upper_limit;
 };
 
+struct cgroup_udp_stats {
+   /* Use atomics to protect against multiple writers */
+   atomic64_t  udp_limitandusage; /* 32MSB => limit, 32LSB => usage */
+   atomic_tudp_maxusage;
+   atomic_tudp_failcnt;
+   atomic_tudp_underflowcnt;
+};
+
 struct net_cgroup {
struct cgroup_subsys_state  css;
 
+   struct cgroup_udp_stats udp_stats;
+
/* these fields are required for