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