Beispiel #1
0
    def schc_recv(self, dst_l2_addr, raw_packet):
        """Receiving a SCHC packet from a lower layer."""
        packet_bbuf = BitBuffer(raw_packet)
        dprint('SCHC: recv from L2:', b2hex(packet_bbuf.get_content()))
        frag_rule = self.rule_manager.FindFragmentationRule(
                deviceID=dst_l2_addr, packet=packet_bbuf)

        dtrace ('\t\t\t-----------{:3}--------->|'.format(len(packet_bbuf._content)))

        dtag_length = frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG]
        if dtag_length > 0:
            dtag = packet_bbuf.get_bits(dtag_length, position=frag_rule[T_RULEIDLENGTH])
        else:
            dtag = None # XXX: get_bits(0) should work?

        rule_id = frag_rule[T_RULEID]
        rule_id_length = frag_rule[T_RULEIDLENGTH]
        session_id = (dst_l2_addr, rule_id, rule_id_length, dtag)
        session = self.session_manager.find_session(session_id)

        if session is not None:
            dprint("{} session found".format(
                session.get_session_type().capitalize()),
                session.__class__.__name__)
        else:
            context = None
            session = self.session_manager.create_reassembly_session(
                context, frag_rule, session_id)
            dprint("New reassembly session created", session.__class__.__name__)

        session.receive_frag(packet_bbuf, dtag)
Beispiel #2
0
    def schc_recv(self, sender_l2_address, raw_packet):
        #self._log("recv-from-L2 {} {}".format(sender_l2_addr, raw_packet))
        frag_rule = self.rule_manager.FindFragmentationRule()

        packet_bbuf = BitBuffer(raw_packet)

        dtrace('>', binascii.hexlify(packet_bbuf.get_content()), ' ')
        dtrace ('\t\t\t-----------{:3}--------->|'.format(len(packet_bbuf._content)))

        dtag_length = frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG]
        if dtag_length > 0:
            dtag = packet_bbuf.get_bits(dtag_length, position=frag_rule[T_RULEIDLENGTH])
        else:
            dtag = None # XXX: get_bits(0) should work?

        rule_id = frag_rule[T_RULEID]
        rule_id_length = frag_rule[T_RULEIDLENGTH]
        session_id = (sender_l2_address, rule_id, rule_id_length, dtag)
        session = self.session_manager.find_session(session_id)

        if session is not None:
            dprint("{} session found".format(
                session.get_session_type().capitalize()),
                session.__class__.__name__)
        else:
            context = None
            session = self.session_manager.create_reassembly_session(
                context, frag_rule, session_id)
            dprint("New reassembly session created", session.__class__.__name__)

        session.receive_frag(packet_bbuf, dtag)
Beispiel #3
0
    def receive_frag(self, bbuf, dtag):
        dprint('state: {}, received fragment -> {}, rule-> {}'.format(
            self.state, bbuf, self.rule))

        schc_frag = frag_msg.frag_receiver_rx(self.rule, bbuf)
        dprint("receiver frag received:", schc_frag.__dict__)

        if schc_frag.rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG] == 0:
            w_dtag = '-'
        else:
            w_dtag = schc_frag.dtag

        if schc_frag.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W] == 0:
            w_w = '-'
        else:
            w_w = schc_frag.win

        all1 = 2**self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN] - 1
        if schc_frag.fcn == all1:
            w_fcn = "All-1"
        elif schc_frag.fcn == 0:
            w_fcn = "All-0"
        else:
            w_fcn = schc_frag.fcn

        dtrace("\t\t\tr:{}/{} (noA) DTAG={} W={} FCN={}".format(
            schc_frag.rule[T_RULEID], schc_frag.rule[T_RULEIDLENGTH], w_dtag,
            w_w, w_fcn))

        # XXX how to authenticate the message from the peer. without
        # authentication, any nodes can cancel the invactive timer.
        self.cancel_inactive_timer()
        dprint(schc_frag.__class__.__name__)
        #
        if schc_frag.abort == True:
            dprint(
                "----------------------- Sender-Abort ---------------------------"
            )
            # XXX needs to release all resources.
            return
        self.tile_list.append(schc_frag.payload)
        #
        if schc_frag.fcn == frag_msg.get_fcn_all_1(self.rule):
            dprint(
                "----------------------- Final Reassembly -----------------------"
            )
            dprint("ALL1 received")
            # MIC calculation
            dprint("tile_list")
            for _ in self.tile_list:
                dprint(_)
            schc_packet = BitBuffer()
            for i in self.tile_list:
                schc_packet += i
            dtrace(binascii.hexlify(schc_packet.get_content()))

            mic_calced = self.get_mic(schc_packet.get_content())
            if schc_frag.mic != mic_calced:
                dtrace("ERROR: MIC mismatched. packet {} != result {}".format(
                    schc_frag.mic, mic_calced))
                self.state = 'ERROR_MIC_NO_ACK'
                return
            else:
                dtrace("SUCCESS: MIC matched. packet {} == result {}".format(
                    schc_frag.mic, mic_calced))
            # decompression
            # dprint("----------------------- Decompression -----------------------")
            if not self.protocol.config.get("debug-fragment"):
                # XXX
                # XXX in hack105, we have separate databases for C/D and F/R.
                # XXX need to merge them into one.  Then, here searching database will
                # XXX be moved into somewhere.
                # XXX
                #rule = self.protocol.rule_manager.FindRuleFromSCHCpacket(schc=schc_packet)
                #dprint("debug: no-ack FindRuleFromSCHCpacket", rule)
                self.protocol.process_decompress(schc_packet,
                                                 self.sender_L2addr, "UP")
            self.state = 'DONE_NO_ACK'
            #dprint(self.state)
            return
        # set inactive timer.
        self.event_id_inactive_timer = self.protocol.scheduler.add_event(
            self.inactive_timer, self.event_inactive, tuple())
        dprint("---", schc_frag.fcn)
