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 __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)
"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")
""" 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")
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
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