예제 #1
0
    def test_rank_computation(self, sim_engine):
        # https://tools.ietf.org/html/rfc8180#section-5.1.2
        sim_engine = sim_engine(
            diff_config = {
                'exec_numMotes'           : 6,
                'exec_numSlotframesPerRun': 10000,
                'app_pkPeriod'            : 0,
                'secjoin_enabled'         : False,
                'tsch_keep_alive_interval': 0,
                'conn_class'              : 'Linear',
            }
        )
        print("TESTING RECEIVED")

        # shorthand
        motes = sim_engine.motes
        asn_at_end_of_simulation = (
            sim_engine.settings.tsch_slotframeLength *
            sim_engine.settings.exec_numSlotframesPerRun
        )

        # get the network ready to be test
        u.run_until_everyone_joined(sim_engine)
        assert sim_engine.getAsn() < asn_at_end_of_simulation

        # set ETX=100/75 (numTx=100, numTxAck=75)
        for mote_id in range(1, len(motes)):
            mote = motes[mote_id]
            parent = motes[mote_id - 1]

            # inject DIO to the mote
            dio = parent.rpl._create_DIO()
            dio['mac'] = {'srcMac': parent.get_mac_addr()}
            mote.rpl.action_receiveDIO(dio)

            # set numTx and numTxAck
            preferred_parent = mote.rpl.of.preferred_parent
            preferred_parent['numTx'] = 100
            preferred_parent['numTxAck'] = 75
            mote.rpl.of._update_neighbor_rank_increase(preferred_parent)

        # test using rank values in Figure 4 of RFC 8180
        assert motes[0].rpl.get_rank()   == 256
        assert motes[0].rpl.getDagRank() == 1

        print motes[1].rpl.of.preferred_parent
        assert motes[1].rpl.get_rank()   == 768
        assert motes[1].rpl.getDagRank() == 3

        assert motes[2].rpl.get_rank()   == 1280
        assert motes[2].rpl.getDagRank() == 5

        assert motes[3].rpl.get_rank()   == 1792
        assert motes[3].rpl.getDagRank() == 7

        assert motes[4].rpl.get_rank()   == 2304
        assert motes[4].rpl.getDagRank() == 9

        assert motes[5].rpl.get_rank()   == 2816
        assert motes[5].rpl.getDagRank() == 11
예제 #2
0
def test_run_until_everyone_joined(
        sim_engine,
        exec_num_motes,
        secjoin_enabled
    ):
    sim_engine = sim_engine(
        diff_config = {
            'exec_numMotes'           : exec_num_motes,
            'secjoin_enabled'         : secjoin_enabled,
            'exec_numSlotframesPerRun': 10000,
            'app_pkPeriod'            :  0,
            'conn_class'              : 'Linear'
        }
    )

    # everyone should have not been joined yet
    assert (
        len([m for m in sim_engine.motes if m.secjoin.getIsJoined() is False]) > 0
    )

    u.run_until_everyone_joined(sim_engine)

    # everyone should have been joined
    assert (
        len([m for m in sim_engine.motes if m.secjoin.getIsJoined() is False]) == 0
    )

    # expect the simulator has the remaining time; that is, the simulator
    # should not be paused by run_until_end() called inside of
    # run_until_everyone_joined()
    slotframe_length = sim_engine.settings.tsch_slotframeLength
    num_slotframes   = sim_engine.settings.exec_numSlotframesPerRun
    asn_at_end       = slotframe_length * num_slotframes
    assert sim_engine.getAsn() < asn_at_end
