Пример #1
0
 def _check(self, value, expected):
     inst = SCIONPath()
     inst._ofs = create_mock(["set"])
     # Call
     inst._set_ofs("label", value)
     # Tests
     inst._ofs.set.assert_called_once_with("label", expected)
Пример #2
0
 def test_empty(self):
     inst = SCIONPath()
     inst._ofs = []
     # Call
     inst._init_of_idxs()
     # Tests
     ntools.eq_(inst._iof_idx, 0)
     ntools.eq_(inst._hof_idx, 0)
Пример #3
0
 def test(self, iof):
     inst = SCIONPath()
     data = create_mock(["pop"])
     inst._ofs = create_mock(["set"])
     # Call
     ntools.eq_(inst._parse_iof(data, "label"), iof.return_value)
     # Tests
     data.pop.assert_called_once_with(iof.LEN)
     iof.assert_called_once_with(data.pop.return_value)
     inst._ofs.set.assert_called_once_with("label", [iof.return_value])
Пример #4
0
 def test(self, hof):
     inst = SCIONPath()
     data = create_mock(["pop"])
     inst._ofs = create_mock(["set"])
     hof.side_effect = ["hof0", "hof1", "hof2"]
     # Call
     inst._parse_hofs(data, "label", 3)
     # Tests
     assert_these_calls(data.pop, [call(hof.LEN)] * 3)
     inst._ofs.set.assert_called_once_with("label",
                                           ["hof0", "hof1", "hof2"])
Пример #5
0
 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
Пример #6
0
 def _build_meta(self,
                 ia=None,
                 host=None,
                 path=None,
                 port=0,
                 reuse=False,
                 one_hop=False):
     if ia is None:
         ia = self.addr.isd_as
     if path is None:
         path = SCIONPath()
     if not one_hop:
         return self._DefaultMeta.from_values(ia,
                                              host,
                                              path,
                                              port=port,
                                              reuse=reuse)
     # One hop path extension in handled in a different way in TCP and UDP
     if self._DefaultMeta == TCPMetadata:
         return TCPMetadata.from_values(ia,
                                        host,
                                        path,
                                        port=port,
                                        reuse=reuse,
                                        flags=TCPFlags.ONEHOPPATH)
     return UDPMetadata.from_values(ia,
                                    host,
                                    path,
                                    port=port,
                                    reuse=reuse,
                                    ext_hdrs=[OneHopPathExt()])
Пример #7
0
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]
Пример #8
0
 def _scmp_validate_error(self, pkt, e):
     if pkt.cmn_hdr.next_hdr == L4Proto.SCMP and pkt.ext_hdrs[0].error:
         # Never respond to an SCMP error with an SCMP error.
         logging.info(
             "Dropping SCMP error packet due to validation error. %s", e)
         return
     if isinstance(e, (SCMPBadIOFOffset, SCMPBadHOFOffset)):
         # Can't handle normally, as the packet isn't reversible.
         reply = self._scmp_bad_path_metadata(pkt, e)
     else:
         logging.warning("Error: %s", type(e))
         reply = pkt.reversed_copy()
         args = ()
         if isinstance(e, SCMPUnspecified):
             args = (str(e),)
         elif isinstance(e, (SCMPOversizePkt, SCMPBadPktLen)):
             args = (e.args[1],)  # the relevant MTU.
         elif isinstance(e, (SCMPTooManyHopByHop, SCMPBadExtOrder,
                             SCMPBadHopByHop)):
             args = e.args
             if isinstance(e, SCMPBadExtOrder):
                 # Delete the problematic extension.
                 del reply.ext_hdrs[args[0]]
         reply.convert_to_scmp_error(self.addr, e.CLASS, e.TYPE, pkt, *args)
     if pkt.addrs.src.isd_as == self.addr.isd_as:
         # No path needed for a local reply.
         reply.path = SCIONPath()
     next_hop, port = self.get_first_hop(reply)
     reply.update()
     self.send(reply, next_hop, port)
