aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-01-22 22:59:13 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-23 13:47:06 -0500
commitb8732fb7f8920e2f6216d2b67faf8b0b0d67ca81 (patch)
tree9e4f5052cea423ec1302e2175211d58adee0e300
parentedfb6a148ce62e5e19354a1dcd9a34e00815c2a1 (diff)
tuntap: limit the number of flow caches
We create new flow caches when a new flow is identified by tuntap, This may lead some issues: - userspace may produce a huge amount of short live flows to exhaust host memory - the unlimited number of flow caches may produce a long list which increase the time in the linear searching Solve this by introducing a limit of total number of flow caches. Cc: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tun.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8939d2117de2..cc09b67c23bc 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -113,6 +113,7 @@ struct tap_filter {
113 * the netdevice to be fit in one page. So we can make sure the success of 113 * the netdevice to be fit in one page. So we can make sure the success of
114 * memory allocation. TODO: increase the limit. */ 114 * memory allocation. TODO: increase the limit. */
115#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES 115#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
116#define MAX_TAP_FLOWS 4096
116 117
117#define TUN_FLOW_EXPIRE (3 * HZ) 118#define TUN_FLOW_EXPIRE (3 * HZ)
118 119
@@ -185,6 +186,7 @@ struct tun_struct {
185 unsigned int numdisabled; 186 unsigned int numdisabled;
186 struct list_head disabled; 187 struct list_head disabled;
187 void *security; 188 void *security;
189 u32 flow_count;
188}; 190};
189 191
190static inline u32 tun_hashfn(u32 rxhash) 192static inline u32 tun_hashfn(u32 rxhash)
@@ -218,6 +220,7 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
218 e->queue_index = queue_index; 220 e->queue_index = queue_index;
219 e->tun = tun; 221 e->tun = tun;
220 hlist_add_head_rcu(&e->hash_link, head); 222 hlist_add_head_rcu(&e->hash_link, head);
223 ++tun->flow_count;
221 } 224 }
222 return e; 225 return e;
223} 226}
@@ -228,6 +231,7 @@ static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
228 e->rxhash, e->queue_index); 231 e->rxhash, e->queue_index);
229 hlist_del_rcu(&e->hash_link); 232 hlist_del_rcu(&e->hash_link);
230 kfree_rcu(e, rcu); 233 kfree_rcu(e, rcu);
234 --tun->flow_count;
231} 235}
232 236
233static void tun_flow_flush(struct tun_struct *tun) 237static void tun_flow_flush(struct tun_struct *tun)
@@ -317,7 +321,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
317 e->updated = jiffies; 321 e->updated = jiffies;
318 } else { 322 } else {
319 spin_lock_bh(&tun->lock); 323 spin_lock_bh(&tun->lock);
320 if (!tun_flow_find(head, rxhash)) 324 if (!tun_flow_find(head, rxhash) &&
325 tun->flow_count < MAX_TAP_FLOWS)
321 tun_flow_create(tun, head, rxhash, queue_index); 326 tun_flow_create(tun, head, rxhash, queue_index);
322 327
323 if (!timer_pending(&tun->flow_gc_timer)) 328 if (!timer_pending(&tun->flow_gc_timer))