예제 #3
0
def test_upstream_routing(sim_engine):
    sim_engine = sim_engine(
        diff_config = {
            'exec_numMotes': 3,
            'conn_class'   : 'FullyMeshed'
        }
    )

    root  = sim_engine.motes[0]
    mote_1 = sim_engine.motes[1]
    mote_2 = sim_engine.motes[2]
    asn_at_end_of_simulation = (
        sim_engine.settings.tsch_slotframeLength *
        sim_engine.settings.exec_numSlotframesPerRun
    )

    u.run_until_everyone_joined(sim_engine)
    assert sim_engine.getAsn() < asn_at_end_of_simulation

    # We're making the RPL topology of "root -- mote_1 (-- mote_2)"
    dio_from_root = root.rpl._create_DIO()
    dio_from_root['mac'] = {'srcMac': root.get_mac_addr()}
    dio_from_root['app']['rank'] = 256
    mote_1.rpl.action_receiveDIO(dio_from_root)
    assert mote_1.rpl.getPreferredParent() == root.get_mac_addr()

    # Then, put mote_1 behind mote_2:    "root -- mote_2 -- mote_1"
    mote_2.rpl.action_receiveDIO(dio_from_root)
    dio_from_mote_2 = mote_2.rpl._create_DIO()
    dio_from_mote_2['mac'] = {'srcMac': mote_2.get_mac_addr()}

    dio_from_root['app']['rank'] = 65535
    mote_1.rpl.action_receiveDIO(dio_from_root)

    dio_from_mote_2['app']['rank'] = 256
    # inject DIO from mote_2 to mote_1
    mote_1.rpl.action_receiveDIO(dio_from_mote_2)

    assert mote_1.rpl.getPreferredParent() == mote_2.get_mac_addr()
    assert mote_2.rpl.getPreferredParent() == root.get_mac_addr()

    # create a dummy packet, which is used to get the next hop
    dummy_packet = {
        'net': {
            'srcIp': mote_1.get_ipv6_global_addr(),
            'dstIp': root.get_ipv6_global_addr()
        }
    }

    # the next hop should be parent
    assert mote_1.sixlowpan._find_nexthop_mac_addr(dummy_packet) == mote_1.rpl.getPreferredParent()
예제 #4
0
    def test_free_run(self, sim_engine):
        # all the motes should be able to join the network
        sim_engine = sim_engine(
            diff_config={
                'exec_numSlotframesPerRun': 10000,
                'conn_class': 'Random',
                'secjoin_enabled': False,
                "phy_numChans": 1,
            })
        asn_at_end_of_simulation = (
            sim_engine.settings.tsch_slotframeLength *
            sim_engine.settings.exec_numSlotframesPerRun)

        u.run_until_everyone_joined(sim_engine)
        assert sim_engine.getAsn() < asn_at_end_of_simulation
예제 #5
0
def test_upstream_routing(sim_engine):
    sim_engine = sim_engine(diff_config={
        'exec_numMotes': 3,
        'conn_class': 'FullyMeshed',
    })

    root = sim_engine.motes[0]
    mote_1 = sim_engine.motes[1]
    mote_2 = sim_engine.motes[2]

    u.run_until_everyone_joined(sim_engine)

    # We're making the RPL topology of "root -- mote_1 (-- mote_2)"
    dio_from_root = root.rpl._create_DIO()
    dio_from_root['mac'] = {'srcMac': root.id}
    dio_from_root['app']['rank'] = 256
    mote_1.rpl.action_receiveDIO(dio_from_root)
    assert mote_1.rpl.getPreferredParent() == root.id

    # Then, put mote_1 behind mote_2:    "root -- mote_2 -- mote_1"
    mote_2.rpl.action_receiveDIO(dio_from_root)
    dio_from_mote_2 = mote_2.rpl._create_DIO()
    dio_from_mote_2['mac'] = {'srcMac': mote_2.id}

    dio_from_root['app']['rank'] = 65535
    mote_1.rpl.action_receiveDIO(dio_from_root)

    dio_from_mote_2['app']['rank'] = 256
    # inject DIO from mote_2 to mote_1
    mote_1.rpl.action_receiveDIO(dio_from_mote_2)

    assert mote_1.rpl.getPreferredParent() == mote_2.id
    assert mote_2.rpl.getPreferredParent() == root.id

    # create a dummy packet, which is used to get the next hop
    dummy_packet = {'net': {'srcIp': mote_1.id, 'dstIp': root.id}}

    # the next hop should be parent
    assert mote_1.sixlowpan.find_nexthop_mac_addr(
        dummy_packet) == mote_1.rpl.getPreferredParent()