Пример #9
0
 def _tcp_sock_from_meta(self, meta):
     assert meta.host
     if meta.ia is None:
         meta.ia = self.addr.isd_as
     if meta.path is None:
         meta.path = SCIONPath()
     dst = meta.get_addr()
     first_ip, first_port = self._get_first_hop(meta.path, dst)
     active = True
     try:
         # Create low-level TCP socket and connect
         sock = SCIONTCPSocket()
         sock.bind((self.addr, 0))
         sock.connect(dst,
                      meta.port,
                      meta.path,
                      first_ip,
                      first_port,
                      flags=meta.flags)
     except SCIONTCPError:
         log_exception(
             "TCP: connection init error, marking socket inactive")
         sock = None
         active = False
     # Create and return TCPSocketWrapper
     return TCPSocketWrapper(sock, dst, meta.path, active)
Пример #10
0
 def _create_one_hop_path(self, egress_if):
     ts = int(SCIONTime.get_time())
     info = InfoOpaqueField.from_values(ts, self.addr.isd_as[0], hops=2)
     hf1 = HopOpaqueField.from_values(self.HOF_EXP_TIME, 0, egress_if)
     hf1.set_mac(self.of_gen_key, ts, None)
     # Return a path where second HF is empty.
     return SCIONPath.from_values(info, [hf1, HopOpaqueField()])
Пример #11
0
 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
Пример #12
0
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
Пример #13
0
 def _build_pkt(self):
     cmn_hdr, addr_hdr = build_base_hdrs(self.addr, self.dst)
     l4_hdr = self._create_l4_hdr()
     spkt = SCIONL4Packet.from_values(cmn_hdr, addr_hdr, SCIONPath(), [],
                                      l4_hdr)
     spkt.set_payload(self._create_payload(spkt))
     spkt.update()
     return spkt
Пример #14
0
 def get_paths(self, dst_ia, flags=()):
     """Return a list of paths."""
     logging.debug("Paths requested for %s %s", dst_ia, flags)
     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.mtu = self.topology.mtu
         return [empty]
     deadline = SCIONTime.get_time() + self.TIMEOUT
     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 []
     return self.path_resolution(dst_ia, flags=flags)
Пример #15
0
 def test_full(self, raw):
     inst = SCIONPath()
     inst._parse_iof = create_mock()
     inst._parse_hofs = create_mock()
     inst._init_of_idxs = create_mock()
     iof_list = []
     for i in 2, 4, 6:
         iof = create_mock(["hops", "shortcut"])
         iof.hops = i
         iof.shortcut = False
         iof_list.append(iof)
     inst._parse_iof.side_effect = iof_list
     data = create_mock()
     data.side_effect = ("A IOF", "A HOFS", "B IOF", "B HOFS", "C IOF",
                         "C HOFS")
     raw.return_value = data
     # Call
     inst._parse("data")
     # Tests
     assert_these_calls(inst._parse_iof, [
         call(data, inst.A_IOF),
         call(data, inst.B_IOF),
         call(data, inst.C_IOF)
     ])
     assert_these_calls(inst._parse_hofs, [
         call(data, inst.A_HOFS, 2),
         call(data, inst.B_HOFS, 4),
         call(data, inst.C_HOFS, 6)
     ])
     inst._init_of_idxs.assert_called_once_with()
Пример #16
0
 def _create_sibra_pkt(self, ext):
     """
     Create a packet that uses a SIBRA path
     """
     ext.setup = False
     ext.active_blocks = self.blocks[:1]
     cmn_hdr, addr_hdr, udp_hdr, payload = self._create_hdrs()
     return SCIONL4Packet.from_values(cmn_hdr, addr_hdr, SCIONPath(), [ext],
                                      udp_hdr, payload)
Пример #17
0
 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)
