Exemple #1
0
 def get_round_request(self):
     if (not all([stream.is_ack for stream in self.notification_streams])
             or not all([stream.is_ack for stream in self.datastreams])):
         return SimMessage(self.node.local_timestamp, self.node,
                           lwb_slot.LWB_CONTENTION_HEADER_LENGTH, 0,
                           self.node.lwb.base, SimMessageType.ROUND_REQUEST)
     else:
         return None
    def receive_message_on_tx_done_before_rx_timeout(
        self, rx_node: 'sim_node.SimNode', modulation, band,
        message: SimMessage, rx_start: float, tx_start: float, transmission
    ) -> Tuple[Optional[SimMessage], Optional['sim_node.SimNode']]:
        if not self.is_reachable(modulation, rx_node, message.source,
                                 lwb_slot.RADIO_POWERS[message.power_level]):
            return None, None

        config = RadioConfiguration(
            modulation, preamble=gloria.GloriaTimings(modulation).preamble_len)
        math = RadioMath(config)

        valid_rx_start = rx_start + math.get_symbol_time() * 0.1

        if valid_rx_start > message.tx_start:
            return None, None

        interfering_set = (
            self.mm.mq.loc[(self.mm.mq.modulation == modulation)
                           & (self.mm.mq.band == band) &
                           (self.mm.mq.tx_end >= message.tx_start) &
                           (self.mm.mq.tx_start <= message.tx_end)]).copy()

        def calc_power_message(item):
            return -self.calculate_path_loss(rx_node, item.source) + item.power

        interfering_set['rx_power'] = interfering_set.apply(calc_power_message,
                                                            axis=1)
        rx_power = -self.calculate_path_loss(
            rx_node,
            message.source) + lwb_slot.RADIO_POWERS[message.power_level]

        interfering_power = 0
        for interferer_index, interferer in interfering_set.iterrows():
            if interferer['message_hash'] != message.hash or not (
                (tx_start - 100E6) < interferer['tx_start'] <
                (tx_start + 100E6)):
                interfering_power += np.power(10, interferer['rx_power'] / 10)

        if np.power(10, rx_power / 10) > (interfering_power *
                                          np.power(10, RADIO_SNR[modulation])):
            rx_node.mm.unregister_rx(rx_node)

            self.network.tracer.log_activity(
                RxActivity(
                    rx_start, self.network.global_timestamp, rx_node,
                    RadioConfiguration.rx_energy(
                        self.network.global_timestamp - rx_start), modulation,
                    True))

            return message.copy(), transmission['source']
        else:
            return None, None
Exemple #3
0
    def get_stream_request(
        self, round: 'lwb_round.LWBRound', modulation: int, power_level: int
    ) -> Tuple[Optional[Union[DataStream, NotificationStream]],
               Optional[SimMessage]]:
        for stream in self.notification_streams:
            if not stream.is_ack and stream.check_request(round, power_level):
                stream = copy(stream)
                stream.advertised_ack_power_level = self.node.lwb.link_manager.get_link(
                    round.master)['power_level']
                message = SimMessage(self.node.local_timestamp,
                                     self.node,
                                     lwb_slot.LWB_CONTENTION_HEADER_LENGTH,
                                     0,
                                     self.node.lwb.base,
                                     SimMessageType.STREAM_REQUEST,
                                     content={
                                         'type': 'notification',
                                         'stream': stream
                                     })
                return stream, message

        for stream in self.datastreams:
            if not stream.is_ack and stream.check_request(round, modulation):
                stream = copy(stream)
                stream.advertised_ack_power_level = self.node.lwb.link_manager.get_link(
                    round.master)['power_level']
                message = SimMessage(self.node.local_timestamp,
                                     self.node,
                                     lwb_slot.LWB_CONTENTION_HEADER_LENGTH,
                                     0,
                                     self.node.lwb.base,
                                     SimMessageType.STREAM_REQUEST,
                                     content={
                                         'type': 'data',
                                         'stream': stream
                                     })
                return stream, message
        return None, None