예제 #6
0
def test_tx_with_two_slotframes(sim_engine):
    sim_engine = sim_engine(
        diff_config={
            'app_pkPeriod': 0,
            'exec_numMotes': 2,
            'exec_numSlotframesPerRun': 1000,
            'secjoin_enabled': False,
            'sf_class': 'SFNone',
            'conn_class': 'Linear',
            'rpl_extensions': [],
            'rpl_daoPeriod': 0
        })

    # shorthands
    root = sim_engine.motes[0]
    hop_1 = sim_engine.motes[1]

    # add one slotframe to the two motes
    for mote in sim_engine.motes:
        mote.tsch.add_slotframe(1, 101)

    asn_at_end_of_simulation = (sim_engine.settings.tsch_slotframeLength *
                                sim_engine.settings.exec_numSlotframesPerRun)

    u.run_until_everyone_joined(sim_engine)
    assert sim_engine.getAsn() < asn_at_end_of_simulation

    # put DIO to hop1
    dio = root.rpl._create_DIO()
    dio['mac'] = {'srcMac': root.get_mac_addr()}
    hop_1.rpl.action_receiveDIO(dio)

    # install one TX cells to each slotframe
    for i in range(2):
        hop_1.tsch.addCell(slotOffset=i + 1,
                           channelOffset=0,
                           neighbor=root.get_mac_addr(),
                           cellOptions=[d.CELLOPTION_TX],
                           slotframe_handle=i)
        root.tsch.addCell(slotOffset=i + 1,
                          channelOffset=0,
                          neighbor=hop_1.get_mac_addr(),
                          cellOptions=[d.CELLOPTION_RX],
                          slotframe_handle=i)

    # the first dedicated cell is scheduled at slot_offset 1, the other is at
    # slot_offset 2
    cell_in_slotframe_0 = hop_1.tsch.get_cells(root.get_mac_addr(), 0)[0]
    cell_in_slotframe_1 = hop_1.tsch.get_cells(root.get_mac_addr(), 1)[0]

    # run until the end of this slotframe
    slot_offset = sim_engine.getAsn() % 101
    u.run_until_asn(sim_engine, sim_engine.getAsn() + (101 - slot_offset - 1))

    # send two application packets, which will be sent over the dedicated cells
    hop_1.app._send_a_single_packet()
    hop_1.app._send_a_single_packet()

    # run for one slotframe
    asn = sim_engine.getAsn()
    assert (asn % 101) == 100  # the next slot is slotoffset 0
    u.run_until_asn(sim_engine, asn + 101)

    # check logs
    ## TX side (hop_1)
    logs = [
        log for log in u.read_log_file(filter=[SimLog.LOG_TSCH_TXDONE['type']],
                                       after_asn=asn)
        if log['_mote_id'] == hop_1.id
    ]
    assert len(logs) == 2
    assert (logs[0]['_asn'] % 101) == cell_in_slotframe_0.slot_offset
    assert (logs[1]['_asn'] % 101) == cell_in_slotframe_1.slot_offset

    ## RX side (root)
    logs = [
        log for log in u.read_log_file(filter=[SimLog.LOG_TSCH_RXDONE['type']],
                                       after_asn=asn)
        if log['_mote_id'] == root.id
    ]
    assert len(logs) == 2
    assert (logs[0]['_asn'] % 101) == cell_in_slotframe_0.slot_offset
    assert (logs[1]['_asn'] % 101) == cell_in_slotframe_1.slot_offset

    # confirm hop_1 has the minimal cell
    assert len(hop_1.tsch.get_cells(None)) == 1
    assert (hop_1.tsch.get_cells(None)[0].options == [
        d.CELLOPTION_TX, d.CELLOPTION_RX, d.CELLOPTION_SHARED
    ])
