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))
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
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)
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)
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
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
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
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
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
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
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)