Commit 29667636 authored by Julien Muchembled's avatar Julien Muchembled

Reset --tunnel-refresh countdown when a tunnel is created

This prevents re6stnet from killing tunnels prematurely.
parent d46b09e1
......@@ -39,10 +39,12 @@ class MultiGatewayManager(dict):
class Connection(object):
def __init__(self, address_list, iface, prefix):
_retry = routes = 0
def __init__(self, tunnel_manager, address_list, iface, prefix):
self.tunnel_manager = tunnel_manager
self.address_list = address_list
self.iface = iface
self.routes = 0
self._prefix = prefix
def __iter__(self):
......@@ -56,26 +58,24 @@ class Connection(object):
self._remote_ip_set.add(ip)
return iter(self._remote_ip_set)
def open(self, write_pipe, timeout, encrypt, ovpn_args, _retry=0):
def open(self):
tm = self.tunnel_manager
self.process = plib.client(
self.iface, (self.address_list[_retry],), encrypt,
self.iface, (self.address_list[self._retry],), tm.encrypt,
'--tls-remote', '%u/%u' % (int(self._prefix, 2), len(self._prefix)),
'--resolv-retry', '0',
'--connect-retry-max', '3', '--tls-exit',
'--remap-usr1', 'SIGTERM',
'--ping-exit', str(timeout),
'--route-up', '%s %u' % (plib.ovpn_client, write_pipe),
*ovpn_args)
_retry += 1
self._retry = _retry < len(self.address_list) and (
write_pipe, timeout, encrypt, ovpn_args, _retry)
def connected(self, db):
try:
i = self._retry[-1] - 1
self._retry = None
except TypeError:
i = len(self.address_list) - 1
'--ping-exit', str(tm.timeout),
'--route-up', '%s %u' % (plib.ovpn_client, tm.write_pipe),
*tm.ovpn_args)
tm.resetTunnelRefresh()
self._retry += 1
def connected(self):
i = self._retry - 1
self._retry = None
db = self.tunnel_manager.peer_db
if i:
db.addPeer(self._prefix, ','.join(self.address_list[i]), True)
else:
......@@ -92,11 +92,11 @@ class Connection(object):
if self.process.poll() != None:
logging.info('Connection with %s has failed with return code %s',
self._prefix, self.process.returncode)
if not self._retry:
if self._retry is None or len(self.address_list) <= self._retry:
return False
logging.info('Retrying with alternate address')
self.close()
self.open(*self._retry)
self.open()
return True
......@@ -106,22 +106,22 @@ class TunnelManager(object):
refresh, client_count, iface_list, network, prefix,
address, ip_changed, encrypt, remote_gateway, disable_proto,
neighbour_list=()):
self._write_pipe = write_pipe
self._peer_db = peer_db
self.encrypt = encrypt
self.ovpn_args = openvpn_args
self.peer_db = peer_db
self.timeout = timeout
self.write_pipe = write_pipe
self._connecting = set()
self._connection_dict = {}
self._disconnected = None
self._distant_peers = []
self._iface_to_prefix = {}
self._ovpn_args = openvpn_args
self._timeout = timeout
self._refresh_time = refresh
self._network = network
self._iface_list = iface_list
self._prefix = prefix
self._address = utils.dump_address(address)
self._ip_changed = ip_changed
self._encrypt = encrypt
self._gateway_manager = MultiGatewayManager(remote_gateway) \
if remote_gateway else None
self._disable_proto = disable_proto
......@@ -134,13 +134,16 @@ class TunnelManager(object):
self.sock.bind(('::', PORT))
self.next_refresh = time.time()
self._next_tunnel_refresh = time.time()
self.resetTunnelRefresh()
self._client_count = client_count
self.new_iface_list = deque('re6stnet' + str(i)
for i in xrange(1, self._client_count + 1))
self._free_iface_list = []
def resetTunnelRefresh(self):
self._next_tunnel_refresh = time.time() + self._refresh_time
def _tuntap(self, iface=None):
if iface:
self.new_iface_list.appendleft(iface)
......@@ -179,8 +182,8 @@ class TunnelManager(object):
if remove:
self._countRoutes()
self._removeSomeTunnels()
self._next_tunnel_refresh = time.time() + self._refresh_time
self._peer_db.log()
self.resetTunnelRefresh()
self.peer_db.log()
self._makeNewTunnels(remove)
# XXX: Commented code is an attempt to clean up unused interfaces but
# it is too aggressive. Sometimes _makeNewTunnels only asks address
......@@ -231,18 +234,18 @@ class TunnelManager(object):
assert prefix != self._prefix, self.__dict__
address = [x for x in utils.parse_address(address)
if x[2] not in self._disable_proto]
self._peer_db.connecting(prefix, 1)
self.peer_db.connecting(prefix, 1)
if not address:
return False
logging.info('Establishing a connection with %u/%u',
int(prefix, 2), len(prefix))
with utils.exit:
iface = self._getFreeInterface(prefix)
self._connection_dict[prefix] = c = Connection(address, iface, prefix)
self._connection_dict[prefix] = c = Connection(self, address, iface, prefix)
if self._gateway_manager is not None:
for ip in c:
self._gateway_manager.add(ip, True)
c.open(self._write_pipe, self._timeout, self._encrypt, self._ovpn_args)
c.open()
return True
def _makeNewTunnels(self, route_counted):
......@@ -270,7 +273,7 @@ class TunnelManager(object):
if disconnected:
# We do have neighbours that are probably also disconnected,
# so force rebootstrapping.
peer = self._peer_db.getBootstrapPeer()
peer = self.peer_db.getBootstrapPeer()
if not peer:
# Registry dead ? Assume we're connected after all.
disconnected = None
......@@ -291,7 +294,7 @@ class TunnelManager(object):
peer = distant_peers[i]
distant_peers[i] = distant_peers[-1]
del distant_peers[-1]
address = self._peer_db.getAddress(peer)
address = self.peer_db.getAddress(peer)
if address:
count -= self._makeTunnel(peer, address)
else:
......@@ -307,7 +310,7 @@ class TunnelManager(object):
# up. Select peers from cache for which we have no route.
new = 0
bootstrap = True
for peer, address in self._peer_db.getPeerList():
for peer, address in self.peer_db.getPeerList():
if peer not in disconnected:
logging.info("Try to bootstrap using peer %u/%u",
int(peer, 2), len(peer))
......@@ -319,12 +322,12 @@ class TunnelManager(object):
if not (new or disconnected):
if bootstrap:
# Startup without any good address in the cache.
peer = self._peer_db.getBootstrapPeer()
peer = self.peer_db.getBootstrapPeer()
if peer and self._makeTunnel(*peer):
return
# Failed to bootstrap ! Last change to connect is to
# retry an address that already failed :(
for peer in self._peer_db.getPeerList(1):
for peer in self.peer_db.getPeerList(1):
if self._makeTunnel(*peer):
break
......@@ -345,7 +348,7 @@ class TunnelManager(object):
other.append(prefix)
else:
self._distant_peers.append(prefix)
registry = self._peer_db.registry_prefix
registry = self.peer_db.registry_prefix
if registry == self._prefix or any(registry in x for x in (
self._distant_peers, other, self._served, self._connection_dict)):
self._disconnected = None
......@@ -385,7 +388,7 @@ class TunnelManager(object):
self._gateway_manager.add(trusted_ip, False)
if prefix in self._connection_dict and self._prefix < prefix:
self._kill(prefix)
self._peer_db.connecting(prefix, 0)
self.peer_db.connecting(prefix, 0)
def _ovpn_client_disconnect(self, common_name, trusted_ip):
prefix = utils.binFromSubnet(common_name)
......@@ -399,7 +402,7 @@ class TunnelManager(object):
def _ovpn_route_up(self, common_name, ip):
prefix = utils.binFromSubnet(common_name)
try:
self._connection_dict[prefix].connected(self._peer_db)
self._connection_dict[prefix].connected()
except KeyError:
pass
if self._ip_changed:
......@@ -420,7 +423,7 @@ class TunnelManager(object):
pass
else:
if prefix != self._prefix:
self._peer_db.addPeer(prefix, address)
self.peer_db.addPeer(prefix, address)
try:
self._connecting.remove(prefix)
except KeyError:
......@@ -438,7 +441,7 @@ class TunnelManager(object):
elif code == 255:
# the registry wants to know the topology for debugging purpose
if utils.binFromIp(address[0])[len(self._network):].startswith(
self._peer_db.registry_prefix):
self.peer_db.registry_prefix):
msg = ['\xfe%s%u/%u\n%u\n' % (msg[1:],
int(self._prefix, 2), len(self._prefix),
len(self._connection_dict))]
......
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