Skip to content
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

I210 implementation + Taprio software support + mapping customization (rebase) #20

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5e65698
Test implementation of i210.
jeppex1 Feb 17, 2023
bc64cd3
Added support for picking flag in taprio setup. (1/2)
jeppex1 Feb 17, 2023
1b324ce
Implemented i210 support
jeppex1 Mar 9, 2023
f1b5e86
Added test for TcTaprioSoftwareSet + fix name
jeppex1 Mar 10, 2023
98905b3
Added capability for i210 to indicate it supports LTC
jeppex1 Mar 14, 2023
18fa2c8
Taprio txassist mode + etf qdisc install functionality (rough impleme…
jeppex1 Mar 14, 2023
6e62464
Preparation of options object, used to pass customization into qdisc
jeppex1 Mar 14, 2023
1838278
Picking taprio + some option fixing
jeppex1 Mar 14, 2023
31840ae
Enabled possibility to pass custom tc flag
jeppex1 Mar 21, 2023
1cbff86
Fixed txassist error
jeppex1 Mar 21, 2023
d352c61
Added Tests for taprio txassist and etf CommandStrings
jeppex1 Mar 21, 2023
4980b99
error fix in txassist
jeppex1 Mar 21, 2023
f1820c0
Finished LTC setup option
jeppex1 Mar 21, 2023
b8a55de
Added possibility to pass map to tc from python script
jeppex1 Mar 21, 2023
989762a
Removed unnecessary code
jeppex1 Mar 21, 2023
5723bb1
Calculating Txoffset-hardware delays
jeppex1 Mar 24, 2023
564b1dc
Revert "Calculating Txoffset-hardware delays"
jeppex1 Mar 27, 2023
29590c3
Revert "Finished LTC setup option"
jeppex1 Mar 27, 2023
50ac499
Revert "error fix in txassist"
jeppex1 Mar 27, 2023
3f659d9
Revert "Added Tests for taprio txassist and etf CommandStrings"
jeppex1 Mar 27, 2023
400e994
Revert "Fixed txassist error"
jeppex1 Mar 27, 2023
3d2942c
revert
jeppex1 Mar 27, 2023
dc30031
Removed to make sure branch contains only Taprio Software Support + I…
jeppex1 Mar 27, 2023
efbfd70
Updated readme for options
jeppex1 Mar 27, 2023
8b368a1
Enable Hints.
kamber-intel May 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,53 @@ ethtool --set-eee eth0 eee off



### Setup a talker from python with options

The following code will connect to the detd service and configure the specified stream with options.

```python
from detd import *



def setup_stream_config():

interface_name = "eno1"
interval = 20 * 1000 * 1000 # ns
size = 1522 # Bytes

txoffset = 250 * 1000 # ns
addr = "03:C0:FF:EE:FF:4E"
vid = 3
pcp = 6

options = Options()
xtor marked this conversation as resolved.
Show resolved Hide resolved
options.qdiscmap = "0 1 0 0 0 0 0 0 2 3 0 0 0 0 0 0"
xtor marked this conversation as resolved.
Show resolved Hide resolved

interface = Interface(interface_name)
stream = StreamConfiguration(addr, vid, pcp, txoffset)
traffic = TrafficSpecification(interval, size)

config = Configuration(interface, stream, traffic, options)

return config




proxy = ServiceProxy()

config = setup_stream_config()
response = proxy.add_talker(config)

print(response)
```

This example specifies the map parameter for taprio, otherwise it behaves same as the example above.




### Setup a talker stream for an arbitrary command, using a script that calls detd functions

The script [setup_qos.sh](./setup_qos.sh) allows for quick experimentation without modifying an existing application.
Expand Down
9 changes: 9 additions & 0 deletions detd/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,12 @@ def __init__(self, template, params):
data = template.substitute(params).replace('\n', '')

super().__init__(data)


class Options:
"""Methods to assign parameters to passs into one convenient Object.
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved
Used for: Passing parameters in Python script for manual customization of the qdisc. """
def __init__(self):

self.qdiscmap = "nomap"
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved

38 changes: 36 additions & 2 deletions detd/devices/intel_i210.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
"""



import time

from ..logger import get_logger

from .device import Capability
from .device import Device


Expand All @@ -23,6 +24,12 @@

class IntelI210(Device):


NUM_TX_QUEUES = 4
NUM_RX_QUEUES = 4

CAPABILITIES = [Capability.LTC]

PCI_IDS_VALID = ['8086:1533', '8086:1536', '8086:1537', '8086:1538', '8086:157B',
'8086:157C', '8086:15F6']

Expand All @@ -35,4 +42,31 @@ def __init__(self, pci_id):

logger.info(f"Initializing {__class__.__name__}")

raise NotImplementedError("Handler class for i210 Ethernet controller not yet implemented")
super().__init__(IntelI210.NUM_TX_QUEUES, IntelI210.NUM_RX_QUEUES)

self.capabilities = [Capability.LTC]

self.features['rxvlan'] = 'off'

# self.num_tx_ring_entries and self.num_rx_ring_entries
# Provides the number of ring entries for Tx and Rx rings.
# Currently, the code just passes the value to ethtool's --set-ring.
self.num_tx_ring_entries = 1024
self.num_rx_ring_entries = 1024

def get_rate(self, interface):

# Without a small delay, the program flow will call ethtool twice too
# fast, causing it to return "Unknown!" speed
time.sleep(1)

return self.systeminfo.get_rate(interface)


def get_base_time_multiple(self):
xtor marked this conversation as resolved.
Show resolved Hide resolved
return -1


def supports_schedule(self, schedule):
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved

return True
1 change: 1 addition & 0 deletions detd/ipc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ message StreamQosRequest {
uint32 txmax = 8;
bool setup_socket = 9;
uint32 basetime = 10;
string qdiscmap = 11;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need to remove qdiscmap and pass the specific options instead.

It is also possible that the application does not specify the options, and then the framework will pick it up.

}


Expand Down
11 changes: 8 additions & 3 deletions detd/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def add_talker(self, config):
with self.lock:

if not config.interface.name in self.talker_manager:
interface_manager = InterfaceManager(config.interface)
interface_manager = InterfaceManager(config.interface, config.options)
self.talker_manager[config.interface.name] = interface_manager

return self.talker_manager[config.interface.name].add_talker(config)
Expand All @@ -96,12 +96,17 @@ def add_talker(self, config):

class InterfaceManager():

def __init__(self, interface):
def __init__(self, interface, options):

logger.info(f"Initializing {__class__.__name__}")

self.interface = interface
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved
self.mapping = Mapping(self.interface)
self.options = options

if self.options.qdiscmap == "nomap":
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved
self.mapping = Mapping(self.interface)
else:
self.mapping = Mapping(self.interface, self.options)
self.scheduler = Scheduler(self.mapping)


Expand Down
10 changes: 7 additions & 3 deletions detd/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,14 @@ class Mapping():
"""


def __init__(self, interface):
def __init__(self, interface, options = None):
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved

logger.info(f"Initializing {__class__.__name__}")

# FIXME: make the number of Tx queues a parameter, so things are not hardcoded

self.interface = interface
self.options = options
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved


# Socket priorities
Expand Down Expand Up @@ -355,8 +356,11 @@ def soprio_to_tc(self):
# Then we assign those socket prios used by other traffic classes
for tc, soprio in enumerate(self.tc_to_soprio):
mapping[soprio] = tc

return mapping

kamber-intel marked this conversation as resolved.
Show resolved Hide resolved
if self.options is None:
return mapping
else:
return [int(x) for x in self.options.qdiscmap.split()]


def assign_and_map(self, pcp, traffics):
Expand Down
1 change: 1 addition & 0 deletions detd/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def send_qos_request(self, configuration, setup_socket):
request.txmin = configuration.stream.txoffset
request.txmax = configuration.stream.txoffset
request.setup_socket = setup_socket
request.qdiscmap = configuration.options.qdiscmap
kamber-intel marked this conversation as resolved.
Show resolved Hide resolved

message = request.SerializeToString()
self.send(message)
Expand Down
7 changes: 6 additions & 1 deletion detd/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import math

from .common import Check
from .common import Options

from .logger import get_logger

Expand All @@ -36,14 +37,18 @@

class Configuration:

def __init__(self, interface, stream, traffic):
def __init__(self, interface, stream, traffic, options = None):

if stream.txoffset > traffic.interval:
raise TypeError("Invalid TxOffset, it exceeds Interval")

self.interface = interface
self.stream = stream
self.traffic = traffic
if options is None:
self.options = Options()
else:
self.options = options


class StreamConfiguration:
Expand Down
6 changes: 5 additions & 1 deletion detd/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
from .systemconf import SystemInformation
from .systemconf import CommandIp

from .common import Options

from .logger import setup_root_logger
from .logger import get_logger

Expand Down Expand Up @@ -248,11 +250,13 @@ def _add_talker(self, request):
size = request.size
interface_name = request.interface

options = Options()
options.qdiscmap = request.qdiscmap
interface = Interface(interface_name)
stream = StreamConfiguration(addr, vid, pcp, txoffset)
traffic = TrafficSpecification(interval, size)

config = Configuration(interface, stream, traffic)
config = Configuration(interface, stream, traffic, options)

vlan_interface, soprio = self.server.manager.add_talker(config)

Expand Down
2 changes: 1 addition & 1 deletion detd/systemconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def setup(self, interface, mapping, scheduler, base_time):
if interface.device.supports_qbv():
tc.set_taprio_offload(interface, mapping, scheduler, base_time)
else:
raise NotImplementedError("tc.set_taprio_software() not implemented")
tc.set_taprio_software(interface, mapping, scheduler, base_time)


def unset(self, interface):
Expand Down
51 changes: 51 additions & 0 deletions detd/tc.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,28 @@ def unset_taprio_offload(self, interface):
cmd = CommandStringTcTaprioOffloadUnset(interface.name)

self.run(cmd)


def set_taprio_software(self, interface, mapping, scheduler, base_time):

# E.g. len(set([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]))
num_tc = len(set(mapping.soprio_to_tc))
soprio_to_tc = transform_soprio_to_tc(mapping.soprio_to_tc)
tc_to_hwq = transform_tc_to_hwq(mapping.tc_to_hwq)
schedule = extract_schedule(scheduler)
sched_entries = transform_sched_entries(schedule)
cmd = CommandStringTcTaprioSoftwareSet(interface.name, num_tc, soprio_to_tc, tc_to_hwq, base_time, sched_entries)

self.run(cmd)


def unset_taprio_software(self, interface):

cmd = CommandStringTcTaprioOffloadUnset(interface.name)

self.run(cmd)



def num_tc(soprio_to_tc):
return len(set(soprio_to_tc))
Expand Down Expand Up @@ -167,3 +186,35 @@ def __init__(self, interface):
params = {"interface" : interface}

super().__init__(template, params)


class CommandStringTcTaprioSoftwareSet(CommandString):

def __init__(self, interface, num_tc, soprio_to_tc, tc_to_hwq, base_time, sched_entries):

template = '''
tc qdisc replace
dev $interface
parent root
taprio
num_tc $num_tc
map $soprio_to_tc
queues $tc_to_hwq
base-time $base_time
$sched_entries
flags 0x0
clockid CLOCK_TAI'''

params = {
'interface' : interface,
'num_tc' : num_tc,
'soprio_to_tc' : soprio_to_tc,
'tc_to_hwq' : tc_to_hwq,
'base_time' : base_time,
'sched_entries' : sched_entries
}

super().__init__(template, params)



35 changes: 34 additions & 1 deletion tests/test_commandstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from detd import CommandStringEthtoolSetRing
from detd import CommandStringEthtoolGetDriverInformation
from detd import CommandStringTcTaprioOffloadSet
from detd import CommandStringTcTaprioSoftwareSet



Expand Down Expand Up @@ -143,7 +144,7 @@ def test_ethtoolgetdriverinformation(self):



def test_iplinksetvlan(self):
def test_tcsettapriooffload(self):

interface_name = "eth0"
soprio_to_tc = "0 0 0 0 0 0 1 0 0 0 0 0"
Expand Down Expand Up @@ -175,5 +176,37 @@ def test_iplinksetvlan(self):



def test_tcsettapriosoftware(self):

interface_name = "eth0"
soprio_to_tc = "0 0 0 0 0 0 1 0 0 0 0 0"
num_tc = 2
tc_to_hwq = "1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7"
base_time = "165858970408520000"
sched_entries = """sched-entry S 01 250000
sched-entry S 02 12176
sched-entry S 01 19737824"""

cmd = CommandStringTcTaprioSoftwareSet(interface_name, num_tc, soprio_to_tc, tc_to_hwq, base_time, sched_entries)
expected = '''
tc qdisc replace
dev eth0
parent root
taprio
num_tc 2
map 0 0 0 0 0 0 1 0 0 0 0 0
queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7
base-time 165858970408520000
sched-entry S 01 250000
sched-entry S 02 12176
sched-entry S 01 19737824
flags 0x0
clockid CLOCK_TAI'''


self.assert_commandstring_equal(cmd, expected)



if __name__ == '__main__':
unittest.main()