def create_simul(self): if self.simul_config is None: self.set_config(DEFAULT_SIMUL_CONFIG.copy()) self.init_stat() Statsct.get_results() sim = net_sim_core.Simul(self.simul_config) self.sim = sim
def finish(self, schc_packet, schc_frag): self.state = "DONE" dprint('state DONE -> {}'.format(self.state)) #input('DONE') # decompression self.protocol.process_decompress(schc_packet, self.sender_L2addr, direction="UP") # ACK message schc_ack = frag_msg.frag_receiver_tx_all1_ack(schc_frag.rule, schc_frag.dtag, schc_frag.win, cbit=1) dprint("ACK success sent:", schc_ack.__dict__) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_OK") dprint( "----------------------- SCHC ACK OK SEND -----------------------" ) """ Changement à corriger args = (schc_ack.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_ack.packet.get_content(), '*') self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) # XXX need to keep the ack message for the ack request. #the ack is build everytime self.schc_ack = schc_ack
def cond_collision(self, frag_size): """Calculates if there is a collision""" frag_ToA = get_toa(frag_size, Statsct.SF) #check if there is a collision at the start of the packet dprint("current time: {}, position: {}, ToA fragment: {}".format(self.current_time,self.position,frag_ToA['t_packet'])) dprint("background_traffic: {}".format(self.background_traffic[self.position])) while self.position < len(self.background_traffic) and self.current_time > self.background_traffic[self.position][0]: self.position += 1 dprint("position: {}, ".format(self.position)) if self.position != len(self.background_traffic): if self.current_time == self.background_traffic[self.position][0]: #special case when both packet start time is the same dprint("Collision! -> packet start at same time as the next") self.current_time += frag_ToA['t_packet'] + Statsct.dc_time_off(frag_ToA['t_packet'],Statsct.dc) return True elif self.position != 0 and self.current_time < self.background_traffic[self.position-1][1]: dprint("Collision! -> packet start before the end of previous packet") self.current_time += frag_ToA['t_packet'] + Statsct.dc_time_off(frag_ToA['t_packet'],Statsct.dc) return True else: if self.current_time + frag_ToA['t_packet'] > self.background_traffic[self.position][0]: dprint("Collision!-> packet ends after next has start") self.current_time += frag_ToA['t_packet'] + Statsct.dc_time_off(frag_ToA['t_packet'],Statsct.dc) return True self.current_time += frag_ToA['t_packet'] + Statsct.dc_time_off(frag_ToA['t_packet'],Statsct.dc) input('') return False
def event_inactive(self): """ event_inactive // TODO : Redaction (here is frag_recv.py) """ #if the ack-ok was received, no ACK REQ will be received, #check for state == "DONE" and return, this means that the ack-ok #was send, before the system returns after sending the ack-ok, now it #waits for one inactivity timer before closing session if self.state == "DONE": return # sending sender abort. schc_frag = frag_msg.frag_receiver_tx_abort(self.rule, self.dtag) """ Changement à corriger args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_frag.packet.get_content(), '*') dprint("Sent Receiver-Abort.", schc_frag.__dict__) dprint( "----------------------- SCHC RECEIVER ABORT SEND -----------------------" ) if enable_statsct: Statsct.set_msg_type("SCHC_RECEIVER_ABORT") Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule)) self.state = "ABORT" self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) # XXX needs to release all resources. return
def create_ack_schc_ko(self, schc_frag): """Create schc_ack packet in case of wrong RCS (C=0) return schc_ack packet """ bit_list = find_missing_tiles_mic_ko_yes_all_1( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule)) for tile in self.tile_list: dprint("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'], tile['t-num'], tile['nb_tiles'])) dprint("raw_tiles:{}".format(tile['raw_tiles'])) dprint('send ack before done {}'.format(bit_list)) assert bit_list is not None if bit_list: # Some tiles are actually missing, send ACK for first window with missing tiles dprint("missing wn={} bitmap={}".format(bit_list[0][0], bit_list[0][1])) # XXX compress bitmap if needed. # ACK failure message schc_ack = frag_msg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=bit_list[0][0], cbit=0, bitmap=bit_list[0][1]) elif not self.tile_list: dprint("No tile received before All-1, sending empty bitmap") # ACK failure message schc_ack = frag_msg.frag_receiver_tx_all1_ack(schc_frag.rule, schc_frag.dtag, win=0, cbit=0, bitmap=BitBuffer([])) else: window_list = make_bit_list_mic_ko( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule)) last_window = max(window_list.keys()) # No tiles are detected missing, send ACK for last window dprint("No missing tiles, sending last window: wn={} bitmap={}". format(last_window, BitBuffer(window_list[last_window]))) # XXX compress bitmap if needed. # ACK failure message schc_ack = frag_msg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=last_window, cbit=0, bitmap=BitBuffer(window_list[last_window])) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_KO") dprint( "----------------------- SCHC ACK KO SEND -----------------------" ) dprint("ACK failure sent:", schc_ack.__dict__) return schc_ack
def send_receiver_abort(self): # sending Receiver abort. self.state = "ABORT" schc_frag = schcmsg.frag_receiver_tx_abort(self.rule, self.dtag) args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) print("Sent Receiver-Abort.", schc_frag.__dict__) print("----------------------- SCHC RECEIVER ABORT SEND -----------------------") if enable_statsct: Statsct.set_msg_type("SCHC_RECEIVER_ABORT") #Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule)) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)
def send_packet(self, packet, src_id, dst_id=None, callback=None, callback_args=tuple() ): self._log("----------------------- SEND PACKET -----------------------") if not self.frame_loss.check(len(packet)): self._log("----------------------- OK -----------------------") self._log("send-packet {}->{} {}".format(src_id, dst_id, packet)) if enable_statsct: Statsct.log("send-packet {}->{} {}".format(src_id, dst_id, packet)) Statsct.add_packet_info(packet, src_id, dst_id, True) # if dst_id == None, it is a broadcast link_list = self.get_link_by_id(src_id, dst_id) count = 0 for link in link_list: count += self.send_packet_on_link(link, packet) else: self._log("----------------------- KO -----------------------") self._log("packet was lost {}->{}".format(src_id, dst_id)) if enable_statsct: Statsct.log("packet was lost {}->{} {}".format(src_id, dst_id, packet)) Statsct.add_packet_info(packet,src_id,dst_id, False) count = 0 # if callback != None: args = callback_args+(count,) # XXX need to check. - CA: # [CA] the 'count' is now passed as 'status' in: # SimulLayer2._event_sent_callback(self, transmit_callback, status # the idea is that is transmission fails, at least you can pass # count == 0 (status == 0), and you can do something there. # (in general case, some meta_information need to be sent) #args = callback_args callback(*args) return count
def init_stat(self): # Statistic module radio_config = self.simul_config["radio"] Statsct.initialize(init_time=0) Statsct.log("Statsct test") Statsct.set_packet_size(radio_config["data_size"]) Statsct.set_SF(radio_config["SF"])
def update_stat(self, node1, rm0, rm1, node0): # --------------------------------- # Information about the devices dprint(32 * "-" + " SCHC device------------------------") dprint("SCHC device L3={} L2={} RM={}".format(node0.layer3.L3addr, node0.id, rm0.__dict__)) dprint(32 * "-" + " SCHC gw ---------------------------") dprint("SCHC gw L3={} L2={} RM={}".format(node1.layer3.L3addr, node1.id, rm1.__dict__)) dprint(32 * "-" + " Rules -----------------------------") dprint("rules -> {}, {}".format(rm0.__dict__, rm1.__dict__)) dprint("") # ---------------------------------- # Statistic configuration Statsct.setSourceAddress(node0.id) Statsct.setDestinationAddress(node1.id)
def generate_background_traffic(self, G, background_frag_size): self.background_traffic T = get_toa(background_frag_size, Statsct.SF) g = G / T['t_packet'] print("g: {}, G:{}, T:{}".format(g, G, T['t_packet'])) for i in range(1000): #aleatoire = machine.rng() #aleatoire2 = aleatoire/(2**24-1) aleatoire = urandom.getrandbits(8) / 256 aleatoire2 = aleatoire / (2**24 - 1) #print(aleatoire2) if aleatoire2 != 0: test = -1 * math.log(aleatoire2) / 1 / g self.background_traffic.append((test, test + T['t_packet'])) if enable_statsct: Statsct.set_background_traffic(self.background_traffic)
def show_stat(self): dprint(32 * '-' + ' Simulation ended -----------------------|') # Results dprint("") dprint("") dprint(32 * "-" + " Statistics -----------------------------") dprint('---- Sender Packet list ') Statsct.print_packet_list(Statsct.sender_packets) dprint('') dprint('---- Receiver Packet list ') Statsct.print_packet_list(Statsct.receiver_packets) dprint('') dprint('---- Packet lost Results ' + '(Status -> True = Received, False = Failed) ') Statsct.print_ordered_packets() dprint('') dprint('---- Performance metrics') params = Statsct.calculate_tx_parameters() dprint('') dprint("---- General result of the simulation {}".format(params))
def send_packetX(self, packet, src_id, dst_id=None, callback=None, callback_args=tuple()): """send a message to another device in a client - server Simulation""" self._log("----------------------- SEND PACKET -----------------------") if not self.frame_loss.check(packet): self._log("----------------------- OK -----------------------") self._log("send-packet {}->{} {}".format(src_id, dst_id, packet)) if enable_statsct: Statsct.log("send-packet {}->{} {}".format(src_id, dst_id, packet)) Statsct.add_packet_info(packet,src_id,dst_id, True) # if dst_id == None, it is a broadcast # link_list = self.get_link_by_id(src_id, dst_id) count = 1 # for link in link_list: # count += self.send_packet_on_link(link, packet) note_table_list = list(self.node_table.items())[-1][1] #self.node_table[0].protocol.layer2.clientSend.send(packet) note_table_list.protocol.layer2.roleSend.send(packet) try: number_tiles_send = \ note_table_list.protocol.fragment_session.session_list[0]["session"].current_number_tiles_sent() state = note_table_list.protocol.fragment_session.session_list[0]["session"].state print("STATE : ", state) print("Lenght queue", len(self.scheduler.queue)) if (state == self.SEND_ALL_1 or state == self.ACK_FAILURE or state == self.ACK_TIMEOUT) \ and number_tiles_send == 0: print("------------------------------- RECEIVE PACKET ------------------------------") message = note_table_list.protocol.layer2.roleSend.Receive() print("Message from Server", message) note_table_list.protocol.layer2.event_receive_packet(note_table_list.id, message) # note_table_list.protocol.fragment_session.session_list[0]["session"].state = 'START' except: print("Not fragment state") else: self._log("----------------------- KO -----------------------") self._log("packet was lost {}->{}".format(src_id, dst_id)) if enable_statsct: Statsct.log("packet was lost {}->{} {}".format(src_id, dst_id, packet)) Statsct.add_packet_info(packet,src_id,dst_id, False) count = 0 # if callback != None: args = callback_args + (count,) # XXX need to check. - CA: # [CA] the 'count' is now passed as 'status' in: # SimulLayer2._event_sent_callback(self, transmit_callback, status # the idea is that is transmission fails, at least you can pass # count == 0 (status == 0), and you can do something there. # (in general case, some meta_information need to be sent) #args = callback_args callback(*args) return count
def ack_timeout(self, *args): self.cancel_ack_wait_timer() print("----------------------- ACK timeout ----------------------- ") assert len(args) == 2 assert isinstance(args[0], schcmsg.frag_sender_tx) assert isinstance(args[1], int) schc_frag = args[0] win = args[1] self.ack_requests_counter += 1 print("ack_requests_counter -> {}".format(self.ack_requests_counter)) if self.ack_requests_counter > max_ack_requests: # sending sender abort. schc_frag = schcmsg.frag_sender_tx_abort(self.rule, self.dtag, win) args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) print("Sent Sender-Abort.", schc_frag.__dict__) if enable_statsct: Statsct.set_msg_type("SCHC_SENDER_ABORT") #Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule)) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) return # set ack waiting timer 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)) schc_frag = schcmsg.frag_sender_ack_req(self.rule, self.dtag, win) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_REQ") # # retransmit MIC. args = (schc_frag.packet.get_content(), self.context["devL2Addr"], self.event_sent_frag) print("SCHC ACK REQ frag:", schc_frag.__dict__) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) """ waits for all the acks before sending the ack request """ """
def init_collision(self, G, background_frag_size): """ Init the collision table""" if enable_statsct: if Statsct.get_background_traffic() is not None: self.background_traffic = Statsct.get_background_traffic() else: self.generate_background_traffic(G, background_frag_size) if Statsct.get_current_time is not None: self.current_time = Statsct.get_current_time() if Statsct.get_position is not None: self.position = Statsct.get_position() else: self.generate_background_traffic(G, background_frag_size) print("background_frag_size: {}".format(background_frag_size)) #y = 0 #calculate the background traffic, one packet each 5000ms of 500ms ToA #for i in range(10): # self.background_traffic.append((y,y+500)) # y += 500000 #The first fragment will be sent after a random time (10 seconds) #make sure the table is begin enough to transmitt the packet self.current_time = 10000 * urandom.getrandbits(8) / 256 input('')
def deliver_packet(self, packet, src_id, dst_id=None, callback=None, callback_args=tuple(), with_hack=False): self._log("----------------------- SEND PACKET -----------------------") lost = self.frame_loss.is_lost(len(packet)) if not lost: self._log("----------------------- OK -----------------------") self._log("send-packet {}->{} {}".format(src_id, dst_id, packet)) if enable_statsct: Statsct.log("send-packet {}->{} {}".format(src_id, dst_id, packet)) clock = self.scheduler.get_clock() Statsct.add_packet_info(clock, packet, src_id, dst_id, True) # if dst_id == None, it is a broadcast link_list = self.get_link_by_id(src_id, dst_id) if not with_hack: count = 0 for link in link_list: count += self.send_packet_on_link(link, packet) else: count = 1 self._send_packetX_hack() # [CA] should be removed else: self._log("----------------------- KO -----------------------") self._log("packet was lost {}->{}".format(src_id, dst_id)) if enable_statsct: Statsct.log("packet was lost {}->{} {}".format(src_id, dst_id, packet)) clock = self.scheduler.get_clock() Statsct.add_packet_info(clock, packet, src_id, dst_id, False) count = 0 # if self.observer is not None: info = {"src":src_id, "dst":dst_id, "packet":packet, "clock": clock, "count":count, "lost":lost, "event-id": self.scheduler._get_event_id() } self.observer.record_packet(info) if callback != None: #XXX: should called by channel after delay args = callback_args+(count,) # XXX need to check. - CA: # [CA] the 'count' is now passed as 'status' in: # SimulLayer2._event_sent_callback(self, transmit_callback, status # the idea is that is transmission fails, at least you can pass # count == 0 (status == 0), and you can do something there. # (in general case, some meta_information need to be sent) #args = callback_args callback(*args) return count
def receive_frag(self, bbuf, dtag): self._last_receive_info = [] dprint('state: {}, recieved 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__) # XXX how to authenticate the message from the peer. without # authentication, any nodes can cancel the invactive timer. self.cancel_inactive_timer() if self.state == "ABORT": self._last_receive_info = [("state-abort", )] self.send_receiver_abort() return # # input("") if schc_frag.abort == True: dprint( "----------------------- Sender-Abort ---------------------------" ) # Statsct.set_msg_type("SCHC_SENDER_ABORT") # XXX needs to release all resources. self._last_receive_info = [("abort", )] return if schc_frag.ack_request == True: dprint("Received ACK-REQ") self._last_receive_info = [("ack-req", )] # if self.state != "DONE": # #this can happen when the ALL-1 is not received, so the state is # #not done and the sender is requesting an ACK. # # sending Receiver abort. # schc_frag = frag_msg.frag_receiver_tx_abort(self.rule, self.dtag) # args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) # dprint("Sent Receiver-Abort.", schc_frag.__dict__) # dprint("----------------------- SCHC RECEIVER ABORT SEND -----------------------") # if enable_statsct: # Statsct.set_msg_type("SCHC_RECEIVER_ABORT") # #Statsct.set_header_size(frag_msg.get_sender_header_size(self.rule)) # self.protocol.scheduler.add_event(0, # self.protocol.layer2.send_packet, args) # # XXX needs to release all resources. # return dprint("XXX need sending ACK back.") self.state = 'ACK_REQ' # input('') self.resend_ack(schc_frag) return info = self._last_receive_info self.fragment_received = True # append the payload to the tile list. # padding truncation is done later. see below. # nb_tiles = schc_frag.payload.count_added_bits()//self.rule["tileSize"] tile_size = self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_TILE] nb_tiles, last_tile_size = (schc_frag.payload.count_added_bits() // tile_size, schc_frag.payload.count_added_bits() % tile_size) info.append(("tile-info", { "nb-tiles": nb_tiles, "tile-size": tile_size, "last-tile-size": last_tile_size })) dprint("---------nb_tiles: ", nb_tiles, " -----last_tile_size ", last_tile_size) tiles = [ schc_frag.payload.get_bits_as_buffer(tile_size) for _ in range(nb_tiles) ] dprint("---------tiles: ", tiles) # Note that nb_tiles is the number of tiles which is exact number of the # size of the tile. the tile of which the size is less than the size # is not included. # The tile that is less than a tile size must be included, so a 1 can be added # in the bitmap when there is a tile in the all-1 message win = schc_frag.win fcn = schc_frag.fcn for tile_in_tiles in tiles: idx = tiles.index(tile_in_tiles) if tile_in_tiles.count_added_bits() % tile_size != 0: # tile found that is smaller than a normal tile dprint("tile found that is smaller than a normal tile") # nb_tiles = 1 # tile should only be append if it is not in the list tile_in_list = False for tile in self.tile_list: if tile["w-num"] == win: if tile["t-num"] == fcn - idx: dprint("tile is already in tile list") tile_in_list = True info.append(("known-tile", idx, tile)) if not tile_in_list: new_tile = ({ "w-num": win, "t-num": fcn - idx, "nb_tiles": 1, "raw_tiles": tile_in_tiles }) self.tile_list.append(new_tile) info.append(("new-tile", idx, new_tile)) self.tile_list = sort_tile_list( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN]) if (fcn - idx) == 0: win += 1 fcn = self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN] << 1 tiles = tiles[(idx + 1):] # !IMPORTANT: it's neccesary to change this condition for one more exact which consider the last tile size cases if last_tile_size > 8: last_tile = schc_frag.payload.get_bits_as_buffer(last_tile_size) dprint('---------tile:', last_tile) info.append(("last-tile", last_tile)) tile_in_list = False for tile in self.tile_list: if tile["w-num"] == win: if tile["t-num"] == 7: # XXX: why 7? dprint("tile is already in tile list") tile_in_list = True info.append(("known-last-tile", None, tile)) if not tile_in_list: new_tile = ({ "w-num": win, "t-num": 7, "nb_tiles": 1, "raw_tiles": last_tile }) self.tile_list.append(new_tile) info.append(("new-last-tile", None, tile)) self.tile_list = sort_tile_list( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN]) # if schc_frag.payload.count_added_bits()%self.rule["tileSize"] != 0: # #tile found that is smaller than a normal tile # dprint("tile found that is smaller than a normal tile") # #nb_tiles = 1 # #tile should only be append if it is not in the list # tile_in_list = False # for tile in self.tile_list: # if tile["w-num"] == schc_frag.win: # if tile["t-num"] == schc_frag.fcn: # dprint("tile is already in tile list") # tile_in_list = True # if not tile_in_list: # self.tile_list.append({ # "w-num": schc_frag.win, # "t-num": schc_frag.fcn, # "nb_tiles": nb_tiles, # "raw_tiles":schc_frag.payload}) # self.tile_list = sort_tile_list(self.tile_list, self.rule["FCNSize"]) for tile in self.tile_list: dprint("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'], tile['t-num'], tile['nb_tiles'])) dprint("") # dprint("raw_tiles:{}".format(tile['raw_tiles'])) # self.tile_list = sort_tile_list(self.tile_list, self.rule["WSize"]) # self.tile_list.append({ # "w-num": schc_frag.win, # "t-num": schc_frag.fcn, # "nb_tiles": nb_tiles, # "raw_tiles":schc_frag.payload}) # self.tile_list = sort_tile_list(self.tile_list, self.rule["FCNSize"]) # self.tile_list = sort_tile_list(self.tile_list, self.rule["WSize"]) should_send_ack = False if self.mic_received is not None: schc_packet, mic_calced = self.get_mic_from_tiles_received() if self.mic_received == mic_calced: info.append("mic-ok") self.finish(schc_packet, schc_frag) return else: # XXX waiting for the fragments requested by ACK. # during MAX_ACK_REQUESTS info.append("mic-not-ok") dprint("waiting for more fragments.") # XXX: do that only when necessary (one per window): #should_send_ack = True elif schc_frag.fcn == frag_msg.get_fcn_all_1(self.rule): # XXX: what if you receive two MICs? dprint( "----------------------- ALL1 received -----------------------" ) self.all1_received = True Statsct.set_msg_type("SCHC_ALL_1") self.mic_received = schc_frag.mic schc_packet, mic_calced = self.get_mic_from_tiles_received() dprint("schc_frag.mic: {}, mic_calced: {}".format( schc_frag.mic, mic_calced)) info.append(("mic-received", schc_frag.mic, mic_calced)) if schc_frag.mic == mic_calced: dprint("SUCCESS: MIC matched. packet {} == result {}".format( schc_frag.mic, mic_calced)) info.append("mic-ok") self.mic_missmatched = False self.finish(schc_packet, schc_frag) return else: self.mic_missmatched = True self.state = 'ERROR_MIC' info.append("mic-not-ok") # XXX: how do you leave ERROR state? dprint("----------------------- ERROR -----------------------") dprint("ERROR: MIC mismatched. packet {} != result {}".format( schc_frag.mic, mic_calced)) should_send_ack = True if should_send_ack: bit_list = find_missing_tiles( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule)) assert bit_list is not None schc_ack = self.create_ack_schc_ko(schc_frag) info.append(("mic-ack", bit_list)) """ Changement à corriger args = (schc_ack.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_ack.packet.get_content(), '*') self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args) # XXX need to keep the ack message for the ack request. # XXX: maybe set timer in all cases (there are 'return's above) # 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 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)
min_packet_size = 250 #60 max_packet_size = 1290 #bytes #packet_sizes = [80,160,320,640,1280] #packet_sizes = [320] #packet_sizes = [320,640,1280] packet_sizes = [80, 160, 320, 640] packet_sizes = [80] tile_size = 49 #tile_size = 240 payload_ack_always = tile_size * 2 ack_on_error = True #--------------------------------------------------------------------------- """ Init stastct module """ Statsct.initialize() Statsct.log("Statsct test") Statsct.set_packet_size(data_size) Statsct.set_SF(SF) #--------------------------------------------------------------------------- #no-ack rm0 = RuleManager() rm0.add_context(rule_context, compress_rule, frag_rule3, frag_rule4) rm1 = RuleManager() rm1.add_context(rule_context, compress_rule, frag_rule4, frag_rule3) #ack-on-error if ack_on_error: rm0 = RuleManager() rm0.add_context(rule_context, compress_rule, frag_rule1, frag_rule2)
def receive_frag(self, bbuf, dtag): print('state: {}, recieved fragment -> {}, rule-> {}'.format(self.state, bbuf, self.rule)) schc_frag = schcmsg.frag_receiver_rx(self.rule, bbuf) print("receiver frag received:", schc_frag.__dict__) # XXX how to authenticate the message from the peer. without # authentication, any nodes can cancel the invactive timer. self.cancel_inactive_timer() if self.state == "ABORT": self.send_receiver_abort() return # #input("") if schc_frag.abort == True: print("Received Sender-Abort.") #Statsct.set_msg_type("SCHC_SENDER_ABORT") # XXX needs to release all resources. return if schc_frag.ack_request == True: print("Received ACK-REQ") # if self.state != "DONE": # #this can happen when the ALL-1 is not received, so the state is # #not done and the sender is requesting an ACK. # # sending Receiver abort. # schc_frag = schcmsg.frag_receiver_tx_abort(self.rule, self.dtag) # args = (schc_frag.packet.get_content(), self.context["devL2Addr"]) # print("Sent Receiver-Abort.", schc_frag.__dict__) # print("----------------------- SCHC RECEIVER ABORT SEND -----------------------") # if enable_statsct: # Statsct.set_msg_type("SCHC_RECEIVER_ABORT") # #Statsct.set_header_size(schcmsg.get_sender_header_size(self.rule)) # self.protocol.scheduler.add_event(0, # self.protocol.layer2.send_packet, args) # # XXX needs to release all resources. # return print("XXX need sending ACK back.") #input('') self.resend_ack(schc_frag) return self.fragment_received = True # append the payload to the tile list. # padding truncation is done later. see below. nb_tiles = schc_frag.payload.count_added_bits()//self.rule["tileSize"] # Note that nb_tiles is the number of tiles which is exact number of the # size of the tile. the tile of which the size is less than the size # is not included. # The tile that is less than a tile size must be included, so a 1 can be added # in the bitmap when there is a tile in the all-1 message if schc_frag.payload.count_added_bits()%self.rule["tileSize"] != 0: #tile found that is smaller than a normal tile print("tile found that is smaller than a normal tile") nb_tiles = 1 #tile should only be append if it is not in the list tile_in_list = False for tile in self.tile_list: if tile["w-num"] == schc_frag.win: if tile["t-num"] == schc_frag.fcn: print("tile is already in tile list") tile_in_list = True if not tile_in_list: self.tile_list.append({ "w-num": schc_frag.win, "t-num": schc_frag.fcn, "nb_tiles": nb_tiles, "raw_tiles":schc_frag.payload}) self.tile_list = sort_tile_list(self.tile_list, self.rule["FCNSize"]) for tile in self.tile_list: print("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'],tile['t-num'],tile['nb_tiles'])) #print("raw_tiles:{}".format(tile['raw_tiles'])) #self.tile_list = sort_tile_list(self.tile_list, self.rule["WSize"]) # self.tile_list.append({ # "w-num": schc_frag.win, # "t-num": schc_frag.fcn, # "nb_tiles": nb_tiles, # "raw_tiles":schc_frag.payload}) # self.tile_list = sort_tile_list(self.tile_list, self.rule["FCNSize"]) #self.tile_list = sort_tile_list(self.tile_list, self.rule["WSize"]) if self.mic_received is not None: schc_packet, mic_calced = self.get_mic_from_tiles_received() if self.mic_received == mic_calced: self.finish(schc_packet, schc_frag) return else: # XXX waiting for the fragments requested by ACK. # during MAX_ACK_REQUESTS print("waiting for more fragments.") elif schc_frag.fcn == schcmsg.get_fcn_all_1(self.rule): print("----------------------- ALL1 received -----------------------") self.all1_received = True #Statsct.set_msg_type("SCHC_ALL_1") self.mic_received = schc_frag.mic schc_packet, mic_calced = self.get_mic_from_tiles_received() print("schc_frag.mic: {}, mic_calced: {}".format(schc_frag.mic,mic_calced)) if schc_frag.mic == mic_calced: self.mic_missmatched = False self.finish(schc_packet, schc_frag) return else: self.mic_missmatched = True print("----------------------- ERROR -----------------------") print("ERROR: MIC mismatched. packet {} != result {}".format( schc_frag.mic, mic_calced)) bit_list = find_missing_tiles_mic_ko_yes_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) assert bit_list is not None if len(bit_list) == 0: #When the find_missing_tiles functions returns an empty array #but we know something is missing because the MIC calculation is wrong #this can happen when the first fragments are lost for example print("bit list empty but the mic missmatched") #if tiles are missing, then the packet is larger, should send a bitmap #that considers the max_fcn and the tiles received bit_list = find_missing_tiles_mic_ko_yes_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) #print("new bit list, should it work???") #input("") for bl_index in range(len(bit_list)): print("missing wn={} bitmap={}".format(bit_list[bl_index][0], bit_list[bl_index][1])) # XXX compress bitmap if needed. # ACK failure message schc_ack = schcmsg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=bit_list[bl_index][0], cbit=0, bitmap=bit_list[bl_index][1]) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_KO") print("----------------------- SCHC ACK KO SEND -----------------------") print("ACK failure sent:", schc_ack.__dict__) args = (schc_ack.packet.get_content(), self.context["devL2Addr"]) self.protocol.scheduler.add_event( 0, self.protocol.layer2.send_packet, args) # XXX need to keep the ack message for the ack request. break # set inactive timer. self.event_id_inactive_timer = self.protocol.scheduler.add_event( self.inactive_timer, self.event_inactive, tuple()) print("---", schc_frag.fcn)
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)
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)
#--------------------------------------------------------------------------- def make_node(sim, rule_manager, devaddr, extra_config={}): node = simul.SimulSCHCNode(sim, extra_config) node.protocol.set_rulemanager(rule_manager) node.layer2.set_devaddr(devaddr) return node #--------------------------------------------------------------------------- #--------------------------------------------------------------------------- """ Init stastct module """ Statsct.initialize() Statsct.log("Statsct test") #--------------------------------------------------------------------------- rule = [] for k in [ opt.context_file, opt.rule_comp_file, opt.rule_fragin_file, opt.rule_fragout_file ]: with open(k) as fd: rule.append(json.loads(fd.read())) rm0 = RuleManager() rm0.add_context(rule[0], rule[1], rule[2], rule[3]) rm1 = RuleManager()
def frag_generic(rules_filename, packet_loss): # -------------------------------------------------- # General configuration l2_mtu = 72 # bits data_size = 14 # bytes SF = 12 simul_config = { "log": True, } # --------------------------------------------------------------------------- # Configuration packets loss if packet_loss: # Configuration with packet loss in noAck and ack-on-error loss_rate = 15 # in % collision_lambda = 0.1 background_frag_size = 54 loss_config = {"mode": "rate", "cycle": loss_rate} # loss_config = {"mode":"collision", "G":collision_lambda, "background_frag_size":background_frag_size} else: # Configuration without packet loss in noAck and ack-on-error loss_rate = None loss_config = None # --------------------------------------------------------------------------- # Init packet loss if loss_config is not None: simul_config["loss"] = loss_config # --------------------------------------------------------------------------- def make_node(sim, rule_manager, devaddr=None, extra_config={}, role=None): extra_config["unique-peer"] = True node = net_sim_core.SimulSCHCNode(sim, extra_config, role) node.protocol.set_rulemanager(rule_manager) if devaddr is None: devaddr = node.id node.layer2.set_devaddr(devaddr) return node # --------------------------------------------------------------------------- # Statistic module Statsct.initialize() Statsct.log("Statsct test") Statsct.set_packet_size(data_size) Statsct.set_SF(SF) # --------------------------------------------------------------------------- devaddr1 = b"\xaa\xbb\xcc\xdd" devaddr2 = b"\xaa\xbb\xcc\xee" dprint("---------Rules Device -----------") rm0 = RuleManager() # rm0.add_context(rule_context, compress_rule1, frag_rule3, frag_rule4) rm0.Add(device=devaddr1, file=rules_filename) rm0.Print() dprint("---------Rules gw -----------") rm1 = RuleManager() # rm1.add_context(rule_context, compress_rule1, frag_rule4, frag_rule3) rm1.Add(device=devaddr2, file=rules_filename) rm1.Print() # --------------------------------------------------------------------------- # Configuration of the simulation Statsct.get_results() sim = net_sim_core.Simul(simul_config) node0 = make_node(sim, rm0, devaddr1, role="device") # SCHC device node1 = make_node(sim, rm1, devaddr2, role="core-server") # SCHC gw sim.add_sym_link(node0, node1) node0.layer2.set_mtu(l2_mtu) node1.layer2.set_mtu(l2_mtu) # --------------------------------------------------------------------------- # Information about the devices dprint( "-------------------------------- SCHC device------------------------") dprint("SCHC device L3={} L2={} RM={}".format(node0.layer3.L3addr, node0.id, rm0.__dict__)) dprint( "-------------------------------- SCHC gw ---------------------------") dprint("SCHC gw L3={} L2={} RM={}".format(node1.layer3.L3addr, node1.id, rm1.__dict__)) dprint( "-------------------------------- Rules -----------------------------") dprint("rules -> {}, {}".format(rm0.__dict__, rm1.__dict__)) dprint("") # --------------------------------------------------------------------------- # Statistic configuration Statsct.setSourceAddress(node0.id) Statsct.setDestinationAddress(node1.id) # -------------------------------------------------- # Message coap = bytearray(b"`\x12\x34\x56\x00\x1e\x11\x1e\xfe\x80\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x01\xfe\x80\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x02\x16" + b"2\x163\x00\x1e\x00\x00A\x02\x00\x01\n\xb3" + b"foo\x03bar\x06ABCD==Fk=eth0\xff\x84\x01" + b"\x82 &Ehello") # --------------------------------------------------------------------------- # Simnulation node0.protocol.layer3.send_later(1, None, node1.layer3.L3addr, coap) old_stdout = sys.stdout set_debug_output(True) sys.stdout = io.StringIO() sim.run() simulation_output = sys.stdout.getvalue() sys.stdout = old_stdout set_debug_output(False) print(simulation_output) return simulation_output
def resend_ack(self, schc_frag): print("resend ack method") print(schc_frag.__dict__) if self.mic_received is not None: schc_packet, mic_calced = self.get_mic_from_tiles_received() print("schc_frag.mic: {}, mic_calced: {}".format(self.mic_received,mic_calced)) if self.mic_received == mic_calced: self.state = "DONE" if self.state == "DONE": # ACK message schc_ack = schcmsg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, schc_frag.win, cbit=1) print("ACK success sent:", schc_ack.__dict__) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_OK") print("----------------------- SCHC ACK OK SEND -----------------------") else: if self.all1_received: print("all-1 received, building ACK") print('send ack before done {},{},{}'.format(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule))) bit_list = find_missing_tiles_mic_ko_yes_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) for tile in self.tile_list: print("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'],tile['t-num'],tile['nb_tiles'])) print("raw_tiles:{}".format(tile['raw_tiles'])) print('send ack before done {}'.format(bit_list)) assert bit_list is not None if len(bit_list) == 0: #When the find_missing_tiles functions returns an empty array #but we know something is missing because the MIC calculation is wrong #this can happen when the first fragments are lost print("bit list empty") bit_list = find_missing_tiles_mic_ko_yes_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) print("new bit list, should it work???") for bl_index in range(len(bit_list)): print("missing wn={} bitmap={}".format(bit_list[bl_index][0], bit_list[bl_index][1])) # XXX compress bitmap if needed. # ACK failure message schc_ack = schcmsg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=bit_list[bl_index][0], cbit=0, bitmap=bit_list[bl_index][1]) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_KO") print("----------------------- SCHC ACK KO SEND -----------------------") print("ACK failure sent:", schc_ack.__dict__) break else: #special case when the ALL-1 message is lost: 2 cases: #1) the all-1 carries a tile (bit in bitmap) #2) the all-1 only carries the MIC (no bit in bitmap) if self.fragment_received is False: print("no fragments received yet, abort") self.send_receiver_abort() return print("all-1 not received, building ACK") print('send ack before done {},{},{}'.format(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule))) for tile in self.tile_list: print("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'],tile['t-num'],tile['nb_tiles'])) print("raw_tiles:{}".format(tile['raw_tiles'])) bit_list = find_missing_tiles_no_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) print('send ack before done {}'.format(bit_list)) assert bit_list is not None if len(bit_list) == 0: bit_list = find_missing_tiles_no_all_1(self.tile_list, self.rule["FCNSize"], schcmsg.get_fcn_all_1(self.rule)) for bl_index in range(len(bit_list)): print("missing wn={} bitmap={}".format(bit_list[bl_index][0], bit_list[bl_index][1])) # XXX compress bitmap if needed. # ACK failure message schc_ack = schcmsg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=bit_list[bl_index][0], cbit=0, bitmap=bit_list[bl_index][1]) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_KO") print("----------------------- SCHC ACK KO SEND -----------------------") print("ACK failure sent:", schc_ack.__dict__) break args = (schc_ack.packet.get_content(), self.context["devL2Addr"]) self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)
# --------------------------------------------------------------------------- def make_node(sim, rule_manager, devaddr=None, extra_config={}): node = net_sim_core.SimulSCHCNode(sim, extra_config) node.protocol.set_rulemanager(rule_manager) if devaddr is None: devaddr = node.id node.layer2.set_devaddr(devaddr) return node # --------------------------------------------------------------------------- # Statistic module Statsct.initialize() Statsct.log("Statsct test") Statsct.set_packet_size(data_size) Statsct.set_SF(SF) # --------------------------------------------------------------------------- devaddr1 = b"\xaa\xbb\xcc\xdd" devaddr2 = b"\xaa\xbb\xcc\xee" dprint("---------Rules Device -----------") rm0 = RuleManager() # rm0.add_context(rule_context, compress_rule1, frag_rule3, frag_rule4) rm0.Add(device=devaddr1, file="../examples/configs/rule1.json") rm0.Print() dprint("---------Rules gw -----------") rm1 = RuleManager() # rm1.add_context(rule_context, compress_rule1, frag_rule4, frag_rule3)
def _set_protocol(self, protocol): self.protocol = protocol Statsct.addInfo('protocol', protocol.__dict__)
def resend_ack(self, schc_frag): dprint("resend ack method") dprint(schc_frag.__dict__) if self.mic_received is not None: schc_packet, mic_calced = self.get_mic_from_tiles_received() dprint("schc_frag.mic: {}, mic_calced: {}".format( self.mic_received, mic_calced)) if self.mic_received == mic_calced: self.state = "DONE" if self.state == "DONE": # ACK message schc_ack = frag_msg.frag_receiver_tx_all1_ack(schc_frag.rule, schc_frag.dtag, schc_frag.win, cbit=1) dprint("ACK success sent:", schc_ack.__dict__) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_OK") dprint( "----------------------- SCHC ACK OK SEND -----------------------" ) else: if self.all1_received: dprint("all-1 received, building ACK") dprint('send ack before done {},{},{}'.format( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule))) schc_ack = self.create_ack_schc_ko(schc_frag) else: #special case when the ALL-1 message is lost: 2 cases: #1) the all-1 carries a tile (bit in bitmap) #2) the all-1 only carries the MIC (no bit in bitmap) if self.fragment_received is False: dprint("no fragments received yet, abort") self.send_receiver_abort() return dprint("all-1 not received, building ACK") dprint('send ack before done {},{},{}'.format( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule))) for tile in self.tile_list: dprint("w-num: {} t-num: {} nb_tiles:{}".format( tile['w-num'], tile['t-num'], tile['nb_tiles'])) dprint("raw_tiles:{}".format(tile['raw_tiles'])) bit_list = find_missing_tiles_no_all_1( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule)) dprint('send ack before done {}'.format(bit_list)) assert bit_list is not None if len(bit_list) == 0: bit_list = find_missing_tiles_no_all_1( self.tile_list, self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_FCN], frag_msg.get_fcn_all_1(self.rule)) for bl_index in range(len(bit_list)): dprint("missing wn={} bitmap={}".format( bit_list[bl_index][0], bit_list[bl_index][1])) # XXX compress bitmap if needed. # ACK failure message schc_ack = frag_msg.frag_receiver_tx_all1_ack( schc_frag.rule, schc_frag.dtag, win=bit_list[bl_index][0], cbit=0, bitmap=bit_list[bl_index][1]) if enable_statsct: Statsct.set_msg_type("SCHC_ACK_KO") dprint( "----------------------- SCHC ACK KO SEND -----------------------" ) dprint("ACK failure sent:", schc_ack.__dict__) """ Changement à corriger args = (schc_ack.packet.get_content(), self.context["devL2Addr"]) """ args = (schc_ack.packet.get_content(), "*") self.protocol.scheduler.add_event(0, self.protocol.layer2.send_packet, args)