Esempio n. 1
0
    def handle_ifid_packet(self, pld, meta):
        """
        Update the interface state for the corresponding interface.

        :param pld: The IFIDPayload.
        :type pld: IFIDPayload
        """
        ifid = pld.p.relayIF
        with self.ifid_state_lock:
            if ifid not in self.ifid_state:
                raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
            br = self.ifid2br[ifid]
            br.interfaces[ifid].to_if_id = pld.p.origIF
            prev_state = self.ifid_state[ifid].update()
            if prev_state == InterfaceState.INACTIVE:
                logging.info("IF %d activated", ifid)
            elif prev_state in [
                    InterfaceState.TIMED_OUT, InterfaceState.REVOKED
            ]:
                logging.info("IF %d came back up.", ifid)
            if not prev_state == InterfaceState.ACTIVE:
                if self.zk.have_lock():
                    # Inform BRs about the interface coming up.
                    state_info = IFStateInfo.from_values(
                        ifid, True, self._get_ht_proof(ifid))
                    pld = IFStatePayload.from_values([state_info])
                    for br in self.topology.border_routers:
                        br_addr, br_port = br.int_addrs[0].public[0]
                        meta = UDPMetadata.from_values(host=br_addr,
                                                       port=br_port)
                        self.send_meta(pld.copy(), meta, (br_addr, br_port))
Esempio n. 2
0
    def get_by_label(self, label, label_idx=None):
        """
        Get an OF list by label. If a label index is supplied, use that to index
        into the label and return a single OF instead.

        :param str label: The label to fetch. E.g. ``UP_HOFS``.
        :param int label_idx:
            (Optional) an index of an OF in the specified label.
        :returns:
            A list of OFs (or if `label_idx` was specified, a single OF).
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
            :any:`SCIONIndexError`: if the specified label index is out of range
        """
        try:
            group = self._labels[label]
        except KeyError:
            raise SCIONKeyError("Opaque field label (%s) unknown" %
                                label) from None
        if label_idx is None:
            return group
        try:
            return group[label_idx]
        except IndexError:
            raise SCIONIndexError(
                "Opaque field label index (%d) for label %s out of range" %
                (label_idx, label)) from None
Esempio n. 3
0
    def handle_ifid_packet(self, cpld, meta):
        """
        Update the interface state for the corresponding interface.

        :param pld: The IFIDPayload.
        :type pld: IFIDPayload
        """
        pld = cpld.union
        assert isinstance(pld, IFIDPayload), type(pld)
        ifid = meta.pkt.path.get_hof().ingress_if
        with self.ifid_state_lock:
            if ifid not in self.ifid_state:
                raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
            br = self.ifid2br[ifid]
            br.interfaces[ifid].to_if_id = pld.p.origIF
            prev_state = self.ifid_state[ifid].update()
            if prev_state == InterfaceState.INACTIVE:
                logging.info("IF %d activated.", ifid)
            elif prev_state in [
                    InterfaceState.TIMED_OUT, InterfaceState.REVOKED
            ]:
                logging.info("IF %d came back up.", ifid)
            if prev_state != InterfaceState.ACTIVE:
                if self.zk.have_lock():
                    # Inform BRs about the interface coming up.
                    metas = []
                    for br in self.topology.border_routers:
                        br_addr, br_port = br.ctrl_addrs.public
                        metas.append(
                            UDPMetadata.from_values(host=br_addr,
                                                    port=br_port))
                    info = IFStateInfo.from_values(ifid, True)
                    self._send_ifstate_update([info], metas)
