Loading src/device/requirements.in +1 −0 Original line number Diff line number Diff line Loading @@ -13,3 +13,4 @@ pytz redis requests xmltodict p4runtime==1.3.0 src/device/service/driver_api/FilterFields.py +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ class DeviceTypeFilterFieldEnum(Enum): OPTICAL_LINE_SYSTEM = 'optical-line-system' PACKET_ROUTER = 'packet-router' PACKET_SWITCH = 'packet-switch' P4_SWITCH = 'p4-switch' class FilterFieldEnum(Enum): DEVICE_TYPE = 'device_type' Loading src/device/service/drivers/__init__.py +7 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from ..driver_api.FilterFields import FilterFieldEnum, DeviceTypeFilterFieldEnum from .emulated.EmulatedDriver import EmulatedDriver from .openconfig.OpenConfigDriver import OpenConfigDriver from .transport_api.TransportApiDriver import TransportApiDriver from .p4.p4_driver import P4Driver DRIVERS = [ (EmulatedDriver, [ Loading @@ -22,4 +23,10 @@ DRIVERS = [ FilterFieldEnum.DRIVER : ORM_DeviceDriverEnum.TRANSPORT_API, } ]), (P4Driver, [ { FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.P4_SWITCH, FilterFieldEnum.DRIVER : ORM_DeviceDriverEnum.P4, } ]), ] src/device/service/drivers/p4/__init__.py 0 → 100644 +0 −0 Empty file added. src/device/service/drivers/p4/p4_driver.py 0 → 100644 +246 −0 Original line number Diff line number Diff line """ P4 driver plugin for the TeraFlow SDN controller. """ import logging import threading from typing import Any, Iterator, List, Optional, Tuple, Union from .p4_util import P4RuntimeClient,\ P4_ATTR_DEV_ID, P4_ATTR_DEV_NAME, P4_ATTR_DEV_VENDOR,\ P4_ATTR_DEV_HW_VER, P4_ATTR_DEV_SW_VER, P4_ATTR_DEV_PIPECONF,\ P4_VAL_DEF_VENDOR, P4_VAL_DEF_HW_VER, P4_VAL_DEF_SW_VER, P4_VAL_DEF_PIPECONF try: from _Driver import _Driver except ImportError: from device.service.driver_api._Driver import _Driver LOGGER = logging.getLogger(__name__) class P4Driver(_Driver): """ P4Driver class inherits the abstract _Driver class to support P4 devices. Attributes ---------- address : str IP address of the P4Runtime server running on the P4 device port : int transport port number of the P4Runtime server running on the P4 device **settings : map id : int P4 device ID (Mandatory) name : str P4 device name (Optional) vendor : str P4 device vendor (Optional) hw_ver : str Hardware version of the P4 device (Optional) sw_ver : str Software version of the P4 device (Optional) pipeconf : str P4 device table configuration (Optional) """ def __init__(self, address: str, port: int, **settings) -> None: # pylint: disable=super-init-not-called self.__client = None self.__address = address self.__port = int(port) self.__settings = settings try: self.__dev_id = self.__settings.get(P4_ATTR_DEV_ID) except Exception as ex: LOGGER.error('P4 device ID is a mandatory setting') raise Exception from ex if P4_ATTR_DEV_NAME in self.__settings: self.__dev_name = self.__settings.get(P4_ATTR_DEV_NAME) else: self.__dev_name = str(self.__dev_id) LOGGER.warning( 'No device name is provided. Setting default name: %s', self.__dev_name) if P4_ATTR_DEV_VENDOR in self.__settings: self.__dev_vendor = self.__settings.get(P4_ATTR_DEV_VENDOR) else: self.__dev_vendor = P4_VAL_DEF_VENDOR LOGGER.warning( 'No vendor is provided. Setting default vendor: %s', self.__dev_vendor) if P4_ATTR_DEV_HW_VER in self.__settings: self.__dev_hw_version = self.__settings.get(P4_ATTR_DEV_HW_VER) else: self.__dev_hw_version = P4_VAL_DEF_HW_VER LOGGER.warning( 'No HW version is provided. Setting default HW version: %s', self.__dev_hw_version) if P4_ATTR_DEV_SW_VER in self.__settings: self.__dev_sw_version = self.__settings.get(P4_ATTR_DEV_SW_VER) else: self.__dev_sw_version = P4_VAL_DEF_SW_VER LOGGER.warning( 'No SW version is provided. Setting default SW version: %s', self.__dev_sw_version) if P4_ATTR_DEV_PIPECONF in self.__settings: self.__dev_pipeconf = self.__settings.get(P4_ATTR_DEV_PIPECONF) else: self.__dev_pipeconf = P4_VAL_DEF_PIPECONF LOGGER.warning( 'No P4 pipeconf is provided. Setting default P4 pipeconf: %s', self.__dev_pipeconf) self.__lock = threading.Lock() self.__started = threading.Event() self.__terminate = threading.Event() LOGGER.info('Initializing P4 device at %s:%d with settings:', self.__address, self.__port) for key, value in settings.items(): LOGGER.info('\t%8s = %s', key, value) def Connect(self) -> bool: """ Establishes a connection between the P4 device driver and a P4 device. :return: boolean connection status. """ LOGGER.info( 'Connecting to P4 device %s:%d ...', self.__address, self.__port) with self.__lock: # Skip if already connected if self.__started.is_set(): return True # Instantiate a gRPC channel with the P4 device grpc_address = f'{self.__address}:{self.__port}' election_id = (1, 0) self.__client = P4RuntimeClient( self.__dev_id, grpc_address, election_id) LOGGER.info('\tConnected!') self.__started.set() return True def Disconnect(self) -> bool: """ Terminates the connection between the P4 device driver and a P4 device. :return: boolean disconnection status. """ LOGGER.info( 'Disconnecting from P4 device %s:%d ...', self.__address, self.__port) # If not started, assume it is already disconnected if not self.__started.is_set(): return True # gRPC client must already be instantiated assert self.__client # Trigger termination of loops and processes self.__terminate.set() # Trigger connection tear down with the P4Runtime server self.__client.tear_down() self.__client = None LOGGER.info('\tDisconnected!') return True def GetInitialConfig(self) -> List[Tuple[str, Any]]: """ Retrieves the initial configuration of a P4 device. :return: list of initial configuration items. """ LOGGER.info('P4 GetInitialConfig()') return [] def GetConfig(self, resource_keys : List[str] = [])\ -> List[Tuple[str, Union[Any, None, Exception]]]: """ Retrieves the current configuration of a P4 device. :param resource_keys: configuration parameters to retrieve. :return: list of values associated with the requested resource keys. """ LOGGER.info('P4 GetConfig()') return [] def SetConfig(self, resources : List[Tuple[str, Any]])\ -> List[Union[bool, Exception]]: """ Submits a new configuration to a P4 device. :param resources: configuration parameters to set. :return: list of results for resource key changes requested. """ LOGGER.info('P4 SetConfig()') return [] def DeleteConfig(self, resources : List[Tuple[str, Any]])\ -> List[Union[bool, Exception]]: """ Revokes P4 device configuration. :param resources: list of tuples with resource keys to be deleted. :return: list of results for resource key deletions requested. """ LOGGER.info('P4 DeleteConfig()') return [] def GetResource(self, endpoint_uuid : str) -> Optional[str]: """ Retrieves a certain resource from a P4 device. :param endpoint_uuid: target endpoint UUID. :return: The path of the endpoint or None if not found. """ LOGGER.info('P4 GetResource()') return "" def GetState(self, blocking=False) -> Iterator[Tuple[str, Any]]: """ Retrieves the state of a P4 device. :param blocking: if non-blocking, the driver terminates the loop and returns. :return: sequences of state sample. """ LOGGER.info('P4 GetState()') return [] def SubscribeState(self, subscriptions : List[Tuple[str, float, float]])\ -> List[Union[bool, Exception]]: """ Subscribes to certain state information. :param subscriptions: list of tuples with resources to be subscribed. :return: list of results for resource subscriptions requested. """ LOGGER.info('P4 SubscribeState()') return [] def UnsubscribeState(self, subscriptions : List[Tuple[str, float, float]])\ -> List[Union[bool, Exception]]: """ Unsubscribes from certain state information. :param subscriptions: list of tuples with resources to be unsubscribed. :return: list of results for resource un-subscriptions requested. """ LOGGER.info('P4 UnsubscribeState()') return [] Loading
src/device/requirements.in +1 −0 Original line number Diff line number Diff line Loading @@ -13,3 +13,4 @@ pytz redis requests xmltodict p4runtime==1.3.0
src/device/service/driver_api/FilterFields.py +1 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ class DeviceTypeFilterFieldEnum(Enum): OPTICAL_LINE_SYSTEM = 'optical-line-system' PACKET_ROUTER = 'packet-router' PACKET_SWITCH = 'packet-switch' P4_SWITCH = 'p4-switch' class FilterFieldEnum(Enum): DEVICE_TYPE = 'device_type' Loading
src/device/service/drivers/__init__.py +7 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from ..driver_api.FilterFields import FilterFieldEnum, DeviceTypeFilterFieldEnum from .emulated.EmulatedDriver import EmulatedDriver from .openconfig.OpenConfigDriver import OpenConfigDriver from .transport_api.TransportApiDriver import TransportApiDriver from .p4.p4_driver import P4Driver DRIVERS = [ (EmulatedDriver, [ Loading @@ -22,4 +23,10 @@ DRIVERS = [ FilterFieldEnum.DRIVER : ORM_DeviceDriverEnum.TRANSPORT_API, } ]), (P4Driver, [ { FilterFieldEnum.DEVICE_TYPE: DeviceTypeFilterFieldEnum.P4_SWITCH, FilterFieldEnum.DRIVER : ORM_DeviceDriverEnum.P4, } ]), ]
src/device/service/drivers/p4/p4_driver.py 0 → 100644 +246 −0 Original line number Diff line number Diff line """ P4 driver plugin for the TeraFlow SDN controller. """ import logging import threading from typing import Any, Iterator, List, Optional, Tuple, Union from .p4_util import P4RuntimeClient,\ P4_ATTR_DEV_ID, P4_ATTR_DEV_NAME, P4_ATTR_DEV_VENDOR,\ P4_ATTR_DEV_HW_VER, P4_ATTR_DEV_SW_VER, P4_ATTR_DEV_PIPECONF,\ P4_VAL_DEF_VENDOR, P4_VAL_DEF_HW_VER, P4_VAL_DEF_SW_VER, P4_VAL_DEF_PIPECONF try: from _Driver import _Driver except ImportError: from device.service.driver_api._Driver import _Driver LOGGER = logging.getLogger(__name__) class P4Driver(_Driver): """ P4Driver class inherits the abstract _Driver class to support P4 devices. Attributes ---------- address : str IP address of the P4Runtime server running on the P4 device port : int transport port number of the P4Runtime server running on the P4 device **settings : map id : int P4 device ID (Mandatory) name : str P4 device name (Optional) vendor : str P4 device vendor (Optional) hw_ver : str Hardware version of the P4 device (Optional) sw_ver : str Software version of the P4 device (Optional) pipeconf : str P4 device table configuration (Optional) """ def __init__(self, address: str, port: int, **settings) -> None: # pylint: disable=super-init-not-called self.__client = None self.__address = address self.__port = int(port) self.__settings = settings try: self.__dev_id = self.__settings.get(P4_ATTR_DEV_ID) except Exception as ex: LOGGER.error('P4 device ID is a mandatory setting') raise Exception from ex if P4_ATTR_DEV_NAME in self.__settings: self.__dev_name = self.__settings.get(P4_ATTR_DEV_NAME) else: self.__dev_name = str(self.__dev_id) LOGGER.warning( 'No device name is provided. Setting default name: %s', self.__dev_name) if P4_ATTR_DEV_VENDOR in self.__settings: self.__dev_vendor = self.__settings.get(P4_ATTR_DEV_VENDOR) else: self.__dev_vendor = P4_VAL_DEF_VENDOR LOGGER.warning( 'No vendor is provided. Setting default vendor: %s', self.__dev_vendor) if P4_ATTR_DEV_HW_VER in self.__settings: self.__dev_hw_version = self.__settings.get(P4_ATTR_DEV_HW_VER) else: self.__dev_hw_version = P4_VAL_DEF_HW_VER LOGGER.warning( 'No HW version is provided. Setting default HW version: %s', self.__dev_hw_version) if P4_ATTR_DEV_SW_VER in self.__settings: self.__dev_sw_version = self.__settings.get(P4_ATTR_DEV_SW_VER) else: self.__dev_sw_version = P4_VAL_DEF_SW_VER LOGGER.warning( 'No SW version is provided. Setting default SW version: %s', self.__dev_sw_version) if P4_ATTR_DEV_PIPECONF in self.__settings: self.__dev_pipeconf = self.__settings.get(P4_ATTR_DEV_PIPECONF) else: self.__dev_pipeconf = P4_VAL_DEF_PIPECONF LOGGER.warning( 'No P4 pipeconf is provided. Setting default P4 pipeconf: %s', self.__dev_pipeconf) self.__lock = threading.Lock() self.__started = threading.Event() self.__terminate = threading.Event() LOGGER.info('Initializing P4 device at %s:%d with settings:', self.__address, self.__port) for key, value in settings.items(): LOGGER.info('\t%8s = %s', key, value) def Connect(self) -> bool: """ Establishes a connection between the P4 device driver and a P4 device. :return: boolean connection status. """ LOGGER.info( 'Connecting to P4 device %s:%d ...', self.__address, self.__port) with self.__lock: # Skip if already connected if self.__started.is_set(): return True # Instantiate a gRPC channel with the P4 device grpc_address = f'{self.__address}:{self.__port}' election_id = (1, 0) self.__client = P4RuntimeClient( self.__dev_id, grpc_address, election_id) LOGGER.info('\tConnected!') self.__started.set() return True def Disconnect(self) -> bool: """ Terminates the connection between the P4 device driver and a P4 device. :return: boolean disconnection status. """ LOGGER.info( 'Disconnecting from P4 device %s:%d ...', self.__address, self.__port) # If not started, assume it is already disconnected if not self.__started.is_set(): return True # gRPC client must already be instantiated assert self.__client # Trigger termination of loops and processes self.__terminate.set() # Trigger connection tear down with the P4Runtime server self.__client.tear_down() self.__client = None LOGGER.info('\tDisconnected!') return True def GetInitialConfig(self) -> List[Tuple[str, Any]]: """ Retrieves the initial configuration of a P4 device. :return: list of initial configuration items. """ LOGGER.info('P4 GetInitialConfig()') return [] def GetConfig(self, resource_keys : List[str] = [])\ -> List[Tuple[str, Union[Any, None, Exception]]]: """ Retrieves the current configuration of a P4 device. :param resource_keys: configuration parameters to retrieve. :return: list of values associated with the requested resource keys. """ LOGGER.info('P4 GetConfig()') return [] def SetConfig(self, resources : List[Tuple[str, Any]])\ -> List[Union[bool, Exception]]: """ Submits a new configuration to a P4 device. :param resources: configuration parameters to set. :return: list of results for resource key changes requested. """ LOGGER.info('P4 SetConfig()') return [] def DeleteConfig(self, resources : List[Tuple[str, Any]])\ -> List[Union[bool, Exception]]: """ Revokes P4 device configuration. :param resources: list of tuples with resource keys to be deleted. :return: list of results for resource key deletions requested. """ LOGGER.info('P4 DeleteConfig()') return [] def GetResource(self, endpoint_uuid : str) -> Optional[str]: """ Retrieves a certain resource from a P4 device. :param endpoint_uuid: target endpoint UUID. :return: The path of the endpoint or None if not found. """ LOGGER.info('P4 GetResource()') return "" def GetState(self, blocking=False) -> Iterator[Tuple[str, Any]]: """ Retrieves the state of a P4 device. :param blocking: if non-blocking, the driver terminates the loop and returns. :return: sequences of state sample. """ LOGGER.info('P4 GetState()') return [] def SubscribeState(self, subscriptions : List[Tuple[str, float, float]])\ -> List[Union[bool, Exception]]: """ Subscribes to certain state information. :param subscriptions: list of tuples with resources to be subscribed. :return: list of results for resource subscriptions requested. """ LOGGER.info('P4 SubscribeState()') return [] def UnsubscribeState(self, subscriptions : List[Tuple[str, float, float]])\ -> List[Union[bool, Exception]]: """ Unsubscribes from certain state information. :param subscriptions: list of tuples with resources to be unsubscribed. :return: list of results for resource un-subscriptions requested. """ LOGGER.info('P4 UnsubscribeState()') return []