Esempio n. 1
0
 def send_packet(self, data, dst_l2_addr=None, callback=None,
                 callback_args=tuple()):
     """Processing a packet from the SCHC layer to southbound"""
     dprint("L2: sending a packet", data.hex())
     self.system.log("L2", "send packet to devaddr={} packet={}".format(
             dst_l2_addr, data.hex()))
     body = json.dumps({"hexSCHCData": data.hex(),
                         "devL2Addr": dst_l2_addr})
     """
     self.system.scheduler.loop.run_in_executor(
             None, self._post_data, self.config["downlink_url"], body,
             self.config["ssl_verify"])
     """
     current_clock = self.system.scheduler.get_clock()
     diff = current_clock - self.last_clock
     if diff > self.config["tx_interval"]:
         delay = self.config["tx_interval"]
     else:
         delay = self.config["tx_interval"] - diff
     self.last_clock = current_clock
     self.system.scheduler.add_event(delay,
                                     self._post_data,
                                     (self.config["downlink_url"],
                                     body, self.config["ssl_verify"]))
     status = 0
     #
     if callback is not None:
         # XXX status should be taken from the run_in_executor().
         args = callback_args + (status,)
         callback(*args)
Esempio n. 2
0
    def schc_recv(self, sender_l2_address, raw_packet):
        #self._log("recv-from-L2 {} {}".format(sender_l2_addr, raw_packet))
        frag_rule = self.rule_manager.FindFragmentationRule()

        packet_bbuf = BitBuffer(raw_packet)

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

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

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

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

        session.receive_frag(packet_bbuf, dtag)
Esempio n. 3
0
 def initialize(init_time=None):
     """Class to initializa the static class
     creates the file to write and the instance of the class """
     dprint('Init statsct module')
     if init_time is None:
         init_time = time.time() # XXX: need refactor, should be obtained from Scheduler
     Statsct.results['init_time'] = init_time #utime.time() -->exception
     Statsct.results['packet_list'] = []
     Statsct.sender_packets['packet_list'] = []
     Statsct.receiver_packets['packet_list'] = []
     Statsct.src_id = None
     Statsct.dst_id = None
     Statsct.device_rule = dict()
     Statsct.gw_rule = dict()
     Statsct.gw_rule['fragSender'] = []
     Statsct.channel_occupancy = 0
     Statsct.goodput = 0
     Statsct.total_delay = 0
     Statsct.reliability = 0
     Statsct.total_packet_send = dict()
     Statsct.msg_type = ""
     Statsct.packet_info = dict()
     Statsct.last_msg_type = ""
     Statsct.succ_packets = 0
     Statsct.fail_packets = 0
     Statsct.total_data_send = 0
     Statsct.msg_type_queue = []
     Statsct.channel_occupancy_sender = 0
     Statsct.channel_occupancy_receiver = 0
Esempio n. 4
0
    def get_mic(self, mic_base, last_frag_base_size, penultimate_size=0):
        assert isinstance(mic_base, BitBuffer)

        # calculate the significant padding bits.
        # 1. get the extra bits.
        #
        #   |<------------ last SCHC frag ------------->|
        #   |<- header ->|<- payload ->|<--- padding -->|
        #   |<---- frag base size ---->|<- extra bits-->|
        #                                      L2Word ->|

        extra_bits = (frag_msg.roundup(last_frag_base_size, self.l2word) -
                      last_frag_base_size)

        # 2. round up the payload of all SCHC fragments
        #    to the MIC word size.
        #
        #   |<----------------- input data  ----------------->|
        #   |<- a SCHC packet ->|<- extra bits->|<- padding ->|
        #            MIC Word ->|                  MIC Word ->|
        mic_base.add_bits(0, extra_bits)
        # XXX
        if penultimate_size != 0:
            extra_bits = (frag_msg.roundup(penultimate_size, self.l2word) -
                          penultimate_size)
            mic_base.add_bits(
                0,
                frag_msg.roundup(extra_bits,
                                 self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_MIC]))
        #
        mic = get_mic(mic_base.get_content()).to_bytes(4, "big")
        dprint("Send MIC {}, base = {}, lenght = {}".format(
            mic.hex(), mic_base.get_content(), len(mic_base.get_content())))
        return mic