Esempio n. 4
0
    def handle_ifid_packet(self, pkt):
        """
        Update the interface state for the corresponding interface.

        :param ipkt: The IFIDPayload.
        :type ipkt: IFIDPayload
        """
        payload = pkt.get_payload()
        ifid = payload.p.relayIF
        if ifid not in self.ifid_state:
            raise SCIONKeyError("Invalid IF %d in IFIDPayload" % ifid)
        er = self.ifid2er[ifid]
        er.interface.to_if_id = payload.p.origIF
        prev_state = self.ifid_state[ifid].update()
        if prev_state == InterfaceState.INACTIVE:
            logging.info("IF %d activated", ifid)
        elif prev_state in [InterfaceState.TIMED_OUT, InterfaceState.REVOKED]:
            logging.info("IF %d came back up.", ifid)
        if not prev_state == InterfaceState.ACTIVE:
            if self.zk.have_lock():
                # Inform ERs about the interface coming up.
                chain = self._get_if_hash_chain(ifid)
                if chain is None:
                    return
                state_info = IFStateInfo.from_values(ifid, True,
                                                     chain.current_element())
                pld = IFStatePayload.from_values([state_info])
                mgmt_packet = self._build_packet()
                for er in self.topology.get_all_edge_routers():
                    if er.interface.if_id != ifid:
                        mgmt_packet.addrs.dst.host = er.addr
                        mgmt_packet.set_payload(pld.copy())
                        self.send(mgmt_packet, er.addr)
Esempio n. 5
0
    def get_idx_by_label(self, label):
        """
        Returns the index of the first element in the given label.

        :param str label: The label for which we want the start index.
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
        """
        idx = 0
        for l in self._order:
            if label == l:
                if self._labels[l]:
                    return idx
                else:
                    raise SCIONKeyError("Opaque field label (%s) is empty." %
                                        label) from None
            idx += len(self._labels[l])
        raise SCIONKeyError("Opaque field label (%s) unknown." %
                            label) from None
Esempio n. 6
0
    def reverse_label(self, label):
        """
        Reverse the contents of a label.

        :param str label: The label to reverse.
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
        """
        try:
            self._labels[label].reverse()
        except KeyError:
            raise SCIONKeyError("Opaque field label (%s) unknown" %
                                label) from None
Esempio n. 7
0
    def set(self, label, ofs):
        """
        Sets an OF label to the supplied value.

        :param str label: OF label to change. E.g. ``UP_IOF``.
        :param list ofs: List of opaque fields to store in the label.
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
        """
        assert isinstance(ofs, list), type(ofs)
        if label not in self._labels:
            raise SCIONKeyError("Opaque field label (%s) unknown" % label)
        self._labels[label] = ofs
Esempio n. 8
0
    def count(self, label):
        """
        Return the number of OFs in a label.

        :param str label: The label to count.
        :returns: The number of OFs in the label.
        :rtype: int
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
        """
        try:
            return len(self._labels[label])
        except KeyError:
            raise SCIONKeyError("Opaque field label (%s) unknown" %
                                label) from None
Esempio n. 9
0
    def reverse_cons_dir_flag(self, label):
        """
        Reverse the ConsDir flag of the first OF in a label, assuming the label isn't
        empty. Used to change direction of IOFs.

        :param str label: The label to modify.
        :raises:
            :any:`SCIONKeyError`: if the label is unknown.
        """
        try:
            group = self._labels[label]
        except KeyError:
            raise SCIONKeyError("Opaque field label (%s) unknown" %
                                label) from None
        if len(group) > 0:
            group[0].cons_dir_flag ^= True
Esempio n. 10
0
    def swap(self, label_a, label_b):
        """
        Swap the contents of two labels. The order of the parameters doesn't
        matter.

        :param str label_a: The first label.
        :param str label_b: The second label.
        :raises:
            :any:`SCIONKeyError`: if either label is unknown.
        """
        try:
            self._labels[label_a], self._labels[label_b] = \
                self._labels[label_b], self._labels[label_a]
        except KeyError as e:
            raise SCIONKeyError("Opaque field label (%s) unknown" %
                                e.args[0]) from None
Esempio n. 11
0
    def register_down_segment(self, pcb):
        """
        Send down-segment to Core Path Server
        """
        core_path = pcb.get_path(reverse_direction=True)
        records = PathRecordsReg.from_values({PST.DOWN: [pcb]})
        dst_ia = pcb.asm(0).isd_as()
        pkt = self._build_packet(SVCType.PS,
                                 dst_ia=dst_ia,
                                 path=core_path,
                                 payload=records)
        fwd_if = core_path.get_fwd_if()
        if fwd_if not in self.ifid2er:
            raise SCIONKeyError("Invalid IF %d in CorePath" % fwd_if)

        next_hop = self.ifid2er[fwd_if].addr
        self.send(pkt, next_hop)