Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jason Wang and committed by
David S. Miller
b8732fb7 edfb6a14

+6 -1
+6 -1
drivers/net/tun.c
··· 113 113 * the netdevice to be fit in one page. So we can make sure the success of 114 114 * memory allocation. TODO: increase the limit. */ 115 115 #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES 116 + #define MAX_TAP_FLOWS 4096 116 117 117 118 #define TUN_FLOW_EXPIRE (3 * HZ) 118 119 ··· 186 185 unsigned int numdisabled; 187 186 struct list_head disabled; 188 187 void *security; 188 + u32 flow_count; 189 189 }; 190 190 191 191 static inline u32 tun_hashfn(u32 rxhash) ··· 220 218 e->queue_index = queue_index; 221 219 e->tun = tun; 222 220 hlist_add_head_rcu(&e->hash_link, head); 221 + ++tun->flow_count; 223 222 } 224 223 return e; 225 224 } ··· 231 228 e->rxhash, e->queue_index); 232 229 hlist_del_rcu(&e->hash_link); 233 230 kfree_rcu(e, rcu); 231 + --tun->flow_count; 234 232 } 235 233 236 234 static void tun_flow_flush(struct tun_struct *tun) ··· 321 317 e->updated = jiffies; 322 318 } else { 323 319 spin_lock_bh(&tun->lock); 324 - if (!tun_flow_find(head, rxhash)) 320 + if (!tun_flow_find(head, rxhash) && 321 + tun->flow_count < MAX_TAP_FLOWS) 325 322 tun_flow_create(tun, head, rxhash, queue_index); 326 323 327 324 if (!timer_pending(&tun->flow_gc_timer))