Exemple #4
0
 def tx_ack_stream_request(self, stream: Union[DataStream,
                                               NotificationStream]):
     return SimMessage(
         self.node.local_timestamp,
         self.node,
         lwb_slot.GLORIA_HEADER_LENGTH,
         0,
         stream.master,
         SimMessageType.ACK,
         content={
             'type':
             ('data' if type(stream) is DataStream else 'notification'),
             'stream': copy(stream)
         })
Exemple #5
0
    def tx_ack(self, stream: Union[DataStream, NotificationStream]):
        for local_stream in self.datastreams:
            if stream.id == local_stream.id:
                local_stream.success()
        for local_stream in self.notification_streams:
            if stream.id == local_stream.id:
                local_stream.success()

        return SimMessage(self.node.local_timestamp,
                          self.node,
                          lwb_slot.GLORIA_HEADER_LENGTH,
                          0,
                          stream.master,
                          SimMessageType.ACK,
                          content={'stream': copy(stream)})
Exemple #6
0
    def get_notification(
        self,
        low_power=False
    ) -> Tuple[Optional[NotificationStream], Optional[SimMessage]]:
        stream = self.select_notification(low_power=low_power)
        content = {'notification': stream.get(), 'stream': stream}

        message = SimMessage(self.node.local_timestamp,
                             self.node,
                             lwb_slot.LWB_CONTENTION_HEADER_LENGTH,
                             0,
                             self.node.lwb.base,
                             SimMessageType.NOTIFICATION,
                             content=content)

        return stream, message
Exemple #7
0
    def get_data(self, slot_size: int) -> Tuple[DataStream, SimMessage]:
        stream = self.select_data(slot_size=slot_size -
                                  lwb_slot.LWB_DATA_HEADER_LENGTH)

        if stream is not None:
            content = {'data': stream.get(), 'stream': copy(stream)}

            message = SimMessage(self.node.local_timestamp,
                                 self.node,
                                 stream.max_payload +
                                 lwb_slot.LWB_DATA_HEADER_LENGTH,
                                 0,
                                 self.node.lwb.base,
                                 SimMessageType.DATA,
                                 content=content)

            return stream, message
        else:
            return None, None
Exemple #8
0
    def process_sync_slot(self, slot: 'lwb_slot.LWBSlot'):
        if self.node.role is sim_node.SimNodeRole.BASE:
            message = SimMessage(slot.slot_marker,
                                 self.node,
                                 slot.payload,
                                 modulation=slot.modulation,
                                 destination=None,
                                 type=SimMessageType.SYNC,
                                 power_level=slot.power_level)

            SimLWBSlot(self.node,
                       slot,
                       self.process_sync_slot_callback,
                       master=self.node,
                       message=message)
        else:
            SimLWBSlot(self.node,
                       slot,
                       self.process_sync_slot_callback,
                       master=self.lwb.base,
                       message=None)
Exemple #9
0
    def tx(self, source: 'sim_node.SimNode', modulation, band,
           message: SimMessage):
        power = lwb_slot.RADIO_POWERS[message.power_level]

        message = copy(message)
        message.hop_count += 1
        message.tx_start = source.transform_local_to_global_timestamp(
            message.timestamp)

        self.mq.loc[len(self.mq)] = [
            source, modulation, band, power, message.tx_start, message.tx_end,
            message, message.hash
        ]

        self.network.tracer.log_activity(
            TxActivity(message.tx_start,
                       message.tx_end,
                       source,
                       RadioConfiguration.tx_energy(
                           power, message.tx_end - message.tx_start),
                       power,
                       modulation,
                       ack=(message.type is SimMessageType.GLORIA_ACK)))

        for rx_node_item_index, rx_node_item in self.rxq.iterrows():
            if (rx_node_item is not None
                    and rx_node_item['rx_start'] < message.tx_start
                    and rx_node_item['modulation'] is modulation
                    and rx_node_item['band'] is band):
                self.network.em.register_event(
                    message.tx_end,
                    rx_node_item['rx_node'],
                    sim_event_type.SimEventType.TX_DONE_BEFORE_RX_TIMEOUT,
                    rx_node_item['callback'], {
                        'source': source,
                        'message': message,
                        'rx': rx_node_item
                    },
                    local=False)
