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