예제 #7
0
def test_retransmission_backoff_algorithm(sim_engine, cell_type):
    sim_engine = sim_engine(
        diff_config={
            'exec_numSlotframesPerRun': 10000,
            'exec_numMotes': 2,
            'app_pkPeriod': 0,
            'secjoin_enabled': False,
            'tsch_keep_alive_interval': 0
        })
    sim_log = SimLog.SimLog()

    # filter logs to make this test faster; we need only SimLog.LOG_TSCH_TXDONE
    sim_log.set_log_filters([SimLog.LOG_TSCH_TXDONE['type']])

    # for quick access
    root = sim_engine.motes[0]
    hop_1 = sim_engine.motes[1]
    slotframe_length = sim_engine.settings.tsch_slotframeLength

    # increase TSCH_MAXTXRETRIES so that we can have enough retransmission
    # samples to validate
    d.TSCH_MAXTXRETRIES = 100

    #== test setup ==

    u.run_until_everyone_joined(sim_engine)

    # make hop_1 ready to send an application packet
    assert hop_1.rpl.dodagId is None
    dio = root.rpl._create_DIO()
    dio['mac'] = {'srcMac': root.get_mac_addr()}
    hop_1.rpl.action_receiveDIO(dio)
    assert hop_1.rpl.dodagId is not None

    # make root ignore all the incoming frame for this test
    def ignoreRx(self, packet, channel):
        self.waitingFor = None
        isACKed = False
        return isACKed

    root.tsch.rxDone = types.MethodType(ignoreRx, root.tsch)

    if cell_type == 'dedicated-cell':
        # allocate one TX=1/RX=1/SHARED=1 cell to the motes as their dedicate cell.
        cellOptions = [d.CELLOPTION_TX, d.CELLOPTION_RX, d.CELLOPTION_SHARED]

        assert len(root.tsch.get_cells(hop_1.get_mac_addr())) == 0
        root.tsch.addCell(1, 1, hop_1.get_mac_addr(), cellOptions)
        assert len(root.tsch.get_cells(hop_1.get_mac_addr())) == 1

        assert len(hop_1.tsch.get_cells(root.get_mac_addr())) == 0
        hop_1.tsch.addCell(1, 1, root.get_mac_addr(), cellOptions)
        assert len(hop_1.tsch.get_cells(root.get_mac_addr())) == 1

    # make sure hop_1 send a application packet when the simulator starts
    hop_1.tsch.txQueue = []
    hop_1.app._send_a_single_packet()
    assert len(hop_1.tsch.txQueue) == 1

    #== start test ==
    asn_starting_test = sim_engine.getAsn()

    # run the simulator until hop_1 drops the packet or the simulation ends
    def drop_packet(self, packet, reason):
        if packet['type'] == d.PKT_TYPE_DATA:
            # pause the simulator
            sim_engine.pauseAtAsn(sim_engine.getAsn() + 1)

    hop_1.drop_packet = types.MethodType(drop_packet, hop_1)
    u.run_until_end(sim_engine)

    # confirm
    # - hop_1 sent the application packet to the root
    # - retransmission backoff worked
    logs = u.read_log_file(filter=[SimLog.LOG_TSCH_TXDONE['type']],
                           after_asn=asn_starting_test)
    app_data_tx_logs = []
    for log in logs:
        if ((log['_mote_id'] == hop_1.id)
                and (root.is_my_mac_addr(log['packet']['mac']['dstMac']))
                and (log['packet']['type'] == d.PKT_TYPE_DATA)):
            app_data_tx_logs.append(log)

    assert len(app_data_tx_logs) == 1 + d.TSCH_MAXTXRETRIES

    # all transmission should have happened only on the dedicated cell if it's
    # available (it shouldn't transmit a unicast frame to the root on the
    # minimal (shared) cell.
    if cell_type == 'dedicated-cell':
        _cell = hop_1.tsch.get_cells(root.get_mac_addr())[0]
        expected_cell_offset = _cell.slot_offset
    elif cell_type == 'shared-cell':
        expected_cell_offset = 0  # the minimal (shared) cell
    else:
        raise NotImplementedError()

    for log in app_data_tx_logs:
        slot_offset = log['_asn'] % slotframe_length
        assert slot_offset == expected_cell_offset

    # retransmission should be performed after backoff wait; we should see gaps
    # between consecutive retransmissions. If all the gaps are 101 slots, that
    # is, one slotframe, this means there was no backoff wait between
    # transmissions.
    timestamps = [log['_asn'] for log in app_data_tx_logs]
    diffs = map(lambda x: x[1] - x[0], zip(timestamps[:-1], timestamps[1:]))
    assert len([diff for diff in diffs if diff != slotframe_length]) > 0