Exemple #10
0
 def process_round_schedule_slot(self, slot: 'lwb_slot.LWBSlot'):
     if self.node.role is sim_node.SimNodeRole.BASE:
         round_schedule = self.lwb.schedule_manager.get_round_schedule(
             self.round)
         message = SimMessage(slot.slot_marker,
                              self.node,
                              slot.payload,
                              modulation=slot.modulation,
                              destination=None,
                              type=SimMessageType.ROUND_SCHEDULE,
                              content=round_schedule,
                              power_level=slot.power_level)
         SimLWBSlot(self.node,
                    slot,
                    self.process_round_schedule_slot_callback,
                    master=self.node,
                    message=message)
     else:
         SimLWBSlot(self.node,
                    slot,
                    self.process_round_schedule_slot_callback,
                    message=None)
Exemple #11
0
    def process_next_slot(self):
        self.slot_index += 1

        if self.is_not_finished():
            slot = self.flood.slots[self.slot_index]

            if slot.type in [
                    gloria_flood.GloriaSlotType.RX_ACK,
                    gloria_flood.GloriaSlotType.TX_ACK
            ]:
                if self.tx_message is not None and self.tx_message.destination is self.node and self.ack_message is None:
                    self.is_ack = True

                    self.ack_message = SimMessage(
                        slot.tx_marker,
                        source=self.tx_message.source,
                        payload=gloria.GLORIA_ACK_LENGTH,
                        destination=self.tx_message.source,
                        type=SimMessageType.GLORIA_ACK,
                        power_level=self.tx_message.power_level,
                        modulation=self.tx_message.modulation)
                    self.node.mm.tx(self.node, self.flood.modulation,
                                    self.flood.band, self.ack_message)

                    self.node.em.register_event(
                        slot.tx_done_marker, self.node,
                        sim_event_manager.SimEventType.TX_DONE,
                        self.progress_gloria_flood)

                    self.ack_counter += 1
                elif self.ack_message is not None:
                    self.ack_message.timestamp = slot.tx_marker

                    self.node.mm.tx(self.node, self.flood.modulation,
                                    self.flood.band, self.ack_message)

                    self.node.em.register_event(
                        slot.tx_done_marker, self.node,
                        sim_event_manager.SimEventType.TX_DONE,
                        self.progress_gloria_flood)

                    self.ack_counter += 1

                else:
                    self.node.mm.register_rx(self.node, slot.rx_marker,
                                             self.flood.modulation,
                                             self.flood.band,
                                             self.progress_gloria_flood)

                    self.rx_timeout_event = self.node.em.register_event(
                        slot.rx_timeout_marker, self.node,
                        sim_event_manager.SimEventType.RX_TIMEOUT,
                        self.progress_gloria_flood)
            elif (self.tx_message and self.retransmission_count > 0
                  and (int((self.slot_index - self.first_rx_slot_index) / 2) %
                       2 if self.flood.acked else
                       int(self.slot_index - self.first_rx_slot_index) % 2)):

                self.tx_message.timestamp = slot.tx_marker

                self.node.mm.tx(self.node, self.flood.modulation,
                                self.flood.band, self.tx_message)

                self.node.em.register_event(
                    slot.tx_done_marker, self.node,
                    sim_event_manager.SimEventType.TX_DONE,
                    self.progress_gloria_flood)

                if (self.power_increase and self.tx_message.power_level <
                        len(lwb_slot.RADIO_POWERS) - 1):
                    self.tx_message.power_level += 1
                self.retransmission_count -= 1

            else:
                self.node.mm.register_rx(self.node, slot.rx_marker,
                                         self.flood.modulation,
                                         self.flood.band,
                                         self.progress_gloria_flood)

                self.rx_timeout_event = self.node.em.register_event(
                    slot.rx_timeout_marker, self.node,
                    sim_event_manager.SimEventType.RX_TIMEOUT,
                    self.progress_gloria_flood)

        else:
            self.finished_callback(self.tx_message)