Commit ee43ad04 authored by Julien Muchembled's avatar Julien Muchembled

New --neighbour option to make sure given peers are reachable directly

This is a workaround waiting that we have better criteria to select tunnels
to create or destroy.
parent bcb18c38
...@@ -10,3 +10,4 @@ key m1/cert.key ...@@ -10,3 +10,4 @@ key m1/cert.key
table 0 table 0
client-count 2 client-count 2
tunnel-refresh 100 tunnel-refresh 100
neighbour 6/16
...@@ -104,7 +104,8 @@ class TunnelManager(object): ...@@ -104,7 +104,8 @@ class TunnelManager(object):
def __init__(self, write_pipe, peer_db, openvpn_args, timeout, def __init__(self, write_pipe, peer_db, openvpn_args, timeout,
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=()):
self._write_pipe = write_pipe self._write_pipe = write_pipe
self._peer_db = peer_db self._peer_db = peer_db
self._connecting = set() self._connecting = set()
...@@ -124,6 +125,7 @@ class TunnelManager(object): ...@@ -124,6 +125,7 @@ class TunnelManager(object):
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
self._neighbour_set = set(map(utils.binFromSubnet, neighbour_list))
self._served = set() self._served = set()
self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
...@@ -135,7 +137,6 @@ class TunnelManager(object): ...@@ -135,7 +137,6 @@ class TunnelManager(object):
self._next_tunnel_refresh = time.time() self._next_tunnel_refresh = time.time()
self._client_count = client_count self._client_count = client_count
self._refresh_count = 1
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 = []
...@@ -190,13 +191,17 @@ class TunnelManager(object): ...@@ -190,13 +191,17 @@ class TunnelManager(object):
if not self._connection_dict[prefix].refresh(): if not self._connection_dict[prefix].refresh():
self._kill(prefix) self._kill(prefix)
def _tunnelScore(self, prefix):
n = self._connection_dict[prefix].routes
return (prefix in self._neighbour_set, n) if n else ()
def _removeSomeTunnels(self): def _removeSomeTunnels(self):
# Get the candidates to killing # Get the candidates to killing
candidates = sorted(self._connection_dict, key=lambda p: count = len(self._connection_dict) - self._client_count + 1
self._connection_dict[p].routes) if count > 0:
for prefix in candidates[0: max(0, len(self._connection_dict) - for prefix in sorted(self._connection_dict,
self._client_count + self._refresh_count)]: key=self._tunnelScore)[:count]:
self._kill(prefix) self._kill(prefix)
def _kill(self, prefix): def _kill(self, prefix):
logging.info('Killing the connection with %u/%u...', logging.info('Killing the connection with %u/%u...',
...@@ -267,9 +272,14 @@ class TunnelManager(object): ...@@ -267,9 +272,14 @@ class TunnelManager(object):
if disconnected is None: if disconnected is None:
# Normal operation. Choose peers to connect to by looking at the # Normal operation. Choose peers to connect to by looking at the
# routing table. # routing table.
neighbour_set = self._neighbour_set.intersection(distant_peers)
while count and distant_peers: while count and distant_peers:
i = random.randrange(0, len(distant_peers)) if neighbour_set:
peer = distant_peers[i] peer = neighbour_set.pop()
i = distant_peers.index(peer)
else:
i = random.randrange(0, len(distant_peers))
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)
......
...@@ -116,6 +116,9 @@ def getConfig(): ...@@ -116,6 +116,9 @@ def getConfig():
help="Do not run any OpenVPN server, but only 1 OpenVPN client," help="Do not run any OpenVPN server, but only 1 OpenVPN client,"
" with specified remotes. Any other option not required in this" " with specified remotes. Any other option not required in this"
" mode is ignored (e.g. client-count, max-clients, etc.)") " mode is ignored (e.g. client-count, max-clients, etc.)")
_('--neighbour', metavar='CN', action='append', default=[],
help="List of peers that should be reachable directly, by creating"
" tunnels if necesssary.")
return parser.parse_args() return parser.parse_args()
...@@ -288,7 +291,7 @@ def main(): ...@@ -288,7 +291,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, remote_gateway, address, ip_changed, config.encrypt, remote_gateway,
config.disable_proto) config.disable_proto, config.neighbour)
cleanup.append(tunnel_manager.sock.close) cleanup.append(tunnel_manager.sock.close)
tunnel_interfaces += tunnel_manager.new_iface_list tunnel_interfaces += tunnel_manager.new_iface_list
else: else:
......
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