Esempio n. 5
0
    def _send_packetX_hack(self):
            self.ACK_SUCCESS = "ACK_SUCCESS" # XXX: this should not be here
            self.ACK_FAILURE = "ACK_FAILURE"
            self.RECEIVER_ABORT = "RECEIVER_ABORT"
            self.SEND_ALL_1 = "SEND_ALL_1"
            self.WAITING_FOR_ACK = "WAITING_FOR_ACK"
            self.ACK_TIMEOUT = "ACK_TIMEOUT"

            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) # XXX: should not be changed

            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
                dprint("STATE : ", state)
                dprint("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:
                    dprint("------------------------------- RECEIVE PACKET ------------------------------")
                    message = note_table_list.protocol.layer2.roleSend.Receive() # XXX: should not be here
                    dprint("Message from Server", message)
                    note_table_list.protocol.layer2.event_receive_packet(note_table_list.id, message)
                    # note_table_list1.protocol.fragment_session.session_list[0]["session"].state = 'START'
            except:
                dprint("Not fragment state")
Esempio n. 6
0
    def test1():
        def compress_bitmap_str(b):
            i = len(b)
            while i > 0:
                if b[i - 1] == "0":
                    break
                i -= 1
            return b[:i + 1]

        def gen_bits_str(N):
            if N < 1:
                return ""
            if N == 1:
                yield "0"
                yield "1"
            else:
                p = (1 << N) - 2
                # 2, 6, 14
                for i in range(p + 1):
                    yield "1" * i + "0" + "1" * (p - i)
                yield "1" * (p + 1)

        for n in range(5):
            for i in gen_bits_str(n):
                dprint(i, compress_bitmap_str(i))
Esempio n. 7
0
    def compress(self, rule, parsed_packet, data, direction=T_DIR_UP):
        """
        Take a compression rule and a parsed packet and return a SCHC pkt
        """
        assert direction in [T_DIR_UP, T_DIR_DW]
        output_bbuf = BitBuffer()
        # set ruleID first.
        if rule[T_RULEID] is not None and rule[T_RULEIDLENGTH] is not None:
            output_bbuf.add_bits(rule[T_RULEID], rule[T_RULEIDLENGTH])
            dprint("rule {}/{}".format(rule[T_RULEID], rule[T_RULEIDLENGTH]))
            #output_bbuf.display(format="bin")

        for r in rule["Compression"]:
            dprint("rule item:", r)

            if r[T_DI] in [T_DIR_BI, direction]:
                if (r[T_FID], r[T_FP]) in parsed_packet:
                    dprint("in packet")
                    self.__func_tx_cda[r[T_CDA]](field=parsed_packet[(r[T_FID], r[T_FP])],
                                                rule = r,
                                                output= output_bbuf)
                else: # not find in packet, but is variable length can be coded as 0
                    dprint("send variable length")
                    self.__func_tx_cda[T_CDA_VAL_SENT](field = [0, 0, "Null Field"], rule = r, output = output_bbuf)
            else:
                dprint("rule skipped, bad direction")

            #output_bbuf.display(format="bin")

        output_bbuf.add_bytes(data)

        return output_bbuf
Esempio n. 8
0
    def test2():
        def gen_bits(N):
            #
            if N < 1:
                return None
            if N == 1:
                b = BitBuffer()
                b.set_bit(0)
                yield b
                b = BitBuffer()
                b._wpos = 0
                b.set_bit(1)
                yield b
            else:
                p = (1 << N) - 2
                for i in range(p + 1):
                    b = BitBuffer()
                    b.add_bits(pow(2, i) - 1, i)
                    b.set_bit(0)
                    b.add_bits(pow(2, p - i) - 1, p - i)
                    yield b
                b = BitBuffer()
                b.add_bits(pow(2, p + 1) - 1, p + 1)
                yield b

        for n in range(5):
            dprint("n=", n)
            for i in gen_bits(n):
                dprint(i, compress_bitmap(i))
Esempio n. 9
0
 def resend_frag(self, schc_frag):
     self.resend = True
     dprint("recv bitmap:", (schc_frag.win, schc_frag.bitmap.to_bit_list()))
     dprint("sent bitmap:", (schc_frag.win, self.bit_list[schc_frag.win]))
     self.all_tiles.unset_sent_flag(schc_frag.win,
                                    schc_frag.bitmap.to_bit_list())
     self.send_frag()
Esempio n. 10
0
 def cancel_ack_wait_timer(self):
     # don't assert here because the receiver sends ACK back anytime.
     #assert self.event_id_ack_wait_timer is not None
     dprint(
         '----------------------- cancel_ack_wait_timer -----------------------'
     )
     self.protocol.scheduler.cancel_event(self.event_id_ack_wait_timer)
     self.event_id_ack_wait_timer = None
Esempio n. 11
0
 def log(self, name, message):
     if not self.simul_config.get("log", False):
         return
     line = "{} [{}] ".format(self.scheduler.get_clock(), name) + message
     dprint(line)
     if self.log_file is not None:
         self.log_file.write(line+"\n")
     if self.observer is not None:
         self.observer.record_log(line)
Esempio n. 12
0
 def tiles_send(self):
     for tile in self.all_tiles.get_all_tiles():
         if not tile['sent']:
             self.number_tiles_send += 1
     self.number_tiles_send = math.ceil(
         self.number_tiles_send /
         (self.protocol.layer2.get_mtu_size() //
          self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_TILE]))
     dprint("----------- ", self.number_tiles_send, "tiles to send")
