Пример #1
0
 def set_packet(self, packet_bbuf):
     super().set_packet(packet_bbuf)
     # because draft-18 requires that in No-ACK mode, each fragment must
     # contain exactly one tile and the tile size must be at least the size
     # of an L2 Word.
     min_size = (schcmsg.get_sender_header_size(self.rule) +
                 schcmsg.get_mic_size(self.rule) + self.rule["L2WordSize"])
     if self.protocol.layer2.get_mtu_size() < min_size:
         raise ValueError(
             "the MTU={} is not enough to carry the SCHC fragment of No-ACK mode={}"
             .format(self.protocol.layer2.get_mtu_size(), min_size))
Пример #2
0
    def send_frag(self):
        print("{} send_frag!!!!!!!!!!!!!!!!!".format(utime.time()))
        print("all1_send-> {}, resend -> {}, state -> {}".format(
            self.all1_send, self.resend, self.state))
        print("all tiles unsend -> {}".format(self.all_tiles))
        for tile in self.all_tiles.get_all_tiles():
            print("w: {}, t: {}, sent: {}".format(tile['w-num'], tile['t-num'],
                                                  tile['sent']))
        if self.state == self.ACK_SUCCESS:
            return

        # if self.state == self.ACK_FAILURE and self.num_of_windows != 1 and self.number_of_ack_waits <= self.num_of_windows:
        #     #waiting for the acks of the others windows
        #     self.number_of_ack_waits += 1 #wait depends on the number of windows
        #     #set ack_time_out_timer
        #     print("waiting for more acks: {}".format(self.number_of_ack_waits))
        #     return

        # get contiguous tiles as many as possible fit in MTU.
        mtu_size = self.protocol.layer2.get_mtu_size()
        window_tiles, nb_remaining_tiles, remaining_size = self.all_tiles.get_tiles(
            mtu_size)
        print("window tiles: {}, nb_remaining_tiles: {}, remaining_size: {}".
              format(window_tiles, nb_remaining_tiles, remaining_size))
        if window_tiles is None and self.resend:
            print("no more tiles to resend")
            #how to identify that all tiles are resend and that the ack timeout should be set
            #to wait for tha last ok. It should be set after retransmission of the last fragment
            if self.state == self.ACK_FAILURE and self.event_id_ack_wait_timer is None:
                win = self.last_window_tiles[0][
                    "w-num"] if self.last_window_tiles[0][
                        "w-num"] is not None else 0
                if self.last_window_tiles[0]["t-num"] == 0:
                    win += 1
                schc_frag = schcmsg.frag_sender_tx(self.rule,
                                                   dtag=self.dtag,
                                                   win=win,
                                                   fcn=schcmsg.get_fcn_all_1(
                                                       self.rule),
                                                   mic=self.mic_sent)
                #set ack waiting timer
                args = (
                    schc_frag,
                    win,
                )
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                print("*******event id {}".format(
                    self.event_id_ack_wait_timer))
            # if self.all1_send and self.state == self.ACK_FAILURE:
            #     #case when with the bitmap is not possible to identify the missing tile,
            #     #resend ALL-1 messages
            #     # send a SCHC fragment
            #     args = (self.schc_all_1.packet.get_content(), self.context["devL2Addr"],
            #     self.event_sent_frag)
            #     print("frag sent:", self.schc_all_1.__dict__)
            #     if enable_statsct:
            #         Statsct.set_msg_type("SCHC_ALL_1")
            #         Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule) +
            #             schcmsg.get_mic_size(self.rule))
            #     self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
            #                                     args)
            #     print("Sending all-1 beacuse there is an ACK FaILURE but cannot find the missing tiles")
            #     input("")

            # win = self.last_window_tiles[0]["w-num"] if self.last_window_tiles[0]["w-num"] is not None else 0
            # if self.last_window_tiles[0]["t-num"] == 0:
            #     win += 1
            # schc_frag = schcmsg.frag_sender_tx(
            #         self.rule, dtag=self.dtag, win=win,
            #         fcn=schcmsg.get_fcn_all_1(self.rule),
            #         mic=self.mic_sent)
            # set ack waiting timer
            #args = (schc_frag, win,)
            #self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
            #        self.ack_wait_timer, self.ack_timeout, args)
            #print("*******event id {}".format(self.event_id_ack_wait_timer))

        #if window_tiles is not None and not self.all1_send and not self.resend:
        if window_tiles is not None:

            print("window_tiles is not None -> {}, resend -> {}".format(
                self.all1_send, self.resend))
            # even when mic is sent, it comes here in the retransmission.
            if self.all1_send and self.state != self.ACK_FAILURE:
                #when there is a retransmission, the all-1 is send again and is send before
                #the ACK-OK is received. One option is not set the timer after the last
                #retransmission, but i don´t know how to idenfy that all missing fragments
                #have been send. Also the ALL-1 is not retransmisted (dont know if this should
                # be like this. For example, if the ALL-1s is lost, the receiver timer expires
                # and a receiver abort is send. If it arrives, there is not need to retransmit
                # the message after the retransmission of the missing fragments)
                #FIX, all-1 is resend
                print('All-1 ones already send')
                #cancel timer when there is success
                # if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                #     self.cancel_ack_wait_timer()
                #else:
                #    print("how to add a timer without sending a message")
                # fcn = schcmsg.get_fcn_all_1(self.rule)
                # args = (schc_frag, window_tiles[0]["w-num"],)
                # elf.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                # self.ack_wait_timer, self.ack_timeout, args)
                #fcn = schcmsg.get_fcn_all_1(self.rule)
                return
            elif (nb_remaining_tiles == 0 and len(window_tiles) == 1
                  and remaining_size >= schcmsg.get_mic_size(self.rule)):
                print("ALL-1 prepared")

                # make the All-1 frag with this tile.
                # the All-1 fragment can carry only one tile of which the size
                # is less than L2 word size.
                fcn = schcmsg.get_fcn_all_1(self.rule)
                last_frag_base_size = (
                    schcmsg.get_sender_header_size(self.rule) +
                    schcmsg.get_mic_size(self.rule) +
                    TileList.get_tile_size(window_tiles))
                #check if mic exists, no need no created again
                if self.mic_sent is None:
                    mic = self.get_mic(self.mic_base, last_frag_base_size)
                    # store the mic in order to know all-1 has been sent.
                    self.mic_sent = mic
                else:
                    mic = self.mic_sent
                print("mic_sent -> {}".format(self.mic_sent))
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_ALL_1")
                    Statsct.set_header_size(
                        schcmsg.get_sender_header_size(self.rule) +
                        schcmsg.get_mic_size(self.rule))
                self.all1_send = True
                self.state = self.SEND_ALL_1
            else:
                print("regular SCHC frag")
                # regular fragment.
                fcn = window_tiles[0]["t-num"]
                mic = None

                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        schcmsg.get_sender_header_size(self.rule))
            schc_frag = schcmsg.frag_sender_tx(
                self.rule,
                dtag=self.dtag,
                win=window_tiles[0]["w-num"],
                fcn=fcn,
                mic=mic,
                payload=TileList.concat(window_tiles))

            if mic is not None:

                print("mic is not None")
                # set ack waiting timer
                #if enable_statsct:
                #    Statsct.set_msg_type("SCHC_FRAG")
                #    Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule))
                args = (
                    schc_frag,
                    window_tiles[0]["w-num"],
                )
                print("all ones")
                self.schc_all_1 = schc_frag
                self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                    self.ack_wait_timer, self.ack_timeout, args)
                print("*******event id {}".format(
                    self.event_id_ack_wait_timer))
            # save the last window tiles.
            self.last_window_tiles = window_tiles
            print("self.last_window_tiles -> {}".format(
                self.last_window_tiles))
        elif self.mic_sent is not None or self.all1_send:
            print("self.mic_sent is not None state -> {}".format(self.state))
            # it looks that all fragments have been sent.
            print(
                "----------------------- all tiles have been sent -----------------------",
                window_tiles, nb_remaining_tiles, remaining_size)
            schc_frag = None
            self.all1_send = True
            if self.event_id_ack_wait_timer and self.state == self.ACK_SUCCESS:
                self.cancel_ack_wait_timer()
            return
        else:
            print("only mic all tiles send")
            # Here, only MIC will be sent since all tiles has been sent.
            assert self.last_window_tiles is not None
            # As the MTU would be changed anytime AND the size of the
            # significant padding bits would be changed, therefore the MIC
            # calculation may be needed again.
            # XXX maybe it's better to check whether the size of MTU is change
            # or not when the previous MIC was calculated..
            last_frag_base_size = (
                schcmsg.get_sender_header_size(self.rule) +
                TileList.get_tile_size(self.last_window_tiles))
            self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size)
            # check the win number.
            # XXX if the last tile number is zero, here window number has to be
            # incremented.
            win = self.last_window_tiles[0]["w-num"]
            if self.last_window_tiles[0]["t-num"] == 0:
                win += 1
            schc_frag = schcmsg.frag_sender_tx(self.rule,
                                               dtag=self.dtag,
                                               win=win,
                                               fcn=schcmsg.get_fcn_all_1(
                                                   self.rule),
                                               mic=self.mic_sent)
            # set ack waiting timer
            args = (
                schc_frag,
                win,
            )
            if enable_statsct:
                Statsct.set_msg_type("SCHC_ALL_1")
                Statsct.set_header_size(
                    schcmsg.get_sender_header_size(self.rule) +
                    schcmsg.get_mic_size(self.rule))
            self.schc_all_1 = schc_frag
            self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                self.ack_wait_timer, self.ack_timeout, args)
            print("*******event id {}".format(self.event_id_ack_wait_timer))

        # send a SCHC fragment
        args = (schc_frag.packet.get_content(), self.context["devL2Addr"],
                self.event_sent_frag)
        print("frag sent:", schc_frag.__dict__)
        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)
