コード例 #1
0
ファイル: protocol.py プロジェクト: adjih/openschc
 def __init__(self, config, system, layer2, layer3):
     self.config = config
     self.system = system
     self.scheduler = system.get_scheduler()
     self.layer2 = layer2
     self.layer3 = layer3
     self.layer2._set_protocol(self)
     self.layer3._set_protocol(self)
     self.default_frag_rule = None  # XXX: to be in  rule_manager
     self.compressor = Compressor(self)
     self.decompressor = Decompressor(self)
     self.fragment_session = Session(self)
     self.reassemble_session = Session(self)
     if hasattr(config, "debug_level"):
         set_debug_output(True)
コード例 #2
0
 def __init__(self, config, system, layer2, layer3, role, unique_peer):
     assert role in ["device", "core-server"]
     self.config = config
     self.unique_peer = unique_peer
     self.role = role
     self.system = system
     self.scheduler = system.get_scheduler()
     self.layer2 = layer2
     self.layer3 = layer3
     self.layer2._set_protocol(self)
     self.layer3._set_protocol(self)
     self.compressor = Compressor(self)
     self.decompressor = Decompressor(self)
     self.session_manager = SessionManager(self, unique_peer)
     if hasattr(config, "debug_level"):
         set_debug_output(True)
コード例 #3
0
            "TV": 0,
            "MO": "ignore",
            "CDA": "compute-checksum"
        },
    ]
}

RM = RuleManager()
RM.Add(dev_info=rule_compress_all)
RM.Print()


class debug_protocol:
    def _log(*arg):
        print(*arg)


P = Parser(debug_protocol)
headers, data = P.parse(packet, direction="UP", layers=["IPv6", "UDP"])

pprint.pprint(headers)
print(binascii.hexlify(data))

rule = RM.FindRuleFromPacket(headers, direction="UP")
print(rule)

C = Compressor(debug_protocol)
result = C.compress(rule, headers, data, direction="UP")