Esempio n. 13
0
 def add_event(self, rel_time, callback, args):
     dprint("Add event {}".format(sanitize_value(self.queue)))
     dprint("callback set -> {}".format(callback.__name__))
     assert rel_time >= 0
     event_id = self.next_event_id
     self.next_event_id += 1
     clock = self.get_clock()
     abs_time = clock+rel_time
     self.queue.append((abs_time, event_id, callback, args))
     return event_id
Esempio n. 14
0
 def add_event(self, rel_time, callback, args):
     dprint("Add event {}".format(
         [e[:-2] + (e[-2].__name__, ) + e[-1:] for e in self.queue]))
     dprint("callback set -> {}".format(callback.__name__))
     assert rel_time >= 0
     event_id = self.next_event_id
     self.next_event_id += 1
     clock = self.get_clock()
     abs_time = clock + rel_time
     self.queue.append((abs_time, event_id, callback, args))
     return event_id
Esempio n. 15
0
    def receive_frag(self, bbuf, dtag):
        # the ack timer can be cancelled here, because it's been done whether
        # both rule_id and dtag in the fragment are matched to this session
        # at process_received_packet().
        self.cancel_ack_wait_timer(
        )  # the timeout is canceled but has to be set
        # when an ack should be received
        self.resend = False
        #
        schc_frag = frag_msg.frag_sender_rx(self.rule, bbuf)
        dprint(
            "-----------------------  Sender Frag Received -----------------------"
        )
        dprint("fragment received -> {}".format(schc_frag.__dict__))
        if ((self.rule[T_FRAG][T_FRAG_PROF][T_FRAG_W] is None
             or schc_frag.win == frag_msg.get_win_all_1(self.rule))
                and schc_frag.cbit == 1
                and schc_frag.remaining.allones() == True):
            dprint(
                "-----------------------  Receiver Abort rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            self.state = self.RECEIVER_ABORT

            return
        if schc_frag.cbit == 1:
            dprint(
                "----------------------- ACK Success rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            self.state = self.ACK_SUCCESS

            # XXX needs to be reviewed.  at least, no one need this log.
            # try:
            #     f = open("client_server_simulation.txt", "r+")
            # except IOError:
            #     f = open("client_server_simulation.txt", "w+")
            #     f = open("client_server_simulation.txt", "r+")
            # content = f.read()
            # seconds = time. time()
            # f.seek(0, 0)
            # f.write(str(int(seconds)) + '\n' + content)
            # f.close()

            return
        if schc_frag.cbit == 0:
            dprint(
                "----------------------- ACK Failure rid={} dtag={} -----------------------"
                .format(self.rule[T_RULEID], self.dtag))
            #self.resend = False
            #self.all1_send = False
            self.state = self.ACK_FAILURE
            self.resend_frag(schc_frag)
            return
Esempio n. 16
0
 def add_event(self, time_in_sec, event_function, event_args):
     dprint(f"Add event: "
            f"call in {time_in_sec} sec: "
            f"{event_function.__name__} {event_args}")
     assert time_in_sec >= 0
     if event_args is None:
         evnet_id = self.loop.call_later(time_in_sec, event_function)
     else:
         evnet_id = self.loop.call_later(time_in_sec, event_function,
                                         *event_args)
     return evnet_id
Esempio n. 17
0
 def create_device(self, rules):
     dprint("---------Rules Device -----------")
     rm0 = RuleManager()
     devaddr1 = DEFAULT_MAC_ADDRESS_TABLE["device"]
     rm0.Add(device=devaddr1, dev_info=rules)
     rm0.Print()
     self.device_rule_manager = rm0
     self.device_node = self._make_schc_node(self.sim,
                                             rm0,
                                             devaddr1,
                                             role="device")
     return self.device_node
Esempio n. 18
0
 def set_packet(self, packet_bbuf):
     super().set_packet(packet_bbuf)
     # because draft-18 requires that in No-ACK mode, each fragment must
     # contain exactly one tile and the tile size must be at least the size
     # of an L2 Word.
     dprint(self.rule)
     min_size = (frag_msg.get_sender_header_size(self.rule) +
                 frag_msg.get_mic_size(self.rule) + self.l2word)
     if self.protocol.layer2.get_mtu_size() < min_size:
         raise ValueError(
             "the MTU={} is not enough to carry the SCHC fragment of No-ACK mode={}"
             .format(self.protocol.layer2.get_mtu_size(), min_size))
Esempio n. 19
0
 def create_core(self, rules):
     dprint("---------Rules gw -----------")
     rm1 = RuleManager()
     devaddr2 = DEFAULT_MAC_ADDRESS_TABLE["gateway"]
     rm1.Add(device=devaddr2, dev_info=rules)
     rm1.Print()
     self.core_rule_manager = rm1
     self.core_node = self._make_schc_node(self.sim,
                                           rm1,
                                           devaddr2,
                                           role="core-server")
     return self.core_node
Esempio n. 20
0
 def run(self):
     while len(self.queue) > 0:
         self.queue.sort()
         event_info = self.queue.pop(0)
         self.clock, event_id, callback, args = event_info
         self.current_event_id = event_id
         if self.observer is not None:
             self.observer("sched-pre-event", event_info)
         callback(*args)
         if self.observer is not None:
             self.observer("sched-post-event", event_info)
         dprint("Queue running event -> {}, callback -> {}".format(event_id, callback.__name__))
Esempio n. 21
0
 def add(self, rule_id, rule_id_size, dtag, session):
     if self.get(rule_id, rule_id_size, dtag) is not None:
         dprint(
             "ERROR: the session rid={}/{} dtag={} exists already".format(
                 rule_id, rule_id_size, dtag))
         return False
     self.session_list.append({
         "rule_id": rule_id,
         "rule_id_size": rule_id_size,
         "dtag": dtag,
         "session": session
     })
     return True
Esempio n. 22
0
def cond_random(rate):
    if sys.implementation.name == "micropython":
        #dprint("micropython")
        random_num = urandom.getrandbits(8)/256
        dprint("1000*random_num -> {} < 10 *rate  -> {}, Packet Loss Condition is -> {}".format(random_num*1000,10*rate,random_num * 1000 < rate * 10))
        #if random.randint(0,1000) <= (1000 * FER)
        #if random.randint(0,1000) <= FER_RANDOM * 10        
        #if urandom.getrandbits(8)/256 * 100 < rate:
        return random_num * 1000 < rate * 10
    else:
        random_num = random.getrandbits(8)/256
        dprint("1000*random_num -> {} < 10 *rate  -> {}, Packet Loss Condition is -> {}".format(random_num*1000,10*rate,random_num * 1000 < rate * 10))
        return random_num * 1000 < rate * 10
Esempio n. 23
0
        def unset_sent_flag_do(wn, tn):
            if tn is None:
                # special case. i.e. the last tile.
                #dont know why it is a special case, if the ALL-1 is received with a tile
                #then it should always be one, if the tile is consired received by the method
                #below, then it should not be false

                #i think the problem is when the sender does not know if it is the last one
                #so the the bitmap is received with the max_fcn bit on 1, but since there are
                #less tiles than the max_fcn. it does not look for that bit
                dprint("last tile case")
                #self.all_tiles[-1]["sent"] = False
                return
            # normal case.
            counter = 0
            dprint('unset_sent_flag_do')
            for t in self.all_tiles:
                if t["w-num"] == wn:
                    if t["t-num"] == self.max_fcn - tn:
                        counter += 1
                        dprint('counter = {}, t-num {}, tn {}'.format(
                            counter, t["t-num"], tn))
                        t["sent"] = False
                    elif t["t-num"] == self.max_fcn:
                        dprint("t-num {} == max_fcn {}".format(
                            t["t-num"], self.max_fcn))
Esempio n. 24
0
 def __init__(self, rule, packet_bbuf):
     """ packet_bbuf: BitBuffer containing the SCHC fragment. """
     dprint("frag_sender_rx")
     dprint(packet_bbuf)
     #input("")
     self.init_param()
     self.set_recvbuf(packet_bbuf)
     self.rule = rule
     self.rule_id = self.packet_bbuf.get_bits(rule[T_RULEIDLENGTH])
     pos = self.rule[T_RULEIDLENGTH]
     pos += self.parse_dtag()
     pos += self.parse_win()
     pos += self.parse_cbit()
     if self.cbit == 0:
         pos += self.parse_bitmap()
     self.remaining = self.packet_bbuf.get_bits_as_buffer()
Esempio n. 25
0
    def no_compress(self, rule, data):
        """
        Take a compression rule and a parsed packet and return a SCHC pkt
        """
        assert T_NO_COMP in rule

        output_bbuf = BitBuffer()
        # set ruleID first.
        if rule[T_RULEID] is not None and rule[T_RULEIDLENGTH] is not None:
            output_bbuf.add_bits(rule[T_RULEID], rule[T_RULEIDLENGTH])
            dprint("rule {}/{}".format(rule[T_RULEID], rule[T_RULEIDLENGTH]))
            #output_bbuf.display(format="bin")

        output_bbuf.add_bytes(data)

        return output_bbuf
Esempio n. 26
0
    def rx_cda_map_sent(self, rule, in_bbuf):
        # 7.5.5.  mapping-sent CDA
        # The number of bits sent is the minimal size for coding all the
        # possible indices.

        size = len(bin(len(rule[T_TV]) - 1)[2:])
        val = in_bbuf.get_bits(size)

        dprint("====>", rule[T_TV][val], len(rule[T_TV][val]), rule[T_FL])

        if rule[T_FL] == "var":
            size = len(rule[T_TV][val])
        else:
            size = rule[T_FL]

        return [rule[T_TV][val], size]
Esempio n. 27
0
    def ack_timeout(self, *args):
        self.cancel_ack_wait_timer()
        dprint("----------------------- ACK timeout -----------------------  ")
        self.state = self.ACK_TIMEOUT
        assert len(args) == 2
        assert isinstance(args[0], frag_msg.frag_sender_tx)
        assert isinstance(args[1], int)
        schc_frag = args[0]
        win = args[1]
        self.ack_requests_counter += 1
        dprint("ack_requests_counter -> {}".format(self.ack_requests_counter))
        if self.ack_requests_counter > max_ack_requests:
            # sending sender abort.
            schc_frag = frag_msg.frag_sender_tx_abort(self.rule, self.dtag)
            """ Changement à corriger
            args = (schc_frag.packet.get_content(), self.context["devL2Addr"])
            """
            args = (schc_frag.packet.get_content(), "*")
            dprint("MESSSAGE TYPE ----> Sent Sender-Abort.",
                   schc_frag.__dict__)
            if enable_statsct:
                Statsct.set_msg_type("SCHC_SENDER_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)
            return
        # set ack waiting timer
        self.event_id_ack_wait_timer = self.protocol.scheduler.add_event(
            self.ack_wait_timer, self.ack_timeout, args)
        dprint("*******event id {}".format(self.event_id_ack_wait_timer))
        schc_frag = frag_msg.frag_sender_ack_req(self.rule, self.dtag, win)
        if enable_statsct:
            Statsct.set_msg_type("SCHC_ACK_REQ")
        # # retransmit MIC.
        """Changement à corriger
        args = (schc_frag.packet.get_content(), self.context["devL2Addr"],
                self.event_sent_frag)
        """
        args = (schc_frag.packet.get_content(), '*', self.event_sent_frag)

        dprint("MESSSAGE TYPE ----> 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
Esempio n. 28
0
    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']
        dprint("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)
            #dprint(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)
Esempio n. 29
0
    def decompress(self, schc, rule, direction):
        assert ("Compression" in rule)
        schc.set_read_position(0)

        self.parsed_packet = {}

        rule_send = schc.get_bits(nb_bits=rule[T_RULEIDLENGTH])
        assert (rule_send == rule["RuleID"])

        for r in rule["Compression"]:
            dprint(r)
            if r[T_DI] in [T_DIR_BI, direction]:
                full_field = self.__func_rx_cda[r[T_CDA]](r, schc)
                dprint("<<<", full_field)
                self.parsed_packet[(r[T_FID], r[T_FP])] = full_field
                #pprint.pprint (self.parsed_packet)

        return self.parsed_packet
Esempio n. 30
0
    def _send_packet_from_queue(self):
        assert not self.is_transmitting
        assert len(self.packet_queue) > 0

        self.is_transmitting = True
        (packet, src_dev_id, dst_dev_id,
         transmit_callback) = self.packet_queue.pop(0)
        dprint("send packet from queue -> {}, {}, {}, {}".format(
            packet, src_dev_id, dst_dev_id, transmit_callback is None))

        if self.role == "client" or self.role == "server":
            self.sim.send_packetX(packet, src_dev_id, dst_dev_id,
                                  self._event_sent_callback,
                                  (transmit_callback, ))
        else:
            self.sim.send_packet(packet, src_dev_id, dst_dev_id,
                                 self._event_sent_callback,
                                 (transmit_callback, ))