Пример #3
0
    def send_frag(self):
        # XXX
        # because No-ACK mode supports variable MTU,
        # sender can't know the fact that it can't send all fragments
        # before it reachs to send the last fragment (All-1).
        #
        #     The All-1 fragment MUST be formed like below.
        #
        #     | header | MIC |    last tile     |
        #                    |<- L2 word size ->|
        #                                       |<- L2 Word
        #
        #     if the size of header+MIC+tile doesn't fit the L2 Word,
        #
        #     | header | MIC |     last tile    |    padding    |
        #                    |<- L2 word size ->|<- less than ->|
        #                                         L2 word size
        #                                                       |<- L2 Word
        payload_size = (self.protocol.layer2.get_mtu_size() -
                        schcmsg.get_sender_header_size(self.rule))
        remaining_data_size = self.packet_bbuf.count_remaining_bits()
        if remaining_data_size >= payload_size:
            # put remaining_size of bits of packet into the tile.
            tile = self.packet_bbuf.get_bits_as_buffer(payload_size)
            transmit_callback = self.event_sent_frag
            fcn = 0
            self.mic_sent = None
            if enable_statsct:
                Statsct.set_msg_type("SCHC_FRAG")
                Statsct.set_header_size(
                    schcmsg.get_sender_header_size(self.rule))
        elif remaining_data_size < payload_size:
            if remaining_data_size <= (payload_size -
                                       schcmsg.get_mic_size(self.rule)):
                tile = None
                if remaining_data_size > 0:
                    tile = self.packet_bbuf.get_bits_as_buffer()
                # make All-1 frag.
                assert self.mic_sent is None
                last_frag_base_size = 0
                if tile is not None:
                    last_frag_base_size += (
                        schcmsg.get_sender_header_size(self.rule) +
                        schcmsg.get_mic_size(self.rule) + remaining_data_size)
                self.mic_sent = self.get_mic(self.mic_base,
                                             last_frag_base_size)
                # callback doesn't need in No-ACK mode.
                transmit_callback = None
                fcn = schcmsg.get_fcn_all_1(self.rule)
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_ALL_1")
                    Statsct.set_header_size(
                        schcmsg.get_sender_header_size(self.rule) +
                        schcmsg.get_mic_size(self.rule))
            else:
                # put the size of the complements of the header to L2 Word.
                tile_size = (remaining_data_size -
                             (schcmsg.get_sender_header_size(self.rule) +
                              remaining_data_size) % self.rule["L2WordSize"])
                tile = self.packet_bbuf.get_bits_as_buffer(tile_size)
                transmit_callback = self.event_sent_frag
                fcn = 0
                self.mic_sent = None
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_FRAG")
                    Statsct.set_header_size(
                        schcmsg.get_sender_header_size(self.rule))
        schc_frag = schcmsg.frag_sender_tx(self.rule,
                                           dtag=self.dtag,
                                           win=None,
                                           fcn=fcn,
                                           mic=self.mic_sent,
                                           payload=tile)

        # send a SCHC fragment
        args = (schc_frag.packet.get_content(), self.context["devL2Addr"],
                transmit_callback)
        print("frag sent:", schc_frag.__dict__)
        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)