Beispiel #4
0
    def schc_recv(self, dev_L2addr, raw_packet):
        # self._log("recv-from-L2 {} {}".format(dev_L2addr, raw_packet))
        frag_rule = self.rule_manager.FindFragmentationRule(dev_L2addr)

        # dprint(dev_L2addr)
        packet_bbuf = BitBuffer(raw_packet)
        # dprint("raw_packet", raw_packet)
        # dprint("schc packet", packet_bbuf)
        # dprint("frag_rule", frag_rule)

        # !IMPORTANT: This condition has to be changed by a context condition like in the last version

        dtrace('>', binascii.hexlify(packet_bbuf.get_content()), ' ')
        dtrace('\t\t\t-----------{:3}--------->|'.format(
            len(packet_bbuf._content)))

        if dev_L2addr == b"\xaa\xbb\xcc\xee":

            if frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG] > 0:
                dtag = packet_bbuf.get_bits(
                    frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG],
                    position=frag_rule[T_RULEIDLENGTH])
            else:
                dtag = None

            # find existing session for fragment or reassembly.
            session = self.reassemble_session.get(frag_rule[T_RULEID],
                                                  frag_rule[T_RULEIDLENGTH],
                                                  dtag)
            if session is not None:
                dprint("Reassembly session found", session.__class__.__name__)
            else:
                # no session is found.  create a new reassemble session.
                context = None
                session = self.new_reassemble_session(context, frag_rule, dtag,
                                                      dev_L2addr)
                self.reassemble_session.add(frag_rule[T_RULEID],
                                            frag_rule[T_RULEIDLENGTH], dtag,
                                            session)
                dprint("New reassembly session created",
                       session.__class__.__name__)
            session.receive_frag(packet_bbuf, dtag)
            return

            self.process_decompress(packet_bbuf,
                                    dev_L2addr,
                                    direction=T_DIR_UP)

        elif dev_L2addr == b"\xaa\xbb\xcc\xdd":
            if frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG] > 0:
                dtag = packet_bbuf.get_bits(
                    frag_rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG],
                    position=frag_rule[T_RULEIDLENGTH])
            else:
                dtag = None
            # find existing session for fragment or reassembly.
            session = self.fragment_session.get(frag_rule[T_RULEID],
                                                frag_rule[T_RULEIDLENGTH],
                                                dtag)
            dprint("rule.ruleID -> {},rule.ruleLength-> {}, dtag -> {}".format(
                frag_rule[T_RULEID], frag_rule[T_RULEIDLENGTH], dtag))
            if session is not None:
                dprint("Fragmentation session found", session)
                session.receive_frag(packet_bbuf, dtag)
            else:
                dprint("context exists, but no {} session for this packet {}".
                       format(dev_L2addr))
            return

        else:
            raise RuntimeError("Not implemented properly", dev_L2addr)
Beispiel #5
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() -
                        frag_msg.get_sender_header_size(self.rule))
        remaining_data_size = self.packet_bbuf.count_remaining_bits()
        if remaining_data_size >= payload_size:
            dprint(
                "----------------------- Fragmentation process -----------------------"
            )
            # 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(
                    frag_msg.get_sender_header_size(self.rule))
        elif remaining_data_size < payload_size:
            dprint(
                "----------------------- Fragmentation process -----------------------"
            )
            if remaining_data_size <= (payload_size -
                                       frag_msg.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 += (
                        frag_msg.get_sender_header_size(self.rule) +
                        frag_msg.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 = frag_msg.get_fcn_all_1(self.rule)
                if enable_statsct:
                    Statsct.set_msg_type("SCHC_ALL_1 ")
                    Statsct.set_header_size(
                        frag_msg.get_sender_header_size(self.rule) +
                        frag_msg.get_mic_size(self.rule))
            else:
                # put the size of the complements of the header to L2 Word.
                tile_size = (remaining_data_size -
                             (frag_msg.get_sender_header_size(self.rule) +
                              remaining_data_size) % self.l2word)
                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(
                        frag_msg.get_sender_header_size(self.rule))
        schc_frag = frag_msg.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._session_id[0],
                transmit_callback)
        dprint("frag sent:", schc_frag.__dict__)
        if self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_DTAG] == 0:
            w_dtag = '-'
        else:
            w_dtag = schc_frag.dtag

        if self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W] == 0:
            w_w = '-'
        else:
            w_w = schc_frag.win

        all1 = 2**self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN] - 1
        if schc_frag.fcn == all1:
            w_fcn = "All-1"
        elif schc_frag.fcn == 0:
            w_fcn = "All-0"
        else:
            w_fcn = schc_frag.fcn

        dtrace("r:{}/{} (noA) DTAG={} W={} FCN={}".format(
            self.rule[T_RULEID], self.rule[T_RULEIDLENGTH], w_dtag, w_w,
            w_fcn))
        dtrace("|----{:3}------------->".format(len(
            schc_frag.packet._content)))

        self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet,
                                          args)