-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changed and refactored the code #2
base: master
Are you sure you want to change the base?
Changes from all commits
e1a5fe0
f23005b
7f338c2
0f1602f
145b33d
1d341c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/usr/bin/env python3 | ||
# coding: utf-8 -*- | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
# | ||
# pifo-fifo.py | ||
|
||
"""First in, first out (FIFO) | ||
|
||
The FIFO scheduling algorithm preserves the order of the scheduled packets. This | ||
implementation is here for completeness and uses a PIFO. It is here to help | ||
people understand how to add new scheduling algorithms to this framework. | ||
""" | ||
|
||
__copyright__ = """ | ||
Copyright (c) 2021, Toke Høiland-Jørgensen <[email protected]> | ||
Copyright (c) 2021, Frey Alfredsson <[email protected]> | ||
""" | ||
|
||
__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 <http://www.gnu.org/licenses/>. | ||
""" | ||
|
||
from sched_lib import Packet, Runner, Pifo, SchedulingAlgorithm | ||
|
||
|
||
class Fifo(SchedulingAlgorithm): | ||
"""First in, first out (FIFO)""" | ||
|
||
def __init__(self, name=None): | ||
super().__init__(name) | ||
self._pifo = Pifo() | ||
|
||
def get_rank(self, _): | ||
"""Rank the items in FIFO order.""" | ||
return self._pifo.qlen | ||
|
||
def enqueue(self, ref, item): | ||
rank = self.get_rank(item) | ||
self._pifo.enqueue(ref, 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), | ||
Packet(flow=1, idn=2, length=2), | ||
Packet(flow=2, idn=1, length=1), | ||
Packet(flow=2, idn=2, length=1), | ||
Packet(flow=2, idn=3, length=1), | ||
] | ||
Runner(pkts, Fifo()).run() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#!/usr/bin/env python3 | ||
# coding: utf-8 -*- | ||
# | ||
# SPDX-License-Identifier: GPL-3.0-or-later | ||
# | ||
# pifo-hpfq.py | ||
|
||
"""HierarchicalPacket Fair Queueing (HPFQ) | ||
|
||
This scheduling algorithm is mentioned in the paper "Programmable packet | ||
scheduling at line rate" by Sivaraman, Anirudh, et al. It creates a hierarchy of | ||
WFQ schedulers. The central scheduler is called root and contains references to | ||
other WFQ schedulers. Those two WFQ schedulers are called left and right. We | ||
chose that packets with flow ids lower than ten go into the left scheduler in | ||
our implementation. In contrast, the others go into the right scheduler.""" | ||
|
||
__copyright__ = """ | ||
Copyright (c) 2021, Toke Høiland-Jørgensen <[email protected]> | ||
Copyright (c) 2021, Frey Alfredsson <[email protected]> | ||
""" | ||
|
||
__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 <http://www.gnu.org/licenses/>. | ||
""" | ||
|
||
from sched_lib import Packet, Runner, SchedulingAlgorithm | ||
from pifo_wfq import Wfq | ||
|
||
|
||
class Hpfq(SchedulingAlgorithm): | ||
"""HierarchicalPacket Fair Queueing (HPFQ)""" | ||
|
||
def __init__(self, name=None): | ||
super().__init__(name) | ||
self._root = Wfq("root") | ||
self._left = Wfq("Left") | ||
self._right = Wfq("Right") | ||
|
||
def enqueue(self, ref, item): | ||
queue = None | ||
if item.flow < 10: | ||
self._left.enqueue(ref, item) | ||
queue = self._left | ||
else: | ||
self._right.enqueue(ref, item) | ||
queue = self._right | ||
|
||
self._root.enqueue(queue, item) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here you're also only enqueueing a single ref to the child queue. You do need the packet to get the length, but the algorithm ends up being wrong: in the root WFQ you'll end up indexing the packet completions by the actual packet flow, not the child queue. So it ends up sorting packets by flows just like the leaf nodes do, meaning it won't actually be hierarchical at all... I think this weirdness comes from mixing of abstraction levels: you've implemented WFQ/STFQ as SchedulingAlgorithms, which has a clear "enqueue this packet" API (i.e., one arg to enqueue()). But here you're implementing a new SchedulingAlgorithm that reuses the others as sub-primitives. Where really, the primitive is a PIFO, all the different SchedulingAlgorithms just happen to reuse the same logic for get_rank() One way around this would be to specify a common base class for all three algorithms instead, which implements a get_rank that does the last_finish tracking, but takes the 'flow' as parameter. And then STFQ/WFQ could pass in an actual flow there, and HPFQ could pass in the child queues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's correct. That's an error on my part. It makes much more sense to schedule the length of the queue to make it hierarchical. I think we aim to do two things. One is to understand the algorithms and agree on them, and the other is to find an interface that helps us write the eBPF abstraction of the code. I think we should have three different PIFOs inside the SchedulingAlgorithm and not try to reuse other SchedulingAlgorithm classes directly. That way, we are getting a little closer to what we are thinking with the eBPF code without introducing too many Python-specific abstractions. If we add more inheritance to the code, I think it makes sense from a Python and objected-oriented approach. However, I believe the SchedulingAlgorithm class should be closer to what we want the eBPF C code to look like, even if it is a bit Pythonized. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, SGTM. |
||
|
||
def dequeue(self): | ||
queue = self._root.dequeue() | ||
return queue.dequeue() if queue is not None else None | ||
|
||
def dump(self): | ||
print(" Root:") | ||
self._root.dump() | ||
print(" Left:") | ||
self._left.dump() | ||
print(" Right:") | ||
self._right.dump() | ||
|
||
|
||
if __name__ == "__main__": | ||
pkts = [ | ||
Packet(flow=1, idn=1, length=200), | ||
Packet(flow=1, idn=2, length=200), | ||
Packet(flow=10, idn=1, length=200), | ||
Packet(flow=10, idn=2, length=200), | ||
Packet(flow=2, idn=1, length=100), | ||
Packet(flow=2, idn=2, length=100), | ||
Packet(flow=2, idn=3, length=100), | ||
Packet(flow=20, idn=1, length=100), | ||
Packet(flow=20, idn=2, length=100), | ||
Packet(flow=20, idn=3, length=100), | ||
] | ||
Runner(pkts, Hpfq()).run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so the logical flow here is "pick a queue from left or right, and enqueue the packet into it". So it doesn't need to arguments to enqueue here either, just pass through the 'item'...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I am going to change this by adding the reference to the item (packet or flow) instead. Then this won't look like this.