diff --git a/src/device/tests/Device_P4.py b/src/device/tests/Device_P4.py new file mode 100644 index 0000000000000000000000000000000000000000..14128ac15a0efa3e2a0f3b0b07e60df202f3c790 --- /dev/null +++ b/src/device/tests/Device_P4.py @@ -0,0 +1,42 @@ +from copy import deepcopy +from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum +from .Tools import config_rule_set + +DEVICE_P4_ID = 0 +DEVICE_P4_NAME = 'device:leaf1' +DEVICE_P4_TYPE = 'p4-switch' +DEVICE_P4_ADDRESS = '127.0.0.1' +DEVICE_P4_PORT = '50101' +DEVICE_P4_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_P4] +DEVICE_P4_VENDOR = 'Open Networking Foundation' +DEVICE_P4_HW_VER = 'BMv2 simple_switch' +DEVICE_P4_SW_VER = 'Stratum' +DEVICE_P4_PIPECONF = 'org.onosproject.pipelines.fabric' +DEVICE_P4_WORKERS = 2 +DEVICE_P4_GRACE_PERIOD = 60 + +DEVICE_P4_UUID = {'device_uuid': {'uuid': DEVICE_P4_NAME}} +DEVICE_P4 = { + 'device_id': deepcopy(DEVICE_P4_UUID), + 'device_type': DEVICE_P4_TYPE, + 'device_config': {'config_rules': []}, + 'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED, + 'device_drivers': DEVICE_P4_DRIVERS, + 'device_endpoints': [], +} + +DEVICE_P4_CONNECT_RULES = [ + config_rule_set('_connect/address', DEVICE_P4_ADDRESS), + config_rule_set('_connect/port', DEVICE_P4_PORT), + config_rule_set('_connect/settings', { + 'id': int(DEVICE_P4_ID), + 'name': DEVICE_P4_NAME, + 'hw-ver': DEVICE_P4_HW_VER, + 'sw-ver': DEVICE_P4_SW_VER, + 'pipeconf': DEVICE_P4_PIPECONF + }), +] + +DEVICE_P4_CONFIG_RULES = [ + config_rule_set('key1', 'value1'), +] diff --git a/src/device/tests/MockP4RuntimeService.py b/src/device/tests/MockP4RuntimeService.py new file mode 100644 index 0000000000000000000000000000000000000000..f190dc20ff90323124c6311bfe140e1428d8c608 --- /dev/null +++ b/src/device/tests/MockP4RuntimeService.py @@ -0,0 +1,50 @@ +import grpc, logging +from concurrent import futures +from p4.v1 import p4runtime_pb2_grpc + +from .Device_P4 import( + DEVICE_P4_ADDRESS, DEVICE_P4_PORT, + DEVICE_P4_WORKERS, DEVICE_P4_GRACE_PERIOD) +from .MockP4RuntimeServicerImpl import MockP4RuntimeServicerImpl + +LOGGER = logging.getLogger(__name__) + + +class MockP4RuntimeService: + def __init__( + self, address=DEVICE_P4_ADDRESS, port=DEVICE_P4_PORT, + max_workers=DEVICE_P4_WORKERS, + grace_period=DEVICE_P4_GRACE_PERIOD): + self.address = address + self.port = port + self.endpoint = '{:s}:{:s}'.format(str(self.address), str(self.port)) + self.max_workers = max_workers + self.grace_period = grace_period + self.pool = None + self.server = None + self.servicer = None + + def start(self): + LOGGER.info( + 'Starting P4Runtime service on {:s} with max_workers: {:s})'.format( + str(self.endpoint), str(self.max_workers))) + + self.pool = futures.ThreadPoolExecutor(max_workers=self.max_workers) + self.server = grpc.server(self.pool) + + self.servicer = MockP4RuntimeServicerImpl() + p4runtime_pb2_grpc.add_P4RuntimeServicer_to_server( + self.servicer, self.server) + + _ = self.server.add_insecure_port(self.endpoint) + LOGGER.info('Listening on {:s}...'.format(str(self.endpoint))) + + self.server.start() + LOGGER.debug('P4Runtime service started') + + def stop(self): + LOGGER.debug( + 'Stopping P4Runtime service (grace period {:s} seconds)...'.format( + str(self.grace_period))) + self.server.stop(self.grace_period) + LOGGER.debug('P4Runtime service stopped') diff --git a/src/device/tests/MockP4RuntimeServicerImpl.py b/src/device/tests/MockP4RuntimeServicerImpl.py new file mode 100644 index 0000000000000000000000000000000000000000..2f5164e20fbc7d3ae0f5a5a097d0c3658ae8f6d5 --- /dev/null +++ b/src/device/tests/MockP4RuntimeServicerImpl.py @@ -0,0 +1,42 @@ +import queue +from google.rpc import code_pb2 +from p4.v1 import p4runtime_pb2, p4runtime_pb2_grpc +from p4.config.v1 import p4info_pb2 + + +class MockP4RuntimeServicerImpl(p4runtime_pb2_grpc.P4RuntimeServicer): + def __init__(self): + self.p4info = p4info_pb2.P4Info() + self.p4runtime_api_version = "1.3.0" + self.stored_packet_out = queue.Queue() + + def GetForwardingPipelineConfig(self, request, context): + rep = p4runtime_pb2.GetForwardingPipelineConfigResponse() + if self.p4info is not None: + rep.config.p4info.CopyFrom(self.p4info) + return rep + + def SetForwardingPipelineConfig(self, request, context): + self.p4info.CopyFrom(request.config.p4info) + return p4runtime_pb2.SetForwardingPipelineConfigResponse() + + def Write(self, request, context): + return p4runtime_pb2.WriteResponse() + + def Read(self, request, context): + yield p4runtime_pb2.ReadResponse() + + def StreamChannel(self, request_iterator, context): + for req in request_iterator: + if req.HasField('arbitration'): + rep = p4runtime_pb2.StreamMessageResponse() + rep.arbitration.CopyFrom(req.arbitration) + rep.arbitration.status.code = code_pb2.OK + yield rep + elif req.HasField('packet'): + self.stored_packet_out.put(req) + + def Capabilities(self, request, context): + rep = p4runtime_pb2.CapabilitiesResponse() + rep.p4runtime_api_version = self.p4runtime_api_version + return rep