def get_paths(self, dst_ia, flags=(), flush=False): """Return a list of paths.""" logging.debug("Paths requested for ISDAS=%s, flags=%s, flush=%s", dst_ia, flags, flush) if flush: logging.info("Flushing PathDBs.") self._flush_path_dbs() if self.addr.isd_as == dst_ia or (self.addr.isd_as.any_as() == dst_ia and self.topology.is_core_as): # Either the destination is the local AS, or the destination is any # core AS in this ISD, and the local AS is in the core empty = SCIONPath() empty_meta = FwdPathMeta.from_values(empty, [], self.topology.mtu) return [empty_meta], SCIONDPathReplyError.OK paths = self.path_resolution(dst_ia, flags=flags) if not paths: key = dst_ia, flags with self.req_path_lock: if key not in self.requested_paths: # No previous outstanding request self.requested_paths[key] = threading.Event() self._fetch_segments(key) e = self.requested_paths[key] if not e.wait(self.PATH_REQ_TOUT): logging.error("Query timed out for %s", dst_ia) return [], SCIONDPathReplyError.PS_TIMEOUT paths = self.path_resolution(dst_ia, flags=flags) error_code = (SCIONDPathReplyError.OK if paths else SCIONDPathReplyError.NO_PATHS) return paths, error_code
def _join_peer(up_segment, down_segment, point, peer_revs): """ Joins the supplied segments into a shortcut (peer) fullpath. :param list up_segment: `up` :any:`PathSegment`. :param list down_segment: `down` :any:`PathSegment`. :param tuple point: Indexes of peer point. :param RevCache peer_revs: Peering revocations. :returns: :any:`CrossOverPath`. """ (up_index, down_index) = point up_iof, up_hofs, up_upstream_hof, up_mtu = \ _copy_segment_shortcut(up_segment, up_index) down_iof, down_hofs, down_upstream_hof, down_mtu = \ _copy_segment_shortcut(down_segment, down_index, up=False) up_iof.shortcut = down_iof.shortcut = True up_iof.peer = down_iof.peer = True path_metas = [] for uph, dph, pm in _find_peer_hfs(up_segment.asm(up_index), down_segment.asm(down_index), peer_revs): um = min(up_mtu, pm) dm = min(down_mtu, pm) args = _shortcut_path_args(up_iof, up_hofs + [uph, up_upstream_hof], down_iof, [down_upstream_hof, dph] + down_hofs) path = SCIONPath.from_values(*args) if_list = _build_shortcut_interface_list(up_segment, up_index, down_segment, down_index, (uph, dph)) mtu = _min_mtu(um, dm) path_meta = FwdPathMeta.from_values(path, if_list, mtu) path_metas.append(path_meta) return path_metas
def _join_xovr(up_segment, down_segment, point): """ Joins the supplied segments into a shortcut (xovr) fullpath. :param list up_segment: `up` :any:`PathSegment`. :param list down_segment: `down` :any:`PathSegment`. :param tuple point: Indexes of xovr point. :returns: :any:`CrossOverPath`. """ (up_index, down_index) = point up_iof, up_hofs, up_upstream_hof, up_mtu = \ _copy_segment_shortcut(up_segment, up_index) down_iof, down_hofs, down_upstream_hof, down_mtu = \ _copy_segment_shortcut(down_segment, down_index, up=False) up_iof.shortcut = down_iof.shortcut = True up_iof.peer = down_iof.peer = False up_hofs.append(up_upstream_hof) down_hofs.insert(0, down_upstream_hof) args = _shortcut_path_args(up_iof, up_hofs, down_iof, down_hofs) path = SCIONPath.from_values(*args) if_list = _build_shortcut_interface_list(up_segment, up_index, down_segment, down_index) mtu = _min_mtu(up_mtu, down_mtu) path_meta = FwdPathMeta.from_values(path, if_list, mtu) return [path_meta]
def get_paths(self, dst_ia, flags=(), flush=False): """Return a list of paths.""" logging.debug("Paths requested for ISDAS=%s, flags=%s, flush=%s", dst_ia, flags, flush) if flush: logging.info("Flushing PathDBs.") self._flush_path_dbs() if self.addr.isd_as == dst_ia or ( self.addr.isd_as.any_as() == dst_ia and self.topology.is_core_as): # Either the destination is the local AS, or the destination is any # core AS in this ISD, and the local AS is in the core empty = SCIONPath() empty_meta = FwdPathMeta.from_values(empty, [], self.topology.mtu) return [empty_meta], SCIONDPathReplyError.OK deadline = SCIONTime.get_time() + self.PATH_REQ_TOUT e = threading.Event() self.requests.put(((dst_ia, flags), e)) if not self._wait_for_events([e], deadline): logging.error("Query timed out for %s", dst_ia) return [], SCIONDPathReplyError.PS_TIMEOUT paths = self.path_resolution(dst_ia, flags=flags) error_code = (SCIONDPathReplyError.OK if paths else SCIONDPathReplyError.NO_PATHS) return paths, error_code
def test_xovr(self, build_list, path_args, copy_segment): up_segment, down_segment, point, exp_time = self._setup(path_args, copy_segment) path_meta = FwdPathMeta.from_values(SCIONPath(), [], 0, exp_time) ntools.eq_( path_combinator._join_xovr(up_segment, down_segment, point)[0], path_meta) copy_segment.assert_any_call(up_segment, 1) copy_segment.assert_any_call(down_segment, 2, cons_dir=True) ntools.eq_(build_list.call_count, 1)
def test_peer(self, find_peers, build_list, path_args, copy_segment): up_segment, down_segment, point, exp_time = self._setup(path_args, copy_segment) find_peers.return_value = [("uph1", "dph1", 1500), ("uph2", "dph2", 1500)] peer_revs = create_mock() path_meta = FwdPathMeta.from_values(SCIONPath(), [], 0, exp_time) ntools.eq_(path_combinator._join_peer( up_segment, down_segment, point, peer_revs)[0], path_meta) copy_segment.assert_any_call(up_segment, 1) copy_segment.assert_any_call(down_segment, 2, cons_dir=True) ntools.eq_(build_list.call_count, 2)
def get_paths(self, dst_ia, flags=(), flush=False): """Return a list of paths.""" logging.debug("Paths requested for ISDAS=%s, flags=%s, flush=%s", dst_ia, flags, flush) if flush: logging.info("Flushing PathDBs.") self._flush_path_dbs() if self.addr.isd_as == dst_ia or (self.addr.isd_as.any_as() == dst_ia and self.topology.is_core_as): # Either the destination is the local AS, or the destination is any # core AS in this ISD, and the local AS is in the core empty = SCIONPath() exp_time = int(time.time()) + self.EMPTY_PATH_TTL empty_meta = FwdPathMeta.from_values(empty, [], self.topology.mtu, exp_time) return [empty_meta], SCIONDPathReplyError.OK paths = self.path_resolution(dst_ia, flags=flags) if not paths: key = dst_ia, flags with self.req_path_lock: r = self.requested_paths.get(key) if r is None: # No previous outstanding request req = PathSegmentReq.from_values(self.addr.isd_as, dst_ia, flags=flags) r = RequestState(req.copy()) self.requested_paths[key] = r self._fetch_segments(req) # Wait until event gets set. timeout = not r.e.wait(PATH_REQ_TOUT) with self.req_path_lock: if timeout: r.done() if key in self.requested_paths: del self.requested_paths[key] if timeout: logging.error("Query timed out for %s", dst_ia) return [], SCIONDPathReplyError.PS_TIMEOUT # Check if we can fulfill the path request. paths = self.path_resolution(dst_ia, flags=flags) if not paths: logging.error("No paths found for %s", dst_ia) return [], SCIONDPathReplyError.NO_PATHS return paths, SCIONDPathReplyError.OK
def tuples_to_full_paths(tuples): """ For a set of tuples of possible end-to-end path [format is: (up_seg, core_seg, down_seg)], return a list of fullpaths. """ res = [] for up_segment, core_segment, down_segment in tuples: if not up_segment and not core_segment and not down_segment: continue if not _check_connected(up_segment, core_segment, down_segment): continue up_iof, up_hofs, up_mtu, up_exp = _copy_segment( up_segment, False, (core_segment or down_segment)) core_iof, core_hofs, core_mtu, core_exp = _copy_segment( core_segment, up_segment, down_segment) down_iof, down_hofs, down_mtu, down_exp = _copy_segment( down_segment, (up_segment or core_segment), False, cons_dir=True) args = [] for iof, hofs in [(up_iof, up_hofs), (core_iof, core_hofs), (down_iof, down_hofs)]: if iof: args.extend([iof, hofs]) path = SCIONPath.from_values(*args) if up_segment: up_core = list(reversed(list(up_segment.iter_asms()))) else: up_core = [] if core_segment: up_core += list(reversed(list(core_segment.iter_asms()))) if_list = _build_interface_list(up_core) if down_segment: down_core = list(down_segment.iter_asms()) else: down_core = [] if_list += _build_interface_list(down_core, cons_dir=True) mtu = _min_mtu(up_mtu, core_mtu, down_mtu) exp = min(up_exp, core_exp, down_exp) path_meta = FwdPathMeta.from_values(path, if_list, mtu, exp) res.append(path_meta) return res
def path(self): if not self._path: self._path = FwdPathMeta(self.p.path) return self._path