diff --git a/queue-exp/pifo_stfq.py b/queue-exp/pifo_stfq.py index 6f20381..bc72b21 100755 --- a/queue-exp/pifo_stfq.py +++ b/queue-exp/pifo_stfq.py @@ -5,6 +5,15 @@ # # pifo-stfq.py +"""Start-Time Fair Queuing (STFQ) + +This scheduling algorithm is mentioned in the paper "Programmable packet +scheduling at line rate" by Sivaraman, Anirudh, et al. + +It schedules packets by their start time within a flow. It defines the start +time as the finish time of the last enqueued packet within a flow. +""" + __copyright__ = """ Copyright (c) 2021 Toke Høiland-Jørgensen Copyright (c) 2021 Frey Alfredsson @@ -26,23 +35,39 @@ """ from pifo_lib import Packet, Runner, Pifo +from pifo_lib import SchedulingAlgorithm + +class Stfq(SchedulingAlgorithm): + """Start-Time Fair Queuing (STFQ)""" -class Stfq(Pifo): def __init__(self): - super().__init__() - self.last_finish = {} - self.virt_time = 0 + self._pifo = Pifo() + + self._last_finish = {} + self._virt_time = 0 def get_rank(self, pkt): - flow = pkt.flow - if flow in self.last_finish: - rank = max(self.virt_time, self.last_finish[flow]) + flow_id = pkt.flow + if flow_id in self._last_finish: + rank = max(self._virt_time, self._last_finish[flow_id]) else: - rank = self.virt_time - self.last_finish[flow] = rank + pkt.length + rank = self._virt_time + self._last_finish[flow_id] = rank + pkt.length return rank + def enqueue(self, item): + rank = self.get_rank(item) + self._pifo.enqueue(item, rank) + + def dequeue(self): + return self._pifo.dequeue() + + def dump(self): + self._pifo.dump() + + + if __name__ == "__main__": pkts = [ Packet(flow=1, idn=1, length=2), diff --git a/queue-exp/pifo_wfq.py b/queue-exp/pifo_wfq.py new file mode 100755 index 0000000..2a76858 --- /dev/null +++ b/queue-exp/pifo_wfq.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# coding: utf-8 -*- +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# pifo-wfq.py + +"""Weighted Fair Queueing (WFQ) + +This scheduling algorithm is mentioned in the paper "Programmable packet +scheduling at line rate" by Sivaraman, Anirudh, et al. It schedules flows by +giving them a fraction of the capacity using predefined weights. In our example, +we defined flows with an odd number to get a weight of 50 and even numbers to +get 100. +""" + +__copyright__ = """ +Copyright (c) 2021 Toke Høiland-Jørgensen +Copyright (c) 2021 Frey Alfredsson +""" + +__license__ = """ +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +""" + +from pifo_lib import Packet, Runner, Pifo +from pifo_lib import SchedulingAlgorithm + + +class Wfq(SchedulingAlgorithm): + """Weighted Fair Queueing (WFQ)""" + + def __init__(self): + self._pifo = Pifo() + self._last_finish = {} + self._virt_time = 0 + + def get_rank(self, pkt): + flow = pkt.flow + weight = 50 if flow % 2 == 1 else 100 + if flow in self._last_finish: + rank = max(self._virt_time, self._last_finish[flow]) + else: + rank = self._virt_time + self._last_finish[flow] = rank + pkt.length / weight + return rank + + def enqueue(self, item): + rank = self.get_rank(item) + self._pifo.enqueue(item, rank) + + def dequeue(self): + return self._pifo.dequeue() + + def dump(self): + self._pifo.dump() + + +if __name__ == "__main__": + pkts = [ + Packet(flow=1, idn=1, length=100), + Packet(flow=1, idn=2, length=100), + Packet(flow=1, idn=3, length=100), + Packet(flow=2, idn=1, length=100), + Packet(flow=2, idn=2, length=100), + Packet(flow=2, idn=3, length=100), + ] + Runner(pkts, Wfq()).run()