result.display()
result.display(format="bin")
コード例 #4
0
"""
packet_src = "6 00 12345 0039 11 33 20011222890504700000000000000057 200141d057d731000000000000000401\
            1634 1633 0039 7a6e\
            5102 00a0 20 b474656d70 d1ea02 ff\
            981f19074b210503010500220622200600250301220401030300220304010122030a05".replace (" ", "")

packet = binascii.unhexlify(packet_src)
print (packet)
    
rule_default_8bits = {
    "RuleID": 8,
    "RuleIDLength" : 7,
    "NoCompression" : []
}

RM = RuleManager()
RM.Add(dev_info=rule_default_8bits)
RM.Print()

r = RM.FindNoCompressionRule()
print (r)

class debug_protocol:
    def _log(*arg):
        print(*arg)

C = Compressor(debug_protocol)
result = C.no_compress (r, packet)

result.display()
result.display(format="bin")
コード例 #5
0
ファイル: protocol.py プロジェクト: ltn22/openschc
class SCHCProtocol:
    """This class is the entry point for the openschc
    (in this current form, object composition is used)

    """

    def __init__(self, config, system, layer2, layer3, role, unique_peer):
        assert role in ["device", "core-server"]
        self.config = config
        self.unique_peer = unique_peer
        self.role = role
        self.system = system
        self.scheduler = system.get_scheduler()
        self.layer2 = layer2
        self.layer3 = layer3
        self.layer2._set_protocol(self)
        self.layer3._set_protocol(self)
        self.compressor = Compressor(self)
        self.decompressor = Decompressor(self)
        self.session_manager = SessionManager(self, unique_peer)
        if ((isinstance(config, object) and hasattr(config, "debug_level")) or
            (isinstance(config, dict) and config.get("debug_level", 0))):
            set_debug_output(True)

    def _log(self, message):
        self.log("schc", message)

    def log(self, name, message):
        self.system.log(name, message)

    def set_rulemanager(self, rule_manager):
        self.rule_manager = rule_manager

    def get_system(self):
        return self.system


    def _apply_compression(self, dst_l3_address, raw_packet):
        """Apply matching compression rule if one exists.
        
        In any case return a SCHC packet (compressed or not) as a BitBuffer
        """
        context = self.rule_manager.find_context_bydstiid(dst_l3_address)
        if self.role == "device":
            t_dir = T_DIR_UP
        else:
            assert self.role == "core-server"
            t_dir = T_DIR_DW

        # Parse packet as IP packet and apply compression rule
        P = Parser(self)
        parsed_packet, residue, parsing_error = P.parse(raw_packet, t_dir)
        self._log("parser {} {} {}".format(parsed_packet, residue, parsing_error))
        if parsed_packet is None:
            return BitBuffer(raw_packet)

        # Apply compression rule
        rule = self.rule_manager.FindRuleFromPacket(parsed_packet, direction=t_dir)
        self._log("compression rule {}".format(rule))
        if rule is None:
            rule = self.rule_manager.FindNoCompressionRule(dst_l3_address)
            self._log("no-compression rule {}".format(rule))

        if rule is None:
            # XXX: not putting any SCHC compression header? - need fix
            self._log("rule for compression/no-compression not found")
            return BitBuffer(raw_packet)

        if rule["Compression"] == []:  # XXX: should be "NoCompression"
            self._log("compression result no-compression")
            return BitBuffer(raw_packet)

        schc_packet = self.compressor.compress(rule, parsed_packet, residue, t_dir)
        dprint(schc_packet)
        schc_packet.display("bin")
        self._log("compression result {}".format(schc_packet))

        return schc_packet


    def _make_frag_session(self, dst_l2_address, direction):
        """Search a fragmentation rule, create a session for it, return None if not found"""
        frag_rule = self.rule_manager.FindFragmentationRule(
                deviceID=dst_l2_address, direction=direction)
        if frag_rule is None:
            self._log("fragmentation rule not found")
            return None

        # Perform fragmentation
        rule = frag_rule
        context = None  # LT: don't know why context is needed, should be self.rule_manager which handle the context
        self._log("fragmentation rule_id={}".format(rule[T_RULEID]))

        session = self.session_manager.create_fragmentation_session(
            dst_l2_address, context, rule)
        if session is None:
            self._log("fragmentation session could not be created") # XXX warning
            return None

        return session


    def schc_send(self, dst_l2_address, dst_l3_address, raw_packet):
        """Starting to send SCHC packet after called by L3.
        
        If dst_l2_address is None, this function is for sending
        from device to core.

        XXX the order of the args should be:
            schc_send(self, dst_l3_address, raw_packet, dst_l2_address=None)
        """
        self._log("recv-from-l3 {} {} {}".format(dst_l2_address, dst_l3_address, raw_packet))

        # Perform compression
        packet_bbuf = self._apply_compression(dst_l3_address, raw_packet)

        # Check if fragmentation is needed.
        if packet_bbuf.count_added_bits() < self.layer2.get_mtu_size():
            self._log("fragmentation not needed size={}".format(
                packet_bbuf.count_added_bits()))
            args = (packet_bbuf.get_content(), dst_l2_address)
            self.scheduler.add_event(0, self.layer2.send_packet, args) # XXX: what about directly send?
            return

        # Start a fragmentation session from rule database
        if dst_l2_address == None:
            direction = T_DIR_UP
        else:
            direction = T_DIR_DW
        frag_session = self._make_frag_session(dst_l2_address, direction)
        if frag_session is not None:
            frag_session.set_packet(packet_bbuf)
            frag_session.start_sending()

    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)


    def process_decompress(self, packet_bbuf, dev_l2_addr, direction):
        rule = self.rule_manager.FindRuleFromSCHCpacket(packet_bbuf, dev_l2_addr)
        if rule is None:
            # reject it.
            self._log("No compression rule for SCHC packet, sender L2addr={}"
                      .format(dev_l2_addr))
            self.scheduler.add_event(0, self.layer3.recv_packet,
                                     (dev_l2_addr, packet_bbuf.get_content()))
            return

        if "Compression" not in rule:
            # reject it.
            self._log("Not compression parameters for SCHC packet, sender L2addr={}".format(
                dev_l2_addr))
            return

        if rule["Compression"]:
            dprint("---------------------- Decompression ----------------------")
            dprint("---------------------- Decompression Rule-------------------------")
            self._log("compression rule_id={}".format(rule[T_RULEID]))
            dprint("receiver frag received:", packet_bbuf)
            dprint('rule {}'.format(rule))
            dprint("------------------------ Decompression ---------------------------")
            raw_packet = self.decompressor.decompress(packet_bbuf, rule, direction)
            dprint("---- Decompression result ----")
            dprint(raw_packet)
            args = (dev_l2_addr, raw_packet)
            self.scheduler.add_event(0, self.layer3.recv_packet, args)

    # def process_decompress(self, context, dev_l2_addr, schc_packet):
    #    self._log("compression rule_id={}".format(context["comp"]["ruleID"]))
    #    raw_packet = self.decompressor.decompress(context, schc_packet)
    #    args = (dev_l2_addr, raw_packet)
    #    self.scheduler.add_event(0, self.layer3.recv_packet, args)

    def get_state_info(self, **kw):
        result =  {
            "sessions": self.session_manager.get_state_info(**kw)
        }
        return result

    def get_init_info(self, **kw):
        result =  {
            "role": self.role,
            "unique-peer": self.unique_peer
        }
        result["rule-manager"] = self.rule_manager.get_init_info(**kw)
        return result
コード例 #6
0
ファイル: protocol.py プロジェクト: adjih/openschc
class SCHCProtocol:
    """This class is the entry point for the openschc
    (in this current form, object composition is used)"""

    # def __init__(self, config, scheduler, schc_layer2, role="sender"):
    def __init__(self, config, system, layer2, layer3):
        self.config = config
        self.system = system
        self.scheduler = system.get_scheduler()
        self.layer2 = layer2
        self.layer3 = layer3
        self.layer2._set_protocol(self)
        self.layer3._set_protocol(self)
        self.default_frag_rule = None  # XXX: to be in  rule_manager
        self.compressor = Compressor(self)
        self.decompressor = Decompressor(self)
        self.fragment_session = Session(self)
        self.reassemble_session = Session(self)
        if hasattr(config, "debug_level"):
            set_debug_output(True)

    def _log(self, message):
        self.log("schc", message)

    def log(self, name, message):
        self.system.log(name, message)

    def set_rulemanager(self, rule_manager):
        self.rule_manager = rule_manager

    def get_system(self):
        return self.system

    def schc_send(self, dst_L3addr, raw_packet, direction="UP"):
        self._log("recv-from-L3 -> {} {}".format(dst_L3addr, raw_packet))
        context = self.rule_manager.find_context_bydstiid(dst_L3addr)
        dprint("raw_packet in schc_send", raw_packet)
        if direction in ["UP", "up"]:
            t_dir = T_DIR_UP
        elif direction in ["DOWN", "down", "DW", "dw"]:
            t_dir = T_DIR_DW
        else:
            raise ValueError(
                "direction must be UP or DOWN, but {}".format(direction))

        P = Parser(debug_protocol)
        parsed_packet = P.parse(raw_packet, t_dir)
        dpprint(parsed_packet)

        try:
            parsed_packet = P.parse(raw_packet, T_DIR_UP)
            dpprint("parsed_packet[0]", parsed_packet[0])
        except:
            dprint("no parsing, try fragmentation")
            parsed_packet = None
            schc_packet = None

        if parsed_packet is not None:
            # pass        # to be done
            rule = self.rule_manager.FindRuleFromPacket(parsed_packet[0],
                                                        direction=t_dir)
            if rule is None:
                schc_packet = None
                # reject it.
                # self._log("Rejected. Not for SCHC packet, L4addr={}".format(
                #    dst_L3addr))
                # return
            else:
                if rule["Compression"] != []:
                    dprint(
                        "-------------------------------------- Compression Proccess -------------------------------------------"
                    )
                    dprint("selected rule is ", rule)
                    schc_packet = self.compressor.compress(
                        rule, parsed_packet[0], parsed_packet[1], t_dir)
                    dprint(schc_packet)
                    schc_packet.display("bin")
                else:
                    schc_packet = None

        if schc_packet == None:
            packet_bbuf = BitBuffer(raw_packet)
        else:
            packet_bbuf = schc_packet

        # check if fragmentation is needed.
        if packet_bbuf.count_added_bits() < self.layer2.get_mtu_size():
            self._log("SCHC fragmentation is not needed. size={}".format(
                packet_bbuf.count_added_bits()))
            """ Changement à corriger
            args = (packet_bbuf.get_content(), context["devL2Addr"])
            """
            args = (packet_bbuf.get_content(), "*")
            self.scheduler.add_event(0, self.layer2.send_packet, args)
            return

        # fragmentation is required.
        lower_addr = self.layer2.get_address()
        frag_rule = self.rule_manager.FindFragmentationRule(lower_addr)
        if frag_rule is None:
            self._log("Rejected the packet due to no fragmenation rule.")
            return
        # Do fragmenation
        dprint(
            "-------------------------------------- Fragmentation Proccess -------------------------------------------"
        )
        rule = frag_rule
        context = None  # LT: don't know why context is needed, should be self.rule_manager which handle the context
        self._log("fragmentation rule_id={}".format(rule[T_RULEID]))
        session = self.new_fragment_session(context, rule)
        session.set_packet(packet_bbuf)
        self.fragment_session.add(rule[T_RULEID], rule[T_RULEIDLENGTH],
                                  session.dtag, session)
        session.start_sending()

    def new_fragment_session(self, context, rule):
        mode = rule[T_FRAG][T_FRAG_MODE]
        if mode == "noAck":
            session = FragmentNoAck(self, context, rule)  # XXX
        elif mode == "ackAlwayw":  #XXX
            raise NotImplementedError(
                "{} is not implemented yet.".format(mode))
        elif mode == "ackOnError":
            session = FragmentAckOnError(self, context, rule)  # XXX
        else:
            raise ValueError("invalid FRMode: {}".format(mode))
        return session

    def new_reassemble_session(self, context, rule, dtag, dev_L2addr):
        mode = rule[T_FRAG][T_FRAG_MODE]
        if mode == "noAck":
            session = ReassemblerNoAck(self, context, rule, dtag, dev_L2addr)
        elif mode == "ackAlways":
            raise NotImplementedError("FRMode:", mode)
        elif mode == "ackOnError":
            session = ReassemblerAckOnError(self, context, rule, dtag,
                                            dev_L2addr)
        else:
            raise ValueError("FRMode:", mode)
        return session

    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)

    # def schc_recv(self, dev_L2addr, raw_packet):
    #     self._log("recv-from-L2 {} {}".format(dev_L2addr, raw_packet))
    #     # find context for the SCHC processing.
    #     # XXX
    #     # the receiver never knows if the packet from the device having the L2
    #     # addrss is encoded in SCHC.  Therefore, it has to search the db with
    #     # the field value of the packet.
    #     context = self.rule_manager.find_context_bydevL2addr(dev_L2addr)
    #     if context is None:
    #         # reject it.
    #         self._log("Rejected. Not for SCHC packet, sender L2addr={}".format(
    #                 dev_L2addr))
    #         return
    #     # find a rule in the context for this packet.
    #     packet_bbuf = BitBuffer(raw_packet)
    #     key, rule = self.rule_manager.find_rule_bypacket(context, packet_bbuf)
    #     if key == "fragSender":
    #         if rule["dtagSize"] > 0:
    #             dtag = packet_bbuf.get_bits(rule.get("dtagSize"),
    #                                 position=rule.get("ruleLength"))
    #         else:
    #             dtag = None
    #         # find existing session for fragment or reassembly.
    #         session = self.fragment_session.get(rule.ruleID,
    #                                             rule.ruleLength, 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(key, dev_L2addr))
    #     elif key == "fragReceiver":
    #         if rule["dtagSize"] > 0:
    #             dtag = packet_bbuf.get_bits(rule.get("dtagSize"),
    #                                 position=rule.get("ruleLength"))
    #         else:
    #             dtag = None
    #         # find existing session for fragment or reassembly.
    #         session = self.reassemble_session.get(rule.ruleID,
    #                                             rule.ruleLength, dtag)
    #         if session is not None:
    #             dprint("Reassembly session found", session)
    #         else:
    #             # no session is found.  create a new reassemble session.
    #             session = self.new_reassemble_session(context, rule, dtag,
    #                                                   dev_L2addr)
    #             self.reassemble_session.add(rule.ruleID, rule.ruleLength,
    #                                         dtag, session)
    #             dprint("New reassembly session created", session)
    #         session.receive_frag(packet_bbuf, dtag)
    #     elif key == "comp":
    #         # if there is no reassemble rule, process_decompress() is directly
    #         # called from here.  Otherwise, it will be called from a reassemble
    #         # function().
    #         self.process_decompress(context, dev_L2addr, packet_bbuf)
    #     elif key is None:
    #         raise ValueError(
    #                 "context exists, but no rule found for L2Addr {}".
    #                 format(dev_L2addr))
    #     else:
    #         raise SystemError("should not come here.")

    def process_decompress(self, packet_bbuf, dev_L2addr, direction):
        rule = self.rule_manager.FindRuleFromSCHCpacket(
            packet_bbuf, dev_L2addr)
        if rule is None:
            # reject it.
            self._log(
                "Rejected. Not rule compression for SCHC packet, sender L2addr={}"
                .format(dev_L2addr))
            return

        if "Compression" not in rule:
            # reject it.
            self._log(
                "Not compression parameters for SCHC packet, sender L2addr={}".
                format(dev_L2addr))
            return

        if rule["Compression"]:
            dprint(
                "---------------------- Decompression ----------------------")
            dprint(
                "---------------------- Decompression Rule-------------------------"
            )
            self._log("compression rule_id={}".format(rule[T_RULEID]))
            dprint("receiver frag received:", packet_bbuf)
            dprint('rule {}'.format(rule))
            dprint(
                "------------------------ Decompression ---------------------------"
            )
            raw_packet = self.decompressor.decompress(packet_bbuf, rule,
                                                      direction)
            dprint("---- Decompression result ----")
            dprint(raw_packet)
            args = (dev_L2addr, raw_packet)
            self.scheduler.add_event(0, self.layer3.recv_packet, args)

    # def process_decompress(self, context, dev_L2addr, schc_packet):
    #    self._log("compression rule_id={}".format(context["comp"]["ruleID"]))
    #    raw_packet = self.decompressor.decompress(context, schc_packet)
    #    args = (dev_L2addr, raw_packet)
    #    self.scheduler.add_event(0, self.layer3.recv_packet, args)

    def get_state(self, **kw):
        result = {
            "reassemble": self.reassemble_session.get_state(**kw),
            "fragment": self.fragment_session.get_state(**kw),
            "state": "XXX - need to be added"
        }
        if kw.get("is_init") == True:
            result[
                "rule-manager"] = None  #XXX:self.rule_manager.get_state(**kw)
        return result