예제 #8
0
    def test_msf(self, sim_engine):
        """ Test Scheduling Function Traffic Adaptation
        - objective   : test if msf adjust the number of allocated cells in
                        accordance with traffic
        - precondition: form a 2-mote linear network
        - precondition: the network is formed
        - action      : change traffic
        - expectation : MSF should trigger ADD/DELETE/RELOCATE accordingly
        """

        sim_engine = sim_engine(
            diff_config={
                'app_pkPeriod': 0,
                'app_pkPeriodVar': 0.05,
                'exec_numMotes': 3,
                'exec_numSlotframesPerRun': 4000,
                'secjoin_enabled': False,
                'sf_class': 'MSF',
                'conn_class': 'Linear',
            })

        # XXX
        d.MSF_MIN_NUM_TX = 10

        # for quick access
        root = sim_engine.motes[0]
        hop_1 = sim_engine.motes[1]
        hop_2 = sim_engine.motes[2]
        asn_at_end_of_simulation = (
            sim_engine.settings.tsch_slotframeLength *
            sim_engine.settings.exec_numSlotframesPerRun)

        # make hop_1 not receive anything on dedicated RX cells other than the
        # first allocated one than one dedicated RX cell so that MSF would
        # perform cell relocation
        hop_1.tsch.original_addCell = hop_1.tsch.addCell
        hop_1.tsch.original_tsch_action_RX = hop_1.tsch._tsch_action_RX

        def new_addCell(self, slotOffset, channelOffset, neighbor,
                        cellOptions):
            if ((cellOptions == [d.CELLOPTION_RX])
                    and (len(self.getRxCells(neighbor)) == 0)):

                # remember the slotoffset of first allocated dedicated cell. While
                # this cell might be deleted later, ignore such an edge case for
                # this test.
                self.first_dedicated_slot_offset = slotOffset

            self.original_addCell(slotOffset, channelOffset, neighbor,
                                  cellOptions)

        def new_action_RX(self):
            slot_offset = self.engine.getAsn(
            ) % self.settings.tsch_slotframeLength
            cell = self.schedule[slot_offset]
            if ((cell['neighbor'] is not None)
                    and hasattr(self, 'first_dedicated_slot_offset')
                    and ((self.first_dedicated_slot_offset) != slot_offset)):
                # do nothing on this dedicated cell
                pass
            else:
                self.original_tsch_action_RX()

        hop_1.tsch.addCell = types.MethodType(new_addCell, hop_1.tsch)
        hop_1.tsch._tsch_action_RX = types.MethodType(new_action_RX,
                                                      hop_1.tsch)

        # wait for the network formed
        u.run_until_everyone_joined(sim_engine)

        # wait for hop_2 to get ready to start application
        run_until_mote_is_ready_for_app(sim_engine, hop_2)
        assert sim_engine.getAsn() < asn_at_end_of_simulation

        # generate application traffic which is supposed to trigger an ADD
        # transaction between hop_2 and hop_1
        asn_starting_app_traffic = sim_engine.getAsn()
        set_app_traffic_rate(sim_engine, 1.4)
        start_app_traffic(hop_2)
        run_until_dedicated_tx_cell_is_allocated(sim_engine, hop_2)
        assert sim_engine.getAsn() < asn_at_end_of_simulation

        # increase the traffic
        asn_increasing_app_traffic = sim_engine.getAsn()
        set_app_traffic_rate(sim_engine, 1.1)
        run_until_dedicated_tx_cell_is_allocated(sim_engine, hop_2)
        assert sim_engine.getAsn() < asn_at_end_of_simulation

        # decrease the traffic; run until a RELOCATE command is issued
        set_app_traffic_rate(sim_engine, 1.4)
        run_until_sixp_cmd_is_seen(sim_engine, hop_2, d.SIXP_CMD_RELOCATE)
        assert sim_engine.getAsn() < asn_at_end_of_simulation

        # stop the traffic; run until a DELETE command is issued
        stop_app_traffic(sim_engine)
        run_until_sixp_cmd_is_seen(sim_engine, hop_2, d.SIXP_CMD_DELETE)
        assert sim_engine.getAsn() < asn_at_end_of_simulation