TL-System/ns.py

[BUG] SP scheduler bug flow id to class mappings

alessandrocornacchia opened this issue · 0 comments

Describe the bug
In function update_stats of sp.py, the debug message should use packet.flow_id instead of packet.packet_id to map a flow to its class.

if self.debug:
    print(
        f"Sent out packet {packet.packet_id} from flow {packet.flow_id} "
        f"belonging to class {self.flow_classes(packet.packet_id)} "
        f"of priority {packet.prio[self.element_id]}")

To Reproduce
Run the following code, where the flow class is assigned at runtime depending on the number of transmitted packets, by looking up the flows dictionary:

"""
A basic example that connects two packet generators to a network wire with
a propagation delay distribution, and then to a packet sink.
"""

from functools import partial
import simpy
from bisect import bisect_left

from ns.packet.dist_generator import DistPacketGenerator
from ns.packet.sink import PacketSink
from ns.scheduler.sp import SPServer
from ns.switch.switch import SimplePacketSwitch


# priortiy queues per server
k = 2
# number of servers
n = 2
# rate of each server
mu = 100
# demotion thresholds
demotion_thresholds = [5]

def arrival_1():
    """ Packets arrive with a constant interval of 1.5 seconds. """
    return 1.5


def arrival_2():
    """ Packets arrive with a constant interval of 2.0 seconds. """
    return 2.0


def packet_size():
    return 100


def flow_to_classes(f_id, flows, thresholds):
    attained_service = flows[f_id].packets_sent
    return bisect_left(thresholds, attained_service)
    #return (f_id + n_id + fib[f_id]) % n_classes_per_port

env = simpy.Environment()

# simple switch with infinite rate, just used as entrypoint node
# for flows to handle routing to different servers
switch = SimplePacketSwitch(
    env,
    nports=n,
    port_rate=0,  # in bits/second
    buffer_size=None,  # in packets
    debug=True)

pg1 = DistPacketGenerator(env, "flow_1", arrival_1, packet_size, flow_id=0)
pg2 = DistPacketGenerator(env, "flow_2", arrival_2, packet_size, flow_id=1)

# connect all packet generators to switch
pg1.out = switch
pg2.out = switch

# route flows
fib = {0: 0, 1: 1}
switch.demux.fib = fib

flows = {
    0: pg1,
    1: pg2
}
flow_classes = partial(flow_to_classes, flows=flows, thresholds=demotion_thresholds)
servers = []
for i in range(n):
    sp = SPServer(
        env,
        mu,
        list(range(k)),
        flow_classes=flow_classes,
        debug=True
        )
    
    ps = PacketSink(env, rec_flow_ids=False, debug=True)

    sp.out = ps
    switch.ports[i].out = sp

    servers.append(sp)

env.run(until=20)

Expected behavior
You get following exception:

Traceback (most recent call last):
  File "C:\Users\d067567\AppData\Local\anaconda3\envs\ns.py\lib\site-packages\ns\scheduler\sp.py", line 190, in run
    self.update_stats(packet)
  File "C:\Users\d067567\AppData\Local\anaconda3\envs\ns.py\lib\site-packages\ns\scheduler\sp.py", line 107, in update_stats
    f"belonging to class {self.flow_classes(packet.packet_id)} "
  File "g:\My Drive\Politecnico\Thesis\python-ns\examples\spatial_diversity.py", line 40, in flow_to_classes
    attained_service = flows[f_id].packets_sent
KeyError: 6