예제 #1
0
 def on_rx_pkt_from_network(self, pkt):
     """
         This function gets called on reception of message from network.
         pkt will be a string of type CyberMessage proto defined in srcs/proto/css.proto
         A packet sent by the SCADA controller will be caught here.
     """
     pkt_parsed = css_pb2.CyberMessage()
     pkt_parsed.ParseFromString(pkt)
     self.PLC.recv_pkt_queue.append(pkt)
예제 #2
0
def process_pcap(pcap_file, keys_to_plot):

    pcap = dpkt.pcap.Reader(open(pcap_file))
    pkt_parsed = css_pb2.CyberMessage()

    unique_app_id_pairs = []

    data_fields = ['timestamp', 'src_dst'] + keys_to_plot

    pcap_dataframe = pd.DataFrame(columns=data_fields)

    for timestamp, buf in pcap:

        #unpack the ethernet frame
        eth = dpkt.ethernet.Ethernet(buf)
        ip = eth.data

        #we are only intersted in the UDP packets that follow our custom protocol
        if ip.p == dpkt.ip.IP_PROTO_UDP:

            udp_payload = ip.data.data
            pkt_parsed.ParseFromString(str(udp_payload))
            #extract the source-dst application ID pair
            src_application_id = pkt_parsed.src_application_id
            dst_application_id = pkt_parsed.dst_application_id

            pcap_dataframe_entry = [
                timestamp, (src_application_id, dst_application_id)
            ]

            if (src_application_id,
                    dst_application_id) not in unique_app_id_pairs:
                unique_app_id_pairs.append(
                    (src_application_id, dst_application_id))

            #Finish this function for when the key requested is not in the packet
            for key in keys_to_plot:
                for content in pkt_parsed.content:
                    if content.key == key:
                        pcap_dataframe_entry.append(float(content.value))

            df_append = pd.DataFrame([pcap_dataframe_entry],
                                     columns=data_fields)
            pcap_dataframe = pd.concat([pcap_dataframe, df_append], axis=0)

    start_time = pcap_dataframe['timestamp'].iloc[0]
    pcap_dataframe['rel_time'] = pcap_dataframe['timestamp'] - start_time
    #convert unix time to pandas datetime
    #pcap_dataframe['time'] = pd.to_datetime(pcap_dataframe['timestamp'],unit='ms',origin='unix')
    # Reset Index
    pcap_dataframe = pcap_dataframe.reset_index()
    # Drop old index column
    pcap_dataframe = pcap_dataframe.drop(columns="index")

    return pcap_dataframe, unique_app_id_pairs
예제 #3
0
파일: pmu.py 프로젝트: ITI/Melody
    def on_rx_pkt_from_network(self, pkt):
        """
            This function gets called on reception of message from network.
            pkt will be a string of type CyberMessage proto defined in srcs/proto/css.proto
        """
        # just print the proto message for now
        pkt_parsed = css_pb2.CyberMessage()
        pkt_parsed.ParseFromString(pkt)

        self.log.info(f"Rx new packet from: {pkt_parsed.src_application_id}")
        self.log.info(f"\n{pkt_parsed}")
예제 #4
0
    def tx_pkt_to_powersim_entity(self, pkt):
        """Transmit a co-simulation packet over the mininet cyber network

        :param pkt: A packet string which is converted to CyberMessage proto and sent over the network
        :type pkt: str
        :return: None
        .. note:: Do not override
        """
        pkt_parsed = css_pb2.CyberMessage()
        pkt_parsed.ParseFromString(pkt)
        cyber_entity_ip = self.application_ids_mapping[
            pkt_parsed.dst_application_id]["mapped_host_ip"]
        cyber_entity_port = self.application_ids_mapping[
            pkt_parsed.dst_application_id]["port"]
        self.raw_sock.sendto(pkt, (cyber_entity_ip, cyber_entity_port))
예제 #5
0
파일: pmu.py 프로젝트: ITI/Melody
    def run(self):

        obj_type_to_read = self.params["objtype"]
        field_type_to_read = self.params["fieldtype"]
        obj_id_to_read = self.params["objid"]
        polling_time = float(self.params["polling_time_secs"])

        request_no = 0
        while not self.stop:
            pkt = css_pb2.CyberMessage()
            pkt.src_application_id = self.pmu_name
            pkt.dst_application_id = "SCADA_CONTROLLER"
            pkt.msg_type = "PERIODIC_UPDATE"

            #Sends an RPC read request to get pilot bus reading.
            pilot_busses_to_read = [(obj_type_to_read, obj_id_to_read,
                                     field_type_to_read)]
            ret = defines.rpc_read(pilot_busses_to_read)
            assert (ret is not None)

            assert (len(ret) == 1)

            data = pkt.content.add()
            data.key = "VOLTAGE"
            data.value = ret[0]

            data = pkt.content.add()
            data.key = "TIMESTAMP"
            data.value = str(time.time())

            data = pkt.content.add()
            data.key = "COUNTER"
            data.value = str(request_no)

            data = pkt.content.add()
            data.key = "OBJ_ID"
            data.value = obj_id_to_read

            #Sends pilot bus reading to SCADA controller.
            self.host_control_layer.log.info(f"Sending reading: {pkt}")
            self.host_control_layer.tx_pkt_to_powersim_entity(
                pkt.SerializeToString())
            time.sleep(polling_time)
            request_no += 1
