diff --git a/src/service/service/service_handlers/l3slice_ietfslice/ConfigRules.py b/src/service/service/service_handlers/l3slice_ietfslice/ConfigRules.py index e720f33bb9b9e527f9502b82ca5613cfececa5fd..466c53fe4b576f794091112f9c5958f2e17d5fca 100644 --- a/src/service/service/service_handlers/l3slice_ietfslice/ConfigRules.py +++ b/src/service/service/service_handlers/l3slice_ietfslice/ConfigRules.py @@ -33,6 +33,11 @@ def setup_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]: src_source_tcp_port: str = json_settings["src_source_tcp_port"] src_destination_ip_prefix: str = json_settings["src_destination_ip_prefix"] src_destination_tcp_port: str = json_settings["src_destination_tcp_port"] + source_one_way_delay: int = int(json_settings["source_one_way_delay"]) + source_one_way_bandwidth: int = int(json_settings["source_one_way_bandwidth"]) + source_one_way_packet_loss: float = float( + json_settings["source_one_way_packet_loss"] + ) dst_node_id: str = json_settings["dst_node_id"] dst_mgmt_ip_address: str = json_settings["dst_mgmt_ip_address"] dst_ac_node_id: str = json_settings["dst_ac_node_id"] @@ -42,10 +47,14 @@ def setup_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]: dst_source_tcp_port: str = json_settings["dst_source_tcp_port"] dst_destination_ip_prefix: str = json_settings["dst_destination_ip_prefix"] dst_destination_tcp_port: str = json_settings["dst_destination_tcp_port"] + destination_one_way_delay: int = int(json_settings["destination_one_way_delay"]) + destination_one_way_bandwidth: int = int( + json_settings["destination_one_way_bandwidth"] + ) + destination_one_way_packet_loss: float = float( + json_settings["destination_one_way_packet_loss"] + ) slice_id: str = json_settings["slice_id"] - delay: str = int(json_settings["delay"]) - bandwidth: str = int(json_settings["bandwidth"]) - packet_loss: str = float(json_settings["packet_loss"]) sdps = [ { @@ -155,17 +164,17 @@ def setup_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]: { "metric-type": "ietf-network-slice-service:one-way-delay-maximum", "metric-unit": "milliseconds", - "bound": delay, + "bound": source_one_way_delay, }, { "metric-type": "ietf-network-slice-service:one-way-bandwidth", "metric-unit": "Mbps", - "bound": bandwidth, + "bound": source_one_way_bandwidth, }, { "metric-type": "ietf-network-slice-service:two-way-packet-loss", "metric-unit": "percentage", - "percentile-value": packet_loss, + "percentile-value": source_one_way_packet_loss, }, ] } @@ -181,17 +190,17 @@ def setup_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]: { "metric-type": "ietf-network-slice-service:one-way-delay-maximum", "metric-unit": "milliseconds", - "bound": delay, + "bound": destination_one_way_delay, }, { "metric-type": "ietf-network-slice-service:one-way-bandwidth", "metric-unit": "Mbps", - "bound": bandwidth, + "bound": destination_one_way_bandwidth, }, { "metric-type": "ietf-network-slice-service:two-way-packet-loss", "metric-unit": "percentage", - "percentile-value": packet_loss, + "percentile-value": destination_one_way_packet_loss, }, ] } diff --git a/src/service/service/service_handlers/l3slice_ietfslice/L3SliceIETFSliceServiceHandler.py b/src/service/service/service_handlers/l3slice_ietfslice/L3SliceIETFSliceServiceHandler.py index 258ea27f05ca27e544c26a0b0fe8f8ddf6692933..b5e9bb43f91919c2e580c50c91cde244b67ca7fc 100644 --- a/src/service/service/service_handlers/l3slice_ietfslice/L3SliceIETFSliceServiceHandler.py +++ b/src/service/service/service_handlers/l3slice_ietfslice/L3SliceIETFSliceServiceHandler.py @@ -18,6 +18,7 @@ import re from typing import Any, Dict, List, Optional, Tuple, TypedDict, Union from deepdiff import DeepDiff +from dataclasses import dataclass from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.proto.context_pb2 import ConfigRule, DeviceId, Empty, Service, ServiceConfig @@ -50,6 +51,16 @@ class DeviceEpInfo(TypedDict): ipv4_info: Ipv4Info node_name: str endpoint_name: str + one_way_delay: int + one_way_bandwidth: int + one_way_packet_loss: float + + +@dataclass +class ConnectivityConstructInfo: + bandwidth: int = 0 + delay: int = 0 + packet_loss: float = 0.0 RUNNING_RESOURCE_KEY = "running_ietf_slice" @@ -149,25 +160,91 @@ def get_removed_items( def extract_source_destination_device_endpoint_info( - device_ep_pairs: list, connection_group: Dict + device_ep_pairs: list, connection_group: Dict, candidate_connection_groups: List ) -> Tuple[DeviceEpInfo, DeviceEpInfo]: connectivity_construct = connection_group["connectivity-construct"][0] sender_sdp = connectivity_construct["p2p-sender-sdp"] + receiver_sdp = connectivity_construct["p2p-receiver-sdp"] if sender_sdp == device_ep_pairs[0][4]: ... elif sender_sdp == device_ep_pairs[1][4]: device_ep_pairs = device_ep_pairs[::-1] else: raise Exception("Sender SDP not found in device_ep_pairs") + cc_info: Dict[Tuple[str, str], ConnectivityConstructInfo] = {} + for cg in candidate_connection_groups: + for cc in cg["connectivity-construct"]: + cc_sender = cc["p2p-sender-sdp"] + cc_receiver = cc["p2p-receiver-sdp"] + cc_key = (cc_sender, cc_receiver) + cc_info[cc_key] = ConnectivityConstructInfo() + for metric_bound in cc["service-slo-sle-policy"]["slo-policy"][ + "metric-bound" + ]: + if ( + metric_bound["metric-type"] + == "ietf-network-slice-service:one-way-delay-maximum" + and metric_bound["metric-unit"] == "milliseconds" + ): + cc_info[cc_key].delay = int(metric_bound["bound"]) + elif ( + metric_bound["metric-type"] + == "ietf-network-slice-service:two-way-packet-loss" + and metric_bound["metric-unit"] == "percentage" + ): + cc_info[cc_key].packet_loss = float( + metric_bound["percentile-value"] + ) + elif ( + metric_bound["metric-type"] + == "ietf-network-slice-service:one-way-bandwidth" + and metric_bound["metric-unit"] == "Mbps" + ): + cc_info[cc_key].bandwidth = int(metric_bound["bound"]) + source_delay = int(1e6) + source_bandwidth = 0 + source_packet_loss = 1.0 + destination_delay = int(1e6) + destination_bandwidth = 0 + destination_packet_loss = 1.0 + if cc_info: + common_sdps = set.intersection(*[set(key) for key in cc_info.keys()]) + if len(cc_info) > 2 and len(common_sdps) != 1: + raise Exception( + "There should be one common sdp in all connectivity constructs, otherwise, it is not supported" + ) + common_sdp = common_sdps.pop() + for (sender, receiver), metrics in cc_info.items(): + cc_bandwidth = metrics.bandwidth + cc_max_delay = metrics.delay + cc_packet_loss = metrics.packet_loss + if sender == common_sdp: + source_bandwidth += cc_bandwidth + if cc_max_delay < source_delay: + source_delay = cc_max_delay + if cc_packet_loss < source_packet_loss: + source_packet_loss = cc_packet_loss + else: + destination_bandwidth += cc_bandwidth + if cc_max_delay < destination_delay: + destination_delay = cc_max_delay + if cc_packet_loss < destination_packet_loss: + destination_packet_loss = cc_packet_loss source_device_ep_info = DeviceEpInfo( ipv4_info=device_ep_pairs[0][5], node_name=device_ep_pairs[0][2], endpoint_name=device_ep_pairs[0][3], + one_way_delay=source_delay, + one_way_bandwidth=source_bandwidth, + one_way_packet_loss=source_packet_loss, ) destination_device_ep_info = DeviceEpInfo( ipv4_info=device_ep_pairs[1][5], node_name=device_ep_pairs[1][2], endpoint_name=device_ep_pairs[1][3], + one_way_delay=destination_delay, + one_way_bandwidth=destination_bandwidth, + one_way_packet_loss=destination_packet_loss, ) return source_device_ep_info, destination_device_ep_info @@ -268,9 +345,6 @@ class L3NMSliceIETFSliceServiceHandler(_ServiceHandler): edge_device_names = [src_device_name, dst_device_name] link_list = context_client.ListLinks(Empty()) links = link_list.links - max_delay = 1e9 - packet_loss = 1.0 - bandwidth = 0.0 device_ep_pairs = [] sdp_ids = [] running_candidate_diff = get_running_candidate_ietf_slice_data_diff( @@ -650,34 +724,6 @@ class L3NMSliceIETFSliceServiceHandler(_ServiceHandler): "connection-group" ] LOGGER.debug(f"connection_groups: {candidate_connection_groups}") - for cg in candidate_connection_groups: - for cc in cg["connectivity-construct"]: - for metric_bound in cc["service-slo-sle-policy"]["slo-policy"][ - "metric-bound" - ]: - if ( - metric_bound["metric-type"] - == "ietf-network-slice-service:one-way-delay-maximum" - and metric_bound["metric-unit"] == "milliseconds" - ): - metric_value = int(metric_bound["bound"]) - if metric_value < max_delay: - max_delay = metric_value - elif ( - metric_bound["metric-type"] - == "ietf-network-slice-service:two-way-packet-loss" - and metric_bound["metric-unit"] == "percentage" - ): - metric_value = float(metric_bound["percentile-value"]) - if metric_value < packet_loss: - packet_loss = metric_value - elif ( - metric_bound["metric-type"] - == "ietf-network-slice-service:one-way-bandwidth" - and metric_bound["metric-unit"] == "Mbps" - ): - metric_value = float(metric_bound["bound"]) - bandwidth += metric_value if ( len( candidate_resource_value_dict["network-slice-services"][ @@ -694,7 +740,9 @@ class L3NMSliceIETFSliceServiceHandler(_ServiceHandler): ) source_device_ep_info, destination_device_ep_info = ( extract_source_destination_device_endpoint_info( - device_ep_pairs, target_connection_group + device_ep_pairs, + target_connection_group, + candidate_connection_groups, ) ) resource_value_dict = { @@ -713,6 +761,11 @@ class L3NMSliceIETFSliceServiceHandler(_ServiceHandler): "src_destination_tcp_port": source_device_ep_info["ipv4_info"][ "dst_port" ], + "source_one_way_delay": source_device_ep_info["one_way_delay"], + "source_one_way_bandwidth": source_device_ep_info["one_way_bandwidth"], + "source_one_way_packet_loss": source_device_ep_info[ + "one_way_packet_loss" + ], "dst_node_id": destination_device_ep_info["node_name"], "dst_mgmt_ip_address": destination_device_ep_info["node_name"], "dst_ac_node_id": destination_device_ep_info["node_name"], @@ -730,12 +783,17 @@ class L3NMSliceIETFSliceServiceHandler(_ServiceHandler): "dst_destination_tcp_port": destination_device_ep_info["ipv4_info"][ "dst_port" ], + "destination_one_way_delay": destination_device_ep_info[ + "one_way_delay" + ], + "destination_one_way_bandwidth": destination_device_ep_info[ + "one_way_bandwidth" + ], + "destination_one_way_packet_loss": destination_device_ep_info[ + "one_way_packet_loss" + ], "slice_id": slice_name, - "delay": max_delay, - "bandwidth": bandwidth, - "packet_loss": packet_loss, } - json_config_rules = setup_config_rules(slice_name, resource_value_dict) del controller.device_config.config_rules[:] for jcr in json_config_rules: