Commit 128edb83 authored by Julien Muchembled's avatar Julien Muchembled

rina: recover from cases where normal.DIF is already registered at startup

Which happens when only re6stnet is restarted. The DIF must even be recreated
if the local certificate has changed, so that we can reconfigure the shim DIF.
parent 3e1a6244
...@@ -111,6 +111,7 @@ class Shim(object): ...@@ -111,6 +111,7 @@ class Shim(object):
def __init__(self, ipcp_id, dif): def __init__(self, ipcp_id, dif):
self.ipcp_id = ipcp_id self.ipcp_id = ipcp_id
self.dif = dif self.dif = dif
self._asking_info = {}
self._enabled = weakref.WeakValueDictionary() self._enabled = weakref.WeakValueDictionary()
def _kernel(self, **kw): def _kernel(self, **kw):
...@@ -131,7 +132,7 @@ class Shim(object): ...@@ -131,7 +132,7 @@ class Shim(object):
len(ap), ap, len(ip), ip, len(port), port)) len(ap), ap, len(ip), ip, len(port), port))
self._enabled[prefix] = tm._getPeer(prefix) self._enabled[prefix] = tm._getPeer(prefix)
def update(self, tm): def init(self, tm):
global resolve_thread global resolve_thread
if resolve_thread is None: if resolve_thread is None:
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
...@@ -142,80 +143,79 @@ class Shim(object): ...@@ -142,80 +143,79 @@ class Shim(object):
resolve_thread.start() resolve_thread.start()
prefix = tm._prefix prefix = tm._prefix
self._enabled[prefix] = tm.cert self._enabled[prefix] = tm.cert
self._asking_info = {prefix: float('inf')} self._asking_info[prefix] = float('inf')
def update(tm):
ap = ap_name(tm._prefix) def update(self, tm):
name = ap + "-1--" enabled = self._enabled
step = 0 # do never retry immediately ap = ap_name(tm._prefix)
while 1: name = ap + "-1--"
normal_id = None step = 0 # do never retry immediately
for ipcp in ipcm.iterIpcp(): while 1:
if ipcp[0] == self.ipcp_id: normal_id = None
registered = name in ipcp[4] for ipcp in ipcm.iterIpcp():
elif ipcp[1] == name: if ipcp[0] == self.ipcp_id:
normal_id = ipcp[0] registered = ipcp[4]
normal_status = ipcp[3] elif ipcp[1] == name:
if registered: normal_id = ipcp[0]
break normal_status = ipcp[3]
if normal_id is None: elif ipcp[1] in registered:
if step or not ipcm("create-ipcp", ap, 1, "normal-ipc"): if step or not ipcm("destroy-ipcp", ipcp[0]):
return return
step = 1 step = 1
elif normal_status == "INITIALIZED": if name in registered:
if step > 1 or not ipcm("assign-to-dif", normal_id, break
NORMAL_DIF, DEFAULT_DIF): if normal_id is None:
return if step > 1 or not ipcm("create-ipcp", ap, 1, "normal-ipc"):
step = 2
elif normal_status.startswith("ASSIGNED TO DIF"):
if step > 2 or not ipcm("register-at-dif",
normal_id, self.dif):
return
step = 3
else:
return return
asking_info = self._asking_info step = 2
enabled = self._enabled elif normal_status == "INITIALIZED":
enrolled = set(ap_prefix(neigh[0].split('-', 1)[0]) if step > 2 or not ipcm("assign-to-dif", normal_id,
for neigh in ipcm.iterNeigh(normal_id)) NORMAL_DIF, DEFAULT_DIF):
now = time.time() return
for neigh_routes in tm.ctl.neighbours.itervalues(): step = 3
for prefix in neigh_routes[1]: elif normal_status.startswith("ASSIGNED TO DIF"):
if not prefix or prefix in enrolled: enabled.clear()
continue self.init(tm)
if prefix in enabled: port = str(PORT)
# Avoid enrollment to a neighbour self._kernel(
# that does not know our address. hostname=utils.ipFromBin(tm._network + tm._prefix, '1'),
if prefix not in asking_info: expReg="1:%s:%s0:%s:%s" % (len(ap), ap, len(port), port))
r = ipcm("enroll-to-dif", normal_id, if step > 3 or not ipcm("register-at-dif", normal_id, self.dif):
NORMAL_DIF, self.dif, ap_name(prefix), 1) return
if r and 'failed' in r[0]: step = 4
del enabled[prefix] else:
# Enrolling may take a while return
# so don't block for too long. asking_info = self._asking_info
if now + 1 < time.time(): enrolled = set(ap_prefix(neigh[0].split('-', 1)[0])
return for neigh in ipcm.iterNeigh(normal_id))
continue now = time.time()
if asking_info.get(prefix, 0) < now and tm.askInfo(prefix): for neigh_routes in tm.ctl.neighbours.itervalues():
self._enroll(tm, prefix) for prefix in neigh_routes[1]:
self._asking_info[prefix] = now + 60 if not prefix or prefix in enrolled:
ap = ap_name(prefix) continue
port = str(PORT) if prefix in enabled:
self._kernel(hostname=utils.ipFromBin(tm._network + prefix, '1'), # Avoid enrollment to a neighbour
expReg="1:%s:%s0:%s:%s" % (len(ap), ap, len(port), port)) # that does not know our address.
self.update = update if prefix not in asking_info:
update(tm) r = ipcm("enroll-to-dif", normal_id,
NORMAL_DIF, self.dif, ap_name(prefix), 1)
if r and 'failed' in r[0]:
del enabled[prefix]
# Enrolling may take a while
# so don't block for too long.
if now + 1 < time.time():
return
elif asking_info.get(prefix, 0) < now and tm.askInfo(prefix):
self._enroll(tm, prefix)
asking_info[prefix] = now + 60
def enabled(self, tm, prefix, enroll): def enabled(self, tm, prefix, enroll):
logging.debug("RINA: enabled(%s, %s)", prefix, enroll) logging.debug("RINA: enabled(%s, %s)", prefix, enroll)
try:
asking_info = self._asking_info
except AttributeError:
return
if enroll: if enroll:
asking_info.pop(prefix, None) self._asking_info.pop(prefix, None)
self._enroll(tm, prefix) self._enroll(tm, prefix)
else: else:
asking_info[prefix] = float('inf') self._asking_info[prefix] = float('inf')
@staticmethod @staticmethod
def _resolve(sock): def _resolve(sock):
...@@ -287,9 +287,9 @@ if os.path.isdir("/sys/rina"): ...@@ -287,9 +287,9 @@ if os.path.isdir("/sys/rina"):
return False return False
dif = sysfs_read(ipcp + "/dif") dif = sysfs_read(ipcp + "/dif")
if dif.endswith("///"): if dif.endswith("///"):
host_name = sysfs_read(ipcp + "/host_name") if shim is None:
if not host_name:
shim = Shim(int(ipcp.rsplit("/", 1)[1]), dif[:-3]) shim = Shim(int(ipcp.rsplit("/", 1)[1]), dif[:-3])
shim.init(tunnel_manager)
if route_dumped: if route_dumped:
shim.update(tunnel_manager) shim.update(tunnel_manager)
return True return True
......
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