예제 #6
0
    def run(self, debug=False):
        """Proportional control logic
        """
        controller_timestep = float(self.params["controller_timestep_secs"])

        _vp_nom = np.array([cfg.BUS_VM[bus] for bus in cfg.PILOT_BUS])
        _vg = np.array([cfg.BUS_VM[gen] for gen in cfg.GEN])
        C = loadObjectBinary("C.bin")
        Cp = np.matrix(
            [C[i] for i in range(cfg.LOAD_NO) if cfg.LOAD[i] in cfg.PILOT_BUS])
        Cpi = Cp.I
        alpha = 0.4

        while not self.stop:
            _vp = np.array(
                [self.host_control_layer.vp[bus] for bus in cfg.PILOT_BUS])
            u = np.ravel(np.dot(Cpi,
                                alpha * (_vp - _vp_nom)))  # 1-d base array
            _vg = np.array(_vg + u)

            for i in range(cfg.GEN_NO):
                # Sends a command to all PLCs
                pkt_new = css_pb2.CyberMessage()
                pkt_new.src_application_id = self.scada_controller_name
                pkt_new.dst_application_id = "PLC_Gen_Bus_%d" % cfg.GEN[i]
                data = pkt_new.content.add()
                data.key = "VOLTAGE_SETPOINT"
                data.value = str(_vg[i])

                data = pkt_new.content.add()
                data.key = "TIMESTAMP"
                data.value = str(time.time())

                self.host_control_layer.log.info(
                    f"Sending new control msg to PLC: {str(pkt_new)}")
                self.host_control_layer.tx_pkt_to_powersim_entity(
                    pkt_new.SerializeToString())

            time.sleep(controller_timestep)
예제 #7
0
    def run(self):
        request_no = 0

        obj_type_to_write = self.params["objtype"]
        field_type_to_write = self.params["fieldtype"]
        obj_id_to_write = self.params["objid"]

        while not self.stop:

            try:
                data = self.recv_pkt_queue.pop()
            except IndexError:
                data = None

            if data is None:
                time.sleep(0.001)
                continue

            pkt_parsed = css_pb2.CyberMessage()
            pkt_parsed.ParseFromString(data)

            self.host_control_layer.log.info(
                f"Received new control message from SCADA controller: {str(pkt_parsed)}"
            )
            voltage_setpoint = None
            for data_content in pkt_parsed.content:
                if data_content.key == "VOLTAGE_SETPOINT":
                    voltage_setpoint = data_content.value
            assert (voltage_setpoint is not None)

            # Sends a write request to the proxy based on the received command from SCADA controller
            self.host_control_layer.log.info("Sending RPC Write Request ...")
            defines.rpc_write([(obj_type_to_write, obj_id_to_write,
                                field_type_to_write, voltage_setpoint)])
            self.host_control_layer.log.info(
                "----------------------------------------")

            request_no += 1
예제 #8
0
    def on_rx_pkt_from_network(self, pkt):
        """
            This function gets called on reception of message from network.
            pkt will be a string of type CyberMessage proto defined in srcs/proto/css.proto
            A packet sent by the PMU will be caught here. It updates the latest reading from a pilot bus.
            The scada controller maintains a local dictionary containing the latest reading.
        """
        pkt_parsed = css_pb2.CyberMessage()
        pkt_parsed.ParseFromString(pkt)

        recv_obj_id = None
        recv_obj_value = None
        for data_content in pkt_parsed.content:
            if data_content.key == "OBJ_ID":
                recv_obj_id = int(data_content.value)
            if data_content.key == "VOLTAGE":
                recv_obj_value = float(data_content.value)
        assert (recv_obj_id is not None and recv_obj_value is not None)
        assert (recv_obj_id in self.vp)

        self.vp[recv_obj_id] = recv_obj_value
        self.log.info(
            f"Rx reading from PMU: {recv_obj_id} = {str(pkt_parsed)}")