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

First draft of register tests #149

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions p4src/include/int/int.p4
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ control IntEgress (
@hidden
Random<bit<16>>() ip_id_gen;
@hidden
@switchstack("register_clear_interval_ms: 1000")
@switchstack("register_clear_value: 0")
Register<bit<32>, bit<6>>(1024) seq_number;
RegisterAction<bit<32>, bit<6>, bit<32>>(seq_number) get_seq_number = {
void apply(inout bit<32> reg, out bit<32> rv) {
Expand Down
61 changes: 61 additions & 0 deletions ptf/tests/ptf/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def import_p4info_names(self):
"actions",
"counters",
"direct_counters",
"registers",
]:
for obj in getattr(self.p4info, p4_obj_type):
pre = obj.preamble
Expand Down Expand Up @@ -822,6 +823,30 @@ def write_indirect_counter(
counter_data.packet_count = packet_count
return req, self.write_request(req, store=False)

def write_register(self, reg_name, index, data):
req = self.get_new_write_request()
update = req.updates.add()
update.type = p4runtime_pb2.Update.MODIFY
register_entry = update.entity.register_entry
register_entry.register_id = self.get_register_id(reg_name)
register_entry.index.index = index
register_entry.data.CopyFrom(data)

return req, self.write_request(req, store=False)

def read_register(self, reg_name, index=None):
req = self.get_new_read_request()
entity = req.entities.add()
register_entry = entity.register_entry
register_entry.register_id = self.get_register_id(reg_name)
if index is not None:
register_entry.index.index = index

for entity in self.read_request(req):
if entity.HasField("register_entry"):
return entity.register_entry
return None

def read_table_entry(self, t_name, mk, priority=0):
req = self.get_new_read_request()
entity = req.entities.add()
Expand Down Expand Up @@ -998,6 +1023,41 @@ def verify_indirect_counter(
)
return None

def verify_register(self, reg_name, index, expected_data):
reg = self.read_register(reg_name, index)
if reg.index.index != index:
self.fail("Incorrect index\n" + format_exp_rcv(index, reg.index.index))
if reg.data != expected_data:
self.fail("Incorrect data:\n" + format_exp_rcv(expected_data, reg.data))

return None

# TODO: check about tv generation
req = self.get_new_read_request()
entity = req.entities.add()
direct_counter_entry = entity.direct_counter_entry
direct_counter_entry.table_entry.CopyFrom(table_entry)

if self.generate_tv:
exp_resp = self.get_new_read_response()
entity = exp_resp.entities.add()
entity.direct_counter_entry.table_entry.CopyFrom(table_entry)
entity.direct_counter_entry.data.byte_count = expected_byte_count
entity.direct_counter_entry.data.packet_count = expected_packet_count
# add to list
exp_resps = []
exp_resps.append(exp_resp)
tvutils.add_read_expectation(self.tc, req, exp_resps)
return None

for entity in self.read_request(req):
if entity.HasField("direct_counter_entry"):
direct_counter = entity.direct_counter_entry
if direct_counter.data.byte_count != expected_byte_count or \
direct_counter.data.packet_count != expected_packet_count:
self.fail("Incorrect direct counter value:\n" + str(direct_counter))
return None

def is_default_action_update(self, update):
return (
update.type == p4runtime_pb2.Update.MODIFY
Expand Down Expand Up @@ -1045,6 +1105,7 @@ def undo_write_requests(self, reqs, create_new_tv=True):
("actions", "action"),
("counters", "counter"),
("direct_counters", "direct_counter"),
("registers", "register"),
]:
name = "_".join(["get", nickname])
setattr(P4RuntimeTest, name, partialmethod(P4RuntimeTest.get_obj, obj_type))
Expand Down
29 changes: 29 additions & 0 deletions ptf/tests/ptf/fabric.ptf/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,35 @@ def runTest(self):
self.doRunTest()


@group("p4rt")
class RegisterTest(FabricTest):
@tvsetup
@autocleanup
def doRunTest(self):
register_name = "pipe.FabricEgress.int_egress.seq_number"
index = 1
default_data = p4data_pb2.P4Data()
default_data.bitstring = stringify(0x0, 1)
# Check that the default reset value is written.
self.verify_register(register_name, index, default_data)

# Write a new value and verify be reading it back.
data = p4data_pb2.P4Data()
data.bitstring = stringify(0xabcd, 2)
req, _ = self.write_register(register_name, index, data)
self.verify_register(register_name, index, data)

# Check the regular register reset.
time.sleep(3)
self.verify_register(register_name, index, default_data)

# Wildcard read
self.read_register(register_name)

def runTest(self):
print("")
self.doRunTest()

# FIXME: remove when will start running TVs on hardware
class FabricIpv4UnicastLoopbackModeTest(IPv4UnicastTest):
"""Emulates TV loopback mode for Ipv4UnicastTest"""
Expand Down
1 change: 1 addition & 0 deletions ptf/tests/ptf/fabric_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import xnt
from base_test import P4RuntimeTest, ipv4_to_binary, mac_to_binary, stringify, tvcreate
from p4.v1 import p4runtime_pb2
from p4.v1 import p4data_pb2
from ptf import testutils as testutils
from ptf.mask import Mask
from scapy.contrib.mpls import MPLS
Expand Down