Пример #4
0
 def send_frag(self):
     # get contiguous tiles as many as possible fit in MTU.
     mtu_size = self.protocol.layer2.get_mtu_size()
     window_tiles, nb_remaining_tiles, remaining_size = self.all_tiles.get_tiles(
         mtu_size)
     #print('**********window_tiles: ', window_tiles)
     #print('**********nb_remaining_tiles: ', nb_remaining_tiles)
     #print('**********remaining_size: ', remaining_size)
     if window_tiles is not None:
         # even when mic is sent, it comes here in the retransmission.
         if (nb_remaining_tiles == 0 and len(window_tiles) == 1
                 and remaining_size >= schcmsg.get_mic_size(self.rule)):
             #make the All-1 frag with this tile.
             # the All-1 fragment can carry only one tile of which the size
             # is less than L2 word size.
             fcn = schcmsg.get_fcn_all_1(self.rule)
             last_frag_base_size = (
                 schcmsg.get_sender_header_size(self.rule) +
                 schcmsg.get_mic_size(self.rule) +
                 TileList.get_tile_size(window_tiles))
             mic = self.get_mic(self.mic_base, last_frag_base_size)
             # store the mic in order to know all-1 has been sent.
             self.mic_sent = mic
         else:
             # regular fragment.
             fcn = window_tiles[0]["t-num"]
             mic = None
         schc_frag = schcmsg.frag_sender_tx(
             self.rule,
             dtag=self.dtag,
             win=window_tiles[0]["w-num"],
             fcn=fcn,
             mic=mic,
             payload=TileList.concat(window_tiles))
         if mic is not None:
             # set ack waiting timer
             args = (
                 schc_frag,
                 window_tiles[0]["w-num"],
             )
             self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
                 self.ack_wait_timer, self.ack_timeout, args)
         # save the last window tiles.
         self.last_window_tiles = window_tiles
     elif self.mic_sent is not None:
         # it looks that all fragments have been sent.
         print("xxx looks all tiles have been sent.", window_tiles,
               nb_remaining_tiles, remaining_size)
         schc_frag = None
         return
     else:
         # Here, only MIC will be sent since all tiles has been sent.
         assert self.last_window_tiles is not None
         # As the MTU would be changed anytime AND the size of the
         # significant padding bits would be changed, therefore the MIC
         # calculation may be needed again.
         # XXX maybe it's better to check whether the size of MTU is change
         # or not when the previous MIC was calculated..
         last_frag_base_size = (
             schcmsg.get_sender_header_size(self.rule) +
             TileList.get_tile_size(self.last_window_tiles))
         self.mic_sent = self.get_mic(self.mic_base, last_frag_base_size)
         # check the win number.
         # XXX if the last tile number is zero, here window number has to be
         # incremented.
         win = self.last_window_tiles[0]["w-num"]
         if self.last_window_tiles[0]["t-num"] == 0:
             win += 1
         schc_frag = schcmsg.frag_sender_tx(self.rule,
                                            dtag=self.dtag,
                                            win=win,
                                            fcn=schcmsg.get_fcn_all_1(
                                                self.rule),
                                            mic=self.mic_sent)
         # set ack waiting timer
         args = (
             schc_frag,
             win,
         )
         self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
             self.ack_wait_timer, self.ack_timeout, args)
     # send a SCHC fragment
     args = (schc_frag.packet.get_content(), self.protocol.layer2.mac_id,
             None, self.event_sent_frag, True)
     print("frag sent:", schc_frag.__dict__)
     self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                       args)