Commit 0769f25f authored by Julien Muchembled's avatar Julien Muchembled

Do not recreate client tap interfaces all the time

parent 76cbea0c
import logging, random, socket, time import logging, random, socket, subprocess, threading, time
from collections import deque
from itertools import chain from itertools import chain
from . import plib, utils from . import plib, utils
...@@ -63,8 +64,40 @@ class TunnelManager(object): ...@@ -63,8 +64,40 @@ class TunnelManager(object):
self._client_count = client_count self._client_count = client_count
self._refresh_count = 1 self._refresh_count = 1
self.free_interface_set = set('re6stnet' + str(i) self.new_iface_list = deque('re6stnet' + str(i)
for i in xrange(1, client_count + 1)) for i in xrange(1, self._client_count + 1))
self._free_iface_list = []
def _tuntap(self, iface=None):
if iface:
self.new_iface_list.appendleft(iface)
action = 'del'
else:
iface = self.new_iface_list.popleft()
action = 'add'
args = 'ip', 'tuntap', action, 'dev', iface, 'mode', 'tap'
logging.debug('%r', args)
subprocess.call(args)
return iface
def delInterfaces(self):
iface_list = self._free_iface_list
iface_list += self._iface_to_prefix
self._iface_to_prefix.clear()
while iface_list:
self._tuntap(iface_list.pop())
def getFreeInterface(self, prefix):
try:
iface = self._free_iface_list.pop()
except IndexError:
iface = self._tuntap()
self._iface_to_prefix[iface] = prefix
return iface
def freeInterface(self, iface):
self._free_iface_list.append(iface)
del self._iface_to_prefix[iface]
def refresh(self): def refresh(self):
logging.debug('Checking tunnels...') logging.debug('Checking tunnels...')
...@@ -76,6 +109,8 @@ class TunnelManager(object): ...@@ -76,6 +109,8 @@ class TunnelManager(object):
self._next_tunnel_refresh = time.time() + self._refresh_time self._next_tunnel_refresh = time.time() + self._refresh_time
self._peer_db.log() self._peer_db.log()
self._makeNewTunnels(remove) self._makeNewTunnels(remove)
if remove and self._free_iface_list:
self._tuntap(self._free_iface_list.pop())
self.next_refresh = time.time() + 5 self.next_refresh = time.time() + 5
def _cleanDeads(self): def _cleanDeads(self):
...@@ -95,13 +130,17 @@ class TunnelManager(object): ...@@ -95,13 +130,17 @@ class TunnelManager(object):
logging.info('Killing the connection with %u/%u...', logging.info('Killing the connection with %u/%u...',
int(prefix, 2), len(prefix)) int(prefix, 2), len(prefix))
connection = self._connection_dict.pop(prefix) connection = self._connection_dict.pop(prefix)
self.freeInterface(connection.iface)
p = connection.process
try: try:
getattr(connection.process, 'kill' if kill else 'terminate')() getattr(p, 'kill' if kill else 'terminate')()
except OSError: except OSError:
# If the process is already exited pass # we already polled an exited process
pass else:
self.free_interface_set.add(connection.iface) t = threading.Timer(5, p.kill)
del self._iface_to_prefix[connection.iface] kill or t.start()
p.wait()
t.cancel()
logging.trace('Connection with %u/%u killed', logging.trace('Connection with %u/%u killed',
int(prefix, 2), len(prefix)) int(prefix, 2), len(prefix))
...@@ -112,10 +151,9 @@ class TunnelManager(object): ...@@ -112,10 +151,9 @@ class TunnelManager(object):
assert prefix != self._prefix, self.__dict__ assert prefix != self._prefix, self.__dict__
logging.info('Establishing a connection with %u/%u', logging.info('Establishing a connection with %u/%u',
int(prefix, 2), len(prefix)) int(prefix, 2), len(prefix))
iface = self.free_interface_set.pop() iface = self.getFreeInterface(prefix)
self._connection_dict[prefix] = Connection(address, self._write_pipe, self._connection_dict[prefix] = Connection(address, self._write_pipe,
self._timeout, iface, prefix, self._encrypt, self._ovpn_args) self._timeout, iface, prefix, self._encrypt, self._ovpn_args)
self._iface_to_prefix[iface] = prefix
self._peer_db.connecting(prefix, 1) self._peer_db.connecting(prefix, 1)
return True return True
......
...@@ -189,7 +189,7 @@ def main(): ...@@ -189,7 +189,7 @@ def main():
config.openvpn_args, timeout, config.tunnel_refresh, config.openvpn_args, timeout, config.tunnel_refresh,
config.client_count, config.iface_list, network, prefix, config.client_count, config.iface_list, network, prefix,
address, ip_changed, config.encrypt) address, ip_changed, config.encrypt)
tunnel_interfaces += tunnel_manager.free_interface_set tunnel_interfaces += tunnel_manager.new_iface_list
else: else:
tunnel_manager = write_pipe = None tunnel_manager = write_pipe = None
...@@ -262,7 +262,7 @@ def main(): ...@@ -262,7 +262,7 @@ def main():
# main loop # main loop
if tunnel_manager is None: if tunnel_manager is None:
sys.exit(os.WEXITSTATUS(os.wait()[1])) sys.exit(os.WEXITSTATUS(os.wait()[1]))
cleanup.append(tunnel_manager.killAll) cleanup += tunnel_manager.delInterfaces, tunnel_manager.killAll
while True: while True:
next = tunnel_manager.next_refresh next = tunnel_manager.next_refresh
if forwarder: if forwarder:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment