diff --git a/proto/context.proto b/proto/context.proto index 01e096233e364be8ad4e3810e7619e8f522e66e6..5b0ea4c75bad84a5d71ab0b2ea73b7ba2a69e09a 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -196,13 +196,13 @@ message Device { DeviceId controller_id = 9; // Identifier of node controlling the actual device } -message Component { //Defined previously to this section - Tested OK - Uuid component_uuid = 1; - string name = 2; - string type = 3; +message Component { // Defined previously in this section + Uuid component_uuid = 1; + string name = 2; + string type = 3; map<string, string> attributes = 4; // dict[attr.name => json.dumps(attr.value)] - string parent = 5; + string parent = 5; } message DeviceConfig { @@ -267,6 +267,7 @@ enum LinkTypeEnum { LINKTYPE_FIBER = 2; LINKTYPE_RADIO = 3; LINKTYPE_VIRTUAL = 4; + LINKTYPE_MANAGEMENT = 5; } message LinkAttributes { @@ -316,11 +317,14 @@ enum ServiceTypeEnum { SERVICETYPE_UNKNOWN = 0; SERVICETYPE_L3NM = 1; SERVICETYPE_L2NM = 2; - SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3; - SERVICETYPE_TE = 4; - SERVICETYPE_E2E = 5; - SERVICETYPE_OPTICAL_CONNECTIVITY = 6; - SERVICETYPE_QKD = 7; + SERVICETYPE_L1NM = 3; + SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 4; + SERVICETYPE_TE = 5; + SERVICETYPE_E2E = 6; + SERVICETYPE_OPTICAL_CONNECTIVITY = 7; + SERVICETYPE_QKD = 8; + SERVICETYPE_INT = 9; + SERVICETYPE_ACL = 10; } enum ServiceStatusEnum { diff --git a/src/common/type_checkers/Checkers.py b/src/common/type_checkers/Checkers.py index e1bbe3f06b75d0a1bfc5873019776b1517f50192..694f1410212137347badbba759cac1a64b1e1c92 100644 --- a/src/common/type_checkers/Checkers.py +++ b/src/common/type_checkers/Checkers.py @@ -13,6 +13,8 @@ # limitations under the License. import re +import ipaddress +from ctypes import c_uint16, sizeof from typing import Any, Container, Dict, List, Optional, Pattern, Set, Sized, Tuple, Union def chk_none(name : str, value : Any, reason=None) -> Any: @@ -107,3 +109,80 @@ def chk_options(name : str, value : Any, options : Container) -> Any: msg = '{}({}) is not one of options({}).' raise ValueError(msg.format(str(name), str(value), str(options))) return value + +# MAC address checker +mac_pattern = re.compile(r"^([\da-fA-F]{2}:){5}([\da-fA-F]{2})$") + +def chk_address_mac(mac_addr : str): + """ + Check whether input string is a valid MAC address or not. + + :param mac_addr: string-based MAC address + :return: boolean status + """ + return mac_pattern.match(mac_addr) is not None + +# IPv4/IPv6 address checkers +IPV4_LOCALHOST = "localhost" + +def chk_address_ipv4(ip_addr : str): + """ + Check whether input string is a valid IPv4 address or not. + + :param ip_addr: string-based IPv4 address + :return: boolean status + """ + if ip_addr == IPV4_LOCALHOST: + return True + try: + addr = ipaddress.ip_address(ip_addr) + return isinstance(addr, ipaddress.IPv4Address) + except ValueError: + return False + +def chk_address_ipv6(ip_addr : str): + """ + Check whether input string is a valid IPv6 address or not. + + :param ip_addr: string-based IPv6 address + :return: boolean status + """ + try: + addr = ipaddress.ip_address(ip_addr) + return isinstance(addr, ipaddress.IPv6Address) + except ValueError: + return False + + +# VLAN ID checker +VLAN_ID_MIN = 1 +VLAN_ID_MAX = 4094 + +def chk_vlan_id(vlan_id : int): + return VLAN_ID_MIN <= vlan_id <= VLAN_ID_MAX + + +# Transport port checker + +def limits(c_int_type): + """ + Discover limits of numerical type. + + :param c_int_type: numerical type + :return: tuple of numerical type's limits + """ + signed = c_int_type(-1).value < c_int_type(0).value + bit_size = sizeof(c_int_type) * 8 + signed_limit = 2 ** (bit_size - 1) + return (-signed_limit, signed_limit - 1) \ + if signed else (0, 2 * signed_limit - 1) + +def chk_transport_port(trans_port : int): + """ + Check whether input is a valid transport port number or not. + + :param trans_port: transport port number + :return: boolean status + """ + lim = limits(c_uint16) + return lim[0] <= trans_port <= lim[1] diff --git a/src/context/service/database/models/enums/LinkType.py b/src/context/service/database/models/enums/LinkType.py index 68624af845ea813aa5ca886de97861852a294516..97eacdd8b647869e9c1393770ad78aafea1152cc 100644 --- a/src/context/service/database/models/enums/LinkType.py +++ b/src/context/service/database/models/enums/LinkType.py @@ -18,15 +18,16 @@ from ._GrpcToEnum import grpc_to_enum # IMPORTANT: Entries of enum class ORM_LinkTypeEnum should be named as in # the proto files removing the prefixes. For example, proto item -# LinkTypeEnum.DEVICEDRIVER_COPPER should be included as COPPER. +# LinkTypeEnum.COPPER should be included as COPPER. # If item name does not match, automatic mapping of proto enums # to database enums will fail. class ORM_LinkTypeEnum(enum.Enum): - UNKNOWN = LinkTypeEnum.LINKTYPE_UNKNOWN - COPPER = LinkTypeEnum.LINKTYPE_COPPER - FIBER = LinkTypeEnum.LINKTYPE_FIBER - RADIO = LinkTypeEnum.LINKTYPE_RADIO - VIRTUAL = LinkTypeEnum.LINKTYPE_VIRTUAL + UNKNOWN = LinkTypeEnum.LINKTYPE_UNKNOWN + COPPER = LinkTypeEnum.LINKTYPE_COPPER + FIBER = LinkTypeEnum.LINKTYPE_FIBER + RADIO = LinkTypeEnum.LINKTYPE_RADIO + VIRTUAL = LinkTypeEnum.LINKTYPE_VIRTUAL + MANAGEMENT = LinkTypeEnum.LINKTYPE_MANAGEMENT grpc_to_enum__link_type_enum = functools.partial( grpc_to_enum, LinkTypeEnum, ORM_LinkTypeEnum diff --git a/src/context/service/database/models/enums/ServiceType.py b/src/context/service/database/models/enums/ServiceType.py index 45f849a2643a328284e200f1718b02191fab9563..899c71acf7bbf72379bf22de9d7badb04994155b 100644 --- a/src/context/service/database/models/enums/ServiceType.py +++ b/src/context/service/database/models/enums/ServiceType.py @@ -25,11 +25,14 @@ class ORM_ServiceTypeEnum(enum.Enum): UNKNOWN = ServiceTypeEnum.SERVICETYPE_UNKNOWN L3NM = ServiceTypeEnum.SERVICETYPE_L3NM L2NM = ServiceTypeEnum.SERVICETYPE_L2NM + L1NM = ServiceTypeEnum.SERVICETYPE_L1NM TAPI_CONNECTIVITY_SERVICE = ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE TE = ServiceTypeEnum.SERVICETYPE_TE E2E = ServiceTypeEnum.SERVICETYPE_E2E OPTICAL_CONNECTIVITY = ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY QKD = ServiceTypeEnum.SERVICETYPE_QKD + INT = ServiceTypeEnum.SERVICETYPE_INT + ACL = ServiceTypeEnum.SERVICETYPE_ACL grpc_to_enum__service_type = functools.partial( grpc_to_enum, ServiceTypeEnum, ORM_ServiceTypeEnum) diff --git a/src/device/service/drivers/p4/p4_common.py b/src/device/service/drivers/p4/p4_common.py index b55296a65922de93370a66301254cacf9ca7220a..b4c0d88323e7a2066c1cb73525edb6cca5b6af1a 100644 --- a/src/device/service/drivers/p4/p4_common.py +++ b/src/device/service/drivers/p4/p4_common.py @@ -23,16 +23,15 @@ as well as static variables used by various P4 driver components. """ import logging +import ipaddress +import macaddress import math -import re import socket -import ipaddress from typing import Any, Dict, List, Optional, Tuple -from ctypes import c_uint16, sizeof -import macaddress from common.type_checkers.Checkers import \ - chk_attribute, chk_string, chk_type, chk_issubclass + chk_attribute, chk_string, chk_type, chk_issubclass,\ + chk_address_mac, chk_address_ipv4, chk_address_ipv6 try: from .p4_exception import UserBadValueError except ImportError: @@ -60,17 +59,6 @@ LOGGER = logging.getLogger(__name__) # MAC address encoding/decoding -mac_pattern = re.compile(r"^([\da-fA-F]{2}:){5}([\da-fA-F]{2})$") - - -def matches_mac(mac_addr_string): - """ - Check whether input string is a valid MAC address or not. - - :param mac_addr_string: string-based MAC address - :return: boolean status - """ - return mac_pattern.match(mac_addr_string) is not None def encode_mac(mac_addr_string): @@ -94,23 +82,6 @@ def decode_mac(encoded_mac_addr): # IP address encoding/decoding -IPV4_LOCALHOST = "localhost" - - -def matches_ipv4(ip_addr_string): - """ - Check whether input string is a valid IPv4 address or not. - - :param ip_addr_string: string-based IPv4 address - :return: boolean status - """ - if ip_addr_string == IPV4_LOCALHOST: - return True - try: - addr = ipaddress.ip_address(ip_addr_string) - return isinstance(addr, ipaddress.IPv4Address) - except ValueError: - return False def encode_ipv4(ip_addr_string): @@ -133,20 +104,6 @@ def decode_ipv4(encoded_ip_addr): return socket.inet_ntoa(encoded_ip_addr) -def matches_ipv6(ip_addr_string): - """ - Check whether input string is a valid IPv6 address or not. - - :param ip_addr_string: string-based IPv6 address - :return: boolean status - """ - try: - addr = ipaddress.ip_address(ip_addr_string) - return isinstance(addr, ipaddress.IPv6Address) - except ValueError: - return False - - def encode_ipv6(ip_addr_string): """ Convert string-based IPv6 address into bytes. @@ -170,31 +127,6 @@ def decode_ipv6(encoded_ip_addr): # Numerical encoding/decoding -def limits(c_int_type): - """ - Discover limits of numerical type. - - :param c_int_type: numerical type - :return: tuple of numerical type's limits - """ - signed = c_int_type(-1).value < c_int_type(0).value - bit_size = sizeof(c_int_type) * 8 - signed_limit = 2 ** (bit_size - 1) - return (-signed_limit, signed_limit - 1) \ - if signed else (0, 2 * signed_limit - 1) - - -def valid_port(port): - """ - Check whether input is a valid port number or not. - - :param port: port number - :return: boolean status - """ - lim = limits(c_uint16) - return lim[0] <= port <= lim[1] - - def bitwidth_to_bytes(bitwidth): """ Convert number of bits to number of bytes. @@ -245,11 +177,11 @@ def encode(variable, bitwidth): if isinstance(variable, int): encoded_bytes = encode_num(variable, bitwidth) elif isinstance(variable, str): - if matches_mac(variable): + if chk_address_mac(variable): encoded_bytes = encode_mac(variable) - elif matches_ipv4(variable): + elif chk_address_ipv4(variable): encoded_bytes = encode_ipv4(variable) - elif matches_ipv6(variable): + elif chk_address_ipv6(variable): encoded_bytes = encode_ipv6(variable) else: try: @@ -471,7 +403,7 @@ def parse_integer_list_from_json(resource, resource_list, resource_item): return integers_list def process_optional_string_field( - #TODO: Consider adding this in common methdos as it is taken by the Emulated driver + #TODO: Consider adding this in common methods as it is taken by the Emulated driver endpoint_data : Dict[str, Any], field_name : str, endpoint_resource_value : Dict[str, Any] ) -> None: field_value = chk_attribute(field_name, endpoint_data, 'endpoint_data', default=None) diff --git a/src/device/service/drivers/p4/p4_driver.py b/src/device/service/drivers/p4/p4_driver.py index c89a42baddaf45737ebfcf26a665f0a6beb8544f..0b109529d49e51b61430da510b9b53942623df77 100644 --- a/src/device/service/drivers/p4/p4_driver.py +++ b/src/device/service/drivers/p4/p4_driver.py @@ -22,10 +22,10 @@ import logging import threading from typing import Any, Iterator, List, Optional, Tuple, Union from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method -from common.type_checkers.Checkers import chk_type, chk_length, chk_string +from common.type_checkers.Checkers import chk_type, chk_length, chk_string, \ + chk_address_ipv4, chk_address_ipv6, chk_transport_port from device.service.driver_api._Driver import RESOURCE_ENDPOINTS, RESOURCE_RULES -from .p4_common import matches_ipv4, matches_ipv6, valid_port,\ - compose_resource_endpoints, parse_resource_string_from_json,\ +from .p4_common import compose_resource_endpoints,\ P4_ATTR_DEV_ID, P4_ATTR_DEV_NAME, P4_ATTR_DEV_ENDPOINTS,\ P4_ATTR_DEV_VENDOR, P4_ATTR_DEV_HW_VER, P4_ATTR_DEV_SW_VER,\ P4_ATTR_DEV_P4BIN, P4_ATTR_DEV_P4INFO, P4_ATTR_DEV_TIMEOUT,\ @@ -336,9 +336,9 @@ class P4Driver(_Driver): :return: void or exception in case of validation error """ # Device endpoint information - assert matches_ipv4(self.__address) or (matches_ipv6(self.__address)),\ + assert chk_address_ipv4(self.__address) or (chk_address_ipv6(self.__address)),\ f"{self.__address} not a valid IPv4 or IPv6 address" - assert valid_port(self.__port), \ + assert chk_transport_port(self.__port), \ f"{self.__port} not a valid transport port" self.__grpc_endpoint = f"{self.__address}:{self.__port}" @@ -395,18 +395,24 @@ class P4Driver(_Driver): # Path to P4 binary file if P4_ATTR_DEV_P4BIN in self.__settings: self.__p4bin_path = self.__settings.get(P4_ATTR_DEV_P4BIN) - assert os.path.exists(self.__p4bin_path),\ - "Invalid path to p4bin file: {}".format(self.__p4bin_path) - assert P4_ATTR_DEV_P4INFO in self.__settings,\ - "p4info and p4bin settings must be provided together" + if not os.path.exists(self.__p4bin_path): + LOGGER.warning( + "Invalid path to p4bin file: {}".format(self.__p4bin_path)) + self.__p4bin_path = "" + else: + assert P4_ATTR_DEV_P4INFO in self.__settings,\ + "p4info and p4bin settings must be provided together" # Path to P4 info file if P4_ATTR_DEV_P4INFO in self.__settings: self.__p4info_path = self.__settings.get(P4_ATTR_DEV_P4INFO) - assert os.path.exists(self.__p4info_path),\ - "Invalid path to p4info file: {}".format(self.__p4info_path) - assert P4_ATTR_DEV_P4BIN in self.__settings,\ - "p4info and p4bin settings must be provided together" + if not os.path.exists(self.__p4info_path): + LOGGER.warning( + "Invalid path to p4info file: {}".format(self.__p4info_path)) + self.__p4info_path = "" + else: + assert P4_ATTR_DEV_P4BIN in self.__settings,\ + "p4info and p4bin settings must be provided together" if (not self.__p4bin_path) or (not self.__p4info_path): LOGGER.warning( diff --git a/src/device/tests/test_internal_p4.py b/src/device/tests/test_internal_p4.py index af99bb86be2dba91cf71cf9a6822fdf0b6acb613..48501bfd81eeb2f47a8593e1d786fdc341e4f4c0 100644 --- a/src/device/tests/test_internal_p4.py +++ b/src/device/tests/test_internal_p4.py @@ -17,11 +17,13 @@ Internal P4 driver tests. """ import pytest +from common.type_checkers.Checkers import chk_address_mac, \ + chk_address_ipv4, chk_address_ipv6 from device.service.drivers.p4.p4_driver import P4Driver from device.service.drivers.p4.p4_common import ( - matches_mac, encode_mac, decode_mac, encode, - matches_ipv4, encode_ipv4, decode_ipv4, - matches_ipv6, encode_ipv6, decode_ipv6, + encode_mac, decode_mac, encode, + encode_ipv4, decode_ipv4, + encode_ipv6, decode_ipv6, encode_num, decode_num ) from .device_p4 import( @@ -172,10 +174,10 @@ def test_p4_common_mac(): :return: void """ wrong_mac = "aa:bb:cc:dd:ee" - assert not matches_mac(wrong_mac) + assert not chk_address_mac(wrong_mac) mac = "aa:bb:cc:dd:ee:fe" - assert matches_mac(mac) + assert chk_address_mac(mac) enc_mac = encode_mac(mac) assert enc_mac == b'\xaa\xbb\xcc\xdd\xee\xfe',\ "String-based MAC address to bytes failed" @@ -193,13 +195,13 @@ def test_p4_common_ipv4(): :return: void """ - assert not matches_ipv4("10.0.0.1.5") - assert not matches_ipv4("256.0.0.1") - assert not matches_ipv4("256.0.1") - assert not matches_ipv4("10001") + assert not chk_address_ipv4("10.0.0.1.5") + assert not chk_address_ipv4("256.0.0.1") + assert not chk_address_ipv4("256.0.1") + assert not chk_address_ipv4("10001") ipv4 = "10.0.0.1" - assert matches_ipv4(ipv4) + assert chk_address_ipv4(ipv4) enc_ipv4 = encode_ipv4(ipv4) assert enc_ipv4 == b'\x0a\x00\x00\x01',\ "String-based IPv4 address to bytes failed" @@ -214,11 +216,11 @@ def test_p4_common_ipv6(): :return: void """ - assert not matches_ipv6('10.0.0.1') - assert matches_ipv6('2001:0000:85a3::8a2e:370:1111') + assert not chk_address_ipv6('10.0.0.1') + assert chk_address_ipv6('2001:0000:85a3::8a2e:370:1111') ipv6 = "1:2:3:4:5:6:7:8" - assert matches_ipv6(ipv6) + assert chk_address_ipv6(ipv6) enc_ipv6 = encode_ipv6(ipv6) assert enc_ipv6 == \ b'\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08',\ diff --git a/src/service/service/service_handler_api/FilterFields.py b/src/service/service/service_handler_api/FilterFields.py index e47fd635f0c02667a052ebb9cff0569496c5fbec..b471497cbc9f3a05078977d4d46d9bc60a219c81 100644 --- a/src/service/service/service_handler_api/FilterFields.py +++ b/src/service/service/service_handler_api/FilterFields.py @@ -23,11 +23,14 @@ SERVICE_TYPE_VALUES = { ServiceTypeEnum.SERVICETYPE_UNKNOWN, ServiceTypeEnum.SERVICETYPE_L3NM, ServiceTypeEnum.SERVICETYPE_L2NM, + ServiceTypeEnum.SERVICETYPE_L1NM, ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, ServiceTypeEnum.SERVICETYPE_TE, ServiceTypeEnum.SERVICETYPE_E2E, ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY, ServiceTypeEnum.SERVICETYPE_QKD, + ServiceTypeEnum.SERVICETYPE_INT, + ServiceTypeEnum.SERVICETYPE_ACL, } DEVICE_DRIVER_VALUES = { diff --git a/src/service/service/service_handlers/__init__.py b/src/service/service/service_handlers/__init__.py index 85545d238f2b93bd77b1beb1fce2d46b01b06800..ccf821b2feb4fe615babdc72c8b505e6c0a6b4b2 100644 --- a/src/service/service/service_handlers/__init__.py +++ b/src/service/service/service_handlers/__init__.py @@ -25,7 +25,7 @@ from .l3nm_ietf_actn.L3NMIetfActnServiceHandler import L3NMIetfActnServiceHandle from .l3nm_nce.L3NMNCEServiceHandler import L3NMNCEServiceHandler from .l3slice_ietfslice.L3SliceIETFSliceServiceHandler import L3NMSliceIETFSliceServiceHandler from .microwave.MicrowaveServiceHandler import MicrowaveServiceHandler -from .p4.p4_service_handler import P4ServiceHandler +from .p4_l1.p4_l1_service_handler import P4L1ServiceHandler from .tapi_tapi.TapiServiceHandler import TapiServiceHandler from .tapi_xr.TapiXrServiceHandler import TapiXrServiceHandler from .e2e_orch.E2EOrchestratorServiceHandler import E2EOrchestratorServiceHandler @@ -105,9 +105,9 @@ SERVICE_HANDLERS = [ FilterFieldEnum.DEVICE_DRIVER : [DeviceDriverEnum.DEVICEDRIVER_IETF_NETWORK_TOPOLOGY, DeviceDriverEnum.DEVICEDRIVER_ONF_TR_532], } ]), - (P4ServiceHandler, [ + (P4L1ServiceHandler, [ { - FilterFieldEnum.SERVICE_TYPE: ServiceTypeEnum.SERVICETYPE_L2NM, + FilterFieldEnum.SERVICE_TYPE: ServiceTypeEnum.SERVICETYPE_L1NM, FilterFieldEnum.DEVICE_DRIVER: DeviceDriverEnum.DEVICEDRIVER_P4, } ]), diff --git a/src/service/service/service_handlers/p4/__init__.py b/src/service/service/service_handlers/p4_l1/__init__.py similarity index 100% rename from src/service/service/service_handlers/p4/__init__.py rename to src/service/service/service_handlers/p4_l1/__init__.py diff --git a/src/service/service/service_handlers/p4/p4_service_handler.py b/src/service/service/service_handlers/p4_l1/p4_l1_service_handler.py similarity index 95% rename from src/service/service/service_handlers/p4/p4_service_handler.py rename to src/service/service/service_handlers/p4_l1/p4_l1_service_handler.py index 49bedbb22f0c9ea18cf3e3b2c8444bd1c956f4ff..b1ff9c600bf995bab250144c288d45d6a7945474 100644 --- a/src/service/service/service_handlers/p4/p4_service_handler.py +++ b/src/service/service/service_handlers/p4_l1/p4_l1_service_handler.py @@ -13,7 +13,8 @@ # limitations under the License. """ -P4 service handler for the TeraFlowSDN controller. +P4 service handler for L1 connectivity services +(in-port to out-port or input endpoint to output endpoint). """ import logging @@ -28,7 +29,7 @@ from service.service.task_scheduler.TaskExecutor import TaskExecutor LOGGER = logging.getLogger(__name__) -METRICS_POOL = MetricsPool('Service', 'Handler', labels={'handler': 'p4'}) +METRICS_POOL = MetricsPool('Service', 'Handler', labels={'handler': 'p4_l1'}) def create_rule_set(endpoint_a, endpoint_b): return json_config_rule_set( @@ -79,14 +80,13 @@ def find_names(uuid_a, uuid_b, device_endpoints): endpoint_a = endpoint.name elif endpoint.endpoint_id.endpoint_uuid.uuid == uuid_b: endpoint_b = endpoint.name - + return (endpoint_a, endpoint_b) -class P4ServiceHandler(_ServiceHandler): - def __init__(self, - service: Service, - task_executor : TaskExecutor, - **settings) -> None: +class P4L1ServiceHandler(_ServiceHandler): + def __init__( # pylint: disable=super-init-not-called + self, service : Service, task_executor : TaskExecutor, **settings + ) -> None: """ Initialize Driver. Parameters: service @@ -106,7 +106,7 @@ class P4ServiceHandler(_ServiceHandler): self, endpoints : List[Tuple[str, str, Optional[str]]], connection_uuid : Optional[str] = None ) -> List[Union[bool, Exception]]: - """ Create/Update service endpoints form a list. + """ Create/Update service endpoints from a list. Parameters: endpoints: List[Tuple[str, str, Optional[str]]] List of tuples, each containing a device_uuid, @@ -126,21 +126,21 @@ class P4ServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid + LOGGER.info("SetEndpoint - Service {}".format(service_uuid)) history = {} - results = [] index = {} i = 0 - for endpoint in endpoints: + for endpoint in endpoints: device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now - if device_uuid in history: + if device_uuid in history: try: matched_endpoint_uuid = history.pop(device_uuid) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) del device.device_config.config_rules[:] - + # Find names from uuids (endpoint_a, endpoint_b) = find_names(matched_endpoint_uuid, endpoint_uuid, device.device_endpoints) if endpoint_a is None: @@ -151,14 +151,14 @@ class P4ServiceHandler(_ServiceHandler): raise Exception('Unable to find name of endpoint({:s})'.format(str(endpoint_uuid))) # One way - rule = create_rule_set(endpoint_a, endpoint_b) + rule = create_rule_set(endpoint_a, endpoint_b) device.device_config.config_rules.append(ConfigRule(**rule)) # The other way - rule = create_rule_set(endpoint_b, endpoint_a) + rule = create_rule_set(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) - + results.append(True) results[index[device_uuid]] = True except Exception as e: @@ -177,7 +177,7 @@ class P4ServiceHandler(_ServiceHandler): self, endpoints : List[Tuple[str, str, Optional[str]]], connection_uuid : Optional[str] = None ) -> List[Union[bool, Exception]]: - """ Delete service endpoints form a list. + """ Delete service endpoints from a list. Parameters: endpoints: List[Tuple[str, str, Optional[str]]] List of tuples, each containing a device_uuid, @@ -197,15 +197,15 @@ class P4ServiceHandler(_ServiceHandler): if len(endpoints) == 0: return [] service_uuid = self.__service.service_id.service_uuid.uuid + LOGGER.info("DeleteEndpoint - Service {}".format(service_uuid)) history = {} - results = [] index = {} i = 0 - for endpoint in endpoints: + for endpoint in endpoints: device_uuid, endpoint_uuid = endpoint[0:2] # ignore topology_uuid by now - if device_uuid in history: + if device_uuid in history: try: matched_endpoint_uuid = history.pop(device_uuid) device = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid))) @@ -222,14 +222,14 @@ class P4ServiceHandler(_ServiceHandler): raise Exception('Unable to find name of endpoint({:s})'.format(str(endpoint_uuid))) # One way - rule = create_rule_del(endpoint_a, endpoint_b) + rule = create_rule_del(endpoint_a, endpoint_b) device.device_config.config_rules.append(ConfigRule(**rule)) # The other way - rule = create_rule_del(endpoint_b, endpoint_a) + rule = create_rule_del(endpoint_b, endpoint_a) device.device_config.config_rules.append(ConfigRule(**rule)) self.__task_executor.configure_device(device) - + results.append(True) results[index[device_uuid]] = True except Exception as e: @@ -338,4 +338,4 @@ class P4ServiceHandler(_ServiceHandler): msg = '[SetConfig] Method not implemented. Resources({:s}) are being ignored.' LOGGER.warning(msg.format(str(resources))) - return [True for _ in range(len(resources))] \ No newline at end of file + return [True for _ in range(len(resources))] diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-acl.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-acl.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-acl.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-acl.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b1.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b1.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b1.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b1.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b2.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b2.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b2.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b2.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b3.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b3.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-int-b3.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-int-b3.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-routing-corp.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-routing-corp.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-routing-corp.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-routing-corp.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-insert-routing-edge.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-routing-edge.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-insert-routing-edge.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-insert-routing-edge.json diff --git a/src/tests/p4-int-routing-acl/descriptors/rules-remove.json b/src/tests/p4-int-routing-acl/descriptors/sbi-rules-remove.json similarity index 100% rename from src/tests/p4-int-routing-acl/descriptors/rules-remove.json rename to src/tests/p4-int-routing-acl/descriptors/sbi-rules-remove.json diff --git a/src/tests/p4-int-routing-acl/descriptors/topology.json b/src/tests/p4-int-routing-acl/descriptors/topology.json index 3b1f6e410cc5a2adc1c99b6208523fd9a9971fe7..30e1f5e9a767310f532f7a20174a20ad14ce8d3d 100644 --- a/src/tests/p4-int-routing-acl/descriptors/topology.json +++ b/src/tests/p4-int-routing-acl/descriptors/topology.json @@ -1,287 +1,113 @@ { "contexts": [ - { - "context_id": { - "context_uuid": { - "uuid": "admin" - } - } - } + {"context_id": {"context_uuid": {"uuid": "admin"}}} ], "topologies": [ - { - "topology_id": { - "context_id": { - "context_uuid": { - "uuid": "admin" - } - }, - "topology_uuid": { - "uuid": "admin" - } - } + {"topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} } ], "devices": [ { - "device_id": { - "device_uuid": { - "uuid": "edge-net" - } - }, + "device_id": {"device_uuid": {"uuid": "tfs-sdn-controller"}}, + "name": "tfs-sdn-controller", + "device_type": "teraflowsdn", + "device_drivers": ["DEVICEDRIVER_IETF_L3VPN"], + "device_operational_status": "DEVICEOPERATIONALSTATUS_UNDEFINED", + "device_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "10.10.10.41"}}, + {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "8002"}}, + {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": { + "endpoints": [{"uuid": "mgmt", "name": "mgmt", "type": "mgmt-int"}], + "scheme": "http", "username": "admin", "password": "admin", "import_topology": "topology" + }}} + ]} + }, + { + "device_id": {"device_uuid": {"uuid": "edge-net"}}, "device_type": "network", - "device_drivers": [ - "DEVICEDRIVER_UNDEFINED" - ], + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], "device_config": { "config_rules": [ - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/address", - "resource_value": "127.0.0.1" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/port", - "resource_value": "0" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/settings", - "resource_value": { - "endpoints": [ - { - "uuid": "eth1", - "type": "copper" - } - ] - } - } - } + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "endpoints": [{"uuid": "eth1", "name": "eth1", "type": "copper"}] + }}} ] } }, { - "device_id": { - "device_uuid": { - "uuid": "corporate-net" - } - }, + "device_id": {"device_uuid": {"uuid": "corporate-net"}}, "device_type": "network", - "device_drivers": [ - "DEVICEDRIVER_UNDEFINED" - ], + "device_drivers": ["DEVICEDRIVER_UNDEFINED"], "device_config": { "config_rules": [ - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/address", - "resource_value": "127.0.0.1" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/port", - "resource_value": "0" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/settings", - "resource_value": { - "endpoints": [ - { - "uuid": "eth1", - "type": "copper" - } - ] - } - } - } + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "0"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "endpoints": [{"uuid": "eth1", "name": "eth1", "type": "copper"}] + }}} ] } }, { - "device_id": { - "device_uuid": { - "uuid": "p4-sw1" - } - }, + "device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "device_type": "p4-switch", - "device_drivers": [ - "DEVICEDRIVER_P4" - ], + "device_drivers": ["DEVICEDRIVER_P4"], "device_operational_status": "DEVICEOPERATIONALSTATUS_DISABLED", "name": "p4-sw1", "device_config": { "config_rules": [ - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/address", - "resource_value": "10.10.10.120" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/port", - "resource_value": "50001" - } - }, - { - "action": "CONFIGACTION_SET", - "custom": { - "resource_key": "_connect/settings", - "resource_value": { - "id": 1, - "name": "p4-sw1", - "vendor": "Open Networking Foundation", - "hw_ver": "BMv2 simple_switch", - "sw_ver": "Stratum", - "p4bin": "/root/p4/bmv2.json", - "p4info": "/root/p4/p4info.txt", - "timeout": 60, - "endpoints": [ - { - "uuid": "1", - "type": "port" - }, - { - "uuid": "2", - "type": "port" - } - ] - } - } - } + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/address", "resource_value": "10.10.10.120"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/port", "resource_value": "50001"}}, + {"action": "CONFIGACTION_SET", "custom": {"resource_key": "_connect/settings", "resource_value": { + "id": 1, + "name": "p4-sw1", + "vendor": "Open Networking Foundation", + "hw_ver": "BMv2 simple_switch", + "sw_ver": "Stratum", + "timeout": 60, + "p4bin": "/root/p4/bmv2.json", + "p4info": "/root/p4/p4info.txt", + "endpoints": [ + {"uuid": "1", "name": "1", "type": "port-dataplane"}, + {"uuid": "2", "name": "2", "type": "port-dataplane"}, + {"uuid": "3", "name": "3", "type": "port-int"} + ] + }}} ] } } ], "links": [ { - "link_id": { - "link_uuid": { - "uuid": "p4-sw1/1==edge-net/eth1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "p4-sw1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "edge-net" - } - }, - "endpoint_uuid": { - "uuid": "eth1" - } - } + "link_id": {"link_uuid": {"uuid": "p4-sw1/1==edge-net/eth1"}}, "link_type": "LINKTYPE_VIRTUAL", "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "endpoint_uuid": {"uuid": "1"}}, + {"device_id": {"device_uuid": {"uuid": "edge-net"}}, "endpoint_uuid": {"uuid": "eth1"}} + ] + }, + { + "link_id": {"link_uuid": {"uuid": "edge-net/eth1==p4-sw1/1"}}, "link_type": "LINKTYPE_VIRTUAL", "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "edge-net"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "endpoint_uuid": {"uuid": "1"}} ] }, { - "link_id": { - "link_uuid": { - "uuid": "edge-net/eth1==p4-sw1/1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "edge-net" - } - }, - "endpoint_uuid": { - "uuid": "eth1" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "p4-sw1" - } - }, - "endpoint_uuid": { - "uuid": "1" - } - } + "link_id": {"link_uuid": {"uuid": "p4-sw1/2==corporate-net/eth1"}}, "link_type": "LINKTYPE_VIRTUAL", "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "endpoint_uuid": {"uuid": "2"}}, + {"device_id": {"device_uuid": {"uuid": "corporate-net"}}, "endpoint_uuid": {"uuid": "eth1"}} ] }, { - "link_id": { - "link_uuid": { - "uuid": "p4-sw1/2==corporate-net/eth1" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "p4-sw1" - } - }, - "endpoint_uuid": { - "uuid": "2" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "corporate-net" - } - }, - "endpoint_uuid": { - "uuid": "eth1" - } - } + "link_id": {"link_uuid": {"uuid": "corporate-net/eth1==p4-sw1/2"}}, "link_type": "LINKTYPE_VIRTUAL", "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "corporate-net"}}, "endpoint_uuid": {"uuid": "eth1"}}, + {"device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "endpoint_uuid": {"uuid": "2"}} ] }, { - "link_id": { - "link_uuid": { - "uuid": "corporate-net/eth1==p4-sw1/2" - } - }, - "link_endpoint_ids": [ - { - "device_id": { - "device_uuid": { - "uuid": "corporate-net" - } - }, - "endpoint_uuid": { - "uuid": "eth1" - } - }, - { - "device_id": { - "device_uuid": { - "uuid": "p4-sw1" - } - }, - "endpoint_uuid": { - "uuid": "2" - } - } + "link_id": {"link_uuid": {"uuid": "p4-sw1/3==tfs-sdn-controller/mgmt"}}, "link_type": "LINKTYPE_MANAGEMENT", "link_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "p4-sw1"}}, "endpoint_uuid": {"uuid": "3"}}, + {"device_id": {"device_uuid": {"uuid": "tfs-sdn-controller"}}, "endpoint_uuid": {"uuid": "mgmt"}} ] } ] diff --git a/src/tests/p4-int-routing-acl/run_test_02_rules_provision.sh b/src/tests/p4-int-routing-acl/run_test_02_sbi_rules_provision.sh similarity index 95% rename from src/tests/p4-int-routing-acl/run_test_02_rules_provision.sh rename to src/tests/p4-int-routing-acl/run_test_02_sbi_rules_provision.sh index 6709d66c62cae11ecc1e555bae81c680dfeaafc8..7c485d4019f45286ffc3909fcdd72278842afa3c 100755 --- a/src/tests/p4-int-routing-acl/run_test_02_rules_provision.sh +++ b/src/tests/p4-int-routing-acl/run_test_02_sbi_rules_provision.sh @@ -14,4 +14,4 @@ # limitations under the License. source tfs_runtime_env_vars.sh -python3 -m pytest --verbose src/tests/p4-int-routing-acl/test_functional_rules_provision.py +python3 -m pytest --verbose src/tests/p4-int-routing-acl/test_functional_sbi_rules_provision.py diff --git a/src/tests/p4-int-routing-acl/run_test_03_rules_deprovision.sh b/src/tests/p4-int-routing-acl/run_test_03_sbi_rules_deprovision.sh similarity index 95% rename from src/tests/p4-int-routing-acl/run_test_03_rules_deprovision.sh rename to src/tests/p4-int-routing-acl/run_test_03_sbi_rules_deprovision.sh index 3a67fad8a04520bc48c666b48d684b5ad7fe3d13..4032c01dfbfe5666c1f825b8f778461f88a62026 100755 --- a/src/tests/p4-int-routing-acl/run_test_03_rules_deprovision.sh +++ b/src/tests/p4-int-routing-acl/run_test_03_sbi_rules_deprovision.sh @@ -14,4 +14,4 @@ # limitations under the License. source tfs_runtime_env_vars.sh -python3 -m pytest --verbose src/tests/p4-int-routing-acl/test_functional_rules_deprovision.py +python3 -m pytest --verbose src/tests/p4-int-routing-acl/test_functional_sbi_rules_deprovision.py diff --git a/src/tests/p4-int-routing-acl/run_test_04_cleanup.sh b/src/tests/p4-int-routing-acl/run_test_06_cleanup.sh similarity index 100% rename from src/tests/p4-int-routing-acl/run_test_04_cleanup.sh rename to src/tests/p4-int-routing-acl/run_test_06_cleanup.sh diff --git a/src/tests/p4-int-routing-acl/test_common.py b/src/tests/p4-int-routing-acl/test_common.py index 8254eddc5bb5f2f2bbf4c0866a9409552872b2c8..f2d00f1dc01815d3567fd371f65f35f1bf078209 100644 --- a/src/tests/p4-int-routing-acl/test_common.py +++ b/src/tests/p4-int-routing-acl/test_common.py @@ -22,9 +22,9 @@ CONTEXT_NAME_P4 = DEFAULT_CONTEXT_NAME ADMIN_CONTEXT_ID = ContextId(**json_context_id(CONTEXT_NAME_P4)) # Device and rule cardinality variables -DEV_NB = 3 +DEV_NB = 4 CONNECTION_RULES = 3 -ENDPOINT_RULES = 2 +ENDPOINT_RULES = 3 DATAPLANE_RULES_NB_INT_B1 = 5 DATAPLANE_RULES_NB_INT_B2 = 6 DATAPLANE_RULES_NB_INT_B3 = 8 @@ -39,6 +39,11 @@ DATAPLANE_RULES_NB_TOT = \ DATAPLANE_RULES_NB_RT_CORP +\ DATAPLANE_RULES_NB_ACL +# Service-related variables +SVC_NB = 1 +NO_SERVICES = 0 +NO_SLICES = 0 + # Topology descriptor DESC_TOPO = os.path.join( os.path.dirname( @@ -47,51 +52,51 @@ DESC_TOPO = os.path.join( 'descriptors', 'topology.json' ) -# Rule insertion descriptors +# SBI rule insertion descriptors # The switch cannot digest all rules at once, hence we insert in batches DESC_FILE_RULES_INSERT_INT_B1 = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-int-b1.json' + 'descriptors', 'sbi-rules-insert-int-b1.json' ) DESC_FILE_RULES_INSERT_INT_B2 = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-int-b2.json' + 'descriptors', 'sbi-rules-insert-int-b2.json' ) DESC_FILE_RULES_INSERT_INT_B3 = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-int-b3.json' + 'descriptors', 'sbi-rules-insert-int-b3.json' ) DESC_FILE_RULES_INSERT_ROUTING_EDGE = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-routing-edge.json' + 'descriptors', 'sbi-rules-insert-routing-edge.json' ) DESC_FILE_RULES_INSERT_ROUTING_CORP = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-routing-corp.json' + 'descriptors', 'sbi-rules-insert-routing-corp.json' ) DESC_FILE_RULES_INSERT_ACL = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-insert-acl.json' + 'descriptors', 'sbi-rules-insert-acl.json' ) -# Rule deletion descriptor +# SBI rule deletion descriptor DESC_FILE_RULES_DELETE_ALL = os.path.join( os.path.dirname( os.path.abspath(__file__) ), - 'descriptors', 'rules-remove.json' + 'descriptors', 'sbi-rules-remove.json' ) def verify_number_of_rules(devices, desired_rules_nb): diff --git a/src/tests/p4-int-routing-acl/test_functional_cleanup.py b/src/tests/p4-int-routing-acl/test_functional_cleanup.py index 60c8684b098aa886fdd62db28a07a2d5c8adc125..fc29be24d5bdc643cb15f09eb69fe288c965687e 100644 --- a/src/tests/p4-int-routing-acl/test_functional_cleanup.py +++ b/src/tests/p4-int-routing-acl/test_functional_cleanup.py @@ -14,7 +14,6 @@ import logging, os from common.Constants import DEFAULT_CONTEXT_NAME -from common.proto.context_pb2 import ContextId from common.tools.descriptor.Loader import DescriptorLoader, validate_empty_scenario from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient diff --git a/src/tests/p4-int-routing-acl/test_functional_rules_deprovision.py b/src/tests/p4-int-routing-acl/test_functional_sbi_rules_deprovision.py similarity index 100% rename from src/tests/p4-int-routing-acl/test_functional_rules_deprovision.py rename to src/tests/p4-int-routing-acl/test_functional_sbi_rules_deprovision.py diff --git a/src/tests/p4-int-routing-acl/test_functional_rules_provision.py b/src/tests/p4-int-routing-acl/test_functional_sbi_rules_provision.py similarity index 100% rename from src/tests/p4-int-routing-acl/test_functional_rules_provision.py rename to src/tests/p4-int-routing-acl/test_functional_sbi_rules_provision.py diff --git a/src/webui/service/static/topology_icons/p4-switch.png b/src/webui/service/static/topology_icons/p4-switch.png index 9afcda1c0e38cb5757574024f1a3f96001b03943..178943d67e0b0a1e501d27b32a5356d8afdd4e56 100644 Binary files a/src/webui/service/static/topology_icons/p4-switch.png and b/src/webui/service/static/topology_icons/p4-switch.png differ