Пример #18
0
 def test_xovr(self, build_list, path_args, copy_segment):
     up_segment, down_segment, point = self._setup(path_args, copy_segment)
     path = SCIONPath.from_values()
     path.mtu = 1400
     ntools.eq_(
         PathCombinator._join_xovr(up_segment, down_segment, point)[0],
         path)
     copy_segment.assert_any_call(up_segment, 1)
     copy_segment.assert_any_call(down_segment, 2, up=False)
     ntools.eq_(build_list.call_count, 1)
Пример #19
0
 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)
Пример #20
0
 def test_peer(self, find_peers, build_list, path_args, copy_segment):
     up_segment, down_segment, point = self._setup(path_args, copy_segment)
     find_peers.return_value = [("uph1", "dph1", 1500),
                                ("uph2", "dph2", 1500)]
     path = SCIONPath.from_values()
     path.mtu = 1400
     ntools.eq_(
         PathCombinator._join_peer(up_segment, down_segment, point)[0],
         path)
     copy_segment.assert_any_call(up_segment, 1)
     copy_segment.assert_any_call(down_segment, 2, up=False)
     ntools.eq_(build_list.call_count, 2)
Пример #21
0
 def get_path(self, reverse_direction=False):
     """
     Returns the list of HopOpaqueFields in the path.
     """
     hofs = []
     info = InfoOpaqueField(self.p.info)
     asms = list(self.iter_asms())
     if reverse_direction:
         asms = reversed(asms)
         info.up_flag ^= True
     for asm in asms:
         hofs.append(asm.pcbm(0).hof())
     return SCIONPath.from_values(info, hofs)
Пример #22
0
    def accept(self):
        self._init_accept_sock()
        sockname = self._lwip_accept.getsockname()[-SOCK_PATH_LEN:]
        sockname = sockname.encode('ascii')
        # Confirmation from old (UNIX) socket.
        req = APICmd.ACCEPT + sockname
        self._exec_cmd(req, True)

        new_sock, _ = self._lwip_accept.accept()
        # Metadata (path and addr) from new (UNIX) socket.
        rep = get_lwip_reply(new_sock)
        self._handle_reply(req[:CMD_SIZE], rep)
        logging.debug("accept() raw reply: %s", rep)
        rep = rep[RESP_SIZE:]
        path_len, = struct.unpack("H", rep[:2])
        rep = rep[2:]
        path = SCIONPath(rep[:path_len])
        path.reverse()
        rep = rep[path_len:]
        addr = SCIONAddr((rep[0], rep[1:]))
        # Everything is ok, create new SCION TCP socket.
        sock = SCIONTCPSocket(new_sock, rpc_mode=False)
        return sock, addr, path
Пример #23
0
 def _create_reg_pkt(self, type_, remote=False):
     if remote:
         dst_ia = self.remote
         path = self.seg.get_path(True)
     else:
         dst_ia = self.addr.isd_as
         path = SCIONPath()
     pcb = self._create_reg_pcb(remote)
     pld = PathRecordsReg.from_values({type_: [pcb]})
     dest = SCIONAddr.from_values(dst_ia, SVCType.PS_A)
     cmn_hdr, addr_hdr = build_base_hdrs(self.addr, dest)
     udp_hdr = SCIONUDPHeader.from_values(self.addr, self._port, dest, 0)
     return SCIONL4Packet.from_values(cmn_hdr, addr_hdr, path, [], udp_hdr,
                                      pld)
Пример #24
0
 def handle_one_hop_path(self, hdr, spkt, from_local_as):
     if len(spkt.path) != InfoOpaqueField.LEN + 2 * HopOpaqueField.LEN:
         logging.error("OneHopPathExt: incorrect path length.")
         return [(RouterFlag.ERROR,)]
     if not from_local_as:  # Remote packet, create the 2nd Hop Field
         info = spkt.path.get_iof()
         hf1 = spkt.path.get_hof_ver(ingress=True)
         exp_time = OneHopPathExt.HOF_EXP_TIME
         hf2 = HopOpaqueField.from_values(exp_time, self.interface.if_id, 0)
         hf2.set_mac(self.of_gen_key, info.timestamp, hf1)
         # FIXME(PSz): quite brutal for now:
         spkt.path = SCIONPath.from_values(info, [hf1, hf2])
         spkt.path.inc_hof_idx()
     return []
Пример #25
0
 def _setup(self, xover=False, peer=False, shortcut=False, up_flag=True):
     inst = SCIONPath()
     inst._iof_idx = 0
     inst._hof_idx = 0
     iof = create_mock(["peer", "shortcut", "up_flag"])
     iof.peer = peer
     iof.shortcut = shortcut
     iof.up_flag = up_flag
     inst.get_iof = create_mock()
     inst.get_iof.return_value = iof
     hof = create_mock(["xover"])
     hof.xover = xover
     inst.get_hof = create_mock()
     inst.get_hof.return_value = hof
     inst._get_hof_ver_normal = create_mock()
     inst._ofs = create_mock(["get_by_idx"])
     return inst, iof, hof
Пример #26
0
 def test_non_peer(self):
     inst = SCIONPath()
     inst._ofs = [1]
     iof = create_mock(["peer"])
     iof.peer = False
     inst.get_iof = create_mock()
     inst.get_iof.return_value = iof
     inst.inc_hof_idx = create_mock()
     # Call
     inst._init_of_idxs()
     # Tests
     ntools.eq_(inst._iof_idx, 0)
     ntools.eq_(inst._hof_idx, 0)
     inst.inc_hof_idx.assert_called_once_with()
Пример #27
0
 def _build_packet(self, dst_host=None, path=None, ext_hdrs=(),
                   dst_ia=None, payload=None, dst_port=0):
     if dst_host is None:
         dst_host = HostAddrNone()
     if dst_ia is None:
         dst_ia = self.addr.isd_as
     if path is None:
         path = SCIONPath()
     if payload is None:
         payload = PayloadRaw()
     dst_addr = SCIONAddr.from_values(dst_ia, dst_host)
     cmn_hdr, addr_hdr = build_base_hdrs(dst_addr, self.addr)
     udp_hdr = SCIONUDPHeader.from_values(
         self.addr, self._port, dst_addr, dst_port)
     return SCIONL4Packet.from_values(
         cmn_hdr, addr_hdr, path, ext_hdrs, udp_hdr, payload)
Пример #28
0
 def _get_path_via_api(self):
     """
     Test local API.
     """
     data = self._try_sciond_api()
     path_len = data.pop(1) * 8
     self.path = SCIONPath(data.pop(path_len))
     haddr_type = haddr_get_type(data.pop(1))
     data.pop(haddr_type.LEN)  # first hop, unused here
     data.pop(2)  # port number, unused here
     self.path.mtu = struct.unpack("!H", data.pop(2))[0]
     ifcount = data.pop(1)
     self.iflist = []
     for i in range(ifcount):
         isd_as = ISD_AS(data.pop(ISD_AS.LEN))
         ifid = struct.unpack("!H", data.pop(2))[0]
         self.iflist.append((isd_as, ifid))
Пример #29
0
 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
Пример #30
0
 def _check_peer(self, xover, expected):
     inst = SCIONPath()
     inst._ofs = create_mock(["__len__", "get_by_idx"])
     iof = create_mock(["peer"])
     inst.get_iof = create_mock()
     inst.get_iof.return_value = iof
     hof = create_mock(["xover"])
     hof.xover = xover
     inst._ofs.get_by_idx.return_value = hof
     inst.inc_hof_idx = create_mock()
     # Call
     inst._init_of_idxs()
     # Tests
     inst._ofs.get_by_idx.assert_called_once_with(1)
     ntools.eq_(inst._iof_idx, 0)
     ntools.eq_(inst